渲染路径【Rendering Path】
5.x之前:
Forward Rendering Path
Deferred Rendering Path
Vertex Lit Rendering Path
5.1之后:
主要改变:
1、顶点照明渲染路径被抛弃【但目前仍然可以对之前使用了顶点渲染路径的兼容】
2、新的延迟渲染路径代替了原来的延迟渲染路径。【同样也兼容旧版本】
可以在 Pass 通道中使用以下形式设置渲染路径:
上面的代码告诉 unity ,该 Pass 使用前向渲染路径中的 ForwardBase 路径。
而前向渲染路径还有一种路径叫做 ForwardAdd。
下面的表给出了 Pass 的 LightMode 标签支持的渲染路径设置选项:
设置了渲染标签,可以访问 unity 提供的内置光照变量以访问属性。
如果没有指定任何的渲染路径,【5.x 的版本中如果使用了前向渲染又没有为 Pass
指定任何前向渲染的标签,就会被当成一个和顶点照明渲染路径等同的 Pass】
一、前向渲染路径
原理:
每进行一次完整的前向渲染,需要渲染该对象的渲染图元,并计算
两个缓冲区的信息:
一个是颜色缓冲区,一个是深度缓冲区。
利用深度缓冲来决定一个片元是否可见,如果可见就更新颜色缓冲区中的
颜色值。可以使用下面的伪代码来描述这一过程:
对于每个逐像素光源,都需要进行上面一次完整的渲染流程。如果一个物体在
多个逐像素光源的影响区域内,那么该物体就需要执行多个 Pass, 每个 Pass
计算一个逐像素光源的光照结果,然后再帧缓冲中巴这些光照结果混合起来
得到最终的颜色值。
Unity 中的前向渲染
一个 Pass 不仅仅可以用来计算逐像素光照,它也可以用来计算逐顶点等其他
光照。这取决于光照计算所处流水阶段以及计算时使用的数学模型。
在 Unity 中,前向渲染有3种处理方式:
逐顶点处理
逐像素处理
球谐函数处理
【Spherical Harmonics, SH】
决定一个光源使用哪种处理模式决定于它的类型和渲染模式:
光源类型:该光源是平行光还是其他类型的光源
渲染模式指该光源是否是重要的。
在前向渲染中,渲染一个物体的时候, unity 会根据场景中各个光源的设置
以及这些光源对物体的影响程度【例如,距离物体的远近,光源强度等】,
对这些光源进行一个重要度排序。其中一定数目的光源会按逐像素的方式,
然后最多有 4 个光源按逐顶点的方式处理,剩下的光源按照SH方式处理:
【1】场景中最亮的平行光总是按逐像素处理的。
【2】渲染模式设置为 Not Important 的光源会按 逐顶点或者SH 处理
【3】渲染模式设置为 Improtant 的光源会按逐像素处理。
【4】如果根据以上规则的逐像素光源数量小于 Quality Setting 中的
逐像素光源 【Pixel Light Count】,会有更多的光源以逐像素的方式进行渲染
前向渲染的两中 Pass:Base Pass 和 Additional Pass
上图的一些说明地方:
【1】处理设置 Pass 标签外,还是使用了 #pragma multi_comile_fwdbase 这样的
编译指令。虽然 #pragma multi_compile_fwdbase 和 #pragma multi_compile_fwdadd
在官方文档中没有给出相关说明,但实验表明,只有分别为 Bass Pass 和 Additional Pass
使用这两个编译指令,才可以在相关的 Pass 中得到一些正确的光照变量,例如:
光照衰减值等。
【2】 Bass Pass 旁边给出了 Bass Pass 中支持的一些光照特性。例如在 Base Pass
中,可以访问光照纹理【lightmap】。
【3】Base Pass 中渲染的平行光默认支持阴影,而 Additional Pass 中渲染的光源在默认
情况下是没有阴影效果的,但可以使用 #pragma multi_compile_fwdadd_fullshadows 开启
阴影
【4】环境光和自发光是在 Base Pass 中计算的,而如果在 Additional Pass 中计算会造成
叠加多次环境光和自发光。
【5】Additional Pass 渲染设置中,还开启了和设置了混合模式。这是希望每个
Additional Pass 可以与上一次的光照结果在帧缓存进行叠加,从而得到最终的有多个
光照渲染效果。如果没有开启,那么渲染结果就会覆盖之前的渲染结果,看起来就好像
物体只受该光源影响。通常情况下的混合模式是: Blend One One
【7】对于前向渲染来说,一个 unity shader 通常会定义一个 Base Pass(也可以多个)
以及一个 Additional Pass。一个Bass Pass执行一次,而一个 Additional Pass会根据
影响该物体的其他逐像素光源的数目被多次调用,即每个逐像素光源会执行一次
Additional Pass
对于前向渲染【即LightMode 为 ForwardBase 或 ForwardAdd】
可以在 shader 中访问到的光照变量:
前向渲染中可以使用的内置光照函数:
二、顶点照明渲染路径
顶点照明渲染路径是对硬件配置要求最少、运算性能最高,但也是效果最差的
一种类型。它是前向渲染的一个子集,即所有可以在顶点照明渲染路径中实现的功能
都可以在前向渲染路径中完成。
unity 中的顶点照明渲染
通常在一个 Pass 中就可以完成对物体的渲染。
在这个 Pass 中,会计算所关心的所有光源对该物体的照明,并且这个计算是逐顶点
处理的,是unity中最快速的渲染路径。
可访问的内置变量
可访问的内置函数
三、延迟渲染路径
前向渲染的问题是:当场景中包含大量的实时光源时,前向渲染性能会急速下降。
延迟渲染是一种更古老的技术。
除了前向渲染中使用的颜色缓冲和深度缓冲外,延迟渲染还会利用额外的缓冲区,
这些缓冲去也被称为 G 缓冲【G (Geometry)- buffer】,里面存储了所关心的表面
【通常指距离摄像机最近的表面】的其他信息,例如:法线、位置、
用于光照计算的材质属性等。
延迟渲染的原理:
主要包含了两个 Pass:
1、不进行任何光照计算,而是计算哪些片元是可见的,主要通过深度缓冲技术来
实现。当一个片元是可见的,就把它的相关信息存储到 G 中。
2、利用 G 中的各个片元信息,例如:表面法线、视角方向、漫反射系数等,进行
真正的光照计算。
用伪代码描述大致过程:
可以看出,延迟渲染使用的 Pass 数目通常就是两个,这跟场景中包含的光源
数目是没有关系的。换句话说,延迟渲染的效率不依赖于场景的复杂的,而是和
使用的屏幕空间的大小有关。这是因为,所需要的信息都存储在缓冲区中,
而这些可以理解成一张纸 2D 图像,实际上的计算就是在这些图像空间中进行的。
unity 中的延迟渲染
如果在游戏中使用了大量的实时光照,可能希望选择延迟渲染路径,
但这需要一定的硬件支持。
对于延迟渲染路径来说,最合适在场景中光源数目很多,如果使用前向渲染会造成
性能瓶颈的情况下。延迟渲染中的每个光源都是按逐像素的方式处理的。但是也
有一些缺点:
【1】不支持真正的 抗锯齿(anti - aliasing)功能
【2】不能处理半透明
【3】对显卡有一定要求
当使用延迟渲染时, unity要求提供两个 Pass
1、第一个 Pass 用于渲染缓冲。在这个 Pass 中,把物体的漫反射颜色、高光反射颜色、平滑度、法线、自发光和深度值等信息渲染到屏幕空间的 G 缓冲区中,对于每个物体来说,这个 Pass 仅会执行一次。
2、第二个 Pass 用于计算真正的光照模型。会使用上一个 Pass 中渲染的数据来计算最终的光照颜色,在存储到帧缓冲中。
可访问的 内置变量和函数:
这些变量可以在 UnityDeferredLibrary.cginc 中找到定义
最后,本书采用的是 前向渲染路径