• 主页

  • 投资

  • IT

    🔥
  • 设计

  • 销售

  • 共240篇

    前端 - HTML5

关闭

返回栏目

关闭

返回前端 - HTML5栏目

115 - 画布元素 - 3D 绘图 - 创建简单 3D 场景

作者:

贺及楼

成为作者

更新日期:2025-02-27 12:26:11

画布元素 - 3D 绘图 - 创建简单 3D 场景

一、引言

在前端开发中,HTML5 的画布(<canvas>)元素为我们提供了强大的绘图能力,不仅可以进行 2D 绘图,借助 WebGL(Web Graphics Library)还能实现 3D 绘图。WebGL 是一种基于 OpenGL ES 2.0 的 JavaScript API,它允许在网页上直接渲染高性能的 3D 图形。本文将带领大家创建一个简单的 3D 场景,通过逐步介绍和示例代码,帮助大家掌握基本的 3D 绘图技巧。

二、基本原理

在进行 3D 绘图时,我们需要了解几个重要的概念:

  • 顶点数据:3D 模型由多个顶点组成,每个顶点包含三维空间中的坐标信息。
  • 着色器:分为顶点着色器和片段着色器。顶点着色器负责处理顶点的位置和变换,片段着色器负责计算每个像素的颜色。
  • 缓冲区:用于存储顶点数据,以便在 GPU 中高效处理。
  • 变换矩阵:用于对 3D 模型进行平移、旋转和缩放等变换。

三、创建简单 3D 场景的步骤

1. 创建 HTML 结构

首先,我们需要在 HTML 文件中创建一个画布元素。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Simple 3D Scene</title>
  7. </head>
  8. <body>
  9. <canvas id="glCanvas" width="640" height="480"></canvas>
  10. <script src="script.js"></script>
  11. </body>
  12. </html>

2. 获取 WebGL 上下文

在 JavaScript 文件(script.js)中,我们需要获取画布的 WebGL 上下文。

  1. // 获取画布元素
  2. const canvas = document.getElementById('glCanvas');
  3. // 获取 WebGL 上下文
  4. const gl = canvas.getContext('webgl');
  5. if (!gl) {
  6. alert('无法初始化 WebGL,你的浏览器可能不支持。');
  7. return;
  8. }

3. 定义顶点数据

我们以一个简单的立方体为例,定义其顶点数据。

  1. // 立方体的顶点数据
  2. const positions = [
  3. // 前面
  4. -1.0, -1.0, 1.0,
  5. 1.0, -1.0, 1.0,
  6. 1.0, 1.0, 1.0,
  7. -1.0, 1.0, 1.0,
  8. // 后面
  9. -1.0, -1.0, -1.0,
  10. -1.0, 1.0, -1.0,
  11. 1.0, 1.0, -1.0,
  12. 1.0, -1.0, -1.0,
  13. // 顶面
  14. -1.0, 1.0, -1.0,
  15. -1.0, 1.0, 1.0,
  16. 1.0, 1.0, 1.0,
  17. 1.0, 1.0, -1.0,
  18. // 底面
  19. -1.0, -1.0, -1.0,
  20. 1.0, -1.0, -1.0,
  21. 1.0, -1.0, 1.0,
  22. -1.0, -1.0, 1.0,
  23. // 右面
  24. 1.0, -1.0, -1.0,
  25. 1.0, 1.0, -1.0,
  26. 1.0, 1.0, 1.0,
  27. 1.0, -1.0, 1.0,
  28. // 左面
  29. -1.0, -1.0, -1.0,
  30. -1.0, -1.0, 1.0,
  31. -1.0, 1.0, 1.0,
  32. -1.0, 1.0, -1.0
  33. ];

4. 创建和编译着色器

我们需要创建顶点着色器和片段着色器,并将它们编译和链接成一个着色器程序。

  1. // 顶点着色器代码
  2. const vertexShaderSource = `
  3. attribute vec3 a_position;
  4. void main() {
  5. gl_Position = vec4(a_position, 1.0);
  6. }
  7. `;
  8. // 片段着色器代码
  9. const fragmentShaderSource = `
  10. precision mediump float;
  11. void main() {
  12. gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  13. }
  14. `;
  15. // 创建着色器函数
  16. function createShader(gl, type, source) {
  17. const shader = gl.createShader(type);
  18. gl.shaderSource(shader, source);
  19. gl.compileShader(shader);
  20. const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  21. if (success) {
  22. return shader;
  23. }
  24. console.log(gl.getShaderInfoLog(shader));
  25. gl.deleteShader(shader);
  26. }
  27. // 创建着色器程序函数
  28. function createProgram(gl, vertexShader, fragmentShader) {
  29. const program = gl.createProgram();
  30. gl.attachShader(program, vertexShader);
  31. gl.attachShader(program, fragmentShader);
  32. gl.linkProgram(program);
  33. const success = gl.getProgramParameter(program, gl.LINK_STATUS);
  34. if (success) {
  35. return program;
  36. }
  37. console.log(gl.getProgramInfoLog(program));
  38. gl.deleteProgram(program);
  39. }
  40. // 创建并编译顶点着色器
  41. const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
  42. // 创建并编译片段着色器
  43. const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
  44. // 创建着色器程序
  45. const program = createProgram(gl, vertexShader, fragmentShader);

5. 创建和绑定缓冲区

将顶点数据存储到缓冲区中,并绑定到着色器的属性上。

  1. // 创建缓冲区
  2. const positionBuffer = gl.createBuffer();
  3. // 绑定缓冲区
  4. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  5. // 将顶点数据写入缓冲区
  6. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
  7. // 获取顶点着色器中属性的位置
  8. const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
  9. // 启用属性
  10. gl.enableVertexAttribArray(positionAttributeLocation);
  11. // 指定属性的数据格式
  12. gl.vertexAttribPointer(
  13. positionAttributeLocation,
  14. 3, // 每个顶点包含 3 个坐标
  15. gl.FLOAT, // 数据类型为浮点数
  16. false,
  17. 0,
  18. 0
  19. );

6. 绘制场景

最后,我们可以使用着色器程序绘制立方体。

  1. // 使用着色器程序
  2. gl.useProgram(program);
  3. // 设置清除颜色
  4. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  5. // 清除颜色缓冲区
  6. gl.clear(gl.COLOR_BUFFER_BIT);
  7. // 绘制立方体
  8. gl.drawArrays(gl.TRIANGLE_FAN, 0, positions.length / 3);

四、总结

通过以上步骤,我们成功创建了一个简单的 3D 场景,绘制了一个红色的立方体。下面是一个简单的总结表格:
| 步骤 | 描述 |
| —— | —— |
| 1. 创建 HTML 结构 | 创建一个包含画布元素的 HTML 文件 |
| 2. 获取 WebGL 上下文 | 获取画布的 WebGL 上下文 |
| 3. 定义顶点数据 | 定义 3D 模型的顶点坐标 |
| 4. 创建和编译着色器 | 创建顶点着色器和片段着色器,并编译链接成着色器程序 |
| 5. 创建和绑定缓冲区 | 将顶点数据存储到缓冲区中,并绑定到着色器的属性上 |
| 6. 绘制场景 | 使用着色器程序绘制 3D 模型 |

当然,这只是一个简单的示例,实际的 3D 场景可能会更加复杂,需要考虑光照、材质、纹理等因素。希望本文能为你打开 3D 绘图的大门,让你在前端开发中创造出更加炫酷的效果。