var vShader = ` attribute vec4 a_Position; attribute vec2 a_TexCoord; varying vec2 v_TexCoord; void main(){ gl_Position = a_Position; v_TexCoord = a_TexCoord; } `; var fShader = ` //设定默认精度 #ifdef GL_ES precision mediump float; #endif uniform sampler2D u_Sampler; uniform sampler2D u_Sampler1; varying vec2 v_TexCoord; void main(){ vec4 color = texture2D(u_Sampler,v_TexCoord); vec4 color1 = texture2D(u_Sampler1,v_TexCoord); gl_FragColor = color * color1; } `; function main(){ //获取canvas元素 var canvas = document.getElementById('webgl'); //获取webgl上下文 var gl = getWebGLContext(canvas); if(!gl){ console.log('Failed to get the rendering context for WebGL!'); return; } //初始化着色器 if(!initShaders(gl,vShader,fShader)){ console.log('Failed to initialize shaders.'); return; } var n = initVertexBuffers(gl); if(n < 0){ console.log('Failed to set the positions of the vertices!'); return; } if(!initTextures(gl,n)){ console.log('Failed to initialize textures.'); return; } //用指定颜色填充webgl容器,就是设置背景 gl.clearColor(0.4, 0.5, 0.0, 1.0); function initVertexBuffers(gl){ var verticesTex = 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 vertexTexBuffer = gl.createBuffer(); if(!vertexTexBuffer){ console.log('Failed to create the buffer object!'); return -1; } //将数据添加到缓冲区(绑定在缓冲区对象上) gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexBuffer); gl.bufferData(gl.ARRAY_BUFFER,verticesTex,gl.STATIC_DRAW); var fsize = verticesTex.BYTES_PER_ELEMENT; //获取shaderProgram中attribute变量‘a_Position’的地址 var a_Position = gl.getAttribLocation(gl.program,'a_Position'); if (a_Position < 0) { console.log('Failed to get the storage location of a_Position'); return -1; } //将缓冲区对象分配给a_Position变量并开启访问 gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,fsize * 4,0); gl.enableVertexAttribArray(a_Position); var a_TexCoord = gl.getAttribLocation(gl.program,'a_TexCoord'); if (a_TexCoord < 0) { console.log('Failed to get the storage location of a_TexCoord'); return -1; } //将缓冲区对象分配给a_TexCoord变量并开启访问 gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,fsize * 4,fsize * 2); gl.enableVertexAttribArray(a_TexCoord); return n; } //初始化纹理图片,通过image传入 function initTextures(){ //创建纹理对象 var texture = gl.createTexture(); var texture1 = gl.createTexture(); //读取u_Sampler存储位置 var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler'); var u_Sampler1 = gl.getUniformLocation(gl.program,'u_Sampler1'); var image = new Image(),image1 = new Image; image.onload = function(){ loadTexture(gl,n,texture,u_Sampler,image,0); } image1.onload = function(){ loadTexture(gl,n,texture1,u_Sampler1,image1,1); } image.src = '../image/sky.JPG'; image1.src = '../image/circle.gif'; return true; } var flag = false,flag1= false; //加载纹理 function loadTexture(gl,n,texture,u_Sampler,image,index){ //对问题图像进行y轴反转 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1); //开启纹理单元 if(index ==0){ gl.activeTexture(gl.TEXTURE0); flag = true; }else{ gl.activeTexture(gl.TEXTURE1); flag1 = true; } //向target绑定纹理对象 gl.bindTexture(gl.TEXTURE_2D,texture); //配置纹理参数 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); //处理图片像素非2的幂次方的配置 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); //配置纹理图像 gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image); //将纹理传递给着色器 gl.uniform1i(u_Sampler,index); if(flag && flag1){ gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas> gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); } } } main();
相对于之前的为正方形添加单个纹理来说,多了一些变化,文中已经用红字标出:
①片元着色器中新增一个取样器,并且main方法输出的颜色是这两个取色器颜色的乘积;
②用两个纹理对象来加载纹理,并且启用不同的纹理单元(gl.TEXTURE0、gl.TEXTURE1);配置好参数后将纹理传递给对应的纹理单元
③在两个纹理都激活之后才开始绘图
效果: