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如何在每个轴(x、y和z)上移动我们的对象。以下是如何创建一个平移矩阵的方法:

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. 我们创建了平移变量(tx和ty)。
  4. 在我们的updateAndDraw函数中,我们:
  • 清除画布
  • 更新我们的平移值
  • 创建一个新的平移矩阵
  • 将这个矩阵发送到GPU
  • 绘制我们的三角形
  • 请求下一帧动画

就这样!你已经用WebGL创建了一个移动的三角形。恭喜你!

结论

WebGL中的平移一开始可能看起来很复杂,但它实际上只是以智能的方式移动对象。在这里,我们已经介绍了基础知识,但你还可以用平移做很多事情——结合旋转和缩放,创建复杂的动画,甚至构建交互式的3D环境。

记住,每一个旅程都是从第一步开始的——或者在我们的例子中,是第一个三角形的移动。继续练习,继续尝试,不久之后,你将能够创造出以你从未想象过的方式移动和交互的惊人的3D图形。

快乐编码,愿你的三角形总能找到回家的路!

Credits: Image by storyset