UnityShader-复杂的光照

it2023-01-11  59

渲染路径


在Unity中,渲染路径决定了光照是如何应用到UnityShader中的。在UnityShader中需要为每一个Pass指定渲染路径,该Shader的光照计算才能正常进行。

Pass{ Tags { "LightModel" = "ForwardBase"} }

Unity5.0之后主要有四种渲染路径:前向渲染路径(Forward)、延迟渲染路径(Deferred)和旧版顶点照明渲染路径(Legacy Vertex Lit)、旧版延迟渲染路径(Legacy Deferred(light prepass)),可以在Edit->Projecting-Graphics中进行设置。设置渲染路径,Unity会把光照属性按渲染流程准备好,可以通过Unity提供的内置光照变量来访问这些属性。

标 签 名描 述Always不管使用哪种渲染路径,该Pass总是会被渲染,但不会计算任何光照ForwardBase用于前向渲染。该Pass会计算环境光、最重要的平行光、逐顶点/SH光源和LightmapsForwardAdd用于前向渲染。该Pass会计算额外的逐像素光源,每个Pass对应一个光源Deferred用于延迟渲染。该Pass会计算额外的逐像素光源,每个Pass对应一个光源ShadowCaster把物体的深度信息渲染到阴影映射纹理(shadowmap)或一张深度纹理中PrepassBase用于遗留的延迟渲染。该Pass会渲染法线和高光反射的指数部分PrepassFinal用于遗留的延迟渲染。该Pass通过合并纹理、光照和自发光来渲染得到最后的颜色Vertex、VertexLMRGBM和VertexLM用于遗留的顶点照明选软

Unity中的前向渲染

原理: 渲染对象的渲染图元时,计算两个缓冲区的信息(颜色缓冲区和深度缓冲区),利用深度缓冲来决定一个片元是否可见,如果可见就更新颜色缓冲区的颜色值,否则就丢弃。 前向渲染路径处理光照的三种方式: 逐顶点处理、逐像素处理、球谐函数(SH)处理。 决定一个光源使用哪种处理模式取决于它的类型和渲染模式。光源类型指的是平行光还是其他类型的光源,渲染模式指的是Render Mode变量,可以设置成Important或者Not Important。判断规则如下:

场景中最亮的平行光按逐像素处理。Render Mode 为 Not Important的光源,会逐顶点或者SH处理。Render Mode 为 Important的光源,会逐像素处理。如果上面得到的逐像素光源小于Quality Setting中的逐像素光源数量,会有过更多光源以逐像素的方式进行渲染。

前向渲染有两种Pass:

Base Pass。一般一个Unity Shader定义一个(双面渲染的话两个),执行一次。Additional Pass。如果有N个光源影响该物体,就会执行N次。

前置渲染可以使用的内置光照变量:

名 称类 型描述_LightColorfloat4该Pass处理的逐像素光源的颜色_WorldSpaceLightPos0float4_WorldSpaceLightPos0.xyz是该pass处理的逐像素光源的位置。如果该光源是平行光,那么_WorldSpaceLightPos0.w是0,其他光源类型w值为1_LightMatrix0float4x4从世界空间到光源空间的变换矩阵。可以用于采样的cookie和光强衰减纹理unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0float4仅用于Base Pass。前4个非重要的电光源在世界空间中的位置unity_4LightAtten0float4仅用于Base Pass。存储了前4个非常重要的电光源的衰减因子unity_LightColorhalf4[4]仅用于Base Pass。存储了前4个非重要的点光源的颜色

顶点照明渲染路径(Vertex)

即逐顶点计算光照。硬件配置要求最低,运算性能最高,效果最差的类型,不支持逐像素效果(如:阴影、法线映射、高精度高光反射等)。

顶点照明渲染可以使用的内置变量和函数:

名 称类 型描 述unity_LightColorhalf4[8]光源颜色unity_LightPositionfloat4[8]xyz分量是视角空间中的光源位置。如果光源是平行光,那么z分量值为0,其他光源类型z分量值为1unity_LightAttenhalf4[8]光源衰减因子。如果光源是聚光灯,x分量是cos(spotAngle/2),y分量是1/cos(spotAngle/4);如果是其他类型的官员,x分量是-1,uy分量是1.z分量是衰减的平方w分量是光源范围开根号的结果unity_SpotDirectionfloat4[8]如果光源是聚光灯的话,值为视角空间的聚光灯的位置;如果是其他类型的官员,值为(0,0,1,0)

延迟渲染路径(Deferred)

使用额外的缓冲区(G缓冲,Geometry-buffer),存储离摄像机最近的表明的其他信息(表面法线、位置、材质属性等)。避免前向渲染在大量实时光照下时的性能急速下降。实现就用两个Pass,与场景光源数目无关,而是和屏幕空间大小有关。

主要包含两个Pass:

第一个Pass:只计算哪些片元可见(深度缓冲技术),可见的就存到G缓冲中。第二个Pass:利用G缓冲中的片元信息,计算光照。

缺点:

不支持真正的抗锯齿(anti-aliasing)功能。不能处理半透明物体。显卡必须支持MRT(Multiple Render Targets)、Shader Mode3.0及以上、深度渲染纹理以及双面的模版缓冲。

光照衰减


Unity默认使用纹理查找的方式来计算逐像素的点光源和聚光灯的衰减。使用这种方法可以在一定程度上提升性能,而且得到的效果大部分情况下都是良好的,但是存在一些弊端:

需要预处理得到采样为例,而且纹理的大小也会影响衰减的精度。不直观,同时也不方便,因此一旦把数据存储到查找表中,我们就无法使用其他的数学公式来计算衰减。

1.光照衰减纹理 UNITY_ATTEN_CHANNEL:可以得到衰减纹理中衰减值所在分量。 光照衰减纹理   需要预处理得到采样纹理,纹理的大小会影响衰减精度。类似渐变纹理,(0, 0)表示与光源重合时的衰减值,(1, 1)为离光源空间最大距离的衰减值。   Unity内部使用_LightTexture0的纹理来计算光源衰减。利用_LightMatrix0变换矩阵来计算点在光源空间的位置。

// 计算衰减纹理坐标值 float3 lightCoord = mul(_LightMatrix0, float4(i.worldPosition, 1)).xyz; // 根据坐标对纹理采样,用dot点乘就是直接做距离的平方,`.rr`的意思就是取得到rgb值的r作为一个新的二维坐标即(r, r)。 fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;

2. 数学公式计算衰减,使用的是线性衰减:

flaot distance = length(_WorldSpaceLightPos0.xyz) - i.worldPosition.xyz); atten = 1.0 / distance;

阴影


Pass { Tags {"LightMode"="ShadowCaster"} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include "UnityCG.cginc" struct v2f { V2F_SHADOW_CASTER;; v2f vert (a2v v){ v2f o; TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) return o; } fixed4 frag(v2f i) : SV_Target { SHADOW_CASTER_FRAGMENT(i) } ENDCG }
最新回复(0)