UnityShader学习——渲染路径

渲染路径

指定渲染路径是我们和Unity的底层渲染引擎的一次重要的沟通。例如,如果我们为一个Pass设置了前向渲染路径的标签,随后,我们可以通过Unity提供的内置光照变量来访问这些属性。如果我们没有指定任何渲染路径,那么一些光照变量很可能不会被正确赋值,我们计算出的效果也就很有可能是错误的。
在这里插入图片描述
以上4种渲染路径在LightMode标签的设置中有以下选项:
在这里插入图片描述

1.前向渲染路径

原理

每进行一次完整的前向渲染,我们需要渲染该对象的渲染图元,并计算两个缓冲区的信息:一个是颜色缓冲区,一个是深度缓冲区。我们利用深度缓冲来决定一个片元是否可见,如果可见就更新颜色缓冲区中的颜色值。

对于每个逐像素光源,我们都需要进行上面一次完整的渲染流程。如果一个物体在多个逐像素光源的影响区域内,那么该物体就需要执行多个Pass,每个Pass计算一个逐像素光源的光照结果,然后在帧缓冲中把这些光照结果混合起来得到最终的颜色值。假设,场景中有N个物体,每个物体受M个光源的影响,那么要渲染整个场景一共需要N*M个Pass。可以看出,如果有大量逐像素光照,那么需要执行的Pass数目也会很大。因此,渲染引擎通常会限制每个物体的逐像素光照的数目

Unity中针对性能优化采用的渲染方式

在Unity中,前向渲染路径有3种处理光照(即照亮物体)的方式:逐顶点处理、逐像素处理,球谐函数处理(成本依次降低)。而决定一个光源使用哪种处理模式取决于以下两点:

  • 光源类型:该光源是平行光还是其他类型的光源。
  • 光源的渲染模式:该光源是否是重要的(Important)。

在前向渲染中,当我们渲染一个物体时,Unity会根据场景中各个光源的设置以及这些光源对物体的影响程度(例如,距离该物体的远近、光源强度等)对这些光源进行一个重要度排序。其中,一定数目的光源会按逐像素的方式处理,然后最多有4个光源按逐顶点的方式处理,剩下的光源可以按SH方式处理。Unity使用的判断规则如下:

  • 场景中最亮的平行光总是按逐像素处理的。
  • 渲染模式被设置成Not Important的光源,会按逐顶点或者SH处理。
  • 渲染模式被设置成Important的光源,会按逐像素处理。
  • 如果根据以上规则得到的逐像素光源数量小于Quality Setting中的逐像素光源数量,会有更多的光源以逐像素的方式进行渲染。

UnityShader 通常设置

前向渲染有两种Pass:Base PassAdditional Pass。对于前向渲染来说,一个Unity Shader通常会定义一个Base Pass(Base Pass也可以定义多次,例如需要双面渲染等情况)以及一个Additional Pass。一个Base Pass仅会执行一次(定义了多个Base Pass的情况除外),而一个Additional Pass会根据影响该物体的其他逐像素光源的数目被多次调用,即每个逐像素光源会执行一次Additional Pass。

(1)Base Pass设置:

  • 光照计算:一个逐像素的平行光以及所有逐顶点和SH光源
  • 此Pass的平行光默认是支持阴影的(如果开启了光源的阴影功能)。
  • 环境光和自发光也是在Base Pass中计算的。这是因为,对于一个物体来说,环境光和自发光我们只希望计算一次即可,而如果我们在Additional Pass中计算这两种光照,就会造成叠加多次环境光和自发光,这不是我们想要的。
  • 此Pass可以访问光照纹理(lightmap)。
Tags { "LightMode"="ForwardBase" } 
//使用如下编译命令后才可以在相关的Pass中得到一些正确的光照变量,例如光照衰减值等
#pragma multi_compile_fwdbase	

(2)Additional Pass设置:

  • 光照计算:其他影响该物体的逐像素光源计算。每个光源执行一次Pass。
  • 此Pass渲染的光源在默认情况下是没有阴影效果的,即便我们在它的Light组件中设置了有阴影的Shadow Type。
  • 我们希望每个Additional Pass可以与上一次的光照结果在帧缓存中进行叠加,从而得到最终的有多个光照的渲染效果。如果我们没有开启和设置混合模式,那么Additional Pass的渲染结果会覆盖掉之前的渲染结果,看起来就好像该物体只受该光源的影响。
Tags { "LightMode"="ForwardAdd" }
//通常情况下,我们选择的混合模式是 Blend One One
Blend One One
//使用如下编译命令后才可以在相关的Pass中得到一些正确的光照变量,例如光照衰减值等
#pragma multi_compile_fwdadd
//替换上述编译命令,为点光源和聚光灯开启阴影效果
#pragma multi_compile_fwdadd_fullshadows 

UnityShader 自定义设置

以上介绍通常情况下我们在每种Pass中进行的计算。实际上,渲染路径的设置用于告诉Unity该Pass在前向渲染路径中的位置,然后底层的渲染引擎会进行相关计算并填充一些内置变量(如_LightColor0等),如何使用这些内置变量进行计算完全取决于开发者的选择。例如,我们完全可以利用Unity提供的内置变量在Base Pass中只进行逐顶点光照;同样,我们也完全可以在Additional Pass中按逐顶点的方式进行光照计算,不进行任何逐像素光照计算。

在这里插入图片描述在这里插入图片描述

2.顶点照明渲染路径

顶点照明渲染路径是对硬件配置要求最少、运算性能最高,但同时也是得到的效果最差的一种类型,它不支持那些逐像素才能得到的效果,例如阴影、法线映射、高精度的高光反射等。实际上,它仅仅是前向渲染路径的一个子集,所有可以在顶点照明渲染路径中实现的功能都可以在前向渲染路径中完成。就如它的名字一样,顶点照明渲染路径只是使用了逐顶点的方式来计算光照

顶点照明渲染路径通常在一个Pass中就可以完成对物体的渲染。在这个Pass中,我们会计算我们关心的所有光源对该物体的照明,并且这个计算是按逐顶点处理的。在Unity中,我们可以在一个顶点照明的Pass中最多访问到8个逐顶点光源。如果我们只需要渲染其中两个光源对物体的照明,可以仅使用表9.4中内置光照数据的前两个。如果影响该物体的光源数目小于8,那么数组中剩下的光源颜色会设置成黑色。
在这里插入图片描述
在这里插入图片描述

3.延迟渲染路径

原理

延迟渲染主要包含了两个Pass。在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现,当发现一个片元是可见的,我们就把它的相关信息存储到G缓冲区中。然后,在第二个Pass中,我们利用G(Geometry)缓冲区的各个片元信息,例如表面法线、视角方向、漫反射系数等,进行真正的光照计算。

延迟渲染使用的Pass数目通常就是两个,它的效率不依赖于场景的复杂度(光源、物体),而是和我们使用的屏幕空间的大小有关。这是因为,我们需要的信息都存储在缓冲区中,而这些缓冲区可以理解成是一张张2D图像

Unity有两种延迟渲染路径,一种是遗留的延迟渲染路径,另一种是Unity5.x中使用的延迟渲染路径。新旧延迟渲染路径之间的差别很小,较旧版本的延迟渲染路径不支持Unity 5的基于物理的Standard Shader。

延迟渲染路径优缺点

优点:

  • 场景中光源数目很多时,可以解决前向渲染的性能瓶颈问题
  • 延迟渲染路径中的每个光源都可以按逐像素的方式处理。

缺点:

  • 不支持真正的抗锯齿(anti-aliasing)功能。
  • 不能处理半透明物体。
  • 对显卡有一定要求。
  • 如果要使用延迟渲染的话,显卡必须支持MRT(Multiple RenderTargets)、Shader Mode 3.0及以上、深度渲染纹理以及双面的模板缓冲。

当使用延迟渲染时,Unity要求我们提供两个Pass:

(1)第一个Pass用于渲染G缓冲。在这个Pass中,我们会把物体的漫反射颜色、高光反射颜色、平滑度、法线、自发光和深度等信息渲染到屏幕空间的G缓冲区中。对于每个物体来说,这个Pass仅会执行一次。

(2)第二个Pass用于计算真正的光照模型。这个Pass会使用上一个Pass中渲染的数据来计算最终的光照颜色,再存储到帧缓冲中。

默认的G缓冲区(注意,不同Unity版本的渲染纹理存储内容会有所不同)包含了以下几个渲染纹理(Render Texture, RT):

  • RT0:格式是ARGB32, RGB通道用于存储漫反射颜色,A通道没有被使用。
  • RT1:格式是ARGB32, RGB通道用于存储高光反射颜色,A通道用于存储高光反射的指数部分。
  • RT2:格式是ARGB2101010, RGB通道用于存储法线,A通道没有被使用。
  • RT3:格式是ARGB32(非HDR)或ARGBHalf(HDR),用于存储自发光+lightmap+反射探针(reflection probes)。
  • 深度缓冲和模板缓冲

当在第二个Pass中计算光照时,默认情况下仅可以使用Unity内置的Standard光照模型。如果我们想要使用其他的光照模型,就需要替换掉原有的Internal-DeferredShading.shader文件。
在这里插入图片描述

4.选择哪个渲染路径?

总体来说,我们需要根据游戏发布的目标平台来选择渲染路径。如果当前显卡不支持所选渲染路径,那么Unity会自动使用比其低一级的渲染路径。

发布了195 篇原创文章 · 获赞 59 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_36622009/article/details/105508375