unity渲染路径
渲染路径(Rendering Path)决定光照如何应用到shader中 ----> 在Pass中指明使用的渲染路径。
通过设置Pass的 LightMode标签实现;
向前渲染路径
没进行一次完整的前向渲染,我们需要渲染该对象的渲染图元,并计算两个缓冲区的信息:一个颜色缓冲区,一个深度缓冲区。利用深度缓冲来决定一个片元是否可见,如果可见就更新颜色缓冲区的颜色值。
//遍历每个片元
for (each primitive in this model){
if(failed in depth test){
//没通过深度测试,该片元不可见
discard;
}else{
//该片元可见,就进行光照计算
float4 color=Shading(material,pos,normal,lightDir,viewDir);
//更新帧缓冲
writeFrameBuffer(fragment,color);
}
}
对每个逐像素光照,都需要进行上面的完整渲染流程。如果在多个逐像素的光照下,需要执行多个pass,每个pass计算一个逐像素光源,在帧缓冲中将这个光照计算结果混合起来得到最终的颜色值。若存在大量逐像素光照下,需要执行的pass数目很大,所以渲染引擎会限制每个物体的逐像素光照数目。
unity的前向渲染路径有三种处理光照的方式:逐顶点处理、逐像素处理、球谐函数处理(SH);决定一个光源使用哪种处理模式取决于它的类型和渲染模式。光源类型指的是该光源是平行光还是其他类型的光源,而光源的渲染模式指的是该光源是否是重要的(Important)。
Auto、Important、Not Important
在向前渲染中,unity会根据场景中的各个光源的设置以及这些光源对物体的影响程度对这些光源进行一个重要度排序。判断规则:
-
场景中最亮的平行光总是按逐像素处理的。
-
渲染模式被设置为Not Important 的光源,会按照逐顶点或SH处理。
-
设置为Important的光源,会按照逐像素处理。
-
若根据以上规则得到的逐像素光源小于Quality Setting中逐像素光源数量(Pixel Light Count),会有更多的光源以逐像素的方式进行渲染。如果超过是设置的逐像素光源数量,后面最多有4个光源按逐顶点的方式处理,剩下的光源按SH方式处理。
向前渲染的两种Pass:Base Pass、Additional Pass;
1. #pragma multi_compile_fwdbase和#pragma multi_compile_fwdadd。只有为base和add Pass这两个编译指令,才能得到正确的光照变量。如光照衰减值。
2. add Pass默认是没有阴影效果的。需要使用#pragma multi_compile_fwdadd_fullshadows。为点光源和聚光灯开启阴影效果,但是需要使用更多的shader变量。
3. base中,对一个物体来说,环境光和自发光只需要计算一次。add 中计算这两种光照会造成叠加多次环境光和自发光。
4. add中需要开启混合。每个add 可以和上一次光照结果的帧缓存进行叠加,从而得到多个光照的渲染效果。若没开启混合,则会覆盖上一次的渲染结果,造成物体在多个光源中,看起来只受该光源的影响。通场混合设置为Blend One One。
5. 前向渲染,通常会定义一个Base和Add ,base执行一次,add会根据影响该物体的其他逐像素光源的数目被多次调用,即每个逐像素光源会执行一次add。
根据使用的渲染路径,unity会把不同的光照变量传递给shader。
顶点照明渲染路径
顶点照明渲染路径对硬件配置要求低、运算性能最高,必然效果也是最差的一种类型,不支持逐像素才能得到的效果,如阴影、法线映射、高精度的高光反射等。不可以使用逐像素光照变量。按照逐顶点处理,这是最快速的渲染路径,现在基本不会使用。
延迟渲染路径
当场景中包含大量实时光源时,前向渲染性能会急速下降-----会进行大量的重复计算。除了前向渲染中使用的颜色缓冲和深度缓冲,延迟渲染还会使用额外的缓冲区,同称为G缓冲(Geometry-Buffer)。它存储了所关心的表面(距离摄像机最近的表面)的其他信息,如法线、位置、材质属性等。
延迟渲染只要包含两个pass,第一个pass中不进行光照计算,只计算那些片元是可见的---通过深度缓冲技术实现,发现一个片元是可见的,就把它的相关联信息存储到G缓冲区中。第二个pass利用G缓冲区的各个片元信息进行真正的关照计算。延迟渲染pass通常就是两个,与场景中包含的光源数目没有关系,延迟渲染的效率不依赖场景的复制度,而是和使用的屏幕空间的大小有关。因为所需要的信息都存储在缓冲区中,缓冲区可以理解为一张张2D图像,实际计算就是在这些图像空间中进行。
最适合在场景中光源数目众多是使用,延迟渲染中的每个光源都可以按照逐像素的方式处理。存在的缺点:
- 不支持真正的抗锯齿(anti-aliasing)。
- 不能处理半透明物体。
- 对显卡有一定的要求,显卡必须支持MRT、shader mode3.0及以上、深度渲染纹理、双面的模板缓冲。
//第一个pass仅仅把光照计算需要的信息存储到GBuffer。
//会把物体的漫反射颜色、高光反射颜色、平滑度、法线、自发光、深度等信息渲染到屏幕空间的GBuffer中,每个物体只会执行一次。
//默认的G缓冲包含的渲染纹理:
// RT0:ARGB32,RGB存储漫反射颜色,A没用到。
// RT1:ARGB32,RGB存储高光反射颜色,A存储高光反射的指数部分。
// RT2:ARGB2101010,RGB存储法线,A没有用到。
// RT3:ARGB32(非HDR)或ARGBHalf(HDR),存储自发光+lightmap+反射探针。
//深度缓冲和模板缓冲
Pass{
CGPROGRAM
//遍历每个片元
for (each primitive in this model){
for(each fragment covered by this primitive){
if(failed in depth test){
//没通过深度测试,该片元不可见
discard;
}else{
//该片元可见
//存储到GBuffer
writeGBuffer(material,pos,normal,lightDir,viewDir);
}
}
}
ENDCG
}
//第二个pass利用GBuffer中的信息进行真正的光照计算。
//默认使用unity内置的standard光照模型。如使用其他,需要替换Internal-DeferredShading.shader文件。
Pass{
CGPROGRAM
for (each pixel in this screen){
if(the pixel is valid){
//该像素有效
//读取对应的GBuffer
readGBuffer(pixel,pos,normal,lightDir,viewDir)
//根据读取到的数据进行光照计算
float4 color=shading(material,pos,normal,lightDir,viewDir)
//更新到帧缓冲
writeFrameBuffer(pixel,color);
}
}
ENDCG
}
渲染路径的选择--->根据游戏发布的平台选择渲染路径。
光源类型的影响
常用的光源有光源的位置、方向、颜色、强度、衰减。
-
平行光:几何定义最简单,没有范围限制,几何属性没有位置(也就没有衰减的概念)只有方向。
-
点光源: 由一个点发出、向所有方向延伸的光。随点光源球心点距离,强度逐渐变弱。
-
聚光灯:最为复杂的一种,需要判断一个点是否在锥体内。
Shader "Unlit/10"
{
Properties{
_Diffuse("",Color)=(1,1,1,1)
_Specular("",Color)=(1,1,1,1)
_Gloss("",Range(1,256))=8
}
SubShader{
Pass{
//base pass
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//该指令保证光照变量正确赋值
#pragma multi_compile_fwdbase
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
fixed _Gloss;
str