Sign in to follow this  

Stumped on Terrain Texture Blending (screenshots)

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have put together a terrain engine where each quad can have its own texture. Where I am stuck is how to get these textures to blend together. I can't seem to find a tuturial that shows how to do it. Can anyone help me out or point me to a resource that shows how to do this? Basically, I want to take this: And turn it into this: Each of my vertices contains this info (C#):
public struct MyVertex
{
	public float X, Y, Z;	
	public Vector3 Normal;
	public float Tu1, Tv1;
	public float Tu2, Tv2;
}



Thanks! [Edited by - strahan on August 20, 2004 3:46:04 PM]

Share this post


Link to post
Share on other sites
Hi strahan:

I'm not the most experienced to talk, but in my vision as player I've to say that normally textures aren't merged by the software (As far As I Know...). In many simulators I've played with there is a transition texture that is used to merge the two parts (i.e green to mud).

Just trying to help!

Bye! :)

Share this post


Link to post
Share on other sites
ok man, you're half way there. next step, take an alpha map and map each pixel to each quad in your landscape. you'll need a map for each texture you'll want to blend.

as you draw each texture you'll look up the appropriately mapped alpha value and do a blend.
to calculate the amount a given texture weights on the quad, look at each adjacent texture and calculate a weighting system.

in most cases you'll need to multipass if you have several textures and want to support legacy hardware.


just google charles bloom texture splatting for a better explanation.

Share this post


Link to post
Share on other sites

Dreddnafious Maelstrom-

How do I create this Alpha Map? Is there a tool that does this?

Also, I don't understand how the grass for example would carry over partially into another quad or the dirt would carry over partially into the grass quad (see screenshots).

Do both the grass and dirt textures get assigned to the same quad?


FoxHunter2 - To map a texture to each quad I simply set the TU and TV coordinates to 0,0 at the upper-left, and 1,1 at the lower right coordinates of the quad.

Kwizatz- I have seen this article but unfortunately it does not do what I want. I want the user to be able to paint the terrain regardless of the height of the terrain.

Thanks everyone.

Share this post


Link to post
Share on other sites
How complicated are you willing to get and what target audience do you want? If you use a pixel shader, this is pretty easy. You can send 4 textures in, one for grass, one for rocks, one for snow, then a fourth texture who's green value contains the transparency of the grass, who's red value contains the transparency for the rock and who's blue value contains the transparency for the snow. All three values (red, blue, green) add up to 1.0. So you may get 10% snow, 50% rock, and 40% grass for instance. Then combining these in the pixel shader to calculate the final pixel color is super easy.

The fourth texture would be created at run-time and be based on the terrain's height. You would take each quad of the terrain, then create a linear transparency texture for the quad. This means that you would calculate the transparency for each terrain texture (rock, grass, snow) at some terrain height. For instance, you'd set the transparency texture's top left and bottom left blue value(snow) corresponding to how high the terrain point is. If it's at some maximum point, the blue value gets 1.0, and red and green are set to 0. If it's mid-way up to the max height value, you set the blue value to 0, because there's no snow half way down the mountain, and set the red value (rocks) to 15% and the green value (grass) to 85%.

These values are specified at design time in a lookup table. Grass will be 100% prevalent at ground height 0 and will fade out to 0 at 3/4 of the max height. Rocks will be 0 at 1/2 max height, 100% at 3/4 max height, and 0 at 15/16 max height. Snow will be 0 at 3/4 max height and 100% at max height. I hope that makes some sense.

Anyway, you find the transparency of each point in the quad, then linearly interpolate between them to create the rest of the texture.

Chris

Share this post


Link to post
Share on other sites
Take a look at the texture ops D3DTOP_LERP, D3DTOP_BLENDDIFFUSEALPHA, D3DTOP_BLENDTEXTUREALPHA, and D3DTOP_BLENDCURRENTALPHA. For example, to do what you want for two textures A and B in D3D8:


Device->SetTexture(0, TextureA);
Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);

Device->SetTexture(1, TextureB);
Device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA); // lerp between TextureA and TextureB based on the alpha in the vertex
Device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
Device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);


Its a bit trickier for more than 2 textures. I've only managed to get 3 textures in one pass (with slightly wrong blending, but looks fine), and if there are more than 3 layers, I have only figured out how to do one layer per pass * n textures.

A pixel shader would be easiest to do this, I'm trying to avoid them for lower end hardware, but you may want to use them. The equation you would basically be looking for to do this in a pixel shader would be:

Texture1 * Weight1 + Texture2 * Weight2 + Texture3 * Weight3 + Texture4 * (1 - (weight1 + weight2 + weight3))

Share this post


Link to post
Share on other sites
OK. I am trying to get D3DTOP_BLENDDIFFUSEALPHA to work first but so far I just see the texture rendered as normal on the quads (no fading in or out):


device.SetTexture(0, _Texture1);
device.SetTextureStageStat(0,TextureStageStates.ColorOperation, (int) TextureOperation.BlendDiffuseAlpha);
device.SetTextureStageStat(0,TextureStageStates.ColorArgument1, (int) TextureArgument.TextureColor );
device.DrawPrimitives( PrimitiveType.TriangleList, 0, offset/3 );



My question is what values do I set for the diffuse color of the vertices.

That is, what colors make the texture stand out more and what colors make it fade more?

I noticed this value is a Int32 value, not a float so I can't set it to like 0.4.

Thanks!

Share this post


Link to post
Share on other sites
Hows your terrain organised? Are you using one set of vertices for the entire terrain or a seperate buffer for each section?

Anyway, what you could do is use the diffuse channel to store a combination of the textures of the surrounding quads which would make a low-detail texture that blends in to different texture cols. After that you could then add the texture for the quad blended with a circular greyscale texture (white in the middle but fades to black).

You'd loose detal at the edges but you could try that.

Or do exactly what your doing now but blending in the low-detail vertex diffuse colours I mentioned. That'd probably look OK.

e.g

v1------v2------v3
| | |
| Grass | Rock |
| | |
v4------v5------v6
| | |
| Sand | Snow |
| | |
v7------v8------v9

In that example v5's diffuse colour would be an average of green (grass), grey (rock), orange (sand) and white (snow).

v4 would be the average of Green and Orange
V7 would be orange
v8 would be the average of orange and white (a bagey colour)
v9 would be white
v6 would be the average of white and grey (a merky white)
v3 would be grey
v2 would be the average of green and grey
v1 would be green

If you blended that with your current render then you might get something you could use or build on.

You'd bend them some at like this:

pd3ddevice->SetTexture (0, &QuadTexture);
pd3ddevice->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pd3ddevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3ddevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

Of course you'd have to create your diffuse colours first.

Hope that helps you out.

Matt

Share this post


Link to post
Share on other sites
Quote:
Original post by strahan
OK. I am trying to get D3DTOP_BLENDDIFFUSEALPHA to work first but so far I just see the texture rendered as normal on the quads (no fading in or out):

*** Source Snippet Removed ***

My question is what values do I set for the diffuse color of the vertices.

That is, what colors make the texture stand out more and what colors make it fade more?

I noticed this value is a Int32 value, not a float so I can't set it to like 0.4.

Thanks!

You need to set only the alpha component of the color to 0-255. There should be a 'macro' or function in C# somewhere that takes alpha, red, green, and blue and converts it into a packed Int32. In C/C++ this macro was called D3DCOLOR_ARGB I believe, if you find the equilvilent, you need to call it like D3DCOLOR_ARGB(TextureWeight 0-255, r, g, b)

Share this post


Link to post
Share on other sites

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this