Modified Terrain Shader (auto-texturing)

Posted By: Zelek

Modified Terrain Shader (auto-texturing) - 03/19/08 16:36

I'm new to shaders, but I've been working on a modified version of the popular terrain multitexturing shader (I think the version I started with was last modified by Loopix). I've made it possible to texture the terrain without providing a blendmap. Instead, it uses a normal map to locate "steep" areas of the terrain and gives those areas a different texture than flat areas. Here's how that looks:



Now it's not too exciting to have only two textures for a terrain, so I implemented three different texture "levels" (low/med/high) so you can have a mountain texture on high areas and maybe dirt on low areas:



I wanted to see if anyone had ideas on ways to improve this or make it more efficient. Currently, the normal map has to be added as a skin to the terrain ahead of time. If I passed the normal information from the vertex shader to the pixel shader, it seems I could find this information automatically (for texturing dynamically generated terrain?). Is this more or less efficient than including a normal map skin?

Here's the important part of the code (the only difference in the vertex shader is that it passes the xyz position):
Code:

// pixelshader
float4 ps( TMULTI_VS_OUT In ) : COLOR {
float tex1_max = 110.0; //the upper boundary of the first texture
float tex2_middle = 100.0; //the middle texture will be strongest at this height
float tex2_width = 120; //the total height the middle texture should cover
float tex3_min = 90; //the height that the top texture will begin at
float tex3_max = 270; //the heightest point of your terrain
float impassable_strength = 8.0; //the strength of the steep texture
float brightness = 0.2; //the overall brightness

float4 NormalMap = tex2D(sTex1,In.Tex1);
float4 ShadowMap = tex2D(sTex2,In.Tex2);
float4 LowTex = tex2D(sTex8,In.Tex8);
float4 MidTex = tex2D(sTex9,In.Tex9);
float4 HighTex = tex2D(sTex10,In.Tex10);
float4 SteepTex = tex2D(sTex11,In.Tex11);

float4 FinalColor;
float theHeight = In.Pos_xyz.y; //the height of the current position
float tmpHeight = theHeight; //for use by each of the textures

//this is how you uncompress a normal map
float3 normal = 2.0f * NormalMap.rgb - 1.0f;

//show the SteepTex in areas with a very low normal.z
normal.z = pow(normal.z, impassable_strength);
normal.z = saturate(normal.z);
FinalColor = lerp(SteepTex, MidTex, normal.z);

//draw the low textures at low heights
if(tmpHeight <= tex1_max) {
tmpHeight /= tex1_max;
FinalColor = lerp(LowTex, FinalColor, tmpHeight);
}

//blend in the middle texture
tmpHeight = theHeight;
float tex2_min = tex2_middle - (tex2_width/2.0);
float tex2_max = tex2_middle + (tex2_width/2.0);
if (tmpHeight > tex2_min && tmpHeight < tex2_max) {
tmpHeight -= tex2_middle;
tmpHeight = abs(tmpHeight)*2.0;
tmpHeight /= tex2_width;
FinalColor = lerp(MidTex, FinalColor, tmpHeight);
}

//draw the high texture
tmpHeight = In.Pos_xyz.y;
float tex3_width = tex3_max-tex3_min;
if (tmpHeight >= tex3_min && tmpHeight <= tex3_max) {
tmpHeight -= (tex3_width/2.0);
tmpHeight /= tex3_width;
FinalColor = lerp(FinalColor, HighTex, tmpHeight);
}

//blend in the shadow map and prevent transparency
FinalColor = FinalColor*(ShadowMap+brightness);
FinalColor.a = 1.0f;
return FinalColor;
}


Posted By: erbismi

Re: Modified Terrain Shader (auto-texturing) - 03/19/08 20:07

this is a great idea
maybe randomise a couple of textures for each area, to make it look a bit more interesting. Its lookin pretty good atm, keep it up!
Posted By: Zelek

Re: Modified Terrain Shader (auto-texturing) - 03/19/08 23:26

Thanks! It would probably look better if the textures I used were more varied (like little rocks and dirt patches mixed in with the grass). For testing purposes though, it helped me to be able to see exactly where one texture was ending and another one was starting.

Question 1: If the vertex shader modifies the XYZ position of the terrain, how do I recalculate the normal?
Question 2: Is there some way I can get around the need for a predefined shadow map? ( maybe an algorithm for dynamically calculating this in the pixel shader?)
© 2024 lite-C Forums