Hello,
I want to dynamically shade my terrain depending on the sun position.
This is what I have as input for my terrain shader:
A Terrain Texture, Sun Direction and a Shading Color (called diffuseSunColor). I get the shading color by interpolation between white,red and black depending on sun position (for example if the sun is low on the horizon the Shading color would be redish).
This was my first approach to shade my terrain (HLSL PS4.0):
return diffuseTexture.Sample(samLinear, input.Tex) * max(0, dot(input.Normal, sunDir) );
So I just do a simple diffuse lighting and mul it with the texture. But here the first two problems approach:
1) The terrain gets too dark if the sun goes down. This is logical since most of my terrain normals point up and if the sun is close to the horizon (for example (0, 0.2, 0.8)) then the dot product is close to 0. I could add a little offset:
saturate( max( 0, dot(input.Normal, sunDir) ) + 0.4 )
but then most of the time my terrain looks flat (as If I just would use an ambient term). Any ideas what I could do to make it look 3D but not completely dark at sunset?
2) Imagine a hill and on the right side of the hill the normals point to the right (for example (0.5, 0.3, 0) and when my sun disappered (below the horizon, so sunangle < 0) then this hill still gets shaded. This looks really bad.
But I cant just make a clamp like if(sunangle < 0) diffuse = 0; because then the terrain would get dark abruptly. Any ideas to solve this problem?
Currently my terrain Pixelshader is this:
return diffuseTexture.Sample(samLinear, input.Tex) *
saturate( max( 0, dot(input.Normal, sunDir) )+0.6) * diffuseSunColor;
I use the offset of 0.6 so that the diffuse factor is at least 0.6 to avoid a complete dark terrain. Unfortunately if the sun is high my terrain looks flat.
Any ideas for a simple but better terrain shading formula?
Thanks!