WebGL - 翻譯:在3D空間中移動物體

你好,有志於成為WebGL開發者的人們!今天,我們將踏上一段令人興奮的旅程,進入3D圖形的世界。我們將探討WebGL中的平移概念,這基本上是一種將“東西移來移去”的花哨說法。在這個教程結束時,你將能夠讓物體在螢幕上跳來跳去,就像數字芭蕾一樣!那麼,讓我們開始吧!

WebGL - Translation

WebGL中的平移是什麼?

在我們開始像棋子一樣移動三角形之前,讓我們先了解在計算機圖形中平移究竟意味著什麼。

平移的基本概念

平移是在2D或3D空間中將物體從一個位置移動到另一個位置的过程。這就像從辦公桌上拿起一杯水,然後把它放在架子上。這個杯子(我們的物體)從原始位置移動到了一個新位置。

在WebGL中,我們使用數學來實現這種移動。別擔心如果你不是數學天才——WebGL為我們承擔了大部分重活!

平移的重要性

想象一下,在一個角色無法移動的電子遊戲中,或者在物體被固定在原位的3D建模軟件中。這會很無聊,不是嗎?平移讓我們能夠創建有動態、互動的圖形,它們能夠對用戶輸入做出反應或遵循預定的動畫。

如何平移一個三角形

現在我們了解了平移是什麼,讓我們分解在WebGL中移動一個簡單三角形的过程。我們會一步一步地進行,這樣你可以輕鬆地跟進。

步驟1:定義你的三角形

首先,我們需要創建我們的三角形。在WebGL中,我們使用頂點(角落點)來定義形狀。以下是如何定義一個簡單三角形的方法:

const vertices = [
0.0, 0.5,   // 頂部頂點
-0.5, -0.5,  // 底部左邊頂點
0.5, -0.5   // 底部右邊頂點
];

這創建了一個頂點在(0, 0.5)且底部角落分别在(-0.5, -0.5)和(0.5, -0.5)的三角形。

步驟2:創建平移矩陣

要移動我們的三角形,我們需要創建一個平移矩陣。這個矩陣告訴WebGL我們要在每個軸上移動多少。以下是如何創建一個平移矩陣的方法:

const translationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1
];

其中txty是我們要在x和y軸上移動的量。

步驟3:在頂點著色器中應用平移

現在來到令人興奮的部分!我們需要修改我們的頂點著色器以應用平移。以下是一個包含平移的簡單頂點著色器:

attribute vec2 a_position;
uniform mat4 u_translation;

void main() {
gl_Position = u_translation * vec4(a_position, 0, 1);
}

這個著色器將每個頂點位置轉換為4D向量(矩陣乘法所需的),然後將它與我們的平移矩陣相乘。

步驟4:更新平移值

要讓我們的三角形移動,我們需要隨著時間更新平移值。我們可以在JavaScript代碼中做到這一點:

function updateAndDraw() {
tx += 0.01;  // 向右移動
ty += 0.005; // 向上移動

// 更新平移矩陣
gl.uniformMatrix4fv(translationLocation, false, translationMatrix);

// 繪製三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);

requestAnimationFrame(updateAndDraw);
}

這個函數更新我們的平移值,將新的矩陣發送到GPU,然後重繪我們的三角形。requestAnimationFrame調用確保這個過程平滑地逐幀發生。

示例 - 平移一個三角形

讓我們把所有東西放在一起,創造一個完整的示例。這段代碼將創建一個在螢幕上對角線移動的三角形:

// 頂點著色器
const vertexShaderSource = `
attribute vec2 a_position;
uniform mat4 u_translation;

void main() {
gl_Position = u_translation * vec4(a_position, 0, 1);
}
`;

// 片元著色器
const fragmentShaderSource = `
precision mediump float;

void main() {
gl_FragColor = vec4(1, 0, 0, 1);  // 紅色
}
`;

// 初始化WebGL
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl');

// 創建並編譯著色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// 創建程序
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// 創建緩存並加載頂點數據
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// 設置屬性
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// 設置一致變量
const translationLocation = gl.getUniformLocation(program, "u_translation");

// 平移變量
let tx = 0;
let ty = 0;

function updateAndDraw() {
// 清除畫布
gl.clear(gl.COLOR_BUFFER_BIT);

// 更新平移
tx += 0.01;
ty += 0.005;

// 創建平移矩陣
const translationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1
];

// 將矩陣發送到著色器
gl.uniformMatrix4fv(translationLocation, false, translationMatrix);

// 繪製
gl.drawArrays(gl.TRIANGLES, 0, 3);

// 請求下一幀
requestAnimationFrame(updateAndDraw);
}

// 開始動畫
updateAndDraw();

這段代碼創建了一個紅色三角形,它在螢幕上對角線移動。讓我們分解一下發生了什麼:

  1. 我們定義了我們的著色器,其中包括平移矩陣。
  2. 我們設置WebGL,創建我們的程序,並加載我們的三角形頂點。
  3. 我們創建了用於平移的變量txty
  4. 在我們的updateAndDraw函數中,我們:
  • 清除畫布
  • 更新我們的平移值
  • 創建一個新的平移矩陣
  • 將這個矩陣發送到GPU
  • 繪製我們的三角形
  • 請求下一幀動畫

這樣,你就創造了一個在螢幕上移動的三角形。讓我們祝賀你!每個旅程都從一個單一的步驟開始——或者在我們的例子中,是一個移動的三角形。繼續練習,繼續嘗試,不久之後,你將能夠創造出以前認為不可能的移動和互動的3D圖形。

祝編程愉快,願你的三角形總是能找到回家的路!

Credits: Image by storyset