Another Terrain Texturing question

Started by
11 comments, last by schupf 15 years, 4 months ago
How do I implement splatting in pixel shader, so that distant parts of the terrain are rendered with low res terrain texture (without detail texture). For blending I do something like this at the end: ... Res = lerp(Temp, Mat, Blend.a) * Bas Bas is low-res terrain texture for the entire terrain. and what about lighting? I'm just doing normal mapping and this is to expensive for distant parts. Thanks
Advertisement
I ussually split the terrain texturing into 2 parts, a basic layer and a detailed layer. The detailed layer is a mix of tiled textures that use vertex(or pixel) weights. The basic layer is just 1 big texture that covers the entire terrain. Farcry/Crysis use a similiar technique, and if you look at the detail textures you will notice that these are heavily satured/grayscaled. The green grass color does not come from the detail texture, its from the base layer.

This combination allows to blend between the basic texture for far-away terrain parts:
result = lerp( detailLayer * baseLayer, baseLayer, distanceFactor )

Everything too far away could use another shader that simply does the base-layer, or an IF statement in your shader to skip the detail-layer part works ok nowadays as well. Furthermore, the detail layer textures can use mipmapping to smooth further.


The lighting is another thing. The base layer texture I was talking about, can also be used as a lightMap. Cheap and simple, but no dynamic lighting. Although you could mix static and dynamic light here. If you don't plan day-night cycle stuff, you could bake the sun or moonlight into the base-layer texture. Extra lights can be projected on top with shadowMaps. If you want a more dynamic solution, you might want to try an Ambient Occlusion map for the sun light. With an AO map, you can still change the sun position/color.

Greetings,
Rick
Thanks for reply.

I'm actually using FarCry terrain textures. It is true, the detail textures are grayscale textures.

I tried your blending formula, but I don't know, what might be a right value for distanceFactor.

Blending works but the distant parts are brighter and the detail parts are darker.

Thanks!
Ah, I noticed that problem. If you look at the FarCry shaders, they are multiplying the detailed result with 2 if I remember correctly. You should play around with a multiplication factor in the shader, something like
baseColor = tex2D( baseLayer, baseTexCoords )detailColor = tex1 * weights.x + tex2 * weights.y + ...detailColor*= 2 <or another value>result = lerp( detailColor * baseColor, baseColor, distance )

I think the actual FarCry shader did something more though, but this simple trick might do the job already. The distance factor is a matter of personal taste as well. The detailed Layer should be completely invisible at the point you won't see the low-res quality of the base layer anymore.... 30 meters? I don't know, just try to tweak your distance factor:
distanceFactor = saturate( pixelCameraDistance / maxDetailRange )

The range where the detailed texture is used as well can make use of mipmaps in the detail textures to create a more smoother transition.

Rick
Thanks,
Multiplying detailed result by 2 fixed the problem. Blending looks fine now.

For dynamic lighting, how do I calculate tangent space vectors in the vertex shader?

Thanks

[Edited by - Hiyar on November 10, 2008 7:57:37 AM]
>> For dynamic lighting, how do I calculate tangent space vectors in the vertex shader?

Sure you need this? Until Crysis lots of terrains did not use normalMapping for the little details. You can use a global normalMap that is stretched over the entire terrain for large details such as cracks in a mountain though. If you are planning to use that, keep in mind that you don't need to mess around with tangents. Just generate that normalMap in 'absolute space' instead of tangent space, which means the pixel color on the normalMap texture represents the world 3D vector, not a local vector.

If you need tangents anyway, I wouldn't calculate them in the vertex shader. There are dozens of examples on the internet where they calculate tangents and biTangents for a group of triangles, and that code is relative intensive for a shader. In fact, I'm not even sure if you can calculate the tangent in a shader with just a normal! Maybe its possible though, you might want to take a look at shaders & animated characters where the normals, and thus also tangents, continously change.

Unless you are planning really wacky terrains, you can pre-calculate all the normal/tangent/biTangents. Store them along with the vertices/texcoords/normals from your terrain. If your terrain deforms (explosion crater), recalculate the tangents for that spot on the terrain.

Greetings,
Rick
How is it done for Crysis, as far as I know there are normalmap textures for each individual detail map.

I don't want the tangents as vertex input, because I have implemented terrain rendering almost the same like explained in this paper-> 5.4 Terrain Rendering. ati.amd.com/developer/SIGGRAPH07/Chapter5-Andersson-Terrain_Rendering_in_Frostbite.pdf
So I'm using a single shared vertex buffer, and I don't want to waste memory for tangents etc.
Heres a trick...only for heightmaps without overhangs, etc.

Just use a flat normal and tangent:

normal= 0,1,0
tangent= 1,0,0
binormal= cross(normal, tangent)

then you can do normal mapping correctly with no precalculation...however, this means that you must have a special normal map that has the main normals calculated from the actual hieghtmap...any detail normal maps must be added to that the large normal map in the pixel shader...like this:

float3 addnormal=lerp(detailnorm.rgb,macronorm.rgb,0.35);
float distSq = 1 - (dot( 2 * (addnormal.xyz - 0.5), 2 * (addnormal.xyz - 0.5)));
addnormal = (distSq*(addnormal-0.5))+(2*(addnormal-0.5));

..........

I use this method because I have a vertex-texture-based terrain (meaning the terrain mesh itself has no inherent vertex normals). You would have to scale the values of your large normal map depending on how steep the final terrain is...
Thanks, I will look into your suggestion.


Another question:
For now, I'm using Crysis and FarCry terrain textures(exported from editor). How are these low-res terrain textures are generated. Using low-res colormaps?

[Edited by - Hiyar on November 23, 2008 7:01:23 AM]
I dont know how its generated in Crysis, but a good bet is this:

at the start of the app render the terrain to texture from the top down, using an ortho projection, with the splatting textures and no lighting. Then in your game project the texture using that matrix...This is how I do it.

This topic is closed to new replies.

Advertisement