好了,現在真正有趣的事情開始了。本節,我們将建立一個旋轉的3D立方體,該立方體具有不同顔色的表面。為了做到這一點,我們将介紹兩類新的緩沖區——顔色緩沖區和索引緩沖區。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iMlZWOmhTYhRzM3IDN5IjNxYjN1YjM0YDZ5AzYwMWM48CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
圖9-3 旋轉的立方體
操作步驟
按照以下步驟,使用WebGL建立一個旋轉立方體:
1. 連結到glMatrix庫和WebGL包裝器:
2. 定義initBuffers()函數,該函數初始化立方體的位置緩沖區,顔色緩沖區,及索引緩沖區:
function initBuffers(gl) {
var cubeBuffers = {}
cubeBuffers.positionBuffer = gl.createArrayBuffer([
// Front face
-1, -1, 1,
1, -1, 1,
1, 1, 1,
-1, 1, 1,
// Back face
-1, -1, -1,
-1, 1, -1,
1, 1, -1,
1, -1, -1,
// Top face
-1, 1, -1,
-1, 1, 1,
1, 1, 1,
1, 1, -1,
// Bottom face
-1, -1, -1,
1, -1, -1,
1, -1, 1,
-1, -1, 1,
// Right face
1, -1, -1,
1, 1, -1,
1, 1, 1,
1, -1, 1,
// Left face
-1, -1, -1,
-1, -1, 1,
-1, 1, 1,
-1, 1, -1
]);
//建構彩色頂點
var colors = [
[1, 0, 1, 1], // Front face - Pink
[0, 1, 0, 1], // Back face - Green
[0, 0, 1, 1], // Top face - Blue
[0, 1, 1, 1], // Bottom face - Turquoise
[1, 1, 0, 1], // Right face - Yellow
[1, 0, 0, 1] // Left face - Red
];
var colorVertices = [];
for (var n in colors) {
var color = colors[n];
for (var i=0; i
colorVertices = colorVertices.concat(color);
}
}
cubeBuffers.colorBuffer = gl.createArrayBuffer(colorVertices);
cubeBuffers.indexBuffer = gl.createElementArrayBuffer([
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
]);
return cubeBuffers;
}
3. 定義stage()函數,該函數設定透視矩陣,把模型-視圖矩陣設定到機關矩陣,平移立方體,旋轉立方體,把位置緩沖區、顔色緩沖區、索引緩沖區發送到顯示卡,最後,因為模型的表面不是三角形,所有要調用drawElements()方法來繪制該立方體:
function stage(gl, cubeBuffers, angle){
// set field of view at 45 degrees
// set viewing range between 0.1 and 100.0 units away.
gl.perspective(45, 0.1, 100);
gl.identity();
// translate model-view matrix
gl.translate(0, 0, -5);
// rotate model-view matrix about x-axis (tilt box downwards)
gl.rotate(Math.PI * 0.15, 1, 0, 0);
// rotate model-view matrix about y-axis
gl.rotate(angle, 0, 1, 0);
gl.pushPositionBuffer(cubeBuffers);
gl.pushColorBuffer(cubeBuffers);
gl.pushIndexBuffer(cubeBuffers);
gl.drawElements(cubeBuffers);
}
4. 頁面加載完成後,初始化WebGL包裝器對象,把着色器程式設定為“VARYING_COLOR”( 因為每個面是變量,并且依賴于顔色緩沖區、初始化緩沖區),為動畫設定stage函數,然後啟動動畫:
window.onload = function(){
var gl = new WebGL("myCanvas", "experimental-webgl");
gl.setShaderProgram("VARYING_COLOR");
var cubeBuffers = initBuffers(gl);
var angle = 0;
gl.setStage(function(){
// update angle
var angularVelocity = Math.PI / 4; // radians / second
var angleEachFrame = angularVelocity * this.getTimeInterval() / 1000;
angle += angleEachFrame;
this.clear();
stage(this, cubeBuffers, angle);
});
gl.start();
};
5. 在HTML文檔的body部分嵌入canvas标簽:
工作原理
本節介紹了索引緩沖區和顔色緩沖區的概念。在前兩節,我們建立了一個三角形的平面,三角形平面的模型是WebGL中最容易實作的,因為它僅僅需要一個緩沖區——位置緩沖區。若要使用非三角形的面來建立一個3D模型,如立方體,就稍微有點複雜,因為我們要把立方體表示為一組三角形的面。我們可以通過建立一個索引緩沖區,把三角形映射為位置緩沖區中的頂點來實作它。
看看前面代碼中的索引緩沖區中的頂點。你将會注意到前6個元素是[0, 1, 2, 0, 2, 3]。前三個元素,[0, 1, 2]指的是位置緩沖區中的第0個,第1個,第2個頂點,它們形成一個立方體正面的半個三角形。第二組元素,[0, 2, 3]相當于位置緩沖區中的第0個,第2個,第3個頂點,它們形成一個立方體正面的另外半個三角形。放在一起,這兩個三角形形成立方體的正面。完整的索引緩沖區中,将包含構成立方體的6個面在位置緩沖區中頂點的映射。
除了索引緩沖區,本節還需要使用顔色緩沖區。顔色緩沖區用來定義模型各個面的顔色。本節的顔色緩沖區為立方體的6個面,定義了6種不同的顔色。跟索引緩沖區類似,顔色緩沖區用來把顔色映射到位置緩沖區中的每個頂點。某種顔色由[紅, 綠, 藍, 透明度]四個元素定義。根據位置緩沖區的定義,我們的立方體由6個面組成,每個面有4個頂點。是以,我們的元素緩沖區數組應該包含(6 個面) * (4 個頂點每個面) * (4 個元素每種顔色) = 96 個元素。
一旦我們的位置緩沖區、顔色緩沖區、索引緩沖區定義完成,剩下的就隻有把每個緩沖區發送到顯示卡,并渲染模型了。前兩節,直接使用drawArrays()方法來渲染三角形,跟前兩節不同,本節我們必須使用drawElements()方法,因為我們的模型是由非三角形面組成的,需要一個索引緩沖區來把三角形面映射到模型的各個正方形的面。
相關參考
第5章 建立Animation類