WebGL立方體旋轉
在本章中,我們將舉一個例子來演示如何使用WebGL繪製一個旋轉3D立方體。
示例 - 繪製一個旋轉的3D立方體
以下程序顯示瞭如何繪製一個旋轉的3D立方體 -
<script>
/\*============= Creating a canvas =================\*/
var canvas = document.getElementById('my\_Canvas');
gl = canvas.getContext('experimental-webgl');
/\*============ Defining and storing the geometry =========\*/
var vertices = \[
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
\];
var colors = \[
5,3,7, 5,3,7, 5,3,7, 5,3,7,
1,1,3, 1,1,3, 1,1,3, 1,1,3,
0,0,1, 0,0,1, 0,0,1, 0,0,1,
1,0,0, 1,0,0, 1,0,0, 1,0,0,
1,1,0, 1,1,0, 1,1,0, 1,1,0,
0,1,0, 0,1,0, 0,1,0, 0,1,0
\];
var indices = \[
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
\];
// Create and store data into vertex buffer
var vertex\_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY\_BUFFER, vertex\_buffer);
gl.bufferData(gl.ARRAY\_BUFFER, new Float32Array(vertices), gl.STATIC\_DRAW);
// Create and store data into color buffer
var color\_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY\_BUFFER, color\_buffer);
gl.bufferData(gl.ARRAY\_BUFFER, new Float32Array(colors), gl.STATIC\_DRAW);
// Create and store data into index buffer
var index\_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT\_ARRAY\_BUFFER, index\_buffer);
gl.bufferData(gl.ELEMENT\_ARRAY\_BUFFER, new Uint16Array(indices), gl.STATIC\_DRAW);
/\*=================== Shaders =========================\*/
var vertCode = 'attribute vec3 position;'+
'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+
'void main(void) { '+//pre-built function
'gl\_Position = Pmatrix\*Vmatrix\*Mmatrix\*vec4(position, 1.);'+
'vColor = color;'+
'}';
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl\_FragColor = vec4(vColor, 1.);'+
'}';
var vertShader = gl.createShader(gl.VERTEX\_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT\_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
/\* ====== Associating attributes to vertex shader =====\*/
var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");
var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");
gl.bindBuffer(gl.ARRAY\_BUFFER, vertex\_buffer);
var position = gl.getAttribLocation(shaderProgram, "position");
gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;
// Position
gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY\_BUFFER, color\_buffer);
var color = gl.getAttribLocation(shaderProgram, "color");
gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;
// Color
gl.enableVertexAttribArray(color);
gl.useProgram(shaderProgram);
/\*==================== MATRIX =====================\*/
function get\_projection(angle, a, zMin, zMax) {
var ang = Math.tan((angle\*.5)\*Math.PI/180);//angle\*.5
return \[
0.5/ang, 0 , 0, 0,
0, 0.5\*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2\*zMax\*zMin)/(zMax-zMin), 0
\];
}
var proj\_matrix = get\_projection(40, canvas.width/canvas.height, 1, 100);
var mov\_matrix = \[1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1\];
var view\_matrix = \[1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1\];
// translating z
view\_matrix\[14\] = view\_matrix\[14\]-6;//zoom
/\*==================== Rotation ====================\*/
function rotateZ(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m\[0\], mv4 = m\[4\], mv8 = m\[8\];
m\[0\] = c\*m\[0\]-s\*m\[1\];
m\[4\] = c\*m\[4\]-s\*m\[5\];
m\[8\] = c\*m\[8\]-s\*m\[9\];
m\[1\]=c\*m\[1\]+s\*mv0;
m\[5\]=c\*m\[5\]+s\*mv4;
m\[9\]=c\*m\[9\]+s\*mv8;
}
function rotateX(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv1 = m\[1\], mv5 = m\[5\], mv9 = m\[9\];
m\[1\] = m\[1\]\*c-m\[2\]\*s;
m\[5\] = m\[5\]\*c-m\[6\]\*s;
m\[9\] = m\[9\]\*c-m\[10\]\*s;
m\[2\] = m\[2\]\*c+mv1\*s;
m\[6\] = m\[6\]\*c+mv5\*s;
m\[10\] = m\[10\]\*c+mv9\*s;
}
function rotateY(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m\[0\], mv4 = m\[4\], mv8 = m\[8\];
m\[0\] = c\*m\[0\]+s\*m\[2\];
m\[4\] = c\*m\[4\]+s\*m\[6\];
m\[8\] = c\*m\[8\]+s\*m\[10\];
m\[2\] = c\*m\[2\]-s\*mv0;
m\[6\] = c\*m\[6\]-s\*mv4;
m\[10\] = c\*m\[10\]-s\*mv8;
}
/\*================= Drawing ===========================\*/
var time\_old = 0;
var animate = function(time) {
var dt = time-time\_old;
rotateZ(mov\_matrix, dt\*0.005);//time
rotateY(mov\_matrix, dt\*0.002);
rotateX(mov\_matrix, dt\*0.003);
time\_old = time;
gl.enable(gl.DEPTH\_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR\_BUFFER\_BIT | gl.DEPTH\_BUFFER\_BIT);
gl.uniformMatrix4fv(Pmatrix, false, proj\_matrix);
gl.uniformMatrix4fv(Vmatrix, false, view\_matrix);
gl.uniformMatrix4fv(Mmatrix, false, mov\_matrix);
gl.bindBuffer(gl.ELEMENT\_ARRAY\_BUFFER, index\_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED\_SHORT, 0);
window.requestAnimationFrame(animate);
}
animate(0);
</script>
這將產生以下結果(這裏只能放靜態圖片,具體旋轉效果可自己運行代碼觀察) -