1.实验目的
学习了解三维图形几何变换原理。 理解掌握WebGL三维图形几何变换的方法。
2. 实验内容
阅读教材有关三维图形变换原理,运行示范实验代码,掌握WebGL程序三维图形变换的方法; 请分别调整观察变换矩阵、模型变换矩阵和投影变换矩阵的参数,观察变换结果; 修改变换矩阵参数,实现一点透视、两点透视和三点透视,并将相关修改代码提交到赛课本次作业中,同时写到实验报告的实验结果中。 示范代码对应教材6.5 编程实例-立方体透视投影内容,运行结果如下图所示:
3.实验代码
(1) 6-5-HelloCube.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<html >
<head >
<meta http-equiv ="Content-Type" content ="text/html; charset=utf-8" >
<title > 6.5 WebGl编程实例——立方体透视投影</title >
</head >
<body onload ="startup()" >
<canvas id ="myGLCanvas" width ="600" height ="600" >
</canvas >
</body >
<script type ="text/javascript" src ="gl-matrix.js" > </script >
<script type ="text/javascript" src ="6-5-HelloCube.js" > </script >
</html >
(3) 6-5-HelloCube.js
var gl;
function startup () {
var canvas = document.getElementById('myGLCanvas' );
gl = createGLContext(canvas);
setupShaders();
var n = initVertexBuffers(gl);
if (n < 0 ) {
console.log('Failed to set the positions of the vertices' );
return ;
}
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 eye = vec3.fromValues(0.0 , 0.0 , 5.0 );
var center = vec3.fromValues(0.0 , 0.0 , 0.0 );
var up = vec3.fromValues(0.0 , 1.0 , 0.0 );
var vMatrix = mat4.create();
mat4.lookAt(vMatrix, eye, center, up);
var mMatrix = mat4.create();
mat4.translate(mMatrix, mMatrix, [0.0 , 0.0 , 0.0 ]);
mat4.scale(mMatrix, mMatrix, [1.0 , 1.0 , 1.0 ]);
mat4.rotate(mMatrix, mMatrix, Math .PI/4 , [0.0 , 1.0 , 1.0 ]);
var pMatrix = mat4.create();
mat4.frustum(pMatrix, -1.0 , 1.0 , -1.0 , 1.0 , 1.5 , 20.0 );
var mvpMatrix = mat4.create();
mat4.multiply(mvpMatrix, vMatrix, mMatrix);
mat4.multiply(mvpMatrix, pMatrix, mvpMatrix);
gl.uniformMatrix4fv(u_MvpMatrix, false , mvpMatrix);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0 );
}
function createGLContext (canvas) {
var names = ["webgl" , "experimental-webgl" ];
var context = null ;
for (var i=0 ; i < names.length; i++) {
try {
context = canvas.getContext(names[i]);
} catch (e) {}
if (context) {
break ;
}
}
if (context) {
context.viewportWidth = canvas.width;
context.viewportHeight = canvas.height;
} else {
alert("Failed to create WebGL context!" );
}
return context;
}
function setupShaders () {
var vertexShaderSource =
'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 fragmentShaderSource =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_FragColor = v_Color;\n' +
'}\n' ;
var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Failed to setup shaders" );
}
gl.useProgram(shaderProgram);
gl.program= shaderProgram;
}
function loadShader (type, shaderSource) {
var shader = gl.createShader(type);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader" + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null ;
}
return shader;
}
function initVertexBuffers (gl) {
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 ,
1.0 , 1.0 , 1.0 , 1.0 ,-1.0 , 1.0 , 1.0 ,-1.0 ,-1.0 , 1.0 , 1.0 ,-1.0 ,
1.0 , 1.0 , 1.0 , 1.0 , 1.0 ,-1.0 , -1.0 , 1.0 ,-1.0 , -1.0 , 1.0 , 1.0 ,
-1.0 , 1.0 , 1.0 , -1.0 , 1.0 ,-1.0 , -1.0 ,-1.0 ,-1.0 , -1.0 ,-1.0 , 1.0 ,
-1.0 ,-1.0 ,-1.0 , 1.0 ,-1.0 ,-1.0 , 1.0 ,-1.0 , 1.0 , -1.0 ,-1.0 , 1.0 ,
1.0 ,-1.0 ,-1.0 , -1.0 ,-1.0 ,-1.0 , -1.0 , 1.0 ,-1.0 , 1.0 , 1.0 ,-1.0
]);
var colors = new Float32Array ([
0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 ,
0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 ,
1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 , 1.0 , 0.4 , 0.4 ,
1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 0.4 ,
1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 ,
0.4 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0
]);
var indices = new Uint8Array ([
0 , 1 , 2 , 0 , 2 , 3 ,
4 , 5 , 6 , 4 , 6 , 7 ,
8 , 9 ,10 , 8 ,10 ,11 ,
12 ,13 ,14 , 12 ,14 ,15 ,
16 ,17 ,18 , 16 ,18 ,19 ,
20 ,21 ,22 , 20 ,22 ,23
]);
var indexBuffer = gl.createBuffer();
if (!indexBuffer)
return -1 ;
if (!initArrayBuffer(gl, vertices, 3 , gl.FLOAT, 'a_Position' ))
return -1 ;
if (!initArrayBuffer(gl, colors, 3 , gl.FLOAT, 'a_Color' ))
return -1 ;
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();
if (!buffer) {
console.log('Failed to create the buffer object' );
return false ;
}
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
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 );
gl.enableVertexAttribArray(a_attribute);
return true ;
}