前一篇 Unity Standard Shader源码阅读(二) AddPass
Standard Shader第三个Pass,用于阴影投射:
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
着色器定义在UnityStandardShadow.cginc中;
先看顶点着色器vertShadowCaster:
VertexOutput vertShadowCaster (VertexInput v
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
, out VertexOutputShadowCaster o
#endif
#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
, out VertexOutputStereoShadowCaster os
#endif
)
{
VertexOutput output;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, output);
#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(os);
#endif
//计算顶点在裁剪空间的位置,存放到output.pos,
TRANSFER_SHADOW_CASTER_NOPOS(o, output.pos)
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
o.tex = TRANSFORM_TEX(v.uv0, _MainTex);
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
#endif
#endif
return output;
}
顶点输入
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv0 : TEXCOORD0;
#if defined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)
half4 tangent : TANGENT;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
顶点输出:
struct VertexOutput
{
UNITY_POSITION(pos);
UNITY_VERTEX_INPUT_INSTANCE_ID
};
out参数:
//顶点传递到片元的附加参数,此处存放到另一个结构体应该是由于先前使用了VPOS,当前没使用了,但延用了先前的拆分
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
struct VertexOutputShadowCaster
{
V2F_SHADOW_CASTER_NOPOS //float3 vec : TEXCOORD0;
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
float2 tex : TEXCOORD1;
#if defined(_PARALLAXMAP)
half3 viewDirForParallax : TEXCOORD2;
#endif
#endif
};
#endif
另一个out参数与vr相关;
再看片元着色器 fragShadowCaster:
half4 fragShadowCaster (VertexOutput input
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
, VertexOutputShadowCaster i
#endif
) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
#if defined(_PARALLAXMAP) && (SHADER_TARGET >= 30)
//使用视差纹理修改uv坐标
half3 viewDirForParallax = normalize(i.viewDirForParallax);
fixed h = tex2D (_ParallaxMap, i.tex.xy).g;
half2 offset = ParallaxOffset1Step (h, _Parallax, viewDirForParallax);
i.tex.xy += offset;
#endif
//获取alpha值,进行alpha测试
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = tex2D(_MainTex, i.tex.xy).a * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip (alpha - _Cutoff);
#endif
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
#if defined(_ALPHAPREMULTIPLY_ON)
//考虑到高光反射,修改alpha值,与BasePass一样
half outModifiedAlpha;
PreMultiplyAlpha(half3(0, 0, 0), alpha, SHADOW_ONEMINUSREFLECTIVITY(i.tex), outModifiedAlpha);
alpha = outModifiedAlpha;
#endif
#if defined(UNITY_STANDARD_USE_DITHER_MASK)
// Use dither mask for alpha blended shadows, based on pixel position xy
// and alpha level. Our dither texture is 4x4x16.
#ifdef LOD_FADE_CROSSFADE
#define _LOD_FADE_ON_ALPHA
alpha *= unity_LODFade.y;
#endif
half alphaRef = tex3D(_DitherMaskLOD, float3(input.pos.xy*0.25,alpha*0.9375)).a;
clip (alphaRef - 0.01);
#else
clip (alpha - _Cutoff);
#endif
#endif
#endif // #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
#ifdef LOD_FADE_CROSSFADE
#ifdef _LOD_FADE_ON_ALPHA
#undef _LOD_FADE_ON_ALPHA
#else
UnityApplyDitherCrossFade(input.pos.xy);
#endif
#endif
//进行阴影投射
SHADOW_CASTER_FRAGMENT(i)
}