WebGL编程指南案例解析之纹理叠加

时间:2021-09-09 05:53:47
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 < ){
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 = ;//点的个数
//创建缓冲区对象
var vertexTexBuffer = gl.createBuffer();
if(!vertexTexBuffer){
console.log('Failed to create the buffer object!');
return -;
}
//将数据添加到缓冲区(绑定在缓冲区对象上)
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 < ) {
console.log('Failed to get the storage location of a_Position');
return -;
}
//将缓冲区对象分配给a_Position变量并开启访问
gl.vertexAttribPointer(a_Position,,gl.FLOAT,false,fsize * ,);
gl.enableVertexAttribArray(a_Position); var a_TexCoord = gl.getAttribLocation(gl.program,'a_TexCoord');
if (a_TexCoord < ) {
console.log('Failed to get the storage location of a_TexCoord');
return -;
}
//将缓冲区对象分配给a_TexCoord变量并开启访问
gl.vertexAttribPointer(a_TexCoord,,gl.FLOAT,false,fsize * ,fsize * );
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,);
}
image1.onload = function(){
loadTexture(gl,n,texture1,u_Sampler1,image1,);
} 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,);
//开启纹理单元
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,,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);配置好参数后将纹理传递给对应的纹理单元

WebGL编程指南案例解析之纹理叠加

③在两个纹理都激活之后才开始绘图

效果:

WebGL编程指南案例解析之纹理叠加WebGL编程指南案例解析之纹理叠加

WebGL编程指南案例解析之纹理叠加