WebGL(三)學會貼紋理

本節代碼在鏈接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);   //繪製一個矩形
  }
}

設置紋理

  1. 頂點着色器中接收的頂點的紋理座標,光柵化後傳遞給片元着色器
  2. 片元着色器根據片元的紋理座標,從紋理圖像中抽取紋素顏色,賦給當前片元
  3. 設置頂點的紋理座標(initVertexBuffers)
  4. 準備待加載的紋理圖像,令瀏覽器讀取它(initTextures)
  5. 監聽紋理圖像的加載事件,一旦加載完成,就在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編程指南]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章