Using HLSL for rendering terrain with multiple textures

Started by
9 comments, last by p0is0n 16 years ago
Hi, I have a terrain engine writen in C++ with directX9. My engine uses the fixed function pipeline. What I want to do is use HLSL to render the terrain with texture blending. At the moment my terrian is textured depending on the height at that point. e.g. if the height is below 50 a grass texture is used, if it is between 50 - 100 a rock texture is used and so on. I have written a simple fx file that uses 2 passes to blend 2 textures together (stretched over the terrain). What I need to do is to change this so that different textures are used depending on the height of the terrain. Does anyone have any pointers on how I would do this?, and what I would need to change to get it to work? I have looked around and found lots of information on how to use HLSL, effect files and so on, but I cannot figure out how to do this. Any help would be appreciated.
Advertisement
Couldn't you just pass your textures in your effect and have your shader determine what texture to use:

//vertex shader:
height is TEXCOORD2;

OUT.height = worldPos.xy;

//pixel shader:
if (IN.height.y < grassHeight)
tex2D(grassTexture, IN.tex);
if (IN.height.y >= grassHeight
tex2D(groundTexture, IN.tex);


Would this not work?
Jeff.

[edit was for naming worldPos.y in pixel shader should be IN.height.y (since your passing this from your vertex shader)]

[Edited by - webjeff on March 19, 2008 4:20:30 PM]
That definately sounds like it would work, i'll give it a shot.

Thanks for the reply.
If in this case definitely the best solution to use dyn. branching? I don't know how how slow it is. Tex2D all the layer textures and blending will be slower I suppose... but using dyn. branching there must be hard transition between layers...
-----KEXIK - Reversity Studios (www.reversity.org)
webjeff's basic idea would work for selecting a primary texture. If you wanted them blended, you could extend that to pick two textures and lerp between the two based on the coordinate. It would look a little bit like this:

const float grassHeight = 50;const float rockHeight = 100;const float snowHeight = 150;float4 texColor1;float4 texColor2;float lerpVal;if ( height < grassHeight ){     texColor1 = tex2D( grassSampler, texCoord );     texColor2 = tex2D( grassSampler, texCoord );     lerpVal = 0;}else if ( height < rockHeight ){     texColor1 = tex2D( grassSampler, texCoord );     texColor2 = tex2D( rockSampler, texCoord );     lerpVal = ( height - grassHeight ) / ( rockHeight - grassHeight );}else if ( height < snowHeight){     texColor1 = tex2D( rockSampler, texCoord );     texColor2 = tex2D( snowSampler, texCoord );     lerpVal = ( height - rockHeight ) / ( snowHeight - rockHeight );}float4 terrainColor = lerp( texColor1, texColor2, lerpVal );


Of course, it's important to keep in mind that unless this is compiled to ps_3_0 and also altered in a few ways, the shader won't use any dynamic branching. This means that all of the branches will be taken (and all of the terrain textures sampled), and the desired result is chosen at the end.
Quote:Original post by KEXIK
If in this case definitely the best solution to use dyn. branching? I don't know how how slow it is. Tex2D all the layer textures and blending will be slower I suppose... but using dyn. branching there must be hard transition between layers...


Dynamic branching probably wouldn't bee too bad in this case, at least for terrain that's close to the camera. Dynamic branching generally only good when large groups of adjacent pixels choose the same branch, which you probably would get for most terrain. Also you wouldn't have hard boundaries with something like the code I posted.

I think the ultimate solution in this case might be to use a texture atlas, and have the shader calculate the proper texture coordinate to use from the atlas. This would guarantee that you don't sample more than you have to, but it would also complicate things in a few ways.

Thanks for all the replies.

I think i understand everything mentioned, but just to be sure, is a texture atlas just like a sprite sheet?
i.e all of the textures that are going to be used for the terrain are put into one texture, and a texture is picked using the texture co-ordinates for that area.
Yes, it's usually called texture atlas... but my another idea is to use volume texture, but I don't know what is the best for your task.
-----KEXIK - Reversity Studios (www.reversity.org)
Thanks, I think i'll try it using a texture atlas first seeing as that's what I was using for my textures with the fixed function pipeline. I just didnt know that there was a name for it.
In my terrain engine I use a 5th opacity map (among grass, sand, snow and rock) where I store the texture weights in the RGBA channels. This way I'm not limited to height-based texturing, but I can put my textures anywhere I like, for example depending on slope, region and other factors. This opacity map requires preprocessing, though.

This topic is closed to new replies.

Advertisement