WebGL - 基础知识
WebGL - 基础入门
Section titled “WebGL - 基础入门”WebGL (Web Graphics Library) 是一种 JavaScript API,用于在任何兼容的 Web 浏览器中无需插件即可渲染交互式 2D 和 3D 图形。它本质上是一个低级 API,基于 OpenGL ES 标准,为在浏览器中直接进行图形渲染提供 GPU 加速。
要使用 WebGL 绘制任何东西,你需要提供数据(例如顶点位置和颜色)和程序(着色器),这些程序告诉 GPU 如何处理这些数据并将其转换为屏幕上的像素。本章将介绍这些基本概念。
WebGL – 坐标系 (归一化设备坐标)
Section titled “WebGL – 坐标系 (归一化设备坐标)”WebGL 在 3D 坐标系中操作。顶点数据经过顶点着色器处理后,WebGL 要求坐标位于一个特定范围内,称为“裁剪空间(Clip Space)”。超出此空间的坐标将被“裁剪”(不会被绘制)。裁剪空间坐标随后被转换为归一化设备坐标(Normalized Device Coordinates,NDC),NDC 在所有三个轴(X、Y、Z)上的范围都是 -1 到 +1。
将可见区域想象为一个中心位于 (0,0,0) 的立方体:
- X 轴:-1 是左边缘,+1 是右边缘。
- Y 轴:-1 是底边缘,+1 是顶边缘。
- Z 轴:-1 是最远可见点,+1 是最近可见点。(注意:这个 Z 方向最初可能看起来与直觉相反,但这与投影矩阵通常的设置方式有关)。
任何超出 NDC 中这个 [-1, +1] 立方体的部分都不会被渲染。你的着色器程序负责将模型的坐标转换到这个裁剪空间,然后它会变成 NDC,最后再映射到屏幕像素(窗口坐标)。
WebGL 基础概念
Section titled “WebGL 基础概念”从 HTML canvas 元素获取 WebGL 渲染上下文后,就可以通过 JavaScript 开始使用 WebGL API。
以下是一些关键术语:
顶点 (Vertices)
Section titled “顶点 (Vertices)”顶点是 2D 或 3D 空间中的一个点,通常由其位置坐标(X、Y 以及可选的 Z)定义。顶点是几何形状(如三角形、线或点)的基本构建块。除了位置,顶点还可以拥有其他相关数据,如颜色、纹理坐标或法线(指示曲面方向的向量,用于光照)。
示例:定义三角形顶点
Section titled “示例:定义三角形顶点”要在 2D 空间(Z 隐式为 0)中定义一个角点位于 (0.0, 0.5)、(-0.5, -0.5) 和 (0.5, -0.5) 的三角形,你可以将这些坐标存储起来,通常存储在 JavaScript 数组或 TypedArray 中:
// Using a standard JavaScript Array (often converted to TypedArray later)const triangleVertices = [ 0.0, 0.5, // Top vertex -0.5, -0.5, // Bottom-left vertex 0.5, -0.5 // Bottom-right vertex];
// Using Float32Array (preferred for WebGL buffers)const triangleVerticesTyped = new Float32Array([ 0.0, 0.5, -0.5, -0.5, 0.5, -0.5]);这些数据需要使用 WebGL 缓冲区(Buffers)传输到 GPU。
索引 (Index Buffers)
Section titled “索引 (Index Buffers)”通常,多个形状会共享顶点。例如,一个正方形可以使用两个共享两个顶点的三角形来绘制。与其重复顶点数据,不如只列出每个唯一的顶点一次,然后使用索引指定绘制它们的顺序。索引仅仅是顶点列表中的一个数字引用(如 0、1、2…)。
示例:正方形的索引
Section titled “示例:正方形的索引”考虑一个顶点为:0=(-0.5, 0.5),1=(0.5, 0.5),2=(0.5, -0.5),3=(-0.5, -0.5) 的正方形。我们可以用两个三角形来绘制它:(0, 3, 1) 和 (1, 3, 2)。
const squareVertices = new Float32Array([ -0.5, 0.5, // Vertex 0 0.5, 0.5, // Vertex 1 0.5, -0.5, // Vertex 2 -0.5, -0.5 // Vertex 3]);
// Indices refer to the positions in squareVerticesconst squareIndices = new Uint16Array([ 0, 3, 1, // First triangle (Top-left, Bottom-left, Top-right) 1, 3, 2 // Second triangle (Top-right, Bottom-left, Bottom-right)]);使用索引可以减少内存使用,并可以提高渲染性能。索引数据存储在 GPU 上特定的索引缓冲区(Index Buffers)中。
类型化数组 (Typed Arrays)
Section titled “类型化数组 (Typed Arrays)”WebGL 要求数值数据(如顶点坐标或索引)采用二进制格式,以便高效地传输到 GPU。JavaScript 类型化数组(Float32Array、Uint16Array 等)提供了这种机制,它们代表原始二进制数据缓冲区。
缓冲区 (Buffers) (VBOs, IBOs)
Section titled “缓冲区 (Buffers) (VBOs, IBOs)”缓冲区是分配在 GPU 上的内存块,用于存储渲染数据。关键类型包括:
- 顶点缓冲区对象 (Vertex Buffer Objects, VBOs):存储顶点属性数据(位置、颜色、纹理坐标、法线)。通常绑定到
gl.ARRAY_BUFFER。 - 索引缓冲区对象 (Index Buffer Objects, IBOs):存储顶点索引。通常绑定到
gl.ELEMENT_ARRAY_BUFFER。 - 帧缓冲区 (Framebuffers):表示渲染的目标,例如屏幕(默认帧缓冲区)或离屏纹理(自定义帧缓冲区)。
你使用 WebGL API 调用来创建缓冲区,绑定它们,然后将你的类型化数组数据上传到其中。
顶点数组对象 (Vertex Array Objects, VAOs)
Section titled “顶点数组对象 (Vertex Array Objects, VAOs)”设置顶点属性(如位置、颜色)如何从 VBO 读取数据涉及多个 WebGL 调用(vertexAttribPointer、enableVertexAttribArray)。顶点数组对象(VAO)封装了所有这些配置状态。通过绑定一个 VAO,你可以用一个简单的调用恢复所有相关的属性设置。VAO 在 WebGL 2 中是强制要求的,并且在 WebGL 1 中(通过扩展或 WebGL 2 标准)为了性能强烈推荐使用。
网格 (Mesh)
Section titled “网格 (Mesh)”网格是顶点、边和面(通常是三角形)的集合,用于定义 3D 对象的形状。在 WebGL 中,通常通过在缓冲区中提供顶点数据和(可选的)索引数据,然后进行绘制调用来渲染网格。
WebGL 提供了两种主要的绘制调用:
gl.drawArrays(mode, first, count):使用当前绑定的 VBO 中的连续顶点绘制图元,从索引first开始,使用count个顶点。gl.drawElements(mode, count, type, offset):使用当前绑定的 IBO 中的索引绘制图元。count是要使用的索引数量,type是索引的数据类型(例如gl.UNSIGNED_SHORT),offset是 IBO 中的字节偏移量。
这两个函数中的 mode 参数指定要绘制的图元类型(例如 gl.TRIANGLES、gl.LINES、gl.POINTS)。复杂的 3D 模型通常由三角形网格构成。