在學習 3D 相關知識之前,請首先看看 2D 的知識。請保持耐心。這篇文章某些人看起來可能非常簡單,但是我們將要講解的知識是建立在前幾篇的文章的基礎之上。如果你沒有閱讀過,我建議你至少閱讀第一章之后再回到這里繼續(xù)學習。
Translation 指的是一些奇特的數(shù)學名稱,它的基本意思是“移動”某物。它同樣適用于將一個句子從英文“移動”成為日語這一說法,但是此處我們談論的是幾何中的移動。通過使用以 the first post 結尾的代碼,你可以僅僅通過修改 setRectangle 距離右邊的的值來使矩形移動。如下是一個基于我們初始示例的代碼:
// First lets make some variables
// to hold the translation of the rectangle
var translation = [0, 0];
// then let's make a function to
// re-draw everything. We can call this
// function after we update the translation.
// Draw a the scene.
function drawScene() {
// Clear the canvas.
gl.clear(gl.COLOR_BUFFER_BIT);
// Setup a rectangle
setRectangle(gl, translation[0], translation[1], width, height);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
在上面的例子中,我在界面中放置了兩個可滑動欄,你可以通過滑動按鈕來修改 translation[0] 和 translation[1] 的值,而且在這個兩個值發(fā)生修改時調用 drawScene 函數(shù)對界面進行更新。拖動滑動條對矩陣進行移動。
到此處你已經覺得很不錯。然而,現(xiàn)在假設我們想要利用相同的操作,但是處理更復雜的圖形,那么該如何實現(xiàn)了。
假設我們想要畫一個包含 6 個三角形的 'F' 形狀,如下所示:
如下是我們將要使用的改變 setRectangle 值的代碼:
// Fill the buffer with the values that define a letter 'F'.
function setGeometry(gl, x, y) {
var width = 100;
var height = 150;
var thickness = 30;
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
// left column
x, y,
x + thickness, y,
x, y + height,
x, y + height,
x + thickness, y,
x + thickness, y + height,
// top rung
x + thickness, y,
x + width, y,
x + thickness, y + thickness,
x + thickness, y + thickness,
x + width, y,
x + width, y + thickness,
// middle rung
x + thickness, y + thickness * 2,
x + width * 2 / 3, y + thickness * 2,
x + thickness, y + thickness * 3,
x + thickness, y + thickness * 3,
x + width * 2 / 3, y + thickness * 2,
x + width * 2 / 3, y + thickness * 3]),
gl.STATIC_DRAW);
}
你會發(fā)現(xiàn)畫出來的圖形伸縮比例不是很好。如果你想畫出有幾百或者幾千條線組成的幾何圖形,我們就需要編寫一些相當復雜的代碼。在上面的代碼中,每次用 JavaScript 就需要更新所有的點。
有一種更簡單的方式。僅僅只需要更新幾何圖形,接著修改渲染器部分。
如下是渲染器部分:
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
uniform vec2 u_translation;
void main() {
// Add in the translation.
vec2 position = a_position + u_translation;
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = position / u_resolution;
...
接著我們將會稍微重構下代碼。我們僅僅需要設置幾何圖形一次。
// Fill the buffer with the values that define a letter 'F'.
function setGeometry(gl) {
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
// left column
0, 0,
30, 0,
0, 150,
0, 150,
30, 0,
30, 150,
// top rung
30, 0,
100, 0,
30, 30,
30, 30,
100, 0,
100, 30,
// middle rung
30, 60,
67, 60,
30, 90,
30, 90,
67, 60,
67, 90]),
gl.STATIC_DRAW);
}
在實現(xiàn)我們想要的移動之前需要更新下 u_translation
變量的值。
...
var translationLocation = gl.getUniformLocation(
program, "u_translation");
...
// Set Geometry.
setGeometry(gl);
..
// Draw scene.
function drawScene() {
// Clear the canvas.
gl.clear(gl.COLOR_BUFFER_BIT);
// Set the translation.
gl.uniform2fv(translationLocation, translation);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 18);
}
注意 setGeometry
只是被調用一次。在 drawScene 中不需要。
如下是一個示例。同樣,你可以通過拖動滑動條來更新圖形的位置。
現(xiàn)在,當我們繪制 WebGL 圖像就包括要實現(xiàn)上面所有的事。我們所作的所有事指的是設置移動變量接著調用函數(shù)進行繪制。即使我們的幾何圖形包含成千上萬的點,main 代碼仍然是相同的。
更多建議: