03 传递贴图给着色器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了03 传递贴图给着色器相关的知识,希望对你有一定的参考价值。

    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 传递贴图给着色器的主要内容,如果未能解决你的问题,请参考以下文章

传递给片段着色器的纹理坐标全部为 0

将数据传递到不同的着色器

如何将浮点矩阵作为 2D 纹理传递给片段着色器?

将统一值传递给顶点和片段着色器

使用金属顶点和片段着色器将 MTLTexture 传递给 SCNProgram

尝试对立方体贴图纹理进行采样时出现 GL_INVALID_OPERATION