Shadow caster code: Code (CSharp): Tags { "RenderType"="TransparentCutout" "Queue"="AlphaTest" "LightMode" = "ShadowCaster" } Blend SrcAlpha OneMinusSrcAlpha AlphaToMask On Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; }; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(float4, _Pos) UNITY_INSTANCING_BUFFER_END(Props) v2f vert (appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz); float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1); float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0); float4 outPos = mul(UNITY_MATRIX_P, viewPos); o.pos = outPos; o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 tex = tex2D(_MainTex, i.uv); clip(tex.a - 0.1); return 0; } ENDCG } Could someone tell me how to make shadow caster billboard effect rotate towards camera, not the caster itself? It causes visual glitches like this:
You need to calculate the orientation in world space using a view matrix that is always for the main camera itself. For example UNITY_MATRIX_V is the current view matrix being used for rendering. You’d need to use something like: Code (csharp): worldCoord.xyz += mul((float3x3)unity_CameraToWorld, vpos); float4 outPos = mul(UNITY_MATRIX_VP, worldCoord);
Now I understand that my technique is wrong. The shadow looks properly only if sprite is shaded from behind (no zwrite): But from the other side: My question now is: How is it possible to shade billboard grass? Should I take another approach or just make a little change? Also if you could guys recommend any good tutorials to learn more complex shaders with problems like this. T My code: Code (ShaderLab): Shader "Engine/GrassShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color ("Color", Color) = (0, 1.0, 0, 1) _Normal("Normal", Vector) = (0.0, 0.0, 0.0, 0.0) _Pos("Normal", Vector) = (0.0, 0.0, 0.0, 0.0) _SemiShadow("Semi Shadow", Color) = (0, 0.6, 0, 1) _SemiShadowThreshold("Semi Shadow Threshold", Float) = 0.4 _Shadow("Shadow", Color) = (0, 0.3, 0, 1) _ShadowThreshold("Shadow Threshold", Float) = 0.2 _TestTex("TestTex", 2D) = "white" {} } SubShader { Tags { "RenderType"="TransparentCutout" "Queue"="AlphaTest" "LightMode"="ForwardBase" } Blend SrcAlpha OneMinusSrcAlpha AlphaToMask On Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #pragma multi_compile_fwdbase #define FORWARD_BASE_PASS #include "UnityCG.cginc" #include "UnityLightingCommon.cginc" #include "AutoLight.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; float3 normal : NORMAL; float3 worldPos : TEXCOORD1; SHADOW_COORDS(2) }; uniform sampler2D _TestTex; uniform float4 _TestTex_ST; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform float3 _Color; uniform float3 _SemiShadow; uniform float _SemiShadowThreshold; uniform float3 _Shadow; uniform float _ShadowThreshold; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(float4, _Normal) UNITY_DEFINE_INSTANCED_PROP(float4, _Pos) UNITY_INSTANCING_BUFFER_END(Props) v2f vert (appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz); float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1); float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0); float4 outPos = mul(UNITY_MATRIX_P, viewPos); o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.pos = outPos; o.normal = normalize(UnityObjectToWorldNormal(UNITY_ACCESS_INSTANCED_PROP(Props, _Normal))); o.uv = TRANSFORM_TEX(v.uv, _MainTex); TRANSFER_SHADOW(o) return o; } fixed4 frag (v2f i) : SV_Target { fixed4 tex = tex2D(_MainTex, i.uv); clip(tex.a); UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos); float diffuse = dot(i.normal, _WorldSpaceLightPos0.xyz) * atten; float3 cel = diffuse < _ShadowThreshold ? _Shadow : (diffuse < _SemiShadowThreshold ? _SemiShadow : _Color); fixed4 col = fixed4(cel * _LightColor0, tex.a); #if defined(FORWARD_BASE_PASS) col += float4(max(0, ShadeSH9(float4(i.normal, 1))).rgb, 0.0); #endif return col; } ENDCG } Tags { "RenderType"="TransparentCutout" "Queue"="AlphaTest" "LightMode" = "ShadowCaster" } Blend SrcAlpha OneMinusSrcAlpha AlphaToMask On Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; }; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(float4, _Pos) UNITY_INSTANCING_BUFFER_END(Props) v2f vert (appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz); float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1); worldCoord.xyz += mul((float3x3)unity_CameraToWorld, vpos); float4 outPos = mul(UNITY_MATRIX_VP, worldCoord); o.pos = outPos; o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 tex = tex2D(_MainTex, i.uv); clip(tex.a - 0.1); return 0; } ENDCG } } }
That just looks like you like the look of the grass with shadow casting disabled. Regardless of how you’re rendering the grass, there should be an option to disable the shadow casting, either on the component or the script function being used.