着色器到底是什么?

预计阅读时间: 4 分钟

1. 着色器简介

学习资料

1.1 概念定义

定义

着色器是一个把输入转换为输出的程序,相互之间不能通信,只能通过输入和输出传递数据。

1.2 特点

  1. 盲视性:着色器程序之间相互不能直接通信
  2. 无状态性:一个线程不知道前一刻运行的任务状态
  3. 抽象性:着色器是对GPU编程的高级抽象

2. 着色器的要素

  1. 版本和模式:需要指定GLSL版本和模式(如核心模式 core
  2. 输入输出变量:定义数据的流入和流出
  3. main函数:着色器程序的入口点

3. 着色器的类型

以下是主要的可编程着色器类型:

3.1 顶点着色器

主要职责
  • 负责坐标位置和坐标系统的变换
  • 处理从模型局部坐标到裁剪空间的转换过程:
    1. 局部坐标 → 世界坐标
    2. 世界坐标 → 观察空间
    3. 观察空间 → 裁剪空间
    4. 裁剪和光栅化
    5. 输出到片段着色器
Three.js中的注意事项

Three.js 中,着色器与材质(Material)绑定。如果多个网格(Mesh)共用同一材质,它们会共享相同的 uniform 变量。

解决方案

  • 使用纹理(Texture)传递个性化数据
  • 参考 BatchedMesh 的实现:通过纹理存储不同模型的变换矩阵,每个模型通过 meshId 获取对应的矩阵

3.2 片元着色器

主要职责
  • 接收光栅化后的像素信息
  • 计算每个像素点的最终颜色
  • 实现光照、材质等视觉效果

3.3 几何着色器

主要职责
  • 修改几何图形的形状
  • 控制光栅化的具体方式

3.4 性能对比

性能考虑
  • 顶点着色器的执行次数远少于片元着色器
  • 顶点着色器性能更优,但效果可能不如片元着色器
  • 片元着色器处理每个像素,可实现更精细的视觉效果

4. GLSL着色器语言

GLSL基础语法
1// 变量声明
2in type in_variable_name;      // 输入变量
3out type out_variable_name;    // 输出变量
4uniform type uniform_name;     // 全局变量

4.1 变量类型

  1. in - 输入变量
  2. out - 输出变量(传递给下一个着色器阶段)
  3. uniform - 全局变量
    • 所有着色器阶段可访问
    • 着色器中只读
    • 可在CPU端更新

4.2 向量类型

常用向量类型
  • vecn: n个浮点数分量的向量
  • bvecn: n个布尔值分量的向量
  • ivecn: n个整数分量的向量
  • uvecn: n个无符号整数分量的向量
  • dvecn: n个双精度浮点数分量的向量

4.3 向量操作示例

1// 向量重组(Swizzling)
2vec2 someVec;
3vec4 differentVec = someVec.xyxx;
4vec3 anotherVec = differentVec.zyw;
5vec4 otherVec = someVec.xxxx + anotherVec.yxzy;
6
7// 向量构造
8vec2 vect = vec2(0.5, 0.7);
9vec4 result = vec4(vect, 0.0, 0.0);
10vec4 otherResult = vec4(result.xyz, 1.0);