Shader - Unity中的渲染管道

着色器用于定义对象的外观(材质属性)以及它对光的反应,因为必须在着色器中构建光照计算,然而可能会存在很多类型的光影,所以编写Shader是非常麻烦的一件事。Unity为了简化编写Shader的操作,提供了Surface Shaders,它会将所有的光照,阴影,光照贴图,向前渲染和延迟渲染都会自动处理。

如何选择渲染通道(Pass)以及灯光如何应用,都取决于采用什么样的渲染路径。Shaer中的每个Pass适用于什么样的渲染路径都是通过PassTags中的LightMode 来定义的。
Unity中包含的渲染路径有:

渲染路径 支持的LightMode
Forwawrd Rendering(正向渲染) ForwardBase和ForwardAdd Pass会被使用
Deferred Shading(延迟着色) Deferred Pass会被使用
legacy Deferred Lighting(遗留 延迟光照) PrepassBase和PrepassFinal Pass会被使用
legacy Vertex Lit(遗留 顶点光照) Vertex,VertexLMRGBM和VertexLM Pass 会被使用
上述任何一个渲染路径,为了渲染阴影或深度纹理,ShadowCaster Pass会被使用

Forward Rendering path(正向渲染路径)
在Forward Rendering 路径中,在影响对象的所有灯光中,一些最亮的灯会以逐像素的方式进行照明,然后会有4个灯光以逐顶点的方式进行照明,剩余的灯光会以SH(球面谐波)的方式进行渲染。主要规则如下:

1.将渲染模式设置为"Not Important"的灯始终是按顶点或者SH进行渲染
2.最亮的平行光会以逐像素的方式进行渲染。
3.将渲染模式设置为“Important”的灯始终为逐像素进行渲染。
4.最多会有4个光源按照逐顶点的方式进行渲染
5.经过以上操作后,如果逐像素渲染的灯光个数小于Quality Setting设置中Pixel Light Count的数量话,会按照亮度从高到低的顺序,选择合适的灯光数量,进行逐像素渲染。

渲染流程如下:

1.Forward Base Pass 会执行最亮的逐像素平行光和所有的逐顶点/SH灯光渲染。
2.Forward Add Pass 会在每个逐像素灯光(除逐像素平行光以外的)进行一次渲染。 

例如:
在这里插入图片描述
上图中,对象(圆圈)受到灯光A到H的影响,假设A到H都具有相同的颜色和强度,且所有灯光都具有自动渲染模式,所以他们将按照与对象距离来进行排序,前面的灯光会以逐像素的方式进行渲染(A-D,具体数量会根据质量设置中的数据来设置),然后就是以逐顶点的灯光渲染(D-G,最到4个灯光),剩余的灯光会以SH(G-H)的方式进行渲染。如图:
在这里插入图片描述

注意,在不同的模式渲染中有重叠渲染的部分,这样当物体和光线移动时,不会出现太多的"灯光跳跃"
除A灯光外,其余逐像素渲染灯光会调用Forward Add Pass。

ForwardBase :使用一个逐像素平行光和所有SH/顶点光源渲染对象,在此过程中还会添加着色器中的光照贴图,环境光和自发光。在此渲染过程中方向光可以具有阴影(注意光照贴图对象不会从SH灯获取照明)。
如果在Pass中使用了“OnlyDirectional”标签,ForwardBase 通道仅渲染主方向光,环境/光探测器和光照贴图(SH和顶点光不包括在Pass数据中)。
ForwardAdd :会为所有影响该对象的逐像素光源渲染一次(除主平行光外) 。默认情况下,这些过程中的灯光是没有阴影的,除非使用了multi_compile_fwdadd_fullshadows这样的编译指令,来生成多个着色器程序变体。
如果着色器没有提供适当的Pass(即没有ForwardBase也不存在ForwardAdd),则该对象的渲染方式语Vertex Lit 路径中的渲染方式相同。

SH(球面谐波)的渲染速度是非常块的,并且在CPU上的成本很低,实际上可以自由地应用GPU(ForwardBase通道总是计算SH照明,由于SH的工作方式,所以无论多少SH灯,成本都是一样的)。
SH的缺点有:

1.它们是在顶点的基础上进行计算,所以不支持Cookie和法线贴图
2.SH照明频率很低,无法有明显的照明过度。也只影响漫反射光照(镜面高管的频率太低)。
3.SH照明不是局部的,靠近某些表面的球谐函数点光源或聚光灯会看起来有些别扭。

Deferred shading Rendering path(延迟着色渲染路径)
使用Deferred shading 时,对可影响GameObject的灯光数量没有限制,所有灯光都会按逐像素的方式评估光照,所以它们可以与法线题图等正确交换,所有的灯光都可以有Cookie和阴影。
Deferred shading 的优点:

照明的处理开销与光照的像素数量成正比,这是由场景中光的大小决定,而不是它照亮了多少游戏物体,因此可以通过保持较小的光线来提高性能。
延迟着色也具有高度一致和可预测的行为,每个光的效果都是按像素计算的,因此没有在大三角形上分解的光照计算。

Deferred shading 的缺点:

延迟照明没有真正的抗锯齿支持,也无法处理半透明的GameObject(这些是使用Forward Rendering渲染的)。
Mesh Render(网格渲染器)和Receive Shadows(接收阴影)标志也不支持。
剔除遮蔽图的支持方式有限(最多可以使用四个剔除遮蔽图,即:剔除层遮蔽图必须至少包含减去 4 个任意层后的所有层,所以 32 层中必须设置 28 层。否则会得到图形假象。)。

使用要求:

1.需要具有多个渲染目标(MRT)的显卡,Shader Model 3.0(或以上)的图形卡,并支持深度渲染纹理。2006年后大多数pc显卡都支持延迟着色,从GeForce 8xxx,Radeon x2400,Intel G45开始。
2.移动设备上不支持,主要由于使用MRT格式(某些GPU支持多个渲染目标,但只支持非常有限的位数)。
3.使用正交投影时,不支持延迟渲染。如果相机的投影模式设置为'Orthographic(正交)',则相机会退回到“Forward Rdndering”。

性能:
延迟着色中的实时光的渲染开销与光照像素的数量成正比,与场景复杂度无关,所以小的点光等和聚光灯在性能上更有优势。如果它们被场景游戏对象完全或部分遮挡,可能会获得更好的效果。
有阴影的灯光比没有的阴影的灯要耗费的性能更多,在延迟渲染中,阴影投射的游戏对象仍然需要为每个阴影投射光渲染一次或多次。此外,应用阴影的光照着色器比禁用阴影时使用的渲染开销更高。

细节:

使用延迟渲染着色时,Unity中的渲染过程分为两步:
G-buffer Pass:游戏对象被渲染成具有漫反射色、高光色、平滑度、世界空间法线、发射和深度的屏幕空间缓冲器。
Lighting Pass:先前生成的缓冲区用于将照明添加到发射缓冲区。

不能处理延迟渲染的着色(物体),在该过程完成后会使用Forward Rendering 路径进行渲染。

默认g-buff布局:
RT0,ARGB32格式:漫反射颜色(RGB),遮挡(A)。
RT1,ARGB32格式:镜面反射颜色(RGB),粗糙度(A)。
RT2,ARGB2101010格式:世界空间标准(RGB),未使用(A)。
RT3,ARGB2101010(非HDR)或ARGBHalf(HDR)格式:Emission+lighting+lightmaps+reflectin 侦探 缓冲。
深度+模板缓冲区。

默认的g缓冲区布局时160位/像素(非HDR)或192位/像素(HDR)。
相机不使用HDR时,Emission+lighting缓冲区(RT3)以对数方式编码,以提供比ARGB32纹理通常可能的更大的动态范围。
注意,相机使用HDR渲染时,没有为Emission +光照缓冲区(RT3)创建单独的渲染目标; 相反,Camera渲染的渲染目标(即传递给图像效果的渲染目标)用作RT3。

G-Buffer Pass:
渲染每个Gameobject一次,漫反射和镜面反射颜色,表面平滑度,世界空间法线和发射+环境+反射+光照贴图渲染为g缓冲区纹理。g-buffer纹理被设置为全局着色器属性,以供稍后访问着色器

Lighting Pass:
照明通过基于g缓冲区和深度计算照明。照明是在屏幕空间中计算的,因此处理时间与场景复杂度无关。灯光会被添加到emission 缓冲区中。
不穿过相机近平面的点光源和聚光灯会渲染为3D形状,并启用Z缓冲区对场景的测试,这使得部分或完全遮挡得点光灯和聚光灯非常块快得渲染。穿过近平面得定向灯和点/聚光灯呈现为全屏四边形。
如果灯光开启了阴影,那么它们也会在此过程中渲染并应用,阴影并不是“免费”出现的。需要渲染阴影投射器并运用更加复杂的光线着色器。
唯一可用的照明模型是 Standard,如果需要不同的模型,可以修改光照通道着色器,将内置着色器中的Internal-DeferredShading.sharder 文件的修改版本放入Asset/Resources文件夹中,然后在Edit/Project Settings/Graphics 窗口中将“Deferred”修改为“Custom Shader”,然后更改这个在使用的着色器选项。

Legacy Deferred Lighting Rendering Paht(旧版延迟光照渲染路径):
与Deferred shadering 相似,从Unity5.0 版本以后被认为是传统功能,因为他不支持某些渲染功能(如标准着色器,反射探测器等)。

使用延迟光照时,Unity中的渲染过程会分为3步:

1.Base Pass:渲染对象以生成具有深度,法线和镜面反射功率的屏幕空间缓冲区。
2.Light Pass:使用前面生成的缓冲区用于计算照明到另一个屏幕空空间缓冲区(唯一可用的照明模型为Blinn-Phong)。
3.Final Pass:再次渲染对象。它们获取计算出的光照,将其与颜色纹理相结合,并添加任何环境/发光照明。

Vertex Lit Rendering Path (顶点照明路径)
Vertex Lit路径通常在一次通过中渲染每个对象,并在对象顶点出计算所有光源的光照。
Vertex Lit是最快的渲染路径,并且具有最广泛的硬件支持(不使用与控制台)。
由于所有的光照都是在顶点级别计算的,因此此渲染路径不支持大多数逐像素效果:不支持阴影,法线贴图,cookie和非常细腻的镜面高光。

发布了28 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_18192161/article/details/90544284