天天看點

用html建立一個立方體,9.4 建立一個旋轉的立方體 - HTML5 Canvas 實戰

好了,現在真正有趣的事情開始了。本節,我們将建立一個旋轉的3D立方體,該立方體具有不同顔色的表面。為了做到這一點,我們将介紹兩類新的緩沖區——顔色緩沖區和索引緩沖區。

用html建立一個立方體,9.4 建立一個旋轉的立方體 - HTML5 Canvas 實戰

圖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類