1. 向其他物体投射阴影需要ShadowCaster的Pass
Diffuse的Fallback调用的VertexLit中的ShadowCaster Pass来实现向其他物体投射阴影
Pass{
Name"ShadowCaster"
Tage{"LightMde" = "ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
Struct v2f {
V2F SHADOW CASTER;
);
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)//需要v中含有顶点位置与法线信息
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
对物体添加顶点动画或局部剔除时要使阴影与变化一致:需要在ShadowCaster的Pass中做出相应的调整
#例如:在顶点动画中
Pass
{
Tags{"LightMode" = "ShadowCaster"}
CGPROGRAM
float _Manitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct a2v{
float4 vertex : POSITION;
float4 normal :NORMAL;
};
struct v2f{
V2F_SHADOW_CASTER;
};
v2f vert(a2v v)
{
v2f o;
float4 offset ;
offset.xzw = float3(0.0,0.0,0.0);
offset.y = sin(_Frequency*_Time.y + v.vertex.x * _InvWaveLength + v.vertex.y*_InvWaveLength + v.vertex.z*_InvWaveLength )*_Manitude;
v.vertex = v.vertex+offset;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);//
return o;
}
fixed4 frag(v2f i):SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
#例如:存在部分剔除时
Pass
{
Tags{"LightMode" = "ShadowCaster"}
CGPROGRAM
float _ResAmount;
sampler2D _ResMap;
float4 _ResMap_ST;
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f{
V2F_SHADOW_CASTER;
float2 uvBurnMap:TEXCOORD1;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
o.uvBurnMap = TRANSFORM_TEX(v.texcoord,_ResMap);
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed3 burn = tex2D(_ResMap,i.uvBurnMap).rgb;
clip(burn.r-_ResAmount);
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
2. 接收其他物体阴影
(1)首先需要引入内置文件:包含计算阴影时所包含的宏
#include "AutoLight.cginc"
(2)在v2f中添加内置的SHADOW_COORDS宏(用于声明一个用于阴影采样的坐标)
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2) //参数为下一个可用的寄存器
}
(3)在顶点着色器中用TRANSFER_SHADOW计算阴影纹理坐标
v2f vert(atv v){
v2f o;
......
TRANSFER_SHADOW(o);//使用上一步在v2f中定义的SHADOW_COORD
}
(4)在片原着色器中使用计算阴影
fixed shadow = SHADOW_ATTENUATION(i)//参数为v2f,得到阴影值与漫反、高光相乘即可实现接收阴影
3.使用UNITY_LIGHT_ATTENUATION统一计算阴影与光衰
代码基本同上引用
#include "Lighting.cginc"
#include "AutoLight.cginc"
在片元着色器中使用宏同时计算光衰与阴影
fixed4 frag(v2f i):SV_Target{
......
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);//第一各参数主动生成,第二个参数v2f用于SHADOW_ATTENUATION计算阴影,第三个参数为世界空间坐标
return fixed4(ambient+(diffuse+specular)*atten,1);
}
FallBack "Transparent/VertexLit"//对于混合实现的透明物体很难实现投射与接收阴影