目錄
#2D紋理
漫反射貼圖
镜面Web學習之怎麼使用紋理貼圖
首頁 web前端 js教程 Web學習之怎麼使用紋理貼圖

Web學習之怎麼使用紋理貼圖

Apr 30, 2019 am 11:29 AM
js web webgl

為了讓圖形能獲得接近真實物體的材質效果,一般會使用貼圖,貼圖類型主要包括兩種:漫反射貼圖和鏡面高光貼圖。其中漫反射貼圖可以同時實現漫反射光和環境光的效果。
實際效果請看demo:紋理貼圖

Web學習之怎麼使用紋理貼圖

#2D紋理

實作貼圖就需要用到紋理,常用的紋理格式有:2D紋理,立方體紋理,3D紋理。我們使用最基本的2D紋理就能達到本節所需的效果,我們來看看使用紋理所需的api。相關教學:js影片教學

因為紋理的座標原點位於左下角,和我們通常的左上角座標原點剛好相反,下面就是將它按Y軸進行反轉,方便我們設定坐標。

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
登入後複製

啟動和綁定紋理,gl.TEXTURE0 表示0號紋理,可以從0一直往上遞增。 TEXTURE_2D 則是表示2D紋理。

gl.activeTexture(gl.TEXTURE0);//激活纹理
gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理
登入後複製

接著就是設定紋理參數,這個api非常重要,也是紋理最複雜的部分。

gl.texParameteri(target, pname, param) ,將param的值賦給綁定到目標的紋理物件的pname參數上。參數:

  • target: gl.TEXTURE_2Dgl.TEXTURE_CUBE_MAP

  • pname: 可指定4個紋理參數

    1. 放大(gl.TEXTURE_MAP_FILTER):當紋理的繪製範圍比紋理本身更大時,如何取得紋理顏色。例如,將16*16的紋理影像映射到32*32像素的空間時,紋理的尺寸會變成原始的兩倍。預設值為gl.LINEAR。
    2. 縮小(gl.TEXTURE_MIN_FILTER): 當紋理的繪製回傳比紋理本身更小時,如何取得紋素顏色。例如,將32*32的紋理影像映射到16*16像素空間裡,紋理的尺寸就只有原始的普通。預設值為gl.NEAREST_MIPMAP_LINEAR。
    3. 水平填充(gl.TEXTURE_WRAP_S): 表示如何對紋理圖像左側或右側區域進行填充。預設值為gl.REPEAT。
    4. 垂直填入(gl.TEXTURE_WRAP_T): 表示如何對紋理影像上方和下方的區域進行填滿。預設值為gl.REPEAT。
  • param: 紋理參數的值

    1. #可賦給gl.TEXTURE_MAP_FILTERgl .TEXTURE_MIN_FILTER 參數的值

      gl.NEAREST: 使用原紋理上距離映射後像素中心最近的那個像素的顏色值,作為新像素的值。

      gl.LINEAR: 使用距離新像素中心最近的四個像素的顏色值的加權平均,作為新像素的值(和gl.NEAREST相比,該方法圖像質量更好,但也會有較大的開銷。)

    2. 可賦給gl.TEXTURE_WRAP_Sgl.TEXTURE_WRAP_T 的常數:

      gl.REPEAT: 平鋪式的重複紋理

      #gl.MIRRORED_REPEAT: 鏡像對稱的重複紋理

      gl.CLAMP_TO_EDGE: 使用紋理影像邊緣值

#設定樣例如下所示:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
登入後複製

#gl .texImage2D,將pixels 指定給綁定的紋理對象,這個api在WebGL1WebGL2 中的重載函數多達十幾個,格式類型非常多樣。 pixels參數既可以是圖像,canvas,也可以是視頻,我們只看 WebGL1中的呼叫形式。

// WebGL1:
void gl.texImage2D(target, level, internalformat, width, height, border, format, type, ArrayBufferView? pixels);
void gl.texImage2D(target, level, internalformat, format, type, ImageData? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLImageElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLCanvasElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLVideoElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, ImageBitmap? pixels);

// WebGL2:
//...
登入後複製

我封裝出了一個紋理載入函數,每個api的呼叫格式可以查看資料,還是先實現我們想要的效果。

function loadTexture(url) {
    const texture = gl.createTexture();
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    
    let textureInfo = {
        width: 1,
        height: 1,
        texture: texture,
    };
    const img = new Image();
    return new Promise((resolve,reject) => {
        img.onload = function() {
            textureInfo.width = img.width;
            textureInfo.height = img.height;
            gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
            resolve(textureInfo);
        };
        img.src = url;
    });
}
登入後複製

漫反射貼圖

首先實現漫反射光貼圖,從網路上下載了個地板的貼圖,裡麵包含了各種類型的貼圖。

緩衝區要增加頂點對應的紋理座標,這樣才能透過紋理座標找到對應的紋理像素,簡稱紋素。

const arrays = {
    position: [
        -1, 0, -1,
        -1, 0, 1,
        1, 0, -1,
        1, 0, 1
    ],
    texcoord: [
        0.0, 1.0,
        0.0, 0.0,
        1.0, 1.0,
        1.0, 0.0
    ],
    normal: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 ],
};
登入後複製

頂點著色器唯一差異是增加了紋理座標,需要插值傳入片元著色器

//...
attribute vec2 a_texcoord;
varying vec2 v_texcoord;

void main() { 
        //...
    v_texcoord = a_texcoord;
}
登入後複製

片元著色器修改的多一些。主要是使用 texture2D 取得對應座標下的紋素,取代之前的顏色就可以了。以下是片元著色器相關程式碼

//...
vec3 normal = normalize(v_normal);
vec4 diffMap = texture2D(u_samplerD, v_texcoord);

//光线方向
vec3 lightDirection = normalize(u_lightPosition - v_position);
// 计算光线方向和法向量夹角
float nDotL = max(dot(lightDirection, normal), 0.0);
// 漫反射光亮度
vec3 diffuse = u_diffuseColor * nDotL * diffMap.rgb;
// 环境光亮度
vec3 ambient = u_ambientColor * diffMap.rgb;
//...
登入後複製

js部分載入貼圖對應的圖片,傳遞紋理單元,然後渲染

//...
(async function (){
    const ret = await loadTexture('/model/floor_tiles_06_diff_1k.jpg')
    setUniforms(program, {
        u_samplerD: 0//0号纹理
    });
    //...
    draw();
})()
登入後複製

效果如下,鏡面高光部分似乎太刺眼了,因為地板是不會有鏡子一樣光滑強烈的反光的。

Web學習之怎麼使用紋理貼圖

镜面Web學習之怎麼使用紋理貼圖

为了实现更逼真的高光效果,继续实现Web學習之怎麼使用紋理貼圖,实现原理和漫反射一样,把对应的高光颜色替换成Web學習之怎麼使用紋理貼圖纹素就可以了。
下面就是片元着色器增加修改高光部分

//...
vec3 normal = normalize(v_normal);
vec4 diffMap = texture2D(u_samplerD, v_texcoord);
vec4 specMap = texture2D(u_samplerS, v_texcoord);

//光线方向
vec3 lightDirection = normalize(u_lightPosition - v_position);
// 计算光线方向和法向量夹角
float nDotL = max(dot(lightDirection, normal), 0.0);
// 漫反射光亮度
vec3 diffuse = u_diffuseColor * nDotL * diffMap.rgb;
// 环境光亮度
vec3 ambient = u_ambientColor * diffMap.rgb;
// 镜面高光
vec3 eyeDirection = normalize(u_viewPosition - v_position);// 反射方向
vec3 halfwayDir = normalize(lightDirection + eyeDirection);
float specularIntensity = pow(max(dot(normal, halfwayDir), 0.0), u_shininess);
vec3 specular = (vec3(0.2,0.2,0.2) + specMap.rgb) * specularIntensity;
//...
登入後複製

js同时加载漫反射和Web學習之怎麼使用紋理貼圖

//...
(async function (){
    const ret = await Promise.all([
        loadTexture('/model/floor_tiles_06_diff_1k.jpg'),
        loadTexture('/model/floor_tiles_06_spec_1k.jpg',1)
    ]);
    setUniforms(program, {
        u_samplerD: 0,//0号纹理
        u_samplerS: 1 //1号纹理
    });
    //...
    draw();
})()
登入後複製

最后实现的效果如下,明显更加接近真实的地板

Web學習之怎麼使用紋理貼圖

以上是Web學習之怎麼使用紋理貼圖的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 Dec 17, 2023 pm 06:55 PM

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

如何使用PHP和JS創建股票蠟燭圖 如何使用PHP和JS創建股票蠟燭圖 Dec 17, 2023 am 08:08 AM

如何使用PHP和JS創建股票蠟燭圖股票蠟燭圖是股票市場中常見的技術分析圖形,透過繪製股票的開盤價、收盤價、最高價和最低價等數據,幫助投資者更直觀地了解股票的價格波動情形。本文將教你如何使用PHP和JS創建股票蠟燭圖,並附上具體的程式碼範例。一、準備工作在開始之前,我們需要準備以下環境:1.一台運行PHP的伺服器2.一個支援HTML5和Canvas的瀏覽器3

如何使用JS和百度地圖實現地圖點擊事件處理功能 如何使用JS和百度地圖實現地圖點擊事件處理功能 Nov 21, 2023 am 11:11 AM

如何使用JS和百度地圖實現地圖點擊事件處理功能概述:在網路開發中,經常需要使用地圖功能來展示地理位置和地理資訊。而地圖上的點擊事件處理是地圖功能中常用且重要的一環。本文將介紹如何使用JS和百度地圖API來實現地圖的點擊事件處理功能,並給出具體的程式碼範例。步驟:匯入百度地圖的API檔案首先,要在HTML檔案中匯入百度地圖API的文件,可以透過以下程式碼實現:

PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 Dec 18, 2023 pm 03:39 PM

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

js和vue的關係 js和vue的關係 Mar 11, 2024 pm 05:21 PM

js和vue的關係:1、JS作為Web開發基石;2、Vue.js作為前端框架的崛起;3、JS與Vue的互補關係;4、JS與Vue的實踐應用。

如何從駕駛艙Web使用者介面啟用管理訪問 如何從駕駛艙Web使用者介面啟用管理訪問 Mar 20, 2024 pm 06:56 PM

Cockpit是一個面向Linux伺服器的基於Web的圖形介面。它主要是為了使新用戶/專家用戶更容易管理Linux伺服器。在本文中,我們將討論Cockpit存取模式以及如何從CockpitWebUI切換Cockpit的管理存取。內容主題:駕駛艙進入模式查找當前駕駛艙訪問模式從CockpitWebUI啟用Cockpit的管理訪問從CockpitWebUI禁用Cockpit的管理訪問結論駕駛艙進入模式駕駛艙有兩種訪問模式:受限訪問:這是駕駛艙的默認訪問模式。在這種存取模式下,您無法從駕駛艙Web用戶

web是什麼意思 web是什麼意思 Jan 09, 2024 pm 04:50 PM

web是全球廣域網,也稱為萬維網,是互聯網的一種應用形式。 Web 是一種基於超文本和超媒體的資訊系統,它允許使用者透過超連結在不同的網頁之間跳轉,從而瀏覽和獲取資訊。 Web 的基礎是互聯網,它使用統一、標準化的協定和語言,使得不同電腦之間能夠進行資料交換和資訊共享。

See all articles