广州应用多的自助建站资讯,东莞微信网站建设品牌,东莞自适应网站建设,wordpress page 2目录
前言
编辑
示例代码
颜色矢量的分量乘法来计算两个纹素最终的片元颜色
注册事件响应函数#xff1a;loadTexture#xff08;#xff09;#xff0c;最后一个参数是纹理单元编号。
请求浏览器加载图像#xff1a;
配置纹理#xff1a;loadTexture#xff0…目录
前言
编辑
示例代码
颜色矢量的分量乘法来计算两个纹素最终的片元颜色
注册事件响应函数loadTexture最后一个参数是纹理单元编号。
请求浏览器加载图像
配置纹理loadTexture函数。该函数的核心部分代码如下所示
需要注意的是 前言
WebGL可以同时处理多幅纹理纹理单元就是为了这个目的而设计的。本例程序在矩形上重叠粘贴两幅纹理图像。下图显示了本例运行效果两张纹理图像在矩形上的混合效果如下。 下图中的两幅图分别显示了示例程序用到的两幅纹理图像。为了说明WebGL具有处理不同纹理图像格式的能力本例故意使用了两种不同格式的图像左侧jpg右侧gif。 示例代码
// 顶点着色器
var VSHADER_SOURCE attribute vec4 a_Position;\n attribute vec2 a_TexCoord;\n varying vec2 v_TexCoord;\n void main() {\n gl_Position a_Position;\n v_TexCoord a_TexCoord;\n }\n;// 片元着色器
var FSHADER_SOURCE #ifdef GL_ES\n precision mediump float;\n #endif\n uniform sampler2D u_Sampler0;\n uniform sampler2D u_Sampler1;\n varying vec2 v_TexCoord;\n void main() {\n vec4 color0 texture2D(u_Sampler0, v_TexCoord);\n vec4 color1 texture2D(u_Sampler1, v_TexCoord);\n gl_FragColor color0 * color1;\n }\n;function main() {var canvas document.getElementById(webgl);var gl getWebGLContext(canvas);if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log(Failed to intialize shaders.);return;}var n initVertexBuffers(gl);gl.clearColor(0.0, 0.0, 0.0, 1.0);// 配置纹理if (!initTextures(gl, n)) {console.log(Failed to intialize the texture.);return;}
}function initVertexBuffers(gl) {var verticesTexCoords 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 vertexTexCoordBuffer gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);var FSIZE verticesTexCoords.BYTES_PER_ELEMENT;var a_Position gl.getAttribLocation(gl.program, a_Position);gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer objectvar a_TexCoord gl.getAttribLocation(gl.program, a_TexCoord);gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);gl.enableVertexAttribArray(a_TexCoord); // Enable the buffer assignmentreturn n;
}function initTextures(gl, n) {// 创建纹理缓冲区对象var texture0 gl.createTexture(); var texture1 gl.createTexture();// 获取u_Sampler1和u_Sampler2的存储位置var u_Sampler0 gl.getUniformLocation(gl.program, u_Sampler0);var u_Sampler1 gl.getUniformLocation(gl.program, u_Sampler1);var image0 new Image();var image1 new Image();// 注册事件响应函数在图像加载完成后调用image0.onload function(){ loadTexture(gl, n, texture0, u_Sampler0, image0, 0); };image1.onload function(){ loadTexture(gl, n, texture1, u_Sampler1, image1, 1); };// 告诉浏览器开始加载图像image0.src ../resources/sky.jpg;image1.src ../resources/circle.gif;return true;
}
// 标记纹理单元是否已经就绪
var g_texUnit0 false, g_texUnit1 false;
function loadTexture(gl, n, texture, u_Sampler, image, texUnit) {gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// 沿反转图像// 激活纹理单元if (texUnit 0) {gl.activeTexture(gl.TEXTURE0);g_texUnit0 true;} else {gl.activeTexture(gl.TEXTURE1);g_texUnit1 true;}// 绑定纹理对象到目标上先绑定到纹理单元后指定纹理类型绑定到目标上gl.bindTexture(gl.TEXTURE_2D, texture); // 配置纹理参数gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 设置纹理图像gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);// 将纹理单元编号传递给取样器gl.uniform1i(u_Sampler, texUnit); gl.clear(gl.COLOR_BUFFER_BIT);// 图像加载是异步的我们无法预测哪一张纹理被加载完成只有两幅都加载好程序才开始绘制if (g_texUnit0 g_texUnit1) {gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); }
}首先让我们来看一下片元着色器本例用到了两幅纹理那么就需要两个定义uniform变量 然后在片元着色器的main函数中我们从两个纹理中取出颜色分别存储在变量color0和color1中 颜色矢量的分量乘法来计算两个纹素最终的片元颜色
使用两个纹素来计算最终的片元颜色gl_FragColor有多种可能的方法。示例程序使用的是颜色矢量的分量乘法——两个矢量中对应的分量相乘作为新矢量的分量如下图所示。这很好理解。在GLSL ES中只需要将两个vec4变量简单相乘一下就可以达到目的。 第55、56行创建了两个纹理缓冲区对象变量名的后缀texture0中的 “0” 和 texture1中的 “1”对应对应着纹理单元的编号纹理单元0和纹理单元1此外uniform变量第68,69行与image对象第70,71行也采用了类似的命名方式
注册事件响应函数loadTexture最后一个参数是纹理单元编号。 请求浏览器加载图像 配置纹理loadTexture函数。该函数的核心部分代码如下所示 需要注意的是
在loadTexture函数中我们无法预测哪一幅纹理图像先被加载完成因为加载的过程是异步进行的。只有当两幅纹理图像都完成加载时程序才会开始绘图。为此我们定义了两个全局变量g_texUnit0和g_texUnit1来指示对应的纹理是否加载完成第81行。
这些变量都被初始化为false第81行。当任意一幅纹理加载完成时就触发onload事件并调用响应函数loadTexture。该函数首先根据纹理单元编号0或1来将g_texUnit0或g_texUnit1赋值为true第85行。换句话说如果触发本次onload事件的纹理的编号是0那么0号纹理单元就被激活了并将g_texUnit0设置为true如果是1那么1号纹理单元被激活了并将g_texUnit0设置为ture。
接着纹理单元编号texUnit被赋给了uniform变量第99行。注意texUnit是通过gl.uniform1i方法传入着色器的。在两幅纹理图像都完成加载后WebGL系统内部的状态就如下图所示。 loadTexture函数的最后通过检查g_texUnit0和g_texUnit1变量来判断两幅图像是否全部完成加载了第103行。如果是就开始执行顶点着色器在图形上重叠着绘制出两层纹理如本文第一张图所示。