5 创建多个缓冲区
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>/*** 设置着色器*/function setShaders(gl) {// 顶底着色气var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute float a_PointSize;\n' +'void main() {\n' +// vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)// w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);' gl_Position = a_Position;\n' + // 设置点的位置' gl_PointSize = a_PointSize;\n' + // 设置点的大小'}\n';// 片元着色气var FSHADER_SOURCE ='precision mediump float;\n' +'uniform vec4 u_FragColor;\n' + // uniform变量'void main() {\n' +' gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba'}\n';if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {throw new TypeError("未能初始化着色器");}// gl.getUniformLocation 获取uniform变量的存储位置var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)}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;}var initVertexBuffers = function () {// 1.创建缓冲区对象var vertexBuffer = gl.createBuffer();var sizeBuffer = gl.createBuffer();if (!vertexBuffer || !sizeBuffer) {throw new TypeError("创建缓冲区失败");}var vertices = new Float32Array([0.0, 0.5,-0.5, -0.5,0.5, -0.5])var sizes = new Float32Array([10.0, 20.0, 30.0])gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);var a_Position = gl.getAttribLocation(gl.program, 'a_Position');if (a_Position < 0) {throw new TypeError("无法获取变量的存储位置")}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_Position);gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');if (a_PointSize < 0) {throw new TypeError("无法获取变量的存储位置")}gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_PointSize);return 3;}setShaders(gl);var n = initVertexBuffers(gl);// 设置背景颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95// gl.COLOR_BUFFER_BIT 颜色缓冲区// 清空颜色缓冲区gl.clear(gl.COLOR_BUFFER_BIT);// gl.drawArrays(mode, first, count);// mode 表示绘制的方式// first 从那个顶点开始绘制// count 绘制几个顶点gl.drawArrays(gl.POINTS, 0, n);}main()</script></body></html>
5.1vertexAttribPointer的进步和偏移参数
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>/*** 设置着色器*/function setShaders(gl) {// 顶底着色气var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute float a_PointSize;\n' +'void main() {\n' +// vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)// w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);' gl_Position = a_Position;\n' + // 设置点的位置' gl_PointSize = a_PointSize;\n' + // 设置点的大小'}\n';// 片元着色气var FSHADER_SOURCE ='precision mediump float;\n' +'uniform vec4 u_FragColor;\n' + // uniform变量'void main() {\n' +' gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba'}\n';if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {throw new TypeError("未能初始化着色器");}// gl.getUniformLocation 获取uniform变量的存储位置var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)}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;}var initVertexBuffers = function () {// 1.创建缓冲区对象var vertexBuffer = gl.createBuffer();if (!vertexBuffer) {throw new TypeError("创建缓冲区失败");}var vertices = new Float32Array([0.0, 0.5, 10.0,-0.5, -0.5, 20.0,0.5, -0.5, 30.0])gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);var a_Position = gl.getAttribLocation(gl.program, 'a_Position');if (a_Position < 0) {throw new TypeError("无法获取变量的存储位置")}var fsize = vertices.BYTES_PER_ELEMENT;gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 3, 0);gl.enableVertexAttribArray(a_Position);var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');if (a_PointSize < 0) {throw new TypeError("无法获取变量的存储位置")}gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, fsize * 3, fsize * 2);gl.enableVertexAttribArray(a_PointSize);return 3;}setShaders(gl);var n = initVertexBuffers(gl);// 设置背景颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95// gl.COLOR_BUFFER_BIT 颜色缓冲区// 清空颜色缓冲区gl.clear(gl.COLOR_BUFFER_BIT);// gl.drawArrays(mode, first, count);// mode 表示绘制的方式// first 从那个顶点开始绘制// count 绘制几个顶点gl.drawArrays(gl.POINTS, 0, n);}main()</script></body></html>
5.2 修改颜色(varying变量)
一致的 (uniform变量)
可变的变量(varying变量)
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>/*** 设置着色器*/function setShaders(gl) {// 顶底着色气var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute float a_PointSize;\n' +'attribute vec4 a_Color;\n' +'varying vec4 v_Color;\n' + // varying'void main() {\n' +' gl_Position = a_Position;\n' + // 设置点的位置' gl_PointSize = a_PointSize;\n' +' v_Color = a_Color;\n' + // 设置点的大小'}\n';// 片元着色气var FSHADER_SOURCE ='precision mediump float;\n' +'varying vec4 v_Color;\n' + // varying'void main() {\n' +' gl_FragColor = v_Color;\n' + // 设置颜色,rgba'}\n';if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {throw new TypeError("未能初始化着色器");}// gl.getUniformLocation 获取uniform变量的存储位置var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)}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;}var initVertexBuffers = function () {// 1.创建缓冲区对象var vertexBuffer = gl.createBuffer();var sizeBuffer = gl.createBuffer();if (!vertexBuffer) {throw new TypeError("创建缓冲区失败");}var vertices = new Float32Array([// 顶点坐标,大小,颜色0.0, 0.5, 1.0, 0.0, 0.0,-0.5, -0.5, 0.0, 1.0, 0.0,0.5, -0.5, 0.0, 0.0, 1.0,])gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);var a_Position = gl.getAttribLocation(gl.program, 'a_Position');if (a_Position < 0) {throw new TypeError("无法获取变量的存储位置")}var fsize = vertices.BYTES_PER_ELEMENT;gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 5, 0);gl.enableVertexAttribArray(a_Position);var a_Color = gl.getAttribLocation(gl.program, 'a_Color');if (a_Color < 0) {throw new TypeError("无法获取变量的存储位置")}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, fsize * 5, fsize * 2);gl.enableVertexAttribArray(a_Color);var sizes = new Float32Array([10.0, 20.0, 30.0])gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');if (a_PointSize < 0) {throw new TypeError("无法获取变量的存储位置")}gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_PointSize);return 3;}setShaders(gl);var n = initVertexBuffers(gl);// 设置背景颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95// gl.COLOR_BUFFER_BIT 颜色缓冲区// 清空颜色缓冲区gl.clear(gl.COLOR_BUFFER_BIT);// gl.drawArrays(mode, first, count);// mode 表示绘制的方式// first 从那个顶点开始绘制// count 绘制几个顶点// gl.drawArrays(gl.POINTS, 0, n);gl.drawArrays(gl.TRIANGLES, 0, n); // 可以画出彩色三角形}main()</script></body></html>
5.3 图形装配,光栅化
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>// HelloTriangle_FragCoord.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'void main() {\n' +' gl_Position = a_Position;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='precision mediump float;\n' +'uniform float u_Width;\n' +'uniform float u_Height;\n' +'void main() {\n' +' gl_FragColor = vec4(gl_FragCoord.x/u_Width, 0.0, gl_FragCoord.y/u_Height, 1.0);\n' +'}\n';function main() {// Retrieve <canvas> elementvar canvas = document.getElementById('webgl');// Get the rendering context for WebGLvar gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}// Initialize shadersif (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// Write the positions of vertices to a vertex shadervar n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the positions of the vertices');return;}// Specify the color for clearing <canvas>gl.clearColor(0.0, 0.0, 0.0, 1.0);// Clear <canvas>gl.clear(gl.COLOR_BUFFER_BIT);// Draw the rectanglegl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {var vertices = new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]);var n = 3; // The number of vertices// Create a buffer objectvar vertexBuffer = gl.createBuffer();if (!vertexBuffer) {console.log('Failed to create the buffer object');return -1;}// Bind the buffer object to targetgl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);// Write date into the buffer objectgl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// Pass the position of a point to a_Position variablevar 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;}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);var u_Width = gl.getUniformLocation(gl.program, 'u_Width');if (!u_Width) {console.log('Failed to get the storage location of u_Width');return;}var u_Height = gl.getUniformLocation(gl.program, 'u_Height');if (!u_Height) {console.log('Failed to get the storage location of u_Height');return;}// Pass the width and hight of the <canvas>gl.uniform1f(u_Width, gl.drawingBufferWidth);gl.uniform1f(u_Height, gl.drawingBufferHeight);// Enable the generic vertex attribute arraygl.enableVertexAttribArray(a_Position);// Unbind the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, null);return n;}main();</script></body></html>
5.3纹理
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>// TexturedQuad.js (c) 2012 matsuda and kanda// Vertex shader programvar 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';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型'uniform sampler2D u_Sampler;\n' +'varying vec2 v_TexCoord;\n' +'void main() {\n' +// 纹理映射// 使用GLSL ES内置函数texture2D来抽取纹素颜色。该函数返回// gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA' gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +'}\n';function main() {// Retrieve <canvas> elementvar canvas = document.getElementById('webgl');// Get the rendering context for WebGLvar gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}// Initialize shadersif (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// Set the vertex informationvar n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}// Specify the color for clearing <canvas>gl.clearColor(0.0, 0.0, 0.0, 1.0);// Set textureif (!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;// Create the buffer objectvar vertexTexCoordBuffer = gl.createBuffer();if (!vertexTexCoordBuffer) {throw new TypeError("创建gl.Buffer失败")}// Bind the buffer object to targetgl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;//Get the storage location of a_Position, assign and enable buffervar 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;}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object// Get the storage location of a_TexCoordvar 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;}// Assign the buffer object to a_TexCoord variablegl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer objectreturn n;}function initTextures(gl, n) {// 创建纹理对象 gl.deleteTexture 删除纹理对象var texture = gl.createTexture();if (!texture) {throw new TypeError("创建纹理对象失败");}// Get the storage location of u_Samplervar u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');if (!u_Sampler) {throw new TypeError("获取uniform变量失败");}var image = new Image(); // Create the image object// 设置图片加载完成的事件image.onload = function () { loadTexture(gl, n, texture, u_Sampler, image); };// 加载图片image.src = '../resources/sky.jpg';return true;}function loadTexture(gl, n, texture, u_Sampler, image) {// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,// 需要对图像进行y轴反转,才能正确显示图片gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// 开启0号纹理单元,激活纹理单元// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元// 在使用纹理单元前,需要激活gl.activeTexture(gl.TEXTURE0);// 绑定纹理对象// gl.TEXTURE_2D 二维纹理// gl.TEXTURE_CUBE_MAP 立方体纹理gl.bindTexture(gl.TEXTURE_2D, texture);// 配置纹理参数 gl.texParameteri(var1, var2, var3)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 纹理参数,下列值// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET// var3 = 纹理参数的值// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量// gl.LINEAR | gl.NEAREST// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量// gl.REPEAT 平铺式的重复纹理// gl.MIRRORED_REPEAT 镜像对称式的重复纹理// gl.CLAMP_TO_EDGE 使用纹理的边缘值gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 配置纹理图像// gl.texImage2D(var1, var2, var3, var4, var5, var6)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA// var4 = 纹理数据的格式,必须与var3的值一致// var5 = 纹理的数据类型// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特// var6 = imagegl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);// 将0号纹理传递给着色器中的取样器变量// 也就是这个gl.TEXTURE0的编号传给u_Samplergl.uniform1i(u_Sampler, 0);gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle}main();</script></body></html>
5.3.1 纹理texParameteri的使用
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>// TexturedQuad.js (c) 2012 matsuda and kanda// Vertex shader programvar 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';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型'uniform sampler2D u_Sampler;\n' +'varying vec2 v_TexCoord;\n' +'void main() {\n' +// 纹理映射// 使用GLSL ES内置函数texture2D来抽取纹素颜色。该函数返回// gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA' gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +'}\n';function main() {// Retrieve <canvas> elementvar canvas = document.getElementById('webgl');// Get the rendering context for WebGLvar gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}// Initialize shadersif (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// Set the vertex informationvar n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}// Specify the color for clearing <canvas>gl.clearColor(0.0, 0.0, 0.0, 1.0);// Set textureif (!initTextures(gl, n)) {console.log('Failed to intialize the texture.');return;}}function initVertexBuffers(gl) {var verticesTexCoords = new Float32Array([// 顶点坐标,纹理坐标-0.5, 0.5, -0.3, 1.7,-0.5, -0.5, -0.3, -0.2,0.5, 0.5, 1.7, 1.7,0.5, -0.5, 1.7, -0.2,]);var n = 4;// Create the buffer objectvar vertexTexCoordBuffer = gl.createBuffer();if (!vertexTexCoordBuffer) {throw new TypeError("创建gl.Buffer失败")}// Bind the buffer object to targetgl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;//Get the storage location of a_Position, assign and enable buffervar 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;}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object// Get the storage location of a_TexCoordvar 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;}// Assign the buffer object to a_TexCoord variablegl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer objectreturn n;}function initTextures(gl, n) {// 创建纹理对象 gl.deleteTexture 删除纹理对象var texture = gl.createTexture();if (!texture) {throw new TypeError("创建纹理对象失败");}// Get the storage location of u_Samplervar u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');if (!u_Sampler) {throw new TypeError("获取uniform变量失败");}var image = new Image(); // Create the image object// 设置图片加载完成的事件image.onload = function () { loadTexture(gl, n, texture, u_Sampler, image); };// 加载图片image.src = '../resources/sky.jpg';return true;}function loadTexture(gl, n, texture, u_Sampler, image) {// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,// 需要对图像进行y轴反转,才能正确显示图片gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// 开启0号纹理单元,激活纹理单元// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元// 在使用纹理单元前,需要激活gl.activeTexture(gl.TEXTURE0);// 绑定纹理对象// gl.TEXTURE_2D 二维纹理// gl.TEXTURE_CUBE_MAP 立方体纹理gl.bindTexture(gl.TEXTURE_2D, texture);// 配置纹理参数 gl.texParameteri(var1, var2, var3)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 纹理参数,下列值// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET// var3 = 纹理参数的值// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量// gl.LINEAR | gl.NEAREST// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量// gl.REPEAT 平铺式的重复纹理// gl.MIRRORED_REPEAT 镜像对称式的重复纹理// gl.CLAMP_TO_EDGE 使用纹理的边缘值gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);// 配置纹理图像// gl.texImage2D(var1, var2, var3, var4, var5, var6)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA// var4 = 纹理数据的格式,必须与var3的值一致// var5 = 纹理的数据类型// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特// var6 = imagegl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);// 将0号纹理传递给着色器中的取样器变量// 也就是这个gl.TEXTURE0的编号传给u_Samplergl.uniform1i(u_Sampler, 0);gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle}main();</script></body></html>
5.3.2 使用多幅纹理
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Clear canvas</title></head><body><canvas id="webgl" width="400" height="400">Please use the browser supporting "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script>// TexturedQuad.js (c) 2012 matsuda and kanda// Vertex shader programvar 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';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型'uniform sampler2D u_Sampler0;\n' +'uniform sampler2D u_Sampler1;\n' +'varying vec2 v_TexCoord;\n' +'void main() {\n' +' vec4 color1 = texture2D(u_Sampler0, v_TexCoord);\n' +' vec4 color0 = texture2D(u_Sampler1, v_TexCoord);\n' +' gl_FragColor = color0 * color1;\n' +'}\n';function main() {// Retrieve <canvas> elementvar canvas = document.getElementById('webgl');// Get the rendering context for WebGLvar gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}// Initialize shadersif (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// Set the vertex informationvar n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}// Specify the color for clearing <canvas>gl.clearColor(0.0, 0.0, 0.0, 1.0);// Set textureif (!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;// Create the buffer objectvar vertexTexCoordBuffer = gl.createBuffer();if (!vertexTexCoordBuffer) {throw new TypeError("创建gl.Buffer失败")}// Bind the buffer object to targetgl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;//Get the storage location of a_Position, assign and enable buffervar 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;}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object// Get the storage location of a_TexCoordvar 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;}// Assign the buffer object to a_TexCoord variablegl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer objectreturn n;}function initTextures(gl, n) {// 创建纹理对象 gl.deleteTexture 删除纹理对象var texture0 = gl.createTexture();var texture1 = gl.createTexture();if (!texture0 || !texture1) {throw new TypeError("创建纹理对象失败");}// Get the storage location of u_Samplervar u_Sampler0 = gl.getUniformLocation(gl.program, 'u_Sampler0');var u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1');if (!u_Sampler0 || !u_Sampler1) {throw new TypeError("获取uniform变量失败");}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) {// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,// 需要对图像进行y轴反转,才能正确显示图片gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// 开启0号纹理单元,激活纹理单元// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元// 在使用纹理单元前,需要激活if (texUnit === 0) {gl.activeTexture(gl.TEXTURE0);g_texUnit0 = true;} else {gl.activeTexture(gl.TEXTURE1);g_texUnit1 = true;}// 绑定纹理对象// gl.TEXTURE_2D 二维纹理// gl.TEXTURE_CUBE_MAP 立方体纹理gl.bindTexture(gl.TEXTURE_2D, texture);// 配置纹理参数 gl.texParameteri(var1, var2, var3)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 纹理参数,下列值// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET// var3 = 纹理参数的值// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量// gl.LINEAR | gl.NEAREST// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量// gl.REPEAT 平铺式的重复纹理// gl.MIRRORED_REPEAT 镜像对称式的重复纹理// gl.CLAMP_TO_EDGE 使用纹理的边缘值gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 配置纹理图像// gl.texImage2D(var1, var2, var3, var4, var5, var6)// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA// var4 = 纹理数据的格式,必须与var3的值一致// var5 = 纹理的数据类型// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特// var6 = imagegl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);// 将0号纹理传递给着色器中的取样器变量// 也就是这个gl.TEXTURE0的编号传给u_Samplergl.uniform1i(u_Sampler, texUnit);gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>if (g_texUnit0 && g_texUnit1) {gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle}}main();</script></body></html>
