案例查看地址:点击这里
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
<style>
body {
margin: 0;
text-align: center;
}
#canvas {
margin: 0;
}
</style>
</head>
<body οnlοad="main()">
<canvas id="canvas" height="800" width="800"></canvas>
</body>
<script src="lib/webgl-utils.js"></script>
<script src="lib/webgl-debug.js"></script>
<script src="lib/cuon-utils.js"></script>
<script src="lib/cuon-matrix.js"></script>
<script>
/*第一部分顶点着色器接收顶点的纹理坐标,传递给片元着色器*/
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 = "" +
"precision mediump float;\n" +//
"uniform sampler2D u_Sampler;\n" +
"uniform sampler2D u_Sampler1;\n" +//
"varying vec2 v_TexCoord;\n" +//
"void main(){\n" +
" vec4 color = texture2D(u_Sampler,v_TexCoord);\n" +
" vec4 color1 = texture2D(u_Sampler1,v_TexCoord);\n" +
" gl_FragColor = color * color1;\n" +//
"}\n";
/*第二部分 main()方法 初始化着色器,设置顶点信息,调用配置纹理方法*/
function main() {
var canvas = document.getElementById("canvas");
var gl = getWebGLContext(canvas);
if(!gl){
console.log("你的电脑不支持WebGL!");
return;
}
if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
console.log("初始化着色器失败!");
return;
}
//设置顶点的相关信息
var n = initVertexBuffers(gl);
if(n < 0){
console.log("无法获取到点的数据");
return;
}
//配置纹理
if(!initTextures(gl,n)){
console.log("无法配置纹理");
return;
}
}
/*第三部分 initVertexBuffers() 设置顶点坐标和纹理坐标 调用initTextures()进行下一步处理*/
function initVertexBuffers(gl) {
var verticesSizes = 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 vertexSizeBuffer = gl.createBuffer();
if(!vertexSizeBuffer){
console.log("无法创建缓冲区");
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER,vertexSizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesSizes,gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program,"a_Position");
if(a_Position < 0){
console.log("无法获取到存储位置");
return;
}
//获取数组一个值所占的字节数
var fsize = verticesSizes.BYTES_PER_ELEMENT;
//将顶点坐标的位置赋值
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,fsize*4,0);
gl.enableVertexAttribArray(a_Position);
//将顶点的纹理坐标分配给a_TexCoord并开启它
var a_TexCoord = gl.getAttribLocation(gl.program,"a_TexCoord");
if(a_TexCoord < 0){
console.log("无法获取到存储位置");
return;
}
//将纹理坐标赋值
gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,fsize*4,fsize*2);
gl.enableVertexAttribArray(a_TexCoord);
return n;
}
/*第四部分 initTextures() 创建纹理对象 并调用纹理绘制方法*/
function initTextures(gl,n) {
var texture = gl.createTexture();//创建纹理对象
var texture1 = gl.createTexture();
if(!texture || !texture1){
console.log("无法创建纹理对象");
return;
}
//获取u_Sampler的存储位置
var u_Sampler = gl.getUniformLocation(gl.program,"u_Sampler");
var u_Sampler1 = gl.getUniformLocation(gl.program,"u_Sampler1");
if(u_Sampler < 0 || u_Sampler1 < 0){
console.log("无法获取变量的存储位置");
return;
}
//创建Image对象,并绑定加载完成事件
var image = new Image();
var 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 = "./resources/blueflower.jpg";
image1.src = "./resources/circle.gif";
return true;
}
/*第五部分 设置纹理相关信息供WebGL使用,并进行绘制*/
var g_texUnit = false,g_texUnit1 = false;
function loadTexture(gl,n,texture,u_Sampler,image,texUnit) {
//对纹理图像进行y轴反转
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
//开启0号纹理单元
if(texUnit == 0){
gl.activeTexture(gl.TEXTURE0);
g_texUnit = true;
}else if(texUnit == 1){
gl.activeTexture(gl.TEXTURE1);
g_texUnit1 = true;
}
//向target绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D,texture);
//配置纹理参数
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
//配置纹理图像
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);
//将0号纹理传递给着色器
gl.uniform1i(u_Sampler,texUnit);
//绘制
if(g_texUnit && g_texUnit1){
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP,0,n);
}
}
</script>
</html>
这次案例选用了两张不同格式的图片,一张jpg和一张gif格式的,这节的案例和20节的案例相比区别在三个地方:
(1)第一部分在片元着色器里能访问两个纹理。
由于20节的案例只使用一个纹理,所以只准备了一个unifrom变量存储纹理,在本案例多声明了一个uniform变量存储另一个变量。
然后在main()里面使用两个变量color和color1获取颜色,使用分量乘法——两个矢量中对应的分量相乘作为新矢量的分量,来获取最终的片元颜色并赋值给了gl_FragColor。
(2)第四部分initTextures()方法里面创建了两个纹理对象。
用于存储两个纹理并赋值给unifrom变量,所以我们需要处理两遍,声明了两个Image的dom对象获取图片,每一张图片加载成功调用一次,并将第几张图片传入了方法。
(3)第五部分loadTexture()方法修改成可以配置多个纹理对象。
由于浏览器图片加载是异步加载(不懂得可以去看js基础),所以我们先在外部声明了两个变量用于保存图片的加载状态154行。根据加载成功的图片开启相应的纹理单元,并相应的配置相关的纹理参数,最后将相应的纹理传递进着色器相应的uniform变量。
最后一段如果两个图片都加载成功,就开始绘制,就实现了现在看到结果。