0x00 Rendering Pipeline "A chain is no stronger than its weakest link."
渲染流水线可粗分为4个阶段:
Application:程序阶段完全可控,由软件驱动,软件通常运行在通用CPU。
程序该阶段末尾,将要渲染的几何图元提交给下一阶段几何处理,这些被称为渲染基元(点、线、三角)。这是该阶段最重要的任务:提交几何图元(渲染基元)。如何正确按需提交成为关键。该阶段也可做其他事:碰撞检测、键鼠输入、头戴显示、剔除算法等
Geometry Processing:几何处理,变换、投影等,该阶段包括绘制内容,如何绘制,在哪绘制。通常在GPU上执行,可编程。
①顶点着色。1是计算顶点坐标,顶点坐标计算需要经过多次变换: 建模坐标->世界坐标->观察坐标(相机空间);2是计算顶点输出数据(如法线和纹理坐标)
② Projection:正交和透视投影。经过正交或透视变换过后,坐标转为clipping coordinate (也称齐次坐标决定相机是否可见) 。投影之后是可选Optional Process:
Tessellation:曲面细分,将一组顶点组成一个pitch,将一组pitch组成一个三角形集合。随着物体距离摄像机的远近,可以控制生成的三角形集合大小,近多远少。
Geometry Shading:常用于模拟粒子特效。
Stream output:常用于模拟粒子特效。
③ Clipping:使用投影阶段生成的齐次坐标进行裁剪,进行透视分割得到normalized device coordinates也被称为视口坐标或裁剪空间,是三维坐标。
④ Screen Mapping:将得到的视口坐标映射到屏幕得到屏幕坐标(x, y)加z_values,二维坐标。注意畸变控制
UnityShader坐标空间转换
建模坐标-(Model Transform)>世界坐标-(View Transform)>观察坐标-(Projection Transform)>视口坐标-(Screen mapping)>屏幕坐标
假定modelPos = (1,2,3).
Model Transform: float4 worldPos = mul(unity_ObjectToWorld, float4(modelPos, 1)) //也可用unity_WorldToObject回到模型坐标
View Transform: float4 projPos = mul(UNITY_MATRIX_V, worldPos)
/*也可用UNITY_MATRIX_MV一次性从模型空间转到观察坐标(相机空间)*/
Projection Transform: float4 viewPos = mul(UNITY_MATRIX_P, projPos )
/*也可用UNITY_MATRIX_MVP一次性从模型空间转到裁剪空间*/
Rasteriztion:光栅化GPU上执行,接收来自上一阶段所有经过变换和投影的顶点及其着色数据,找到基元内所有像素。可编程
①Triangle Setup(primitive assembly):在这个阶段执行三角形的差异化计算、边缘均分。
②Triangle Traversal:三角形遍历。Finding which samples or pixels are inside a triangle is often called triangle traversal
Pixel Processing: GPU执行。像素处理是对像素或图元内的采样点进行逐像素或逐采样点计算和操作的阶段。可编程
①Pixel Shading:可编程,所有的像素着色计算都在此阶段。
②Merging:像素颜色存储在color buffer,任务1是负责将像素着色阶段产生的片元颜色与当前缓冲区中颜色相合并;任务2是负责解决可见性问题
0x01 Unity's Rendering Path
“如何应用光照以及使用着色器哪个通道都取决于使用了哪个渲染路径,着色器内每个通道经由它的通道标签来传递光照类型"
Forward Rendering path
ForwardBase and ForwardAdd passes are used.
- ForwardBase通道会立即渲染环境光、光照贴图、主方向光和不重要的顶点光。
- ForwardAdd通道被用于增强逐像素光照,每个物体都被这样的光照亮。
如果着色器中没有上述两种合适的光照通道,则自动切换到Vertex Lit path。
在Forward渲染下,一些最亮的光(默认4个)对每个物体的影响是用完全逐像素光照方式渲染;其次每个顶点最多接受4个光计算;其他的光是以SH计算近似值。一个光是否用逐像素光照取决于:
(超过默认数量的光将被添加到环境光中)
光的渲染模式设为Not Important总是逐顶点/SH;设为Important总是逐像素
最亮的方向光总是逐像素
场景中的光少于Quality Setting Pixel Light Count,多余的光按逐像素渲染并按强度递减排序
每个物体渲染的过程:
Base pass应用一个per-pixel光和其他所有per-vertex/SH光
其他per-pixel光在额外的pass渲染,一个pass对应一个光
示意图。假设A-H光的颜色和强度以及render model为auto,亮度排序基于距离了。
A-D为最亮的光采用per-pixel渲染(默认4个);D-G为per-vertex最多受到的4个光;G-H为SH。重叠为尽可能防止light popping,若过渡出现问题先查看光组件render model、intensity,以及Quality Setting pixel light count,然后查看代码。
场景中的可见光源数目和计算复杂度是成线性增长,会影响vertex shader效率
Base Pass
Base pass用一个per-pixel方向光和所有SH/Vertex光渲染物体,该通道也增加了所有的光照贴图、环境光、和来自着色器的自发光。该通道渲染的方向光可以有阴影。但光照贴图不会接受SH光。
Additional Passes
Additional passes 用额外的per-pixel光渲染物体。除非开启multi_compile_fwdadd _fullshadows variant变种。
Performance Considerations
Spherical Harmonics lights(球谐光照)非常高效。对CPU的消耗极其微小,对于GPU来说不会有额外的负担(因为base pass原本就会一直计算SH Lighting;和球谐光照的机制有关,无论有多少球谐光的存在,消耗都是一样的)。
SH光照的缺点:
利用物体的vertices进行计算,而不是pixels。因此不支持法线贴图和Light Cookies。
SH光照函数是种非常低频的照明函数,不会有非常锐利的照明过渡,另外也只会响应Diffuse Lighting(漫反射),对于Specular Highlight(镜面高光)而言其频率太低了。
SH lighting is not local; point or spot SH lights close to some surface will "look wrong". 球谐照明不是局部的,点光源或聚光灯形式的SH Light在靠近一些表面时看上去会不正常。
Deferred Shading path
//待续
Deferred Lighting path
//待续Vertex Lit Rendering path
//待续
0x100 待补充
Tessellation详解