寫在前面html
建議先閱讀下前面個人三篇文章。web
webgl學習筆記一-繪圖單點canvas
術語 :webgl
紋理繪圖流程code
重點介紹紋理的流程。orm
demohtm
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <canvas id="canvas" width="200px" height="200px"></canvas> </body> </html>
<script> window.onload = function () { //頂點着色器程序 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);" + // 設置顏色 "}"; //獲取canvas元素 var canvas = document.getElementById('canvas'); //獲取繪製webgl繪圖上下文 var gl = canvas.getContext('webgl'); if (!gl) { console.log("Failed"); return; } //編譯着色器 // (1)建立Shader(着色器)對象 // (2)將着色器程序附加到Shader上 // (3)編譯程序 var vertShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertShader, VSHADER_SOURCE); gl.compileShader(vertShader); var fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragShader, FSHADER_SOURCE); gl.compileShader(fragShader); //合併程序 // (1)建立一個程序對象 // (2)附加着色器 // (3)連接着色器 // (4)使用程序 var shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertShader); gl.attachShader(shaderProgram, fragShader); gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram); gl.clearColor(0.0, 0.0, 0.0, 1.0); var n = initBuffers(gl, shaderProgram); initTexture(gl, shaderProgram, n); gl.clear(gl.COLOR_BUFFER_BIT); //繪製一個點 gl.drawArrays(gl.POINTS, 0, 1); } // 使用緩衝區對象向頂點傳入多個頂點數據 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; } // 初始建立紋理,建立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 = "../../resources/st2_256*128.png"; return true; } // 加載紋理圖像,配置屬性 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); } </script>