当前位置:  首页>> 技术小册>> 微信小程序全栈开发实战(上)

46 | WebGL介绍(十):绘制一个旋转的立方体

在WebGL的广阔世界里,从基础的图形绘制到复杂的三维场景构建,每一步都充满了探索的乐趣与挑战。本章节,我们将深入WebGL的核心,通过编写代码来绘制一个旋转的立方体,这不仅是WebGL三维图形渲染能力的一个直观展示,也是理解WebGL中顶点着色器、片元着色器以及矩阵变换等关键概念的重要实践。

一、WebGL基础回顾

在开始之前,让我们简要回顾一下WebGL的基础知识。WebGL是一种在网页浏览器中渲染3D图形的API,它基于OpenGL ES 2.0,允许开发者使用HTML5的<canvas>元素来创建和显示3D图形。WebGL通过GPU加速,能够在网页上实现高效的图形渲染,是构建复杂三维应用和游戏的重要技术基础。

WebGL的工作流程大致如下:

  1. 获取WebGL上下文:通过HTML的<canvas>元素,使用getContext('webgl')getContext('experimental-webgl')方法获取WebGL渲染上下文。
  2. 设置顶点和片元着色器:编写GLSL(OpenGL Shading Language)编写的着色器代码,分别处理顶点和像素的渲染逻辑。
  3. 初始化缓冲区:将顶点数据(如位置、颜色等)存储到WebGL的缓冲区中,供GPU使用。
  4. 绘制图形:调用WebGL的绘制命令(如drawArraysdrawElements),根据设置的着色器和缓冲区数据,在画布上绘制图形。

二、绘制立方体的准备

为了绘制一个立方体,我们需要定义其八个顶点的位置,并考虑如何通过这些顶点来构建六个面。在WebGL中,通常使用三角形来构建更复杂的图形,因为GPU对三角形的处理非常高效。一个立方体可以由12个三角形(每个面两个)组成,共需要24个顶点(但实际上,由于立方体结构的对称性,我们可以通过顶点索引复用,仅使用8个顶点加上适当的索引数组来绘制)。

2.1 顶点数据定义

首先,我们定义立方体的顶点位置。为了简化,假设立方体位于原点,边长为1,且每个面的法线方向分别指向或背离原点。

  1. const vertices = new Float32Array([
  2. // 顶点位置,X, Y, Z
  3. -0.5, -0.5, -0.5, // 0
  4. 0.5, -0.5, -0.5, // 1
  5. 0.5, 0.5, -0.5, // 2
  6. -0.5, 0.5, -0.5, // 3
  7. -0.5, -0.5, 0.5, // 4
  8. 0.5, -0.5, 0.5, // 5
  9. 0.5, 0.5, 0.5, // 6
  10. -0.5, 0.5, 0.5 // 7
  11. ]);
  12. // 索引数组,定义顶点的连接顺序以形成三角形
  13. const indices = new Uint16Array([
  14. // 每个数字代表vertices数组中的顶点索引
  15. // 前面
  16. 0, 1, 2,
  17. 0, 2, 3,
  18. // 后面
  19. 4, 5, 6,
  20. 4, 6, 7,
  21. // 顶部
  22. 3, 2, 6,
  23. 3, 6, 7,
  24. // 底部
  25. 0, 1, 5,
  26. 0, 5, 4,
  27. // 左面
  28. 1, 5, 6,
  29. 1, 6, 2,
  30. // 右面
  31. 4, 0, 3,
  32. 4, 3, 7
  33. ]);
2.2 着色器代码

接下来,我们需要编写顶点着色器和片元着色器。顶点着色器负责处理每个顶点的位置、颜色等数据,并可能执行变换(如平移、旋转、缩放)。片元着色器则负责为每个像素输出颜色。

  1. // 顶点着色器
  2. attribute vec3 a_position;
  3. uniform mat4 u_modelViewMatrix;
  4. uniform mat4 u_projectionMatrix;
  5. void main() {
  6. gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(a_position, 1.0);
  7. }
  8. // 片元着色器
  9. precision mediump float;
  10. uniform vec4 u_color;
  11. void main() {
  12. gl_FragColor = u_color;
  13. }

三、WebGL实现步骤

3.1 初始化WebGL环境
  1. const canvas = document.getElementById('webgl-canvas');
  2. const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  3. if (!gl) {
  4. alert('Unable to initialize WebGL. Your browser may not support it.');
  5. return;
  6. }
3.2 编译着色器与创建程序

加载并编译顶点着色器和片元着色器,链接它们到WebGL程序对象中。

3.3 设置顶点属性与缓冲区

创建缓冲区对象,将顶点数据(位置和索引)上传至GPU,并设置顶点属性指针。

3.4 矩阵变换与旋转

为了实现立方体的旋转,我们需要不断更新模型视图矩阵(Model-View Matrix),并通过WebGL的uniform变量传递给顶点着色器。这通常涉及到三维空间中的旋转矩阵计算,可以使用WebGL的矩阵库(如glMatrix.js)来辅助完成。

  1. // 假设有一个函数rotateCube(angle)用于计算旋转矩阵并更新uniform
  2. function rotateCube(angle) {
  3. // 计算旋转矩阵
  4. const modelViewMatrix = mat4.create();
  5. mat4.rotateY(modelViewMatrix, modelViewMatrix, angle);
  6. // 更新uniform
  7. gl.uniformMatrix4fv(u_modelViewMatrixLoc, false, modelViewMatrix);
  8. }
3.5 渲染循环

设置动画循环,不断调用rotateCube函数更新旋转角度,并重新绘制立方体。

  1. function animate() {
  2. requestAnimationFrame(animate);
  3. let angle = Date.now() * 0.001; // 旋转角度基于时间
  4. rotateCube(angle);
  5. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  6. gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
  7. }
  8. animate();

四、总结

通过本章节的学习,我们掌握了如何在WebGL中绘制一个旋转的立方体。这不仅仅是一个简单的图形渲染示例,更是对WebGL核心概念(如着色器编程、缓冲区管理、矩阵变换等)的一次深入实践。希望读者能够在此基础上,进一步探索WebGL的更多可能性,创作出更加丰富和复杂的三维图形与场景。


该分类下的相关小册推荐: