WebGL 的出現(xiàn)使得在瀏覽器上面實時顯示 3D 圖像成為,WebGL 本質上是基于光柵化的 API ,而不是基于 3D 的 API。
WebGL 只關注兩個方面,即投影矩陣的坐標和投影矩陣的顏色。使用 WebGL 程序的任務就是實現(xiàn)具有投影矩陣坐標和顏色的 WebGL 對象即可。可以使用“著色器”來完成上述任務。頂點著色器可以提供投影矩陣的坐標,片段著色器可以提供投影矩陣的顏色。
無論要實現(xiàn)的圖形尺寸有多大,其投影矩陣的坐標的范圍始終是從 -1 到 1 。下面是一個關于實現(xiàn) WebGL 對象的一個簡單例子。
// Get A WebGL context
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("experimental-webgl");
// setup a GLSL program
var program = createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
// Create a buffer and put a single clipspace rectangle in
// it (2 triangles)
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
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]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// draw
gl.drawArrays(gl.TRIANGLES, 0, 6);
下面是兩個著色器。
它將繪出一個綠色的長方形來填充整個畫板。
后面內容還會更精彩,我們繼續(xù):-P
我們再次降調一下,無論畫板尺寸多大,投影矩陣坐標的范圍只會在 -1 到 1 之間。從上面的例子中,我們可以看出我們只是將位置信息直接寫在了程序里。 因為位置信息已經在投影矩陣中,所以并沒有其他額外的工作要做。 如果想實現(xiàn) 3D 的效果,那么可以使用著色器來將 3D 轉換為投影矩陣,這是因為 WebGL 是基于光柵的 API。
對于 2D 的圖像,也許會使用像素而不是投影矩陣來表述尺寸,那么這里我們就更改這里的著色器,使得我們實現(xiàn)的矩形可以以像素的方式來度量,下面是新的頂點著色器。
下面我們將我們的數(shù)據(jù)從投影矩陣改為像素。
// set the resolution
var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
// setup a rectangle from 10,20 to 80,30 in pixels
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
10, 20,
80, 20,
10, 30,
10, 30,
80, 20,
80, 30]), gl.STATIC_DRAW);
上面例子矩陣位于底部邊框,下面我們讓它位于左上邊框:
修改代碼如下:
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
效果如下圖:
下面我們將上述關于矩陣的實現(xiàn)寫成函數(shù)以便可以以函數(shù)調用的方式來實現(xiàn)不同尺寸的矩陣。 然而,這里的顏色應該是可變的。
首先,我們?yōu)槠沃髟O計一個關于顏色的輸入。
下面是實現(xiàn)繪畫 50 個尺寸和顏色均隨機的矩陣的代碼。
var colorLocation = gl.getUniformLocation(program, "u_color");
...
// Create a buffer
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// draw 50 random rectangles in random colors
for (var ii = 0; ii < 50; ++ii) { // Setup a random rectangle setRectangle( gl, randomInt(300), randomInt(300), randomInt(300), randomInt(300)); // Set a random color. gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1); // Draw the rectangle. gl.drawArrays(gl.TRIANGLES, 0, 6); } } // Returns a random integer from 0 to range - 1. function randomInt(range) { return Math.floor(Math.random() * range); } // Fills the buffer with the values that define a rectangle. function setRectangle(gl, x, y, width, height) { var x1 = x; var x2 = x + width; var y1 = y; var y2 = y + height; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW); }
下面就是實現(xiàn)出來的效果。
到此可以看出 WebGL 實質上是一種輕量級的 API。但是,它可以實現(xiàn)較為復雜的 3D 效果,其復雜性由程序定制。WebGL API 本身是 2D 的且相對比較簡單。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網(wǎng)站上部分文章為轉載,并不用于任何商業(yè)目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯(lián)系我們,我們將根據(jù)著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。