本章主要是對紋理的進一步講解,咱們不少時候須要將現實中已有 的圖片在網頁中展現出來而不是去創造圖片,經過紋理 咱們能夠將光柵化的圖形和圖片紋理造成映射而且將圖片在圖形 中顯示出來。基本過程與前幾章一致,在着色器中主要是添加了一個取樣器的變量做用是從紋理單元中取出圖形在不一樣座標的片元上顯示出來,這裏先要設置紋理座標將紋理座標和webGL座標造成映射,而後是建立圖像對象,建立紋理對象,開啓某個紋理單元,將紋理對象與紋理單元綁定,配置紋理參數,將圖像對象添加進紋理單元,將紋理單元中的紋理傳給取樣器,取樣器根據紋理座標和webGL座標的對應關係顯示紋理圖像。javascript
效果以下:css
看代碼:html
<!DOCTYPE html> <html> <head> <title>TexturedQuad.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> <script src="js/cuon-matrix.js"></script> <script src="js/cuon-utils.js"></script> <script src="js/webgl-debug.js"></script> <script src="js/webgl-utils.js"></script> <script type="text/javascript"> var VSHADER_SOURCE=//定點着色器 'attribute vec4 a_Position;\n'+//定義vec4的變量 而且聲明該變量是attribute型的 'attribute float a_PointSize;\n'+ 'attribute vec2 a_TextCoord;\n'+ 'varying vec2 v_TextCoord;\n'+ 'void main(){\n'+ 'gl_Position=a_Position;\n'+//將attribute的變量賦值給內部 'gl_PointSize=a_PointSize;\n'+ 'v_TextCoord=a_TextCoord;\n'+//將數據傳給片元着色器 '}\n'; var FSHADER_SOURCE=//片元着色器 'precision mediump float;\n' + 'uniform sampler2D u_Sampler;\n'+ 'varying vec2 v_TextCoord;\n'+ 'void main(){\n'+ 'gl_FragColor=texture2D(u_Sampler,v_TextCoord);\n'+// '}\n'; function main(){ var canvas=document.getElementById("webgl"); var gl=getWebGLContext(canvas); if(!gl){ console.log("gl load fail!"); return; } if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){//初始化着色器 console.log("fail init shader()!"); return ; } var n=initVertexBuffers(gl);//將頂點座標和紋理座標賦值 if(n<0){ console.log("failed to set the positions of the vertices"); return; } gl.clearColor(0.0, 0.0, 1.0, 1.0); initTextures(gl,n); } function initVertexBuffers(gl){ var verticesTextCoords=new Float32Array([ -0.5,0.5,2,-0.3,1.7, -0.5,-0.5,2,-0.3,-0.2, 0.5,0.5,2,1.7,1.7, 0.5,-0.5,2,1.7,-0.2, ]);//類型化數組 var n=4;//點的個數 var vertexTexcoordBuffer=gl.createBuffer();//在webGL中建立緩衝區 if(!vertexTexcoordBuffer){ console.log("failed to create the buffer object!"); return -1; } gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexcoordBuffer);//將緩衝區與ARRAY_BUFFER綁定就是指定了緩衝區的用途 gl.bufferData(gl.ARRAY_BUFFER,verticesTextCoords,gl.STATIC_DRAW);//往緩衝區寫數據 STATIC_DRAW對緩衝區優化 將頂點座標和紋理座標放進緩衝區 var FSize=verticesTextCoords.BYTES_PER_ELEMENT;//數組中每一個元素的字節大小 alert(FSize); //設置頂點座標 從緩衝區取出座標 var a_Position=gl.getAttribLocation(gl.program,'a_Position'); gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,5*FSize,0);//將緩衝區的數據傳入分配給attribute對象 2是定點的份量個數 3*FSize表示相鄰兩個頂點間相距的字節數也能夠理解爲每隔3*FSize字節取倆值 是這些 0表示它的其實 偏移量就是從哪開始的 gl.enableVertexAttribArray(a_Position);//開啓attribute變量 //將紋理座標分配給webgl var a_TextCoord=gl.getAttribLocation(gl.program,'a_TextCoord'); gl.vertexAttribPointer(a_TextCoord,2,gl.FLOAT,false,5*FSize,3*FSize); gl.enableVertexAttribArray(a_TextCoord); //設置點的大小 var a_PointSize=gl.getAttribLocation(gl.program,'a_PointSize'); gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,5*FSize,2*FSize); gl.enableVertexAttribArray(a_PointSize); return n; } function initTextures(gl,n){ alert(n); var texture=gl.createTexture();//建立紋理對象 用來管理紋理 if(!texture){ console.log("failed to texture"); return false; } //u_Sampler是用來存儲紋理的 var u_Sampler=gl.getUniformLocation(gl.program,'u_Sampler'); if(!u_Sampler){ console.log("failed to u_Sampler"); return false; } //加載圖片建立圖片對象異步加載圖片加載完後調用loadTexture函數 未完成前也繼續執行下面的代碼 var image=new Image(); image.onload=function(){ loadTexture(gl,n,texture,u_Sampler,image);//將紋理單元的圖像以及參數傳給取樣器 }; image.src="image/sky.jpg"; return true; } function loadTexture(gl,n,texture,u_Sampler,image){ alert(image.height); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);//對圖像進行Y軸反轉 gl.activeTexture(gl.TEXTURE0);//開啓0號單元 //console.log(gl.activeTexture(gl.TEXTURE0)); gl.bindTexture(gl.TEXTURE_2D,texture);//將紋理對象綁定到紋理單元中 由於無法直接操做紋理對象可是能夠操做紋理單元 gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//配置紋理的參數 /* gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);//在X軸上不足會自動填充 gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//在y軸上不足的灰自動tian */ gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);//配置紋理圖像 gl.uniform1i(u_Sampler,0);//將0單元的紋理傳給紋理取樣器 gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP,0,n); } </script> </head> <body onload="main()"> <canvas id="webgl" width="600" height="400"></canvas> </body> </html>