Skip to main content
gamedev.net
🔒 Locked

Terrain Texturing

Started by Hiyar 6 replies 2.1k views
Original Post
Hiyar
Hiyar
Hi, I'm beginner in writing shaders, and I'm trying to implement texture-splatting in shader(fx file). My first question is: Do I need to define texture samplers for each texture? Actually, I don't want to use a fixed number of textures. Second question: How do I generate texture coords for cliffs? and correct texture distortion? [Edited by - Hiyar on September 29, 2008 5:20:57 AM]
Matt Aufderheide
Matt Aufderheide
You must always define each individual texture sampler, unless you are using DirectX10 which supports texture arrays.

There may be a way to use 3D texture to get access to more than one texture per sampler, but i have not had much success with this. Also there are ways to use texture atlasing, but this doesnt work well with tiling, as seams are impossible to get rid of completely.

The other option is have a giant virtual texture (like 64,000 * 64,000), and then stream in chunks from this dynamically (clipmapping, mega texture, etc.).

Then there is the possiblity or using procedural textures, generated with methods like perlin noise, but realism is difficult unless you do a lot of complex stuff (procedural rock is a lot easier than grass).

So unless you are prepared to spend a long time or only support the newest hardware and API, you're best bet is splatting. To date, most commercial games still use a form of splatting for terrain texturing.

----------------------------------------------------------------------------------

as far as tex coords for steep angles: most engines dont bother.

it really depends on how you are modelling terrain. If you are using heightmaps, you cant have a vertical surface anyway. If you are using a special mesh where you define everything in modelling program, you can relax UVs to make less distortion, but this affects everything.

You can try another trick: take samples from multiple directions...most terrain uses what is the tiled equivalent of a projected texture from directly above. You can also take two additional samples, using projective coords from the front-back and left-right. Then you blend between these samples using the surface normal.

That approach however needs 3 times the samples for every texture, so you will need a huge amount of texture samples if you are doing splatting.

--------------------------------------------------------------------------------

Most current engines use consistent top-projection coords, and use a discrete number of texture samples. Each terrain "chunk" or whatever may use both different and shared textures.
Hiyar
Hiyar
thanks for response

using projective coords is a good idea, but I don't know how to do this in shader(implementation details, some code examples might help)

For splatting:
How do I combine the textures most efficient way. If I use rgb colors of a texture for blending, I'm limited by 3 texture per terrain sector. Therefore I'm using a grayscale blend map for each color texture on terrain sector and combine the textures using lerp operator. is that okay?

Another question is, how do I combine normalmaps?
Matt Aufderheide
Matt Aufderheide
For the basic coords for a heightmap, just UV map the grid like any plane mapping...when the grid is distorted by the heightmap, this is the same as top-projected coords.

To generate additional projective cordinates, you will need to define a view, projection, and offset matrix. There are many articles and discussions of projective texturing. The basic methodto make a side view projection for terrain: make a view matrix and put it's world coords at 0,0,0 and lookat 90,0,0 ..then define a basic ortho matrix, doesnt matter what params, and multiply these matrices. Then make an offset matrix like :

float fTexOffs = 0.5f + (0.5f / float(800.0f));
matTexAdj= D3DXMATRIX ( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
fTexOffs, fTexOffs, 0.0f, 1.0f );

Then you multiply that by the world space of the terrain to a get a 3d coord...then to take a tiled projection sample your best is to devide the xy/z to get 2d homogenous coords and sacale that accordingly for the tex2D() sample

IF this doesnt make any sense I can clarify it :)

------------------------------------------

you can combine textures in numerous ways. You can actually use the RGBA chanels of a single texture to do 4 textures...just make sure it has the alpha channel. Or you can use 2 blend texture giving you 8 textures.

Also, you can use vertex data to blend textures. IN your vertex declaration just define any number of float 4 components or colors or whatever, and you do lots of blends this way.. you can specifiy the valuesfor each vertex by reading any number of textures in your application and putting the data in the vertex buffer...this only gives you per vetex data which is interpolated..

Aditionally, you can use procedural methods to blend textures...values such as slope and height can caluculated and wieghted accordingly.

-------------------------------------------

Ultimately, i suggest you first make a basic shader that just does one tiled texture with standard UV coordinates to get a basic feel for what to do..then come up with various blending schemes. Remember that tiled textures look very repetitive, so eventually you may want to try to some kind of macro-texturing.
Hiyar
Hiyar
I have already made basic shader for splatting, before I created this thread. But I wanted to reduce the number of the texture samplers. I have used blendmaps for each color texture. This was the problem.

Okay, I will try your suggestions, thanks.

Edit: So, I tried to use two blendmaps for 6 textures, but I don't know how to combine them at the end to get the final color.

I'm combining textures with lerp, like that (using blendmap for each texture):

float3 lerpOp(float3 src0, float3 src1, float3 src2)
{
return src0 * src1 + (1 - src0) * src2;
}

or alternatively I can use one blendmap and use the rgb channels for blending, like so:

float3 blendColor = tex2D(BlendMapSampler, tex1).rgb;

float3 texColor01 = tex2D(sampler01, tex0).rgb;
float3 texColor02 = tex2D(sampler02, tex0).rgb;
float3 texColor03 = tex2D(sampler03, tex0).rgb;

float inv = 1.0f / (blendColor.r + blendColor.g + blendColor.b);

texColor01 *= blendColor.r * inv;
texColor02 *= blendColor.g * inv;
texColor03 *= blendColor.b * inv;

float3 texFinal = (texColor01 + texColor02 + texColor03);


I don't know how to use two blendmaps for 6 textures

[Edited by - Hiyar on October 1, 2008 6:38:13 AM]
dpadam450
dpadam450
You can bind 8 textures total (maybe more on newer cards).

So: if you use RGBA (4 terrain types) per texture

SplatMap1 = RGBA
type1,type2,type3,type4

Thats 5 textures.

SplateMap2 = RGBA //6, so 2 more
type5, type6

There is your answer. For the second part, you do the same:

inv = 1/(blendColor.r + g + b + blendColor2.r + g + b)

Basically a given pixel cant add up to more than one, otherwise your terrain will look stupid. Just a note though, you should already save them in the texture "normalized". Meaning the textures R+G+B should = 255;
NBA2K, Madden, Maneater, Killing Floor, Sims 
Matt Aufderheide
Matt Aufderheide
I'm not sure I understand the blending method being used here..

I just do this:

lerp(tex1,tex2,blend1);
lerp(tex1,tex4,blend2);
lerp(tex1,tex5,blend3);
...etc

you dont even need specific blend texture for the first texture or base.
Waramp81
Waramp81
You can actually have 5 blend amounts per RGBA texture, the 5th is just implicit. Just make sure the RGBA blend factors don't sum to 1, and the 5th becomes the remainder. ie:

Tex0 = Blend.r;
Tex1 = Blend.g;
Tex2 = Blend.b;
Tex3 = Blend.a;
Tex4 = 1.0f - (Blend.r + Blend.g + Blend.b + Blend.a);


If you are using PS 3.0, then you can avoid this method altogether, and pack 16 or so 512x512 (or whatever) textures into a 2048x2048 texture, then use the height and slope of a pixel to index into this atlas.

for more info, see Ysaneya's journals at:
http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=263350&cmonth=4&cyear=2008

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.