1. 程式人生 > >03 傳遞貼圖給著色器

03 傳遞貼圖給著色器

tac cti arc port -- angle span com shader

WebGL很容易把圖片傳遞給著色器程序當作貼圖。下面是一些需要註意的地方:

1、貼圖圖片長寬像素必須是2的冪,例如16、32、64、128、256,否則貼圖無法顯示。

2、WebGL只能繪制三角形。為了避免重復,頂點數組裏只給了正方形四個頂點的坐標。然後索引數組裏說明第0、1、2三個頂點組成一個三角形、0、2、3三個頂點組成一個三角形。索引數組的每個面是有順序的,遵循右手定則,四指彎向三個頂點的方法,那麽拇指將指向面的方向。

3、uv坐標表示每個頂點對應貼圖上的位置。(0.0, 0.0)是貼圖左下角,x軸向右,y軸向上,x軸和y軸的最大值為1.例如(1.0, 0.0)表示右下角,(1.0, 1.0)表示右上角,(0.0, 1.0)表示右上角。

  1 <!DOCTYPE html>
  2 
  3 <html lang="zh-CN">
  4 
  5 <head>
  6     <meta charset="UTF-8" />
  7     <title>03_傳遞貼圖給著色器</title>
  8 
  9     <!-- 頂點著色器 -->
 10     <script id="shader-vs" type="x-shader/x-vertex">
 11         attribute vec3 aVertexPosition;
12 attribute vec2 aTextureCoord; 13 varying vec2 vTextureCoord; 14 15 void main(void) { 16 gl_Position = vec4(aVertexPosition, 1.0); 17 vTextureCoord = aTextureCoord; 18 } 19 </script> 20 21 <!-- 片源著色器 --> 22 <script
id="shader-fs" type="x-shader/x-fragment"> 23 precision mediump float; 24 varying vec2 vTextureCoord; 25 uniform sampler2D uSampler; 26 27 void main(void) { 28 gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); 29 } 30 </script> 31 32 <script type="text/javascript"> 33 var start = function () { 34 // 上下文環境 35 var canvas = document.getElementById("mycanvas"); 36 var gl = canvas.getContext("experimental-webgl"); 37 gl.viewportWidth = canvas.width; 38 gl.viewportHeight = canvas.height; 39 gl.viewport(0, 0, gl.viewportWidth, gl.viewportWidth); 40 gl.clearColor(0.0, 0.0, 0.0, 1.0); 41 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 42 gl.enable(gl.DEPTH_TEST); 43 44 // 頂點著色器 45 var shader = gl.createShader(gl.VERTEX_SHADER); 46 gl.shaderSource(shader, document.getElementById(shader-vs).innerHTML); 47 gl.compileShader(shader); 48 var vertexShader = shader; 49 50 // 片源著色器 51 var shader = gl.createShader(gl.FRAGMENT_SHADER); 52 gl.shaderSource(shader, document.getElementById(shader-fs).innerHTML); 53 gl.compileShader(shader); 54 var fragmentShader = shader; 55 56 // 著色器程序 57 var shaderProgram = gl.createProgram(); 58 gl.attachShader(shaderProgram, vertexShader); 59 gl.attachShader(shaderProgram, fragmentShader); 60 gl.linkProgram(shaderProgram); 61 gl.useProgram(shaderProgram); 62 63 // 獲取參數地址 64 var vertexPositionAttr = gl.getAttribLocation(shaderProgram, aVertexPosition); 65 gl.enableVertexAttribArray(vertexPositionAttr); 66 var textureCoordAttr = gl.getAttribLocation(shaderProgram, aTextureCoord); 67 gl.enableVertexAttribArray(textureCoordAttr); 68 var samplerUniform = gl.getUniformLocation(shaderProgram, uSampler); 69 70 // 頂點 71 var vertices = [ 72 -0.5, -0.5, 0.0, 73 0.5, -0.5, 0.0, 74 0.5, 0.5, 0.0, 75 -0.5, 0.5, 0.0 76 ]; 77 var vertexPositionBuffer = gl.createBuffer(); 78 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer); 79 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 80 81 // 索引 82 var vertexIndices = [ 83 0, 1, 2, 84 0, 2, 3 85 ]; 86 var vertexIndexBuffer = gl.createBuffer(); 87 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer); 88 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndices), gl.STATIC_DRAW); 89 90 // uv坐標 91 var textureCoords = [ 92 0.0, 0.0, 93 1.0, 0.0, 94 1.0, 1.0, 95 0.0, 1.0 96 ]; 97 var vertexTextureCoordBuffer = gl.createBuffer(); 98 gl.bindBuffer(gl.ARRAY_BUFFER, vertexTextureCoordBuffer); 99 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW); 100 101 // 貼圖 102 var texture = gl.createTexture(); 103 texture.image = new Image(); 104 texture.image.onload = function () { 105 gl.bindTexture(gl.TEXTURE_2D, texture); 106 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 107 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); 108 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 109 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 110 gl.bindTexture(gl.TEXTURE_2D, null); 111 112 } 113 texture.image.src = "nehe.gif"; 114 115 var render = function () { // 渲染循環 116 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 117 118 // 頂點 119 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer); 120 gl.vertexAttribPointer(vertexPositionAttr, 3, gl.FLOAT, false, 0, 0); 121 122 // uv坐標 123 gl.bindBuffer(gl.ARRAY_BUFFER, vertexTextureCoordBuffer); 124 gl.vertexAttribPointer(textureCoordAttr, 2, gl.FLOAT, false, 0, 0); 125 126 // 貼圖 127 gl.activeTexture(gl.TEXTURE0); 128 gl.bindTexture(gl.TEXTURE_2D, texture); 129 gl.uniform1i(samplerUniform, 0); 130 131 // 畫圖 132 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer); 133 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 134 requestAnimationFrame(render); 135 } 136 render(); 137 } 138 </script> 139 </head> 140 141 <body onload="start();"> 142 <canvas id="mycanvas" style="border: none;" width="500" height="500"></canvas> 143 </body> 144 145 </html>

效果圖:

技術分享

參考資料:

Lessen 5 引入紋理貼圖:http://www.hiwebgl.com/?p=201

03 傳遞貼圖給著色器