WebGL - 旋转:让您的图形生动起来

你好,有抱负的WebGL开发者们!今天,我们将深入计算机图形学中最令人兴奋的方面之一:旋转。作为你友好的计算机科学老师,我将引导你进入旋转三角形和旋转形状的神奇世界。所以,戴上你想象中的3D眼镜,让我们开始吧!

WebGL - Rotation

理解 WebGL 中的旋转

在我们跳入代码之前,让我们花点时间理解一下在WebGL上下文中旋转意味着什么。想象你手里拿着一张纸飞机。当你旋转它时,你在改变它在空间中的方向。在WebGL中,我们做同样的事情,但具有数学上的精确性!

WebGL中的旋转涉及围绕中心轴改变顶点(构成我们形状的点)的位置。这可以是X轴、Y轴或Z轴,甚至是它们的组合。

矩阵的魔法

我知道你现在在想什么:“矩阵?这不是《黑客帝国》电影里的东西吗?” 嗯,不完全是这样,但它们同样酷炫!在WebGL中,我们使用矩阵来高效地执行旋转。别担心这听起来很复杂——我们会一步一步地解释。

示例 - 旋转一个三角形

让我们从一个简单的示例开始:旋转一个三角形。我们将从一个基本的三角形开始,然后让它像一个几何芭蕾舞者一样旋转!

步骤 1:设置我们的 WebGL 环境

首先,我们需要设置我们的WebGL上下文。下面是一个基本的HTML结构:

<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
// 我们的 WebGL 代码将放在这里
</script>

步骤 2:初始化 WebGL

现在,让我们初始化WebGL:

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('WebGL 不支持');
return;
}

这段代码获取我们的画布元素并尝试获取WebGL上下文。如果WebGL不支持,我们将看到一个错误消息。

步骤 3:创建我们的着色器

着色器是运行在GPU上的特殊程序。我们需要两种类型:顶点着色器和片段着色器。这里有一组简单的着色器:

const vertexShaderSource = `
attribute vec2 a_position;
uniform mat3 u_matrix;
void main() {
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}
`;

const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0, 1);
}
`;

顶点着色器应用我们的旋转矩阵,而片段着色器只是将我们的三角形染成红色。

步骤 4:编译和链接着色器

接下来,我们需要编译和链接我们的着色器:

function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

这段代码创建我们的着色器程序,我们将用它来渲染我们的旋转三角形。

步骤 5:创建我们的三角形

现在,让我们定义我们的三角形:

const positions = [
0, 0.5,
-0.5, -0.5,
0.5, -0.5
];

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

这创建了一个以原点为中心的简单三角形。

步骤 6:旋转魔法

这里才是真正的魔法所在。我们将创建一个函数来生成我们的旋转矩阵:

function createRotationMatrix(angleInRadians) {
const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);
return [
c, -s, 0,
s, c, 0,
0, 0, 1
];
}

这个函数接收一个以弧度表示的角度并返回一个3x3的旋转矩阵。

步骤 7:渲染我们的旋转三角形

最后,让我们把所有东西放在一起,让我们的三角形旋转:

let angleInRadians = 0;

function render() {
angleInRadians += 0.01;

gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(program);

const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

const matrixLocation = gl.getUniformLocation(program, "u_matrix");
const matrix = createRotationMatrix(angleInRadians);
gl.uniformMatrix3fv(matrixLocation, false, matrix);

gl.drawArrays(gl.TRIANGLES, 0, 3);

requestAnimationFrame(render);
}

render();

这个函数做了以下几件事:

  1. 增加我们的旋转角度
  2. 清除画布
  3. 设置我们的着色器程序和属性
  4. 创建并应用我们的旋转矩阵
  5. 绘制三角形
  6. 请求下一个动画帧

就这样!我们有一个旋转的三角形!

结论

恭喜你!你刚刚在WebGL中创建了你的第一个旋转形状。记住,这只是一个开始。有了这些基本原理,你可以创建包含多个旋转物体的复杂3D场景。

在我们结束之前,我想起了一个学生曾经说过:“我以为计算机图形学只是关于花哨的软件,但现在我发现它更像是在做一个数字木偶戏!”她说得对——有了WebGL,你就是自己数字木偶剧的操控者。

继续练习,继续实验,最重要的是,继续在WebGL中享受乐趣。在你意识到之前,你将能够创造出令人惊叹的3D可视化,即使是经验最丰富的开发者也会说“哇!”

方法 描述
createShader(gl, type, source) 创建并编译一个着色器
createRotationMatrix(angleInRadians) 生成一个2D旋转矩阵
render() 渲染旋转的三角形
gl.clearColor(r, g, b, a) 设置用于清除画布的颜色
gl.clear(gl.COLOR_BUFFER_BIT) 清除画布
gl.useProgram(program) 设置当前着色器程序
gl.getAttribLocation(program, name) 获取属性的位置
gl.enableVertexAttribArray(location) 启用一个顶点属性数组
gl.bindBuffer(gl.ARRAY_BUFFER, buffer) 绑定一个缓冲区
gl.vertexAttribPointer(location, size, type, normalized, stride, offset) 指定顶点数据的布局
gl.getUniformLocation(program, name) 获取统一变量的位置
gl.uniformMatrix3fv(location, transpose, value) 设置矩阵统一值
gl.drawArrays(mode, first, count) 从数组数据渲染图元
requestAnimationFrame(callback) 请求下一个动画帧

快乐编码,愿你的三角形总是向正确的方向旋转!

Credits: Image by storyset