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 program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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,0
viewMatrix.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, z
modalMatrix.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 program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Retrieve the nearFar element
var nf = document.getElementById('nearFar');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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_ProjMatrix
var 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 sight
var projMatrix = new Matrix4();
// Register the event handler to be called on key press
document.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 color
0.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 object
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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
return n;
}
// The distances to the near and far clipping plane
var 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 pressed
case 37: g_near -= 0.01; break; // The left arrow key was pressed
case 38: g_far += 0.01; break; // The up arrow key was pressed
case 40: g_far -= 0.01; break; // The down arrow key was pressed
default: 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_ProjMatrix
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);
gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
// Display the current near and far values
nf.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 program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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,0
viewMatrix.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, z
modalMatrix.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 program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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,upZ
viewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);
// 设置可视空间,定义透视投影矩阵
// projMatrix.setPerspective(fov, aspect, near, far)
// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0
// aspect:指定近裁剪面的宽高比
// near:近裁剪面的位置,必须大于0
// far:远裁剪面的位置,必须大于0
projMatrix.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 triangles
gl.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 object
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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
return n;
}
7.4 在上一个例子,绘制中间的三个三角形,通过模型矩阵,绘制两次,一次偏移0.75,一次偏移-0.75,达到和上个例子一样的效果
// PerspectiveView.js (c) 2012 matsuda
// Vertex shader program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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.75
modelMatrix.setTranslate(0.75, 0, 0);
// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZ
viewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);
// 定义透视投影矩阵
// projMatrix.setPerspective(fov, aspect, near, far)
// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0
// aspect:指定近裁剪面的宽高比
// near:近裁剪面的位置,必须大于0
// far:远裁剪面的位置,必须大于0
projMatrix.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 triangles
gl.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 color
0.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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
return n;
}
7.5 在7.4的例子上,合并了 投影矩阵,视图矩阵,模型矩阵
// PerspectiveView.js (c) 2012 matsuda
// Vertex shader program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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.75
modelMatrix.setTranslate(0.75, 0, 0);
// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZ
viewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);
// 定义透视投影矩阵
// projMatrix.setPerspective(fov, aspect, near, far)
// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0
// aspect:指定近裁剪面的宽高比
// near:近裁剪面的位置,必须大于0
// far:远裁剪面的位置,必须大于0
projMatrix.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 triangles
gl.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 color
0.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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
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 program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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.75
modelMatrix.setTranslate(0.75, 0, 0);
// 定义 eyeX,eyeY,eyeZ,atX,atY,atX,upX,upY,upZ
viewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);
// 定义透视投影矩阵
// projMatrix.setPerspective(fov, aspect, near, far)
// fov:指定垂直视角,即可视空间顶面和地面间的夹角,必须大于0
// aspect:指定近裁剪面的宽高比
// near:近裁剪面的位置,必须大于0
// far:远裁剪面的位置,必须大于0
projMatrix.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 triangles
gl.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 color
0.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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
return n;
}
7.7 z值相同,会产生深度冲突,解决深度冲突
// Zfighting.js (c) 2012 matsuda
// Vertex shader program
var 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 program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!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 function
gl.clearColor(0, 0, 0, 1);
gl.enable(gl.DEPTH_TEST);
// Get the storage locations of u_ViewProjMatrix
var 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_ViewProjMatrix
gl.uniformMatrix4fv(u_ViewProjMatrix, false, viewProjMatrix.elements);
// Clear color and depth buffer
gl.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 color
0.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 object
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 object
gl.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 assignment
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);
// Assign the buffer object to a_Color and enable the assignment
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);
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------v3
var verticesColors = new Float32Array([
// Vertex coordinates and color
1.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 Red
1.0, -1.0, 1.0, 1.0, 1.0, 0.0, // v3 Yellow
1.0, -1.0, -1.0, 0.0, 1.0, 0.0, // v4 Green
1.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, // front
0, 3, 4, 0, 4, 5, // right
0, 5, 6, 0, 6, 1, // up
1, 6, 7, 1, 7, 2, // left
7, 4, 3, 7, 3, 2, // down
4, 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);
// 顶点索引值的长度 36
return indices.length;
}
7.8 通过索引绘制每个面颜色值固定的立方体,相同顶点需要应用不同颜色值
7.7例子有一个问题,就是相同顶点需要应用不同颜色
// ColoredCube.js (c) 2012 matsuda
// Vertex shader program
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';
// Fragment shader program
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() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Set the vertex information
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the vertex information');
return;
}
// Set the clear color and enable the depth test
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
// Get the storage location of u_MvpMatrix
var 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 volume
var 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_MvpMatrix
gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
// Clear color and depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Draw the cube
gl.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 front
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-v3-v4-v5 right
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-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 down
1.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([ // Colors
0.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 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 down
0.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, // front
4, 5, 6, 4, 6, 7, // right
8, 9,10, 8,10,11, // up
12,13,14, 12,14,15, // left
16,17,18, 16,18,19, // down
20,21,22, 20,22,23 // back
]);
// Create a buffer object
var indexBuffer = gl.createBuffer();
if (!indexBuffer)
return -1;
// Write the vertex coordinates and color to the buffer object
if (!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 object
gl.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 object
if (!buffer) {
console.log('Failed to create the buffer object');
return false;
}
// Write date into the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// Assign the buffer object to the attribute variable
var 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 variable
gl.enableVertexAttribArray(a_attribute);
return true;
}