陰影處理
1、物體能投射陰影以及物體能接受陰影為兩個(gè)方面。
a.物體投射陰影在unity中應(yīng)該打開CastShadow選項(xiàng)。這樣物體深度就可以加入到深度紋理的計(jì)算中,從而影響深度紋理中的depth值。這個(gè)深度紋理生成unity3D中采用的方法與OpenGL大同小異,即:以光源位置,光源方向?yàn)橄鄼C(jī)參數(shù),得到相應(yīng)的深度紋理。
b.物體接受陰影,這個(gè)過程是判斷正常相機(jī)下看到的片段是否在陰影中,采用的方法是傳遞光源下相機(jī)的MVP,然后做position變換到clip空間,然后對(x,y)做[0,1]處理,根據(jù)這個(gè)處理后的值對上一步中的深度紋理進(jìn)行采樣得到相應(yīng)的深度d0,如果d0<postion.z([0,1]變換后的depth值),說明這個(gè)片段在陰影中,應(yīng)該對顏色進(jìn)行乘以shadow值。
2、Unity3D shader中寫法。
unity3d中讓物體參與到陰影紋理的生成中,除了castShadow打開外,要在pass中執(zhí)行上述說的深度紋理生成,此過程一般不放到basePass與addtionPass中,因?yàn)檫@兩個(gè)pass一般進(jìn)行光照計(jì)算,而深度紋理計(jì)算只是得到深度紋理,因此可以使用一個(gè)單獨(dú)的pass,即“LightMode” = “ShadowCaster”的pass來得到。而這個(gè)pass一般在FallBack “Diffuse”等FallBack中得到。
接受紋理可以用下面步驟:
a.單獨(dú)處理shadow可以在v2f中添加SHADOW_COORD(x) ,x為下一個(gè)可以使用的寄存器編號。注意使用這個(gè)宏最后不加“;”,因?yàn)檫@個(gè)定義是在struct中,且在“autolight.cginc”的定義中已經(jīng)添加了最后的分號。
b.在vert中使用TRANSFER_SHADOW(o);這個(gè)宏可以將v2f變量o中的紋理采樣坐標(biāo)變換得到相應(yīng)的屏幕空間紋理,為采樣深度紋理使用。
c.在frg中使用SHADOW_ATTENUTION(i),計(jì)算對應(yīng)的fragment是否在shadow中,這個(gè)宏返回一個(gè)fixed值,然后將此值與frag中得到的col值相乘,即可得到相應(yīng)的陰影效果。
3、實(shí)例代碼
Shader "FFD/shadow1"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"}
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//要想有正確的衰減內(nèi)置變量等,必須要有這句
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "autolight.cginc"
#include "lighting.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
SHADOW_COORDS(1) //宏表示為定義一個(gè)float4的采樣坐標(biāo),放到編號為1的寄存器中
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
TRANSFER_SHADOW(o) //根據(jù)變換求解上面結(jié)構(gòu)體中的float4坐標(biāo),unity5中采用的是屏幕空間陰影貼圖
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
fixed shadow = SHADOW_ATTENUATION(i); //根據(jù)貼圖與紋理坐標(biāo)對紋理采樣得到shadow值。
col = col*shadow; //最終影響光照
return col;
}
ENDCG
}
}
FallBack "Specular"
}