返回

走进 WebGL:描绘立体的正方体世界,踏入 3D 图形领域

前端

在计算机图形学的殿堂中,WebGL 闪耀着夺目的光彩,它赋予了浏览器呈现 3D 图形的能力,将虚拟世界栩栩如生地呈现在您的眼前。而正方体,作为三维空间中最基本、最具代表性的几何图形之一,是 WebGL 学习的理想起点。

在这个激动人心的篇章中,我们将携手踏上 WebGL 之旅,从搭建 WebGL 画布开始,一步步构建正方体的顶点数据和索引数据,并运用 WebGL 着色器为其赋予色彩。最终,您将掌握渲染正方体的奥秘,为进一步探索 3D 图形世界奠定坚实的基础。

WebGL 的舞台:画布的搭建

首先,我们需要搭建 WebGL 的舞台——画布。这块画布如同艺术家的调色板,等待着我们挥洒创意。通过创建一个 元素,并获取其 WebGL 上下文,我们便搭建起了 WebGL 的运行环境。

<canvas id="webgl-canvas"></canvas>
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');

正方体的轮廓:顶点数据的构建

接下来,我们需要为正方体勾勒出轮廓,这需要用到顶点数据。顶点数据包含了正方体每个顶点的坐标信息,这些坐标点共同定义了正方体的形状。我们将使用一个 Float32Array 来存储这些顶点数据。

const vertices = new Float32Array([
  // 前面
  -1.0, -1.0,  1.0,
  1.0, -1.0,  1.0,
  1.0,  1.0,  1.0,
  -1.0,  1.0,  1.0,

  // 后面
  -1.0, -1.0, -1.0,
  -1.0,  1.0, -1.0,
  1.0,  1.0, -1.0,
  1.0, -1.0, -1.0,

  // 顶部
  -1.0,  1.0, -1.0,
  -1.0,  1.0,  1.0,
  1.0,  1.0,  1.0,
  1.0,  1.0, -1.0,

  // 底部
  -1.0, -1.0, -1.0,
  1.0, -1.0, -1.0,
  1.0, -1.0,  1.0,
  -1.0, -1.0,  1.0,

  // 左侧
  -1.0, -1.0, -1.0,
  -1.0, -1.0,  1.0,
  -1.0,  1.0,  1.0,
  -1.0,  1.0, -1.0,

  // 右侧
  1.0, -1.0, -1.0,
  1.0,  1.0, -1.0,
  1.0,  1.0,  1.0,
  1.0, -1.0,  1.0
]);

正方体的结构:索引数据的构建

有了顶点数据,我们还需要构建索引数据。索引数据定义了顶点之间的连接方式,告诉 WebGL 如何将顶点组合成三角形,从而形成正方体的各个面。

const indices = new Uint16Array([
  0,  1,  2,      0,  2,  3,    // 前面
  4,  5,  6,      4,  6,  7,    // 后面
  8,  9,  10,     8,  10, 11,   // 顶部
  12, 13, 14,     12, 14, 15,   // 底部
  16, 17, 18,     16, 18, 19,   // 左侧
  20, 21, 22,     20, 22, 23    // 右侧
]);

着色器的艺术:赋予正方体色彩

为了让正方体焕发生机,我们需要借助着色器。着色器是一种程序,用于处理顶点数据和片段数据,并最终生成像素颜色。我们将在顶点着色器中定义顶点位置的变换,并在片段着色器中定义像素的颜色。

顶点着色器

attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

片段着色器

precision mediump float;
uniform vec3 color;

void main() {
  gl_FragColor = vec4(color, 1.0);
}

绘制正方体:将数据写入缓冲区

现在,我们需要将顶点数据和索引数据写入缓冲区。缓冲区是显卡中的内存区域,用于存储数据。我们将使用两个缓冲区:顶点缓冲区和索引缓冲区。

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

着色器的舞台:编译和链接

接下来,我们需要将着色器编译并链接到一个着色器程序中。着色器程序是包含顶点着色器和片段着色器的程序,用于处理图形数据。

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);

渲染正方体:连接数据和着色器

现在,我们需要将顶点数据、索引数据和着色器程序连接起来,以便 WebGL 可以使用它们来渲染正方体。

gl.useProgram(program);

const positionLocation = gl.getAttribLocation(program, 'position');
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

const colorLocation = gl.getUniformLocation(program, 'color');
gl.uniform3f(colorLocation, 1.0, 0.0, 0.0);

gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

旋转正方体:增添动态效果

为了让正方体更加生动,我们可以通过旋转矩阵来控制正方体的旋转。

const modelViewMatrix = mat4.create();
mat4.rotate(modelViewMatrix, modelViewMatrix, rotationAngle, [0, 1, 0]);
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'modelViewMatrix'), false, modelViewMatrix);

结语

至此,我们已经完成了 WebGL 正方体渲染之旅。通过一步步的讲解,您已经掌握了 WebGL 的基本知识,包括画布搭建、顶点数据构建、索引数据构建、着色器编写、数据写入缓冲区、着色器编译和链接、连接数据和着色器、以及旋转正方体。相信您已经对 WebGL 有了初步的了解,可以继续探索 WebGL 的更多奥秘,创作出更加精彩的 3D 图形作品。