7、视点,观察目标点,上方向
模型视图矩阵 = 视图矩阵 模型矩阵
从视点看上去的“旋转后的顶点坐标”=模型视图矩阵 原顶点坐标
移动视点与移动被观察对象等效,不过他们的移动方向正好相反
{“eyeX”:0,”eyeY”:0,”eyeZ”:0,”atX”:-0.25,”atY”:-0.25,”atZ”:-0.25,”upX”:0,”upY”:1,”upZ”:0}
=
{“eyeX”:0.25,”eyeY”:0.25,”eyeZ”:0.25,”atX”:0,”atY”:0,”atZ”:0,”upX”:0,”upY”:1,”upZ”:0}
<!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><div><button onclick="change('add', 'eyeX')">eyeX+</button><button onclick="change('remove', 'eyeX')">eyeX-</button><br /><button onclick="change('add', 'eyeY')">eyeY+</button><button onclick="change('remove', 'eyeY')">eyeY-</button><br /><button onclick="change('add', 'eyeZ')">eyeZ+</button><button onclick="change('remove', 'eyeZ')">eyeZ-</button><br /><button onclick="change('add', 'atX')">atX+</button><button onclick="change('remove', 'atX')">atX-</button><br /><button onclick="change('add', 'atY')">atY+</button><button onclick="change('remove', 'atY')">atY-</button><br /><button onclick="change('add', 'atZ')">atZ+</button><button onclick="change('remove', 'atZ')">atZ-</button><br /><button onclick="change('add', 'upX')">upX+</button><button onclick="change('remove', 'upX')">upX-</button><br /><button onclick="change('add', 'upY')">upY+</button><button onclick="change('remove', 'upY')">upY-</button><br /><button onclick="change('add', 'upZ')">upZ+</button><button onclick="change('remove', 'upZ')">upZ-</button><br /><div><div id="content"></div></div></div><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>const obj = {eyeX: 0.25,eyeY: 0.25,eyeZ: 0.25,atX: 0,atY: 0,atZ: 0,upX: 0,upY: 1,upZ: 0}function innerHtml() {document.getElementById("content").innerHTML = JSON.stringify(obj)}function change(type, name) {if (type === 'add') {obj[name] += 0.01;} else {obj[name] -= 0.01;}if (obj[name] > 1) {obj[name] = 0;} else if (obj[name] < 0) {obj[name] = 1}main()innerHtml()}// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' + // 视图矩阵'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ViewMatrix * a_Position;\n' + // 视图矩阵 * 原始顶点坐标' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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 coordinates and color (the blue triangle is in the front)var n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}gl.clearColor(0, 0, 0, 1);// 获取试图矩阵变量var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');if (!u_ViewMatrix) {console.log('Failed to get the storage locations of u_ViewMatrix');return;}// 视图矩阵var viewMatrix = new Matrix4();// viewMatrix.setLookAt(v1, v2, v3, v4, v5, v6, v7, v8, v9)// v1 ~ v3 视点 默认是0,0,0// v4 ~ v6 观察目标点,默认是0,0,1// v7 ~ v9 上方向,默认是0,1,0viewMatrix.setLookAt(obj.eyeX, obj.eyeY, obj.eyeZ,obj.atX, obj.atY, obj.atZ,obj.upX, obj.upY, obj.upZ,);// 模型矩阵,(平移,旋转)var modalMatrix = new Matrix4();// angle, x, y, zmodalMatrix.setRotate(0, 0, 0, 1);var modalViewMatrix = viewMatrix.multiply(modalMatrix)gl.uniformMatrix4fv(u_ViewMatrix, false, modalViewMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// 前三个点是顶点坐标,后三个点是颜色坐标0.0, 0.5, -0.4, 0.4, 1.0, 0.4, // 绿色三角形在最后面-0.5, -0.5, -0.4, 0.4, 1.0, 0.4,0.5, -0.5, -0.4, 1.0, 0.4, 0.4,0.5, 0.4, -0.2, 1.0, 0.4, 0.4, // 黄色三角形在中间-0.5, 0.4, -0.2, 1.0, 1.0, 0.4,0.0, -0.6, -0.2, 1.0, 1.0, 0.4,0.0, 0.5, 0.0, 0.4, 0.4, 1.0, // 蓝色三角形在最前面-0.5, -0.5, 0.0, 0.4, 0.4, 1.0,0.5, -0.5, 0.0, 1.0, 0.4, 0.4,]);var n = 9;var vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;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;}gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);var a_Color = gl.getAttribLocation(gl.program, 'a_Color');if (a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);gl.bindBuffer(gl.ARRAY_BUFFER, null);return n;}main();</script></body></html>
7.1 调整盒子的可视空间
<!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><p id="nearFar">The near and far values are displayed here.</p><p id="nearFar">The near and far values are displayed here.</p><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>// OrthoView.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ProjMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ProjMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\n' +'}\n';function main() {// Retrieve <canvas> elementvar canvas = document.getElementById('webgl');// Retrieve the nearFar elementvar nf = document.getElementById('nearFar');// 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 coordinates and color (the blue triangle is in the front)var 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, 1);// get the storage location of u_ProjMatrixvar u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');if (!u_ProjMatrix) {console.log('Failed to get the storage location of u_ProjMatrix');return;}// Create the matrix to set the eye point, and the line of sightvar projMatrix = new Matrix4();// Register the event handler to be called on key pressdocument.onkeydown = function(ev){ keydown(ev, gl, n, u_ProjMatrix, projMatrix, nf); };draw(gl, n, u_ProjMatrix, projMatrix, nf); // Draw the triangles}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// Vertex coordinates and color0.0, 0.6, -0.4, 0.4, 1.0, 0.4, // The back green one-0.5, -0.4, -0.4, 0.4, 1.0, 0.4,0.5, -0.4, -0.4, 1.0, 0.4, 0.4,0.5, 0.4, -0.2, 1.0, 0.4, 0.4, // The middle yellow one-0.5, 0.4, -0.2, 1.0, 1.0, 0.4,0.0, -0.6, -0.2, 1.0, 1.0, 0.4,0.0, 0.5, 0.0, 0.4, 0.4, 1.0, // The front blue one-0.5, -0.5, 0.0, 0.4, 0.4, 1.0,0.5, -0.5, 0.0, 1.0, 0.4, 0.4,]);var n = 9;// Create a buffer objectvar vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}// The distances to the near and far clipping planevar g_near = 0.0, g_far = 0.5;function keydown(ev, gl, n, u_ProjMatrix, projMatrix, nf) {switch(ev.keyCode){case 39: g_near += 0.01; break; // The right arrow key was pressedcase 37: g_near -= 0.01; break; // The left arrow key was pressedcase 38: g_far += 0.01; break; // The up arrow key was pressedcase 40: g_far -= 0.01; break; // The down arrow key was presseddefault: return; // Prevent the unnecessary drawing}draw(gl, n, u_ProjMatrix, projMatrix, nf);}function draw(gl, n, u_ProjMatrix, projMatrix, nf) {// projMatrix.setOrtho(left, right, bottom, top, near, far) 调整可视空间// projMatrix.setOrtho(-1.0, 1.0, -1.0, 1.0, g_near, g_far); // 将视点置于原点处projMatrix.setOrtho(-1.0, 1.0, -1.0, 1.0, g_near, g_far);// Pass the projection matrix to u_ProjMatrixgl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>// Display the current near and far valuesnf.innerHTML = 'near: ' + Math.round(g_near * 100)/100 + ', far: ' + Math.round(g_far*100)/100;gl.drawArrays(gl.TRIANGLES, 0, n); // Draw the triangles}main();</script></body></html>
7.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><div><button onclick="change('add', 'eyeX')">eyeX+</button><button onclick="change('remove', 'eyeX')">eyeX-</button><br /><button onclick="change('add', 'eyeY')">eyeY+</button><button onclick="change('remove', 'eyeY')">eyeY-</button><br /><button onclick="change('add', 'eyeZ')">eyeZ+</button><button onclick="change('remove', 'eyeZ')">eyeZ-</button><br /><button onclick="change('add', 'atX')">atX+</button><button onclick="change('remove', 'atX')">atX-</button><br /><button onclick="change('add', 'atY')">atY+</button><button onclick="change('remove', 'atY')">atY-</button><br /><button onclick="change('add', 'atZ')">atZ+</button><button onclick="change('remove', 'atZ')">atZ-</button><br /><button onclick="change('add', 'upX')">upX+</button><button onclick="change('remove', 'upX')">upX-</button><br /><button onclick="change('add', 'upY')">upY+</button><button onclick="change('remove', 'upY')">upY-</button><br /><button onclick="change('add', 'upZ')">upZ+</button><button onclick="change('remove', 'upZ')">upZ-</button><br /><div><div id="content"></div></div></div><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>const obj = {eyeX: 0.25,eyeY: 0.25,eyeZ: 0.25,atX: 0,atY: 0,atZ: 0,upX: 0,upY: 1,upZ: 0}function innerHtml() {document.getElementById("content").innerHTML = JSON.stringify(obj)}function change(type, name) {if (type === 'add') {obj[name] += 0.01;} else {obj[name] -= 0.01;}if (obj[name] > 1) {obj[name] = 0;} else if (obj[name] < 0) {obj[name] = 1}main()innerHtml()}// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' + // 视图矩阵'uniform mat4 u_ProjMatrix;\n'+'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;\n' + // 视图矩阵 * 原始顶点坐标' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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 coordinates and color (the blue triangle is in the front)var n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}gl.clearColor(0, 0, 0, 1);// 获取视图矩阵变量var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');// 获取投影矩阵变量var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');if (!u_ViewMatrix) {console.log('Failed to get the storage locations of u_ViewMatrix');return;}// 视图矩阵var viewMatrix = new Matrix4();// viewMatrix.setLookAt(v1, v2, v3, v4, v5, v6, v7, v8, v9)// v1 ~ v3 视点 默认是0,0,0// v4 ~ v6 观察目标点,默认是0,0,1// v7 ~ v9 上方向,默认是0,1,0viewMatrix.setLookAt(obj.eyeX, obj.eyeY, obj.eyeZ,obj.atX, obj.atY, obj.atZ,obj.upX, obj.upY, obj.upZ,);// 模型矩阵,(平移,旋转)var modalMatrix = new Matrix4();// angle, x, y, zmodalMatrix.setRotate(0, 0, 0, 1);var modalViewMatrix = viewMatrix.multiply(modalMatrix)gl.uniformMatrix4fv(u_ViewMatrix, false, modalViewMatrix.elements);var projMatrix = new Matrix4();// 设置可视空间,定义正射投影矩阵// projMatrix.setOrtho(left, right, top, bottom, near, far);// near,far 指定近裁剪面和远裁剪面的位置,即可视空间的近边界和远边界projMatrix.setOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 2.0);gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// 前三个点是顶点坐标,后三个点是颜色坐标0.0, 0.5, -0.4, 0.4, 1.0, 0.4, // 绿色三角形在最后面-0.5, -0.5, -0.4, 0.4, 1.0, 0.4,0.5, -0.5, -0.4, 1.0, 0.4, 0.4,0.5, 0.4, -0.2, 1.0, 0.4, 0.4, // 黄色三角形在中间-0.5, 0.4, -0.2, 1.0, 1.0, 0.4,0.0, -0.6, -0.2, 1.0, 1.0, 0.4,0.0, 0.5, 0.0, 0.4, 0.4, 1.0, // 蓝色三角形在最前面-0.5, -0.5, 0.0, 0.4, 0.4, 1.0,0.5, -0.5, 0.0, 1.0, 0.4, 0.4,]);var n = 9;var vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;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;}gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);var a_Color = gl.getAttribLocation(gl.program, 'a_Color');if (a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);gl.bindBuffer(gl.ARRAY_BUFFER, null);return n;}main();</script></body></html>
7.3透视投影矩阵
// PerspectiveView.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' +'uniform mat4 u_ProjMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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 coordinates and color (the blue triangle is in the front)var 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, 1);var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');if (!u_ViewMatrix || !u_ProjMatrix) {console.log('Failed to get the storage location of u_ViewMatrix and/or u_ProjMatrix');return;}var viewMatrix = new Matrix4(); // 视图矩阵var projMatrix = new Matrix4(); // 投影矩阵,这里是透视投影矩阵// 旋转,平移,缩放,的矩阵被称为模型矩阵// 视点(0,0,0),观察点(0,0,-1),上方向(如果上方向是y轴的正方向,那么upX,upY,upZ就是0,1,0) 组成 视图矩阵// 在平面直角坐标系中, y轴正方向 是指 从原点沿纵轴向上的方向.”// 模型视图矩阵 = 视图矩阵 * 模型矩阵// 模型视图矩阵 * 顶点坐标// 投影矩阵 * 模型视图矩阵 * 顶点坐标// 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点坐标// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZviewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);// 设置可视空间,定义透视投影矩阵// projMatrix.setPerspective(fov, aspect, near, far)// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0// aspect:指定近裁剪面的宽高比// near:近裁剪面的位置,必须大于0// far:远裁剪面的位置,必须大于0projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);// Clear <canvas>gl.clear(gl.COLOR_BUFFER_BIT);// Draw the trianglesgl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {// 三角形的位置x,y完全相同// 渲染出的三角形距离远的看上去变小了,其次,三角形被不同程度地平移以贴近中心线(即视线),// 使他们看上去在视线的左右排出了两列var verticesColors = new Float32Array([// 右侧三个三角形0.75, 1.0, -4.0, 0.4, 1.0, 0.4, // 绿色0.25, -1.0, -4.0, 0.4, 1.0, 0.4,1.25, -1.0, -4.0, 1.0, 0.4, 0.4,0.75, 1.0, -2.0, 1.0, 1.0, 0.4, //黄色0.25, -1.0, -2.0, 1.0, 1.0, 0.4,1.25, -1.0, -2.0, 1.0, 0.4, 0.4,0.75, 1.0, 0.0, 0.4, 0.4, 1.0, // 蓝色0.25, -1.0, 0.0, 0.4, 0.4, 1.0,1.25, -1.0, 0.0, 1.0, 0.4, 0.4,// 左侧三个三角形-0.75, 1.0, -4.0, 0.4, 1.0, 0.4, // 绿色-1.25, -1.0, -4.0, 0.4, 1.0, 0.4,-0.25, -1.0, -4.0, 1.0, 0.4, 0.4,-0.75, 1.0, -2.0, 1.0, 1.0, 0.4, // 黄色-1.25, -1.0, -2.0, 1.0, 1.0, 0.4,-0.25, -1.0, -2.0, 1.0, 0.4, 0.4,-0.75, 1.0, 0.0, 0.4, 0.4, 1.0, // 蓝色-1.25, -1.0, 0.0, 0.4, 0.4, 1.0,-0.25, -1.0, 0.0, 1.0, 0.4, 0.4,]);var n = 18; // Three vertices per triangle * 6// Create a buffer objectvar vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}
7.4 在上一个例子,绘制中间的三个三角形,通过模型矩阵,绘制两次,一次偏移0.75,一次偏移-0.75,达到和上个例子一样的效果
// PerspectiveView.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' +'uniform mat4 u_ProjMatrix;\n' +'uniform mat4 u_ModelMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +// 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点位置' gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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 coordinates and color (the blue triangle is in the front)var 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, 1);var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');var u_ModelMatrix = gl.getUniformLocation(gl.program, "u_ModelMatrix")if (!u_ViewMatrix || !u_ProjMatrix || !u_ModelMatrix) {throw new TypeError("获取uniform变量失败")}var viewMatrix = new Matrix4(); // 视图矩阵var projMatrix = new Matrix4(); // 透视投影矩阵var modelMatrix = new Matrix4(); // 模型矩阵// 旋转,平移,缩放,的矩阵被称为模型矩阵// 视点(0,0,0),观察点(0,0,-1),上方向(如果上方向是y轴的正方向,那么upX,upY,upZ就是0,1,0) 组成 视图矩阵// 在平面直角坐标系中, y轴正方向 是指 从原点沿纵轴向上的方向.”// 模型视图矩阵 = 视图矩阵 * 模型矩阵// 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点坐标// 模型矩阵,平移0.75modelMatrix.setTranslate(0.75, 0, 0);// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZviewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);// 定义透视投影矩阵// projMatrix.setPerspective(fov, aspect, near, far)// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0// aspect:指定近裁剪面的宽高比// near:近裁剪面的位置,必须大于0// far:远裁剪面的位置,必须大于0projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);// Clear <canvas>gl.clear(gl.COLOR_BUFFER_BIT);// Draw the trianglesgl.drawArrays(gl.TRIANGLES, 0, n);// 设置矩阵modelMatrix.setTranslate(-0.75, 0, 0);gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);gl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {// 三角形的位置x,y完全相同// 渲染出的三角形距离远的看上去变小了,其次,三角形被不同程度地平移以贴近中心线(即视线),// 使他们看上去在视线的左右排出了两列var verticesColors = new Float32Array([// Vertex coordinates and color0.0, 1.0, -4.0, 0.4, 1.0, 0.4, // The back green one-0.5, -1.0, -4.0, 0.4, 1.0, 0.4,0.5, -1.0, -4.0, 1.0, 0.4, 0.4,0.0, 1.0, -2.0, 1.0, 1.0, 0.4, // The middle yellow one-0.5, -1.0, -2.0, 1.0, 1.0, 0.4,0.5, -1.0, -2.0, 1.0, 0.4, 0.4,0.0, 1.0, 0.0, 0.4, 0.4, 1.0, // The front blue one-0.5, -1.0, 0.0, 0.4, 0.4, 1.0,0.5, -1.0, 0.0, 1.0, 0.4, 0.4,]);var n = 9;var vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}
7.5 在7.4的例子上,合并了 投影矩阵,视图矩阵,模型矩阵
// PerspectiveView.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +// 'uniform mat4 u_ViewMatrix;\n' +// 'uniform mat4 u_ProjMatrix;\n' +// 'uniform mat4 u_ModelMatrix;\n' +'uniform mat4 u_MvpMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +// 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点位置// ' gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +// 合并 投影矩阵 * 视图矩阵 * 模型矩阵 这三个矩阵' gl_Position = u_MvpMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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)) {throw new TypeError("着色器初始化失败")return;}// Set the vertex coordinates and color (the blue triangle is in the front)var 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, 1);// var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');// var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');// var u_ModelMatrix = gl.getUniformLocation(gl.program, "u_ModelMatrix")var u_MvpMatrix = gl.getUniformLocation(gl.program, "u_MvpMatrix")if (!u_MvpMatrix) {throw new TypeError("获取uniform变量失败")}var viewMatrix = new Matrix4(); // 视图矩阵var projMatrix = new Matrix4(); // 透视投影矩阵var modelMatrix = new Matrix4(); // 模型矩阵var mvpMatrix = new Matrix4();// 旋转,平移,缩放,的矩阵被称为模型矩阵// 视点(0,0,0),观察点(0,0,-1),上方向(如果上方向是y轴的正方向,那么upX,upY,upZ就是0,1,0) 组成 视图矩阵// 在平面直角坐标系中, y轴正方向 是指 从原点沿纵轴向上的方向.”// 模型视图矩阵 = 视图矩阵 * 模型矩阵// 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点坐标// 模型矩阵,平移0.75modelMatrix.setTranslate(0.75, 0, 0);// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZviewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);// 定义透视投影矩阵// projMatrix.setPerspective(fov, aspect, near, far)// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0// aspect:指定近裁剪面的宽高比// near:近裁剪面的位置,必须大于0// far:远裁剪面的位置,必须大于0projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix)gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);// gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);// gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);// gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);// Clear <canvas>gl.clear(gl.COLOR_BUFFER_BIT);// Draw the trianglesgl.drawArrays(gl.TRIANGLES, 0, n);// 设置矩阵modelMatrix.setTranslate(-0.75, 0, 0);mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix)gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);gl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {// 三角形的位置x,y完全相同// 渲染出的三角形距离远的看上去变小了,其次,三角形被不同程度地平移以贴近中心线(即视线),// 使他们看上去在视线的左右排出了两列var verticesColors = new Float32Array([// Vertex coordinates and color0.0, 1.0, -4.0, 0.4, 1.0, 0.4, // The back green one-0.5, -1.0, -4.0, 0.4, 1.0, 0.4,0.5, -1.0, -4.0, 1.0, 0.4, 0.4,0.0, 1.0, -2.0, 1.0, 1.0, 0.4, // The middle yellow one-0.5, -1.0, -2.0, 1.0, 1.0, 0.4,0.5, -1.0, -2.0, 1.0, 0.4, 0.4,0.0, 1.0, 0.0, 0.4, 0.4, 1.0, // The front blue one-0.5, -1.0, 0.0, 0.4, 0.4, 1.0,0.5, -1.0, 0.0, 1.0, 0.4, 0.4,]);var n = 9;var vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}
7.6 隐藏面清除功能开启
原来的例子是先画远的,在画近处的内容,这样有一个问题,后面画的内容会出现在画布中,他应该被挡住才是的,开启隐藏面清除功能,可以解决此问题
// 开启隐藏面消除功能
gl.enable(gl.DEPTH_TEST);
// 清除默认颜色和深度缓冲区
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// PerspectiveView.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +// 'uniform mat4 u_ViewMatrix;\n' +// 'uniform mat4 u_ProjMatrix;\n' +// 'uniform mat4 u_ModelMatrix;\n' +'uniform mat4 u_MvpMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +// 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点位置// ' gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +// 合并 投影矩阵 * 视图矩阵 * 模型矩阵 这三个矩阵' gl_Position = u_MvpMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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)) {throw new TypeError("着色器初始化失败")return;}// Set the vertex coordinates and color (the blue triangle is in the front)var 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, 1);// var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');// var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');// var u_ModelMatrix = gl.getUniformLocation(gl.program, "u_ModelMatrix")var u_MvpMatrix = gl.getUniformLocation(gl.program, "u_MvpMatrix")if (!u_MvpMatrix) {throw new TypeError("获取uniform变量失败")}var viewMatrix = new Matrix4(); // 视图矩阵var projMatrix = new Matrix4(); // 透视投影矩阵var modelMatrix = new Matrix4(); // 模型矩阵var mvpMatrix = new Matrix4();// 旋转,平移,缩放,的矩阵被称为模型矩阵// 视点(0,0,0),观察点(0,0,-1),上方向(如果上方向是y轴的正方向,那么upX,upY,upZ就是0,1,0) 组成 视图矩阵// 在平面直角坐标系中, y轴正方向 是指 从原点沿纵轴向上的方向.”// 模型视图矩阵 = 视图矩阵 * 模型矩阵// 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 模型视图矩阵 * 顶点坐标// 透视投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点坐标// 模型矩阵,平移0.75modelMatrix.setTranslate(0.75, 0, 0);// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZviewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);// 定义透视投影矩阵// projMatrix.setPerspective(fov, aspect, near, far)// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0// aspect:指定近裁剪面的宽高比// near:近裁剪面的位置,必须大于0// far:远裁剪面的位置,必须大于0projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix)gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);// gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);// gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);// gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);// 开启隐藏面消除功能gl.enable(gl.DEPTH_TEST);// 清除默认颜色和深度缓冲区gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);// Draw the trianglesgl.drawArrays(gl.TRIANGLES, 0, n);// 设置矩阵modelMatrix.setTranslate(-0.75, 0, 0);mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix)gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);gl.drawArrays(gl.TRIANGLES, 0, n);}function initVertexBuffers(gl) {// 三角形的位置x,y完全相同// 渲染出的三角形距离远的看上去变小了,其次,三角形被不同程度地平移以贴近中心线(即视线),// 使他们看上去在视线的左右排出了两列var verticesColors = new Float32Array([// Vertex coordinates and color0.0, 1.0, 0.0, 0.4, 1.0, 0.4, // 绿色,在最前面-0.5, -1.0, 0.0, 0.4, 1.0, 0.4,0.5, -1.0, 0.0, 1.0, 0.4, 0.4,0.0, 1.0, -2.0, 1.0, 1.0, 0.4, // 黄色,在中间-0.5, -1.0, -2.0, 1.0, 1.0, 0.4,0.5, -1.0, -2.0, 1.0, 0.4, 0.4,0.0, 1.0, -4.0, 0.4, 0.4, 1.0, // 蓝色,在最后面-0.5, -1.0, -4.0, 0.4, 0.4, 1.0,0.5, -1.0, -4.0, 1.0, 0.4, 0.4,]);var n = 9;var vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}
7.7 z值相同,会产生深度冲突,解决深度冲突
// Zfighting.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewProjMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ViewProjMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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 coordinates and color (the blue triangle is in the front)var n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the vertex information');return;}//Set clear color and enable the hidden surface removal functiongl.clearColor(0, 0, 0, 1);gl.enable(gl.DEPTH_TEST);// Get the storage locations of u_ViewProjMatrixvar u_ViewProjMatrix = gl.getUniformLocation(gl.program, 'u_ViewProjMatrix');if (!u_ViewProjMatrix) {console.log('Failed to get the storage locations of u_ViewProjMatrix');return;}var viewProjMatrix = new Matrix4();// Set the eye point, look-at point, and up vector.viewProjMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);viewProjMatrix.lookAt(3.06, 2.5, 10.0, 0, 0, -2, 0, 1, 0);// Pass the view projection matrix to u_ViewProjMatrixgl.uniformMatrix4fv(u_ViewProjMatrix, false, viewProjMatrix.elements);// Clear color and depth buffergl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);// 启用多边形偏移,这个会自动偏移z值,给每个多边形自动加上一个偏移值gl.enable(gl.POLYGON_OFFSET_FILL);gl.drawArrays(gl.TRIANGLES, 0, n/2); // The green triangle// gl.polygonOffset(factor, units);// m * factor + r * units// m 表示顶点所在表面相对于观察者的视线的角度// r 表示 硬件能够区分两个z值之差的最小值gl.polygonOffset(1.0, 1.0); // 指定加到每个顶点绘制后z值上的偏移量gl.drawArrays(gl.TRIANGLES, n/2, n/2); // The yellow triangle}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// Vertex coordinates and color0.0, 2.5, -5.0, 0.4, 1.0, 0.4, // The green triangle-2.5, -2.5, -5.0, 0.4, 1.0, 0.4,2.5, -2.5, -5.0, 1.0, 0.4, 0.4,0.0, 3.0, -5.0, 1.0, 0.4, 0.4, // The yellow triagle-3.0, -3.0, -5.0, 1.0, 1.0, 0.4,3.0, -3.0, -5.0, 1.0, 1.0, 0.4,]);var n = 6;// Create a buffer objectvar vertexColorbuffer = gl.createBuffer();if (!vertexColorbuffer) {console.log('Failed to create the buffer object');return -1;}// Write the vertex coordinates and color to the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// Assign the buffer object to a_Position and enable the assignmentvar 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, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// Assign the buffer object to a_Color and enable the assignmentvar a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {console.log('Failed to get the storage location of a_Color');return -1;}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);return n;}
7.7 通过顶点索引绘制立方体
// 顶点着色器var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_MvpMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_MvpMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// 片源着色器var FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\n' +'}\n';function main() {// canvas对象var canvas = document.getElementById('webgl');// 创建webgl对象var gl = getWebGLContext(canvas);if (!gl) {throw new TypeError("创建webgl对象失败")}if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {throw new TypeError("初始化着色器失败");}var n = initVertexBuffers(gl);if (n < 0) {throw new TypeError("初始化Buffer失败");}// 设置默认颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 开启隐藏面消除gl.enable(gl.DEPTH_TEST);// 获取 矩阵对象变量var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');if (!u_MvpMatrix) {console.log('Failed to get the storage location of u_MvpMatrix');return;}// 创建矩阵对象var mvpMatrix = new Matrix4();// 定义透视投影矩阵mvpMatrix.setPerspective(30, 1, 1, 100);// 设置视点,观察点,上方向mvpMatrix.lookAt(3, 3, 7, 0, 0, 0, 0, 1, 0);// 矩阵对象变量赋值gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);// 清除默认颜色和深度缓冲区gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);// 按索引值来绘制顶点gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);}function initVertexBuffers(gl) {// Create a cube// v6----- v5// /| /|// v1------v0|// | | | |// | |v7---|-|v4// |/ |/// v2------v3var verticesColors = new Float32Array([// Vertex coordinates and color1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // v0 White-1.0, 1.0, 1.0, 1.0, 0.0, 1.0, // v1 Magenta-1.0, -1.0, 1.0, 1.0, 0.0, 0.0, // v2 Red1.0, -1.0, 1.0, 1.0, 1.0, 0.0, // v3 Yellow1.0, -1.0, -1.0, 0.0, 1.0, 0.0, // v4 Green1.0, 1.0, -1.0, 0.0, 1.0, 1.0, // v5 Cyan-1.0, 1.0, -1.0, 0.0, 0.0, 1.0, // v6 Blue-1.0, -1.0, -1.0, 0.0, 0.0, 0.0 // v7 Black]);// 生成索引顶点坐标,12个三角形的顶点var indices = new Uint8Array([0, 1, 2, 0, 2, 3, // front0, 3, 4, 0, 4, 5, // right0, 5, 6, 0, 6, 1, // up1, 6, 7, 1, 7, 2, // left7, 4, 3, 7, 3, 2, // down4, 7, 6, 4, 6, 5 // back]);// 创建buffer对象var vertexColorBuffer = gl.createBuffer();var indexBuffer = gl.createBuffer();if (!vertexColorBuffer || !indexBuffer) {return -1;}// 绑定颜色Buffer变量gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;// 获取顶点位置变量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;}gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);// 设置顶点颜色var a_Color = gl.getAttribLocation(gl.program, 'a_Color');if(a_Color < 0) {throw new TypeError("获取Attribute变量失败");}gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);// 绑定变量,设置变量gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);// 顶点索引值的长度 36return indices.length;}
7.8 通过索引绘制每个面颜色值固定的立方体,相同顶点需要应用不同颜色值
7.7例子有一个问题,就是相同顶点需要应用不同颜色
// ColoredCube.js (c) 2012 matsuda// Vertex shader programvar VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_MvpMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_MvpMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';// Fragment shader programvar FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\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;}// Set the clear color and enable the depth testgl.clearColor(0.0, 0.0, 0.0, 1.0);gl.enable(gl.DEPTH_TEST);// Get the storage location of u_MvpMatrixvar u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');if (!u_MvpMatrix) {console.log('Failed to get the storage location of u_MvpMatrix');return;}// Set the eye point and the viewing volumevar mvpMatrix = new Matrix4();mvpMatrix.setPerspective(30, 1, 1, 100);mvpMatrix.lookAt(3, 3, 7, 0, 0, 0, 0, 1, 0);// Pass the model view projection matrix to u_MvpMatrixgl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);// Clear color and depth buffergl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);// Draw the cubegl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);}function initVertexBuffers(gl) {// Create a cube// v6----- v5// /| /|// v1------v0|// | | | |// | |v7---|-|v4// |/ |/// v2------v3// 六个面的顶点var vertices = new Float32Array([1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0,-1.0, 1.0, // v0-v1-v2-v3 front1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0, // v0-v3-v4-v5 right1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0,-1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up-1.0, 1.0, 1.0, -1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0,-1.0, 1.0, // v1-v6-v7-v2 left-1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0, 1.0, -1.0,-1.0, 1.0, // v7-v4-v3-v2 down1.0,-1.0,-1.0, -1.0,-1.0,-1.0, -1.0, 1.0,-1.0, 1.0, 1.0,-1.0 // v4-v7-v6-v5 back]);// 六个面的顶点颜色坐标var colors = new Float32Array([ // Colors0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, // v0-v1-v2-v3 front(blue)0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, // v0-v3-v4-v5 right(green)1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, // v0-v5-v6-v1 up(red)1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, // v1-v6-v7-v2 left1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // v7-v4-v3-v2 down0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0 // v4-v7-v6-v5 back]);// 两个三角形一个面,一共六个面var indices = new Uint8Array([0, 1, 2, 0, 2, 3, // front4, 5, 6, 4, 6, 7, // right8, 9,10, 8,10,11, // up12,13,14, 12,14,15, // left16,17,18, 16,18,19, // down20,21,22, 20,22,23 // back]);// Create a buffer objectvar indexBuffer = gl.createBuffer();if (!indexBuffer)return -1;// Write the vertex coordinates and color to the buffer objectif (!initArrayBuffer(gl, vertices, 3, gl.FLOAT, 'a_Position'))return -1;if (!initArrayBuffer(gl, colors, 3, gl.FLOAT, 'a_Color'))return -1;// Write the indices to the buffer objectgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);return indices.length;}function initArrayBuffer(gl, data, num, type, attribute) {var buffer = gl.createBuffer(); // Create a buffer objectif (!buffer) {console.log('Failed to create the buffer object');return false;}// Write date into the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, buffer);gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);// Assign the buffer object to the attribute variablevar a_attribute = gl.getAttribLocation(gl.program, attribute);if (a_attribute < 0) {console.log('Failed to get the storage location of ' + attribute);return false;}gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);// Enable the assignment of the buffer object to the attribute variablegl.enableVertexAttribArray(a_attribute);return true;}
