Surface Shader: Vertex Displacement - shadows aren't adjusted...

I have a shader that is supposed to warp terrain the further it is away from the camera. The problem is shadows are still based off the un-deformed vertices, which casts against the deformed terrain. Essentially casting a shadow on itself.

Googling around said I need to use ‘addshadow’, but it doesn’t do anything for me.

Anyone have any ideas?

Shader "Cylinder/Diffuse-Cyl" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		Cull Back

		CGPROGRAM
		#pragma surface surf Lambert vertex:vert addshadow

		sampler2D _MainTex;
		fixed4 _Color;
		float CURVE_OFFSET;

		void vert(inout appdata_full v)
		{
			if(CURVE_OFFSET != 0)
			{
				float4 vpos = mul(UNITY_MATRIX_MVP, v.vertex);
				float l = length(float2(vpos.x, vpos.z));
				v.vertex.xyz += mul(_World2Object, float4(0,-1,0,0)) * l * l * CURVE_OFFSET;
			}
		}

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}

		ENDCG

	}

	Fallback "Diffuse"
}

(note: CURVE_OFFSET is a global value, it’s constant through out the game. I usually have it set to 0.001 → 0.004)

No assistance?

I really would like to know how to make dynamic shadows be calculated off the deformed mesh, and not the original mesh.

I’ve been searching around, playing with the shader, and just gambling left and right with no luck.

Does anyone have resources on how the dynamic shadows are calculated?

Images of the problem…

here is what it looks like with out the vertex deformation, everything is correct:

here is with the deformation, NO SHADOWS, works

here is with the deformation, shadows included, note the shadowing on the terrain… that is coming from what would be the terrain if it weren’t deformed.

One last bump for good measure…

That seems strange to me. As far as I can tell, specifying a custom vertex function in a surface shader generates appropriate shadow passes. Everything should just work. The standard tree shaders use the same approach, and their shadow passes reflect distortion from wind.

Does your shader produce correct shadows when used on regular meshes? If so, then perhaps terrain shadows are handled in a special way. In this case, you might have to get input from Unity on whether the terrain shadow pass can be replaced.

As an aside, you should avoid branching (usually if statements) in shaders whenever possible. It could very well be being optimized out by the compiler in this case, but it’s very unlikely that you’ll gain any performance on any hardware by enclosing your vertex function in a conditional.

the mesh is just a basic mesh, it’s not a special terrain mesh.

And the conditional isn’t for efficiency, it’s for turning it on or off from scripting side in game. Removing it doesn’t change anything.

You are making changes to vertex positions, but not updating its normals. Hence you will not get shadows on the modified vertex data.

do the same for normals:
v.normal = normalize(v.normal + mul(_World2Object, float4(0,-1,0,0)) * l * l * CURVE_OFFSET);

Wow… that’s a necro of a very old post of mine.

This game is WAYYYYY in my past.

1 Like

Just FYI This was 6 years old when you resurrected it XD

hah, I did see that, but as no answer was posted, I thought to post it so that anyone who is wandering in search for it would find it helpful :slight_smile:

Haha, back in those days I was learning computers :stuck_out_tongue:

1 Like