菩萨开课,讲的贼好👍
思维导图:
- 应用阶段:模型、摄像机、光源等的位置、朝向等设置
- 几何阶段
曲面细分:通过现有顶点生成更多顶点
几何着色器:通过现有图元生成更多顶点或图元,比如生成法线 - 光栅化阶段
三角形设置:将顶点组装成三角形
三角形遍历:确定三角形包含了哪些2D空间的像素点 - 逐片元操作
混合:同一像素点对应不同片元时,进行颜色混合 - 后处理:图像处理,比如模糊、景深、高光
粗粒度剔除:剔除被挡住的物体
GPU内同类运算可并行
3.2 绘制顺序:场景从远到近?不透明到半透明?
3.3 渲染目标:渲染结果输出到RenderTexture(渲染贴图)? FrameBuffer(帧缓冲区)?
3.4 渲染模式:前向渲染?延迟渲染?
1.1 物体变换数据(transform数据)
2.4 BVH包围盒
1.2 合批方式:GPU instance、动态批处理
- 顶点着色(可编程)
- 可选步骤,对GPU有要求
1~3步完成定点空间到投影空间的转换
4.1 CVV视锥体裁剪
4.2 可在shader内通过代码配置其开关,比如顶点的法线背向视角即剔除
5.1 投影空间内顶点是连续的,从3D空间变换到2D屏幕空间后变为离散的像素点
模型变换+视图变换+投影变换=MVP矩阵
视口变换由Unity完成
顶点着色器的另一作用:顶点着色,比如计算顶点光照
图元可以是一个顶点,一个线段两个顶点,多个顶点构成的连续线段,三个顶点的三角形…
对于顶点在裁剪空间里的位置,采用透视除法,用xyz除以w,完成投影操作。从投影坐标系转换到标准设备坐标系NDC
正交投影的w=1;透视投影的w近小远大
设备坐标系在OpenGL和D3D中不同:
OpenGL中,xyz的维度从-1到1
D3D中xy维度为-1到1,z从0到1
标准设备坐标系中,xy∈(-1,1);在屏幕坐标系中的范围是输出设备的长和宽
屏幕坐标系的原点:
OpenGL在左下方
D3D在左上方
三角形设置:计算图元边界信息
三角形遍历:寻找被三角形网格所覆盖的所有像素
得到被覆盖的所有像素之后,用三角形顶点对每一个像素进行线性插值,得到当前三角形在这一像素对应片元的数据
注意!这里得到的片元不等同于像素,因为同一像素可能对应不同片元,着色器需要筛选和混合,最终输出到像素位置
MSAA:对每个像素设置多个子采样点,进行覆盖测试和遮挡测试
覆盖测试:看子采样点是否在三角形内部
遮挡测试:将子采样点的深度与ZBuffer(深度缓存)里的数值比较
两个测试均通过则说明子采样点属于三角形,最后即得到当前像素被三角形覆盖的信息,信息被保存到后面的逐片元操作,用于后续的着色混合。比如右图,着色时会按比例取色
片元着色:可编程
颜色混合:可配置。选取什么方式混合?
(具体流程可见OpenGL官方文档)
同时可得UV信息、深度信息等
再用偏远数据与其他全局数据(光照、阴影等)计算,得到最终片元颜色
透明度小于给定阈值的片元被舍弃,不渲染
深度测试:将片元的深度值与深度缓冲中的深度值作比较,通过测试即保留
左图: - 背景颜色为黑色,没有渲染片元,深度缓冲中没有数值
- 渲染地表:由于深度缓冲中没有数值,直接渲染地表,并将地表的深度值写入深度缓冲
- 渲染远处立方体:将远处立方体的深度值与深度缓冲比较,结果重叠部分立方体的深度值更小,即覆盖,并更新深度缓冲值
注意!这个例子是近处片元覆盖远处片元,这里的测试可配置,也可以改成远处覆盖近处。即深度比较方式可配置(大于/小于/等于),且覆盖完后仍可配置是否更新深度缓冲的数值。
模板测试:比较模板值
右图: - 对两个立方体整体进行描边(任何一个立方体的描边都不会挡住其他立方体)
- 把两个立方体的顶点放大一点,绘制成描边的颜色,绘制时写入模板值
- 真实立方体绘制时,比较其模板值与描边颜色的模板值,相等即覆盖,可实现立方体永远在描边之上
注意!同理深度值,比较方式可配置(大于/小于/等于),比较完后是否写入模板缓冲也可配置。
Q:模板测试的目的是啥?
混合阶段可配置,混合方式有多种。
片元着色阶段,可能是取顶点颜色进行插值,也可能是取得顶点的UV信息进行插值以后,再去取得贴图的数据
Bloom辉光、HDR高动态色彩范围、抗锯齿FXAA、Depth od View景深