使用Unity Shader的阴影计算宏时需要注意的东西
旧版本
在Unity的旧版本中,根据TRANSFER_SHADOW的宏定义,a2v结构体中的顶点坐标变量名必须是vertex,顶点着色器的输入结构体a2v必须命名为v,且v2f中的顶点位置变量必须命名为pos。
#if defined (SHADOWS_SCREEN)
#if defined(UNITY_NO_SCREENSPACE_SHADOWS)
UNITY_DECLARE_SHADOWMAP(_ShadowMapTexture);
#define TRANSFER_SHADOW(a) a._ShadowCoord = mul( unity_WorldToShadow[0], mul( unity_ObjectToWorld, v.vertex ) );
inline fixed unitySampleShadow (unityShadowCoord4 shadowCoord)
{
#if defined(SHADOWS_NATIVE)
fixed shadow = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, shadowCoord.xyz);
shadow = _LightShadowData.r + shadow * (1-_LightShadowData.r);
return shadow;
#else
unityShadowCoord dist = SAMPLE_DEPTH_TEXTURE(_ShadowMapTexture, shadowCoord.xy);
// tegra is confused if we use _LightShadowData.x directly
// with "ambiguous overloaded function reference max(mediump float, float)"
unityShadowCoord lightShadowDataX = _LightShadowData.x;
unityShadowCoord threshold = shadowCoord.z;
return max(dist > threshold, lightShadowDataX);
#endif
}
#else // UNITY_NO_SCREENSPACE_SHADOWS
UNITY_DECLARE_SCREENSPACE_SHADOWMAP(_ShadowMapTexture);
#define TRANSFER_SHADOW(a) a._ShadowCoord = ComputeScreenPos(a.pos);
inline fixed unitySampleShadow (unityShadowCoord4 shadowCoord)
{
fixed shadow = UNITY_SAMPLE_SCREEN_SHADOW(_ShadowMapTexture, shadowCoord);
return shadow;
}
#endif
#define SHADOW_COORDS(idx1) unityShadowCoord4 _ShadowCoord : TEXCOORD##idx1;
#define SHADOW_ATTENUATION(a) unitySampleShadow(a._ShadowCoord)
#endif
新版本
在Unity的新版本中,使用TRANSFER_SHADOW_CASTER_NORMALOFFSET来计算阴影的纹理坐标,根据其源码的定义,顶点着色器的输入结构体a2v必须命名为v,且v2f中的需要有法线变量normal,裁剪空间的位置向量vertex.
#define V2F_SHADOW_CASTER V2F_SHADOW_CASTER_NOPOS UNITY_POSITION(pos)
#if defined(SHADOWS_CUBE) && !defined(SHADOWS_CUBE_IN_DEPTH_TEX)
// Rendering into point light (cubemap) shadows
#define V2F_SHADOW_CASTER_NOPOS float3 vec : TEXCOORD0;
#define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) o.vec = mul(unity_ObjectToWorld, v.vertex).xyz - _LightPositionRange.xyz; opos = UnityObjectToClipPos(v.vertex);
#define TRANSFER_SHADOW_CASTER_NOPOS(o,opos) o.vec = mul(unity_ObjectToWorld, v.vertex).xyz - _LightPositionRange.xyz; opos = UnityObjectToClipPos(v.vertex);
#define SHADOW_CASTER_FRAGMENT(i) return UnityEncodeCubeShadowDepth ((length(i.vec) + unity_LightShadowBias.x) * _LightPositionRange.w);
#else
// Rendering into directional or spot light shadows
#define V2F_SHADOW_CASTER_NOPOS
// Let embedding code know that V2F_SHADOW_CASTER_NOPOS is empty; so that it can workaround
// empty structs that could possibly be produced.
#define V2F_SHADOW_CASTER_NOPOS_IS_EMPTY
#define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) \
opos = UnityObjectToClipPos(v.vertex.xyz); \
opos = UnityApplyLinearShadowBias(opos);
#define TRANSFER_SHADOW_CASTER_NOPOS(o,opos) \
opos = UnityClipSpaceShadowCasterPos(v.vertex, v.normal); \
opos = UnityApplyLinearShadowBias(opos);
#define SHADOW_CASTER_FRAGMENT(i) return 0;
#endif