Article directory
- Preface
- 1. We urgently need to use the Shader in the previous Offset as a test
- 2. Generate shadows
-
- 1. Add the Pass of “LightMode” = “ShadowCaster”.
- 2. Declare float4 vertex:POSITION; and half3 normal:NORMAL; in appdata. This is the semantics required to generate shadows.
- 3. Add V2F_SHADOW_CASTER in v2f; used to declare the data that needs to be transferred to the fragment.
- 4. Add TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) in the vertex shader, mainly to calculate the offset of the shadow to solve the incorrect Shadow Acne and Peter Panning phenomena.
- 5. Add SHADOW_CASTER_FRAGMENT(i) in the fragment shader
- 3. Let the shadow and the little fox change together as they dissolve
-
- 1. The logic of previous little fox ablation can be reused
Foreword
Shader shadow casting in Unity
1. We urgently need to use the Shader in the previous Offset as a test
Shader’s depth offset Offset in Unity
We will find that the little fox has no shadow at this time. This is because our Shader does not write shadow casting.
2. Generate shadow
1. Add “LightMode” = “ShadowCaster” Pass.
Tags{“LightMode” = “ShadowCaster”}
Need to add a Unity variant
#pragma multi_compile_shadowcaster
Defined in the Pass of LightMode=ShadowCaster, two macros will be automatically generated:
- SHADOWS_DEPTH: Used to generate linear light and spotlight shadows.
- SHADOW_CUBE: used to generate point light shadows.
2. Declare float4 vertex:POSITION; and half3 normal:NORMAL; in appdata. This is the semantics required to generate shadows.
Note: In the appdata section, we almost do not need to modify the name and the corresponding type.
Because many methods encapsulated in Unity use these standard names and types
struct appdata
{
float4 vertex:POSITION;
half3 normal:NORMAL;
};
3. Add V2F_SHADOW_CASTER in v2f; used to declare the data that needs to be transferred to the fragment.
struct v2f
{
V2F_SHADOW_CASTER;
};
4. Add TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) in the vertex shader, mainly to calculate the offset of the shadow to solve the incorrect Shadow Acne and Peter Panning phenomena.
v2f vert(appdata v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
return o;
}
5. Add SHADOW_CASTER_FRAGMENT(i) in the fragment shader
fixed4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i);
}
As you can see, our little fox now has a shadow
After writing this, we can control whether to cast shadows in the Mesh Renderer
3. Let the shadow and the little fox change together as they dissolve
1. The logic of previous little fox ablation can be reused
Final code:
Shader "MyShader/P1_7_2" { Properties { [Enum(Off,0,On,1)]_ZWrite("ZWrite",int) = 0 [Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("ZTest",int) = 0 //Use this tag to expose external attributes and have titles. [Header(Base)] [NoScaleOffset]_MainTex ("Texture", 2D) = "white" {} _Clip("Clip",Range(0,1)) = 0 //Use this tag to add a gap between two rows of exposed attributes [Space(10)] [Header(Dissolve)] _DissolveTex("DissolveTex",2D) = "black"{} [NoScaleOffset]_RampTex("RampTex(RGB)",2D) = "black" {} } SubShader { Tags{"Queue" = "Geometry"} Blend Off Cull Back /*ZWrite [_ZWrite] ZTest [_ZTest]*/ Offset -1,-1 UsePass "MyShader/P1_6_4/XRay" Pass { CGPROGRAM #pragma vertex vert #pragma fragment fragment #include "UnityCG.cginc" sampler2D _MainTex; float _Clip; sampler2D _DissolveTex; //This four-dimensional vector, xyzw represents the xy of Tilling and Offset respectively. The naming method is to add _ST after the texture name. float4 _DissolveTex_ST; //Because when using the gradient texture, only the u coordinate of the gradient texture is used, so replace sampler2D with sampler sampler _RampTex; struct appdata { float4 vertex : POSITION; float4 uv : TEXCOORD0; }; struct v2f { float4 uv : TEXCOORD0; float4 pos : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); //In order to reduce the value passed in, we do not create new variables for storage, but change uv to a four-dimensional vector. //Use xy of o.uv to store the original character map //Use zw of o.uv to store the scaled and offset values of the noise map o.uv.xy = v.uv.xy; //o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw; o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv.xy); //Texture obtained externally needs to be sampled before use fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw); //fragment selection clip(dissolveTex.r - _Clip); //Perform normalization fixed4 dissolveValue = saturate((dissolveTex.r - _Clip) / (_Clip + 0.1 - _Clip)); fixed4 rampTex = tex1D(_RampTex,dissolveValue.r); //col + = rampTex; return col; } ENDCG } //Shadow casting Pass { //1. Set "LightMode" = "ShadowCaster" Tags{"LightMode" = "ShadowCaster"} CGPROGRAM #pragma vertex vert #pragma fragment fragment //Need to add a Unity variant #pragma multi_compile_shadowcaster #include "UnityCG.cginc" //Declare variables used for ablation float _Clip; sampler2D _DissolveTex; float4 _DissolveTex_ST; //2. Declare float4 vertex:POSITION; and half3 normal:NORMAL; in appdata. This is the semantics required to generate shadows. //Note: In the appdata part, we almost don't need to modify the name and corresponding type. //Because many methods encapsulated in Unity use these standard names. struct appdata { float4 vertex:POSITION; half3 normal:NORMAL; float4 uv:TEXCOORD; }; //3. Add V2F_SHADOW_CASTER in v2f; used to declare the data that needs to be transferred to the fragment. struct v2f { float4 uv : TEXCOORD; V2F_SHADOW_CASTER; }; //4. Add TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) in the vertex shader, mainly to calculate the offset of the shadow to solve the incorrect Shadow Acne and Peter Panning phenomena. v2f vert(appdata v) { v2f o; o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex); TRANSFER_SHADOW_CASTER_NORMALOFFSET(o); return o; } //5. Add SHADOW_CASTER_FRAGMENT(i) in the fragment shader fixed4 frag(v2f i) : SV_Target { //Externally obtained texture needs to be sampled before use fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw); //fragment selection clip(dissolveTex.r - _Clip); SHADOW_CASTER_FRAGMENT(i); } ENDCG } } }
Finally we saw that the shadow melted with the little fox and also disappeared at the same time.