WebGL - 旋转:让您的图形生动起来
你好,有抱负的WebGL开发者们!今天,我们将深入计算机图形学中最令人兴奋的方面之一:旋转。作为你友好的计算机科学老师,我将引导你进入旋转三角形和旋转形状的神奇世界。所以,戴上你想象中的3D眼镜,让我们开始吧!
理解 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();
这个函数做了以下几件事:
- 增加我们的旋转角度
- 清除画布
- 设置我们的着色器程序和属性
- 创建并应用我们的旋转矩阵
- 绘制三角形
- 请求下一个动画帧
就这样!我们有一个旋转的三角形!
结论
恭喜你!你刚刚在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