要把WebGL繪製到頁面上,通常需要執行如下工作:
1.創建畫布元素
2.獲取呈現上下文
3.初始化視口
4.創建頂點數組
5.創建矩陣
6.加載著色器
7.繪製
創建畫布元素並獲取上下文
WebGL都發生在Canvas 元素的上下文中,Canvs的上下文是一個JavaScript對象,它提供了完整的WebGL API,你可以愛屏幕上創建和操作圖形。
由於WebGL 規範仍在開發中,因此上下文仍處於「實驗」階段。當前,大部分瀏覽器都使用語法 canvas.getContext("experimental-webgl") 來獲取 WebGLRenderingContext。
//從Canvas中獲取上下文
function initWebGL(canvas) {
var gl;
try {
gl = canvas.getContext("experimental-webgl") || canvas.getContext("webgl");
} catch (e) {
//Fail quietly
}
return gl;
}
初始化視口
獲得Canvas的上下文後,我們就可以設置在哪塊區域繪製WebGL了。在WebGL中,這被稱為視口(viewport)。
//將WebGL的視口設置為整個畫布的大小
function initViewport(gl, canvas) {
gl.viewport(0, 0, canvas.width, canvas.height);
}
創建頂點數組
WebGL的繪製由圖元(primitive)組成。圖元的數據數組稱為Buffer,它定義了頂點的位置。
下面的代碼展示了如何創建一個大小為1x1的正方形的頂點數據。返回的JavaSript對象存儲了頂點數據信息、數組中每個頂點所佔的尺寸(在這個實例中包含三個浮點數來存儲x、y、z的值)、需要繪製的頂點的數據,以及用於繪製正方形的圖元的類型。
頂點數組是 Float32Array 類型的類型化數組。 這是一種為了WebGL專門引入的新數據類型。它相比傳統數組速度更快並且佔用更少的內存。
//創建用於繪製正方形的定點數據
function createSquare(gl) {
var vertexBuffer;
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
var verts = [
.5, .5, 0.0,
-.5, .5, 0.0,
.5, -.5, 0.0,
-.5, -.5, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
var square = {buffer:vertexBuffer, vertSize:3, nVerts:4, primtype:gl.TRIANGLE_STRIP};
return square;
}
創建矩陣
在繪製正方形之前,我們需要先建立兩個矩陣。首先我們需要一個矩陣來定義正方形在3D坐標系中相對於攝像機的位置,這個矩陣也被稱為模型視圖矩陣(modelview matrix)。
第二個矩陣是投影矩陣(projection matrix),這個矩陣將被用於在著色器中將攝像機空間中的模型的3D坐標轉換為繪製的視口的2D坐標。
function initMatrices(){
// 正方形的變換矩陣——相對與相機沿著z軸稍微後移一些
modelViewMatrix = new Float32Array(
[1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, -3.333, 1]);
// 變換矩陣*45度視野(
projectionMatrix = new Float32Array(
[2.41421, 0, 0, 0,
0, 2.41421, 0, 0,
0, 0, -1.002002, -1,
0, 0, -0.2002002, 0]);
}
著色器
著色器由兩部分組成:頂點著色器(vertex shader)和片元著色器(fragment shader)。頂點著色器負責將模型的坐標轉換帶2D視口,片元著色器負責將元素輸出到轉換後的頂點像素。
因為篇幅有限,我們在這裡只展示部分代碼:
var vertexShaderSource =
" attribute vec3 vertexPos;\n" +
" uniform mat4 modelViewMatrix;\n" +
" uniform mat4 projectionMatrix;\n" +
" void main(void) {\n" +
" // 返回變換並投影后的頂點數據\n" +
" gl_Position = projectionMatrix * modelViewMatrix * \n" +
" vec4(vertexPos, 1.0);\n" +
" }\n";
var fragmentShaderSource =
" void main(void) {\n" +
" // 返回像素顏色,永遠輸出白色\n" +
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
"}\n";
繪製圖元
現在我們開始真正繪製正方形。首先清理畫布並設置黑色為背景色。然後將頂點數組綁定到上下文中,使用著色器,並把定點數組和矩陣作為輸入傳遞給著色器。最後調用WebGL的drawArrays() 方法來繪製正方形。
function draw(gl, obj) {
// 用黑色清空背景
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// 設置頂點數組
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
// 設置著色器
gl.useProgram(shaderProgram);
// 設置著色器參數:頂點坐標、投影矩陣和模型試圖矩陣
gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0);
gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix);
gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix);
// 繪製物體
gl.drawArrays(obj.primtype, 0, obj.nVerts);
}