前面文章:
WebGL入門教程(一)-初識webgl
WebGL入門教程(二)-webgl繪制三角形
WebGL入門教程(三)-webgl動畫
WebGL入門教程(四)-webgl顏色
這里就需要用到紋理映射,他就是將一張真實圖片貼到一個幾何圖像表面。
紋理圖像:映射的這個圖像稱為紋理圖像;
紋素:組成紋理圖像的像素稱為紋素;
紋理坐標:是紋理圖像上的坐標,通過紋理坐標可以在紋理圖像上獲取紋素顏色;
效果圖:
操作步驟:
1.創建HTML5 canvas
2.獲取畫布 canvas 的 ID
3.獲取WebGL
4.編譯着色器,合並程序
5.使用緩沖區對象向頂點傳入多個頂點數據
6.創建紋理,加載紋理圖像,配置屬性,在webgl中使用它;
7.加載紋理圖像,配置屬性,在webgl中使用它;
以上1~3參考:http://www.cnblogs.com/bsman/p/6128447.html
4.編譯着色器
//頂點着色器程序 var VSHADER_SOURCE = "attribute vec4 a_Position;" + "attribute vec2 a_TextCoord;" + // 接受紋理坐標 "varying vec2 v_TexCoord;" + // 傳遞紋理坐標 "void main() {" + //設置坐標 "gl_Position = a_Position; " + // 設置坐標 //設置紋素 "v_TexCoord = a_TextCoord; " + // 設置紋理坐標 "} "; //片元着色器 var FSHADER_SOURCE = "precision mediump float;" + //需要聲明浮點數精度,否則報錯No precision specified for (float) "uniform sampler2D u_Sampler;" + // 取樣器 "varying vec2 v_TexCoord;" + // 接受紋理坐標 "void main() {" + //設置顏色 "gl_FragColor = texture2D(u_Sampler, v_TexCoord);" + // 設置顏色 "}";
解釋:在頂點着色器中為每個頂點指定紋理坐標,然后在片元着色器中根據每個片元的紋理坐標從紋理圖像中抽取紋素顏色
5.使用緩沖區對象向頂點傳入多個頂點數據
function initBuffers(gl, shaderProgram) { //頂點坐標和顏色 var vertices = new Float32Array([ -0.5, 0.5, 0.0, 1.0, -0.5, -0.5, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.5, -0.5, 1.0, 0.0 ]); var n = 4;//點的個數 //創建緩沖區對象 var vertexBuffer = gl.createBuffer(); //將緩沖區對象綁定到目標 gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer); //向緩沖區寫入數據 gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW); var FSIZE = vertices.BYTES_PER_ELEMENT; //獲取坐標點 var a_Position = gl.getAttribLocation(shaderProgram, "a_Position"); //將緩沖區對象分配給a_Position變量 gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*4, 0); //連接a_Position變量與分配給它的緩沖區對象 gl.enableVertexAttribArray(a_Position); //獲取Color坐標點 var a_TextCoord = gl.getAttribLocation(shaderProgram, "a_TextCoord"); //將緩沖區對象分配給a_Position變量 gl.vertexAttribPointer(a_TextCoord, 2, gl.FLOAT, false, FSIZE*4, FSIZE*2); //連接a_Position變量與分配給它的緩沖區對象 gl.enableVertexAttribArray(a_TextCoord); return n; }
6.初始創建紋理,創建image對象
function initTexture(gl, shaderProgram, n){ //創建紋理對象 var texture = gl.createTexture(); //獲取u_Sampler的存儲位置 var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler'); //創建image對象 var image = new Image(); //加載紋理 image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); }; // 瀏覽器開始加載圖片 注意:一定是2^mx2^n尺寸的圖片 image.src = "../TexturedQuad/shan.jpg"; return true; }
u_Sampler代表從紋理圖像中獲取紋理顏色
gl.createTexture();創建紋理對象以存儲紋理對象;gl.TEXTURE0~gl.TEXTURE7是管理紋理圖像的8個紋理單元
注意:這樣圖片的尺寸一定是2^mx2^n尺寸的圖片,不然會報錯 WebGL: drawArrays: texture bound to texture unit 0 is not renderable.
瀏覽器異步加載圖片
7.加載紋理圖像,配置屬性,在webgl中使用它;
function loadTexture(gl, n, texture, u_Sampler,image){ //1.對紋理圖像進行Y軸反轉 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); //2.開啟0號紋理單元 gl.activeTexture(gl.TEXTURE0); //3.向target綁定紋理對象 gl.bindTexture(gl.TEXTURE_2D, texture); //4.配置紋理參數 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); //5.配置紋理圖像 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); //6.將0號紋理圖像傳遞給着色器 gl.uniform1i(u_Sampler, 0); // 清空 <canvas> gl.clear(gl.COLOR_BUFFER_BIT); //繪制矩形 gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); }
7.1對紋理圖像進行Y軸反轉,因為WebGL紋理坐標系統的t軸(分為t軸和s軸)的方向和圖片的坐標系統Y軸方向相反。因此將Y軸進行反轉。
gl.pixelStorei 第一個參數:有兩個,一個UNPACK_FLIP_Y_WEBGL代表對Y軸反轉,默認為false;一個UNPACK_PREMULTIPLY_ALPHA_WEBGL代表將圖像 RGB顏色值得每一個分量乘以A,默認值為false;
7.2開啟0號紋理單元
WebGL通過紋理單元的機制來同時使用多個紋理,gl.TEXTURE0~gl.TEXTURE7是管理紋理圖像的8個紋理單元
7.3綁定紋理對象
gl.bindTexture兩個參數
第一個參數:有兩個選擇TEXTURE_2D代表二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:表示綁定的紋理單元
7.4配置紋理參數
gl.texParameteri三個參數
第一個參數:有兩個選擇TEXTURE_2D代表二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:有4個紋理參數
1.TEXTURE_MAX_FILTER:放大方法 默認:gl.LINEAR
2.TEXTURE_MIN_FILTER:縮小方法 默認:gl.NEAREST_MIPMAP_LINEAR
3.TEXTURE_WRAP_S: 水平填充方法 默認:gl.REPEAT
4.TEXTURE_WRAP_T: 垂直填充方法 默認:gl.REPEAT
第三個參數:
gl.LINEAR:使用距離新像素中心最近的四個像素的顏色值得加權值平均(圖片質量好,但是開銷大)
gl.NEAREST_MIPMAP_LINEAR:使用原紋理上的距離映射后像素中心最近的那個像素的顏色值作為新像素的值
gl.REPEAT:平鋪式的重復紋理
gl.REPEAT:鏡像對稱式的重復紋理
gl.REPEAT:使用紋理圖像邊緣值
7.5配置紋理圖像
gl.texImage2D有六個參數
第一個參數:有兩個選擇TEXTURE_2D代表二維紋理,TEXTURE_CUBE_MAP 立方體紋理;
第二個參數:默認為0,涉及到三維再說
第三個參數:圖像的內部格式
有:gl.RGB(紅綠藍)、gl.RGBA(紅綠藍透明度)、gl.ALPHA(0.0,0.0,0.0,透明度)、gl.LUMINANCE(L、L、L、1L:流明)、
gl.LUMINANCE_ALPHA(L、L、L,透明度)、
流明:表示我們感知到的物體表面的亮度,等於紅綠藍顏色分量值的加權平均來計算流明
第四個參數:紋理的數據格式,必須與第三個參數相同
第五個參數:紋理數據格式 UNSIGNED_BYTE:表示無符號整形,每一個顏色分量占據1字節
UNSIGNED_SHORT_5_6_5:表示RGB,每一個分量分別占據占據5,6,5比特
UNSIGNED_SHORT_4_4_4_4:表示RGBA,每一個分量分別占據占據4,4,4,4比特
UNSIGNED_SHORT_5_5_5_1:表示RGBA,每一個分量分別占據占據5比特,A分量占據1比特
第六個參數:紋理圖像的image對象
7.6將0號紋理圖像傳遞給着色器
uniform1i(u_Sampler, 0);這里和上面的片元着色器"gl_FragColor = texture2D(u_Sampler, v_TexCoord);" + // 設置顏色,有聯系
其中:sampler2D綁定到gl.TEXTURE_2D上,samplerCube綁定到gl.TEXTURE_CUBE_MAP上