可编程渲染管线(Scriptable Render Pipeline, SRP)

本文最后更新于:2023年3月23日 晚上

可编程渲染管线处理数据的流程可分为以下3大阶段

1. 应用阶段

这个阶段大概会由CPU处理4件事情。首先会对模型数据进行可见性判断。模型数据由顶点位置、法线方向、顶点颜色、纹理坐标等构成。然后会将模型数据加载到显存以提高读取速度。再为每个图元设置常数寄存器和渲染状态。最后为一个渲染图元列表调用DrawCall指令。

图元可以是点、线、三角形。

2. 几何阶段

这个阶段由GPU进行处理,会对每一个需要渲染的图元进行逐顶点、逐多边形处理,最根本的任务是将顶点的模型坐标转换到屏幕空间。

2.1 顶点着色器

顶点着色器的基本任务是将顶点转换到齐次裁剪空间,还可以进行的其他任务有:

  • 逐顶点着色操作,如逐顶点光照
  • 纹理计算
  • 逐顶点蒙皮
  • 逐顶点程序式动画(procedural animation)

2.1.1 投影变换

\[Aspect=\frac{近裁剪平面宽度}{近裁剪平面高度}=\frac{远裁剪平面宽度}{远裁剪平面高度}\]

透视投影

在摄像机使用透视投影的时候,为了呈现出近大远小的透视收缩(perspective foreshortening)效果,需要对顶点进行透视投影变换。使用透视投影矩阵进行变换后,并没有进行裁剪,只是使得w值有了意义,为后面的裁剪做准备。

\(透视投影近裁剪平面高度=2 \cdot Near \cdot tan\frac{FOV}{2}\)

\(透视投影远裁剪平面高度=2 \cdot Far \cdot tan\frac{FOV}{2}\)

Unity透视投影矩阵(右乘)

\[ \begin{vmatrix} \frac{cot\frac{FOV}{2}}{Aspect} & 0 & 0 & 0 \\ 0 & cot\frac{FOV}{2} & 0 & 0 \\ 0 & 0 & -\frac{Far+Near}{Far-Near} & -\frac{2 \cdot Near \cdot Far}{Far-Near} \\ 0 & 0 & -1 & 0 \end{vmatrix} \]

会改变空间手系,从右手系变成了左手系,因为Unity的观察空间是右手系,NDC空间是左手系

观察空间中的顶点(x,y,z)透视投影到齐次裁剪空间后变为

\[(x \cdot \frac{cot\frac{FOV}{2}}{Aspect}, y \cdot cot\frac{FOV}{2}, -z \cdot \frac{Far+Near}{Far-Near}-\frac{2 \cdot Near \cdot Far}{Far-Near}, -z)\]

透视投影齐次裁剪空间中坐标的w值为 \(-Z_{posInViewSpace}\)

变换情况

正交投影

\[正交投影远(近)裁剪平面高度=2 \cdot Size\]

Unity正交投影矩阵(右乘)

\[ \begin{vmatrix} \frac{1}{Aspect \cdot Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far-Near} & -\frac{Far+Near}{Far-Near} \\ 0 & 0 & 0 & 1 \\ \end{vmatrix} \]

会改变空间手系,从右手系变成了左手系,因为Unity的观察空间是右手系,NDC空间是左手系

观察空间种的顶点(x,y,z)正交投影到齐次裁剪空间后变为 \((\frac{x}{Aspect \cdot Size}, \frac{y}{Size}, -\frac{2z}{Far-Near}-\frac{Far+Near}{Far-Near}, 1)\)

正交投影齐次裁剪空间中坐标的w值为1

2.2 曲面细分着色器

用于细分图元

2.3 几何着色器

  • 几何着色器的功能是修改、剔除、创建图元,可以实现以下效果:
    • 阴影体积拉伸(shadow volume extrusion)
    • 渲染立方体贴图(cube map)的6个面
    • 在网格的轮廓边拉伸毛发的鳍(fur in)
    • 从点数据生成例子四边形
    • 动态镶嵌
    • 把线段分形细分(fractal subdivision)以模拟闪电、布料
    • 将数据传到管线开头重新进入管线
      • 用例:在顶点着色器内对头发样条的控制点进行物理模拟,在几何着色器内把样条镶嵌成线段,通过流输出将线段传到管线开头重新进入管线进行渲染

2.4 裁剪

裁剪的作用是将每个三角形在平截头体以外的部分切掉,把在平截头体以外的三角形剔除。

满足以下条件的顶点才会被保留下来:

\[-w<=x<=w\] \[-w<=y<=w\] \[-w<=z<=w\]

2.5 齐次除法

所谓的齐次除法就是让x、y、z都除以w,这时就可以得到NDC空间中的坐标

透视投影的齐次除法
正交投影的齐次除法

上图右边都是OpenGL的NDC,DirectX的NDC也和上图右边类似,但z范围在[0,1]

2.6屏幕映射

视口空间:程序运行窗口构成的空间

屏幕空间:整个显示屏幕构成的空间
Unity中将NDC坐标转换为屏幕坐标的右乘矩阵

矩阵中的X、Y是视口空间原点的屏幕坐标

3. 光栅化阶段

这个阶段由GPU来决定绘制哪些片元以及这些片元的颜色

片元=片段:三角形被栅格化后,其中的每一个小方块都是一个片元,可以看成是还不确定最终是否可以呈现到屏幕上的像素

3.1 三角形设置

这个阶段的任务是找出三角形边界所覆盖的像素

3.2 三角形遍历

这个阶段会对每个三角形进行栅格化,即找出每个三角形覆盖的像素区域。区域中的片元中信息(屏幕坐标、深度值、法线坐标、纹理坐标)由3个顶点数据进行插值(必要时会采用透视校正插值)得到

3.3 提前深度测试

如果用户没有在片元着色器中改变深度或自我丢弃(discard),显卡会自动开启该功能

3.4 片元着色器

用于执行逐像素着色操作,如纹理采样、多重纹理采样、逐像素光照

3.5 逐片元操作

3.5.1 模板测试

1
2
3
4
5
6
7
if 开启了模板测试 then
比较参考值(使用读取掩码)和模板缓冲区中的模板值(使用读取掩码)
if not 通过模板测试 then
舍弃该片元
end
根据已设置的渲染状态更新模板缓冲区中的值(使用写入掩码)
end
3.5.2 深度测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if 开启了深度测试 then
比较该片元的深度值和深度缓冲区中的深度值
if 通过了深度测试 then
if 开启了深度写入 then
将深度值写入深度缓冲区
end
else
舍弃该片元
end
else
if 开启了深度写入 then
将深度值写入深度缓冲区
end
end
3.5.3 混合
1
2
3
4
5
6
if 开启了混合 then
用alpha混合函数(alpha blending function)将该片元的颜色值和颜色缓冲区中的颜色值进行混合
else
直接使用该片元的颜色值
end
更新颜色缓冲区中的颜色值


可编程渲染管线(Scriptable Render Pipeline, SRP)
https://roudersky.com/posts/e35daff.html
作者
Rouder
发布于
2021年12月25日
许可协议