在學(xué)習(xí) 3D 相關(guān)知識(shí)之前,請(qǐng)首先看看 2D 的知識(shí)。請(qǐng)保持耐心。這篇文章某些人看起來可能非常簡(jiǎn)單,但是我們將要講解的知識(shí)是建立在前幾篇的文章的基礎(chǔ)之上。如果你沒有閱讀過,我建議你至少閱讀第一章之后再回到這里繼續(xù)學(xué)習(xí)。
Translation 指的是一些奇特的數(shù)學(xué)名稱,它的基本意思是“移動(dòng)”某物。它同樣適用于將一個(gè)句子從英文“移動(dòng)”成為日語這一說法,但是此處我們談?wù)摰氖菐缀沃械囊苿?dòng)。通過使用以 the first post 結(jié)尾的代碼,你可以僅僅通過修改 setRectangle 距離右邊的的值來使矩形移動(dòng)。如下是一個(gè)基于我們初始示例的代碼:
// 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);
}
在上面的例子中,我在界面中放置了兩個(gè)可滑動(dòng)欄,你可以通過滑動(dòng)按鈕來修改 translation[0] 和 translation[1] 的值,而且在這個(gè)兩個(gè)值發(fā)生修改時(shí)調(diào)用 drawScene 函數(shù)對(duì)界面進(jìn)行更新。拖動(dòng)滑動(dòng)條對(duì)矩陣進(jìn)行移動(dòng)。
到此處你已經(jīng)覺得很不錯(cuò)。然而,現(xiàn)在假設(shè)我們想要利用相同的操作,但是處理更復(fù)雜的圖形,那么該如何實(shí)現(xiàn)了。
假設(shè)我們想要畫一個(gè)包含 6 個(gè)三角形的 '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);
}
你會(huì)發(fā)現(xiàn)畫出來的圖形伸縮比例不是很好。如果你想畫出有幾百或者幾千條線組成的幾何圖形,我們就需要編寫一些相當(dāng)復(fù)雜的代碼。在上面的代碼中,每次用 JavaScript 就需要更新所有的點(diǎn)。
有一種更簡(jiǎn)單的方式。僅僅只需要更新幾何圖形,接著修改渲染器部分。
如下是渲染器部分:
<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;
...
接著我們將會(huì)稍微重構(gòu)下代碼。我們僅僅需要設(shè)置幾何圖形一次。
// 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);
}
在實(shí)現(xiàn)我們想要的移動(dòng)之前需要更新下 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
只是被調(diào)用一次。在 drawScene 中不需要。
如下是一個(gè)示例。同樣,你可以通過拖動(dòng)滑動(dòng)條來更新圖形的位置。
現(xiàn)在,當(dāng)我們繪制 WebGL 圖像就包括要實(shí)現(xiàn)上面所有的事。我們所作的所有事指的是設(shè)置移動(dòng)變量接著調(diào)用函數(shù)進(jìn)行繪制。即使我們的幾何圖形包含成千上萬的點(diǎn),main 代碼仍然是相同的。
更多建議: