一、整体架构:从3D数据到屏幕的"旅程"

WebGL 的渲染管线(Render Pipeline)是将 3D 场景中的几何数据和像素信息转换为 2D 屏幕图像的一系列有序处理阶段。基于 OpenGL ES 2.0/3.0 标准,采用流水线架构,各阶段依次处理数据,部分阶段可以通过着色器(Shader)自定义逻辑。

数据流向:CPU 准备数据 → 顶点着色器变换 → 图元装配与裁剪 → 光栅化生成像素 → 片元着色器计算颜色 → 帧缓冲处理显示。

1. 顶点数据输入(CPU)

  • 作用:将应用程序定义的顶点数据(如位置、颜色、法线、纹理坐标等)传递给 GPU。

  • 数据来源:顶点数据通常存储在缓冲区对象(Buffer Object)中(通过 gl.createBuffer创建),并通过 gl.vertexAttribPointer绑定到顶点属性(Vertex Attributes)。

  • 关键操作

    • 应用程序通过 JavaScript 定义顶点数组(如 Float32Array),并将其上传到 GPU 内存。

    • 每个顶点属性(如位置 aPosition、颜色 aColor)对应缓冲区中的一段数据,通过步长(Stride)偏移(Offset)描述其布局。

2. 顶点着色器

  • 作用:对每个顶点进行独立计算,完成坐标变换、颜色计算等自定义逻辑。

  • 核心功能

    • 坐标变换:将顶点从模型空间(Model Space)转换到裁剪空间(Clip Space),通过模型-视图-投影矩阵(MVP Matrix)实现。公式:gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPosition, 1.0);

    • 自定义计算:可计算顶点颜色、法线、纹理坐标,或传递数据到片元着色器(如通过 varying变量)。

  • 特性

    • 顶点着色器是 WebGL 渲染管线中必须的阶段

    • 每个顶点独立处理,适合并行计算(GPU 擅长)。

3. 图元装配

  • 作用:将顶点数据组合成图元(Primitive)(如点、线、三角形),并准备进行光栅化。

  • 关键操作

    • 根据绘制命令(如 gl.drawArrays(gl.TRIANGLES, ...))确定图元类型。

    • 执行裁剪(Clipping):将超出视锥体(View Frustum)的图元部分切除,仅保留可见区域。

    • 执行透视除法(Perspective Division):将裁剪空间坐标转换为标准化设备坐标(NDC,范围 [-1, 1]),得到屏幕空间坐标。

4. 光栅化

  • 作用:将图元(如三角形)转换为片元(Fragment)(即屏幕上的像素候选点),并计算每个片元的属性(如颜色、深度)。

  • 关键操作

    • 确定覆盖区域:计算图元在屏幕上的覆盖范围,生成对应的片元

    • 属性插值:根据顶点属性(如颜色、纹理坐标)在三角形内的位置,通过重心坐标插值计算每个片元的属性值(如 varying变量)。

    • 深度计算:计算每个片元的深度值(Z 值),用于后续深度测试。

5. 片元着色器

  • 作用:对每个片元进行计算,确定其最终颜色(或丢弃该片元)。

  • 核心功能

    • 颜色计算:基于插值的属性(如纹理坐标)采样纹理(texture2D),或结合光照模型(如 Phong)计算颜色。

    • 丢弃片元:通过 discard语句跳过某些片元(如透明物体的不可见部分)。

  • 特性

    • 片元着色器也是 WebGL 渲染管线中必须的阶段

    • 每个片元独立处理,但需注意相邻片元的计算可能影响性能(避免分支和复杂循环)。

6. 片元测试与写入

  • 作用:对片元进行一系列测试,决定是否将其写入帧缓冲(Frame Buffer)。

  • 常见测试

    • 深度测试(Depth Test):比较当前片元的深度值与深度缓冲区中对应位置的值,仅当当前片元更近(深度值更小)时保留(需启用 gl.enable(gl.DEPTH_TEST))。

    • 模板测试(Stencil Test):根据模板缓冲区的掩码和比较规则决定是否保留片元(需启用 gl.enable(gl.STENCIL_TEST))。

    • 混合(Blending):若启用(gl.enable(gl.BLEND)),将当前片元颜色与颜色缓冲区中的原有颜色按混合因子(如 gl.blendFunc)混合(用于透明效果)。

7. 帧缓冲写入(Frame Buffer Write)

  • 作用:将通过所有测试的片元颜色、深度、模板等信息写入帧缓冲。

  • 帧缓冲类型

    • 默认帧缓冲:对应屏幕的显示缓冲区(由浏览器创建)。

    • 离屏帧缓冲(FBO, Frame Buffer Object):开发者创建的离屏缓冲区,用于离屏渲染(如纹理生成、后期处理)。

核心阶段作用:

  • 顶点着色器:处理坐标变换和顶点属性传递;

  • 片元着色器:处理像素级颜色计算;

  • 光栅化:连接几何图形与像素的桥梁;

  • 深度测试 / 混合:解决遮挡和透明效果。