本節代碼在鏈接的ch05文件夾
MultiTexture.js(貼了兩張紋理)
重點在片元着色器,還有loadTexture函數
// MultiTexture.js (c) 2012 matsuda and kanda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' + // 紋理座標
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' v_TexCoord = a_TexCoord;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
'uniform sampler2D u_Sampler0;\n' + //紋理0
'uniform sampler2D u_Sampler1;\n' + //紋理1
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' vec4 color0 = texture2D(u_Sampler0, v_TexCoord);\n' +
' vec4 color1 = texture2D(u_Sampler1, v_TexCoord);\n' +
' gl_FragColor = color0 * color1;\n' +
'}\n';
//.......省略部分代碼
// 標記紋理單元是否就緒
var g_texUnit0 = false, g_texUnit1 = false;
function loadTexture(gl, n, texture, u_Sampler, image, texUnit) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// Flip the image's y-axis
// 激活紋理
if (texUnit == 0) {
gl.activeTexture(gl.TEXTURE0);
g_texUnit0 = true;
} else {
gl.activeTexture(gl.TEXTURE1);
g_texUnit1 = true;
}
// 綁定紋理對象到目標上
gl.bindTexture(gl.TEXTURE_2D, texture);
//綁定紋理參數
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
//設置紋理圖像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
//將紋理單元編號傳遞給取樣器
gl.uniform1i(u_Sampler, texUnit);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
if (g_texUnit0 && g_texUnit1) {
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); //繪製一個矩形
}
}
設置紋理
- 頂點着色器中接收的頂點的紋理座標,光柵化後傳遞給片元着色器
- 片元着色器根據片元的紋理座標,從紋理圖像中抽取紋素顏色,賦給當前片元
- 設置頂點的紋理座標(initVertexBuffers)
- 準備待加載的紋理圖像,令瀏覽器讀取它(initTextures)
- 監聽紋理圖像的加載事件,一旦加載完成,就在WebGL系統中使用紋理(loadTexture)
配置紋理對象的參數
這步是設置紋理對象映射到圖像上的具體方式:如何根據紋理座標獲取紋理顏色,按哪種當時重複紋理。
GLenum 的意思是常量
void gl.texParameterf(GLenum target, GLenum pname, GLfloat param);
void gl.texParameteri(GLenum target, GLenum pname, GLint param);
target:GLenum 指定綁定點(目標)。可能的值:
gl.TEXTURE_2D: 二維紋理.
gl.TEXTURE_CUBE_MAP: 立方體紋理.
當使用 WebGL 2 context 時,還可以使用以下值
gl.TEXTURE_3D: 三維貼圖.
gl.TEXTURE_2D_ARRAY: 二維數組貼圖.
pname 參數是 Glenum 指定要設置的紋理參數. param 參數是 GLfloat 或 GLint 已指定的 pname參數的值。
pname:紋理參數
param:紋理參數的值(按哪種當時重複紋理)
紋理參數 | 描述 | 默認紋理參數的值 |
---|---|---|
gl.TEXTURE_MAG_FILTER | 紋理放大濾波器 | gl.LINEAR |
gl.TEXTURE_MIN_FILTER | 紋理縮小濾波器 | gl.NEAREST_MIPMAP_LINEAR |
gl.TEXTURE_WRAP_S | 紋理座標水平填充 | gl.REPEAT |
gl.TEXTURE_WRAP_T | 紋理座標垂直填充 | gl.REPEAT |
將紋理圖像分配給紋理對象
void gl.texImage2D(target, level, internalformat, width, height, format, type, HTMLImageElement source);
方法指定了二維紋理圖像,最後一個參數也可以用HTMLCanvasElement source、HTMLVideoElement source、 ImageBitmap source、ImageData source等等
target:GLenum 指定綁定點(目標)。可能的值:
gl.TEXTURE_2D: 二維紋理.
gl.TEXTURE_CUBE_MAP: 立方體紋理.
level:傳入0,0級是基本圖像等級,n級是第n個金字塔簡化級.
internalformat:圖像內部格式
width:指定紋理的寬度。
height:指定紋理的高度。
format: 紋理數據的格式,必須和internalformat相同
image:包含紋理圖像的對象
在片元着色器中獲取紋理像素顏色
vec4 texture2D(sampler2D sampler, vec2 coord)
sample:指定紋理單元編號
coord:指定紋理座標(頂點着色器傳過來的)
紋理座標系統
uv其實就是紋理座標,因爲xyz已經被頂點座標佔用了,所以uvw就用來表示紋理座標。它時候貼圖影射到模型表面的依據,把表面的點與平面上的像素對應起來,一般取值在0~1;
u:圖片在顯示器水平的座標
v:垂直方向
w:垂直於顯示器表面
一般情況只是在表面貼圖,就涉及不到w,所以常稱爲uv。
取值如果都是0,1,一般就算是整張圖片整鋪在平面上。
我們看下紋理座標取值不在0~1的情況。
參考
- [1] [WebGL編程指南]