Sign in to follow this  

Single-pass Texture Splatting

This topic is 4537 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

Maybe this is impossible and I should just do multi-pass... I'm wanting to splat a grass texture as a base, followed by an alpha mapped dirt texture. When I do this:
device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;

device.TextureState[1].ColorOperation = TextureOperation.SelectArg1;
device.TextureState[1].ColorArgument1 = TextureArgument.TextureColor;
device.TextureState[1].AlphaOperation = TextureOperation.SelectArg1;
device.TextureState[1].AlphaArgument1 = TextureArgument.Current;

device.SetTexture(0, texAlphaGrass);
device.SetTexture(1, texGrass);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numVertices, 0, numTriangles);

device.SetTexture(0, texAlphaDirt);
device.SetTexture(1, texDirt);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numVertices, 0, numTriangles);


it works! texAlphaGrass is just a white .dds...is there a way to not have to use this alphamap? However, that's multi-pass, and what I want to do is use TextureStages 2 and 3 to set another alphamap and dirt texture, removing the need for another DIP call. When I try it, setting up the TextureStages the same as 0 and 1, I just get the base grass texture showing...my textures 2 and 3 don't seem to have any effect. So, does anyone know if/how I can do this in a single pass? Cheers, James [Edited by - jameswren on July 9, 2005 4:52:00 AM]

Share this post


Link to post
Share on other sites
As far as my research showed, you cannot do texture splatting with alpha maps in a single pass. Since the single-pass blends everything all at once...

Share this post


Link to post
Share on other sites
Oh Indeed.
A shader will allow a single pass no problem, especially cuz you can compact alpha's into each color or a texture.

http://www.gamedev.net/columns/hardcore/splatting/

Read up on that article.
His explanations are said better in the text he refers to at the beginning.
His method is an upgrade tho since it use's a pixel shader. The PS code is provided, I am using it now since it is very small and effecient.
Remember tho, it only shows the most basic approach to texture splatting, it can be way more.

Share this post


Link to post
Share on other sites
I have tried to do this as well. Unfortunately, there is no way to do base textuer + texture splatting using the fixed function pipeline in one pass.

Share this post


Link to post
Share on other sites
I believe it would be possible with vertex alpha. Just change the texture stage state for the second texture to use the vertex alpha component rather than the texture alpha.

Share this post


Link to post
Share on other sites
Thanks everyone.

If I use vertex alpha, I guess that would give me the same alpha resolution as my heightmap, so would this be worse quality than using say a heightmap of 1024 and an alphamap of 4096? Although would that loss in quality be acceptable due to the gain in speed by doing just a single pass instead of 3 or 4?

Share this post


Link to post
Share on other sites
Actually, the blend from one texture to another does not need to be any more linear with vertices than with pixels. You could achieve the same result with a decent resolution mesh. Usually, the alpha map would need to be pretty huge in order to have a resolution that couldn't be handled by vertices. So unless the vertices are really spaced out (like my system - 32 inches apart), or the alpha map is mega huge, you can get just as pretty results with vertices.

I think the alpha map management is a pain. It also hogs memory. Every single layer needs it's own full-scale map, other than the base. So if you want cool spotting effects, your video memory requirements are going to shoot into the sky.

I've also thought about trying an alternative system. Where a precalculated (drawn in a paint program) alpha map per transition type could be used on different areas. For example, you could have a corner section, a straight section, a blurry section, a speckled grass section, a hard edged corner, etc. They could all be stored in the same alpha texture, but each quad would use it's own coordinates (secondary alpha coordinates, where the primary coordinates still tile across the landscape) to reference the mask it wants to use. It should allow you to use extremely high res alpha values for small parts of the terrain, since each quad can share the same texture coordinates. Allowing you to literally provide any shape or pattern you want, specific to any layer or texture, in extreme resolution. At the same time, non-faded quads could be rendered with tiny, totally opaque, single pixel coordinates to speed up the rendering. The most difficult part would be building an editor that used all of this flexibility to make an easy job out of building the terrain :)

Share this post


Link to post
Share on other sites
When 4 alpha maps can be combined into one texture, you would only need to load 1-2 textures to get some pretty detailed terrain. Of course, if you want to layer 32+ textures onto each chunk of terrain, alphamaps wouldn't be ideal. In all other cases, I prefer the flexibility that alpha maps give. The advantage of using alpha maps is that you don't need a decent resolution mesh at all -- the mesh can be super low resolution, yet you can still achieve crisp and very flexible transitions between terrain types. Of course, there is always a good middle ground...

True, you would need a relatively high res texture to get better blending across a single quad than vertex alpha in a high res mesh. However, I think you would only need 4x the size of your heightmap to achieve superior blending (regardless of the spacing of your terrain verts, as long as it is > 1). With a 256x256 terrain, a single 1024x1024 texture should do the trick and allow for up to 5 texture layers.

An example of this can be seen here. My terrain is using a 64x64 heightmap with verts 10 units apart. I stretch a single 256x256 alpha map texture across it (4x the resolution). In my experience, a 4x alpha map will give higher detail on a mesh with verts as low as 1 unit apart (very high resolution).

edit: sorry about the crappy wireframe in that pic

[Edited by - kosmon_x on July 10, 2005 4:02:42 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by kosmon_x
When 4 alpha maps can be combined into one texture, you would only need to load 1-2 textures to get some pretty detailed terrain.

Are you talking about using a pixel shader to pull the alpha from the RGBA channels? If so, that would exclude the routine to pixel shader capable cards. And it's kind of hard to fall back on generic routines for less than newer cards when the generic routines use more resources. Seems backwards.

Quote:
I stretch a single 256x256 alpha map texture across it (4x the resolution). In my experience, a 4x alpha map will give higher detail on a mesh with verts just 1 unit apart (very high resolution).

In all of the documentation I've seen, 4 pixels of the alpha map were used on each quad. That's twice as high resolution as using the vertices, regardless of spacing. The result with vertices looks identical if you double the mesh resolution, except you have a twice-as-smooth landscape ;)

Share this post


Link to post
Share on other sites
I'm pretty sure that you can do this sort of alpha map blending with the fixed-function pipeline. I've never done terrain rendering with texture splatting but after reading the various articles mentioned in this thread I think I have a better idea of what you guys are trying to do. Pixel shaders seem to be made for this sort of thing, but here's my idea on how to do this using the texture blending unit. Please let me know if I've overlooked something obvious.


Stage 0
COLORARG1 = DIFFUSE
COLORARG2 = TEXTURE (dirt texture)
COLOROP = MODULATE
ALPHAOP = DISABLE
RESULTARG = TEMP

Stage 1
COLORARG1 = DIFFUSE
COLORARG2 = TEXTURE (grass texture)
COLOROP = MODULATE
ALPHAOP = DISABLE
RESULTARG = CURRENT

Stage 2
COLORARG1 = CURRENT
COLORARG2 = TEMP
COLOROP = D3DTA_BLENDTEXTUREALPHA
ALPHAARG1 = TEXTURE (grass alpha map)
ALPHAOP = SELECTARG1
RESULTARG = TEMP

Stage 3
COLORARG1 = DIFFUSE
COLORARG2 = TEXTURE (sand texture)
COLOROP = MODULATE
ALPHAOP = DISABLE
RESULTARG = CURRENT

Stage 4
COLORARG1 = CURRENT
COLORARG2 = TEMP
COLOROP = D3DTA_BLENDTEXTUREALPHA
ALPHAARG1 = TEXTURE (sand alpha map)
ALPHAOP = SELECTARG1
RESULTARG = CURRENT



Share this post


Link to post
Share on other sites
What is the "TEMP" texture stage argument? I don't think you can store a texture stage result into a temporary slot to be used later... anyone know if there is a way?

[Edited by - kosmon_x on July 11, 2005 10:51:08 PM]

Share this post


Link to post
Share on other sites
"TEMP" is D3DTA_TEMP.

Your card may not support it. Check D3DCAPS9::PrimitiveMiscCaps for D3DPMISCCAPS_TSSARGTEMP.

Share this post


Link to post
Share on other sites
Hmmm still can't get it to work though.. Here's what I'm doing:


pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_TEMP );

pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT );

pd3dDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );
pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_CURRENT );
pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_TEMP );
pd3dDevice->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
pd3dDevice->SetTextureStageState( 2, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT );


// stage 0 is dirt, stage 1 is grass, stage 2 is grass alpha
// I'm enabling alpha blending and using this:
//
pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );





When I do that, nothing actually gets drawn to the screen... My card does support the temp slot. This doesn't really make sense since it seems like it should work perfectly.

Share this post


Link to post
Share on other sites
Don't use frame buffer alpha blending (set D3DRS_ALPHABLEND to FALSE). Other than that, call ValidateDevice to see if your card can handle the texture stage settings. You might want to try the reference rasterizer while you're debugging things.

I'll be honest, I didn't try any of this, I just read the SDK docs and scribbled down what I thought would do what you guys are attempting to do.

Share this post


Link to post
Share on other sites
The easiest way is to use a pixel shader. That way you can use the different channels in your alpha texture to save memory.

If you have to use the FFP, I believe it should work if you set up 0/1 with the first texture and then LERP that output using the second texture and its alpha as the weight.

Share this post


Link to post
Share on other sites
With pixel shaders, it's also possible to cram almost as many layers as you see fit. One alpha map could potentially carry with it the alphas for 8 or even 16 textures if you sacrifice alpha values. IE. for each pixel, you have 4 components. For each of those components you can retrieve two halves. Each of those can be a percentage. Of course, this is super slow, but you can see the potential.

Makes me wonder when the FFP is going to be allowed to gracefully die, and the "oh my god it must be backwards compatible with GF2!" mentality will fade away into the night..

Share this post


Link to post
Share on other sites
Hmmm if I set alpha blending to false, I just get the very first base layer and nothing else. Has anyone else been able to get this to work?

I'm sticking with the FFP for my first project so I can learn the ropes and not get in over my head... for the next project I will definitely delve into shaders. For now though, it would be great if I could get this thing to work in one pass!

Share this post


Link to post
Share on other sites
If I've got these layers to splat

base
tex1 + alphamap
tex2 + alphamap

then I'll need 5 textures.

I was looking at graphics card specs, and the GF3 supports 8 texture blend ops and 4 textures per pass...does this mean I can't use the FFP in a single pass, but I can use a pixel shader in a single pass if I use the RGB channels of a single alphamap for the separate textures?

Share this post


Link to post
Share on other sites
I'm using a Radeon 8500 card, and even though it supports pixel shaders, enabling PS support is always a great way to slow any game to a crawl. Hitman 2's systems relied on pixel shaders. As a result, I was unable to play it and returned the sucker the next day. I guess it won't be a big deal in about two or three years. But until then, I see it as dangerous to use any PS system that the user cannot freely turn off and on.

Making your system use 4X more video memory in older cards doesn't sound like a good idea to me. You should at least find a better alternative, or shrink the textures down to 1/4 of their size.

Share this post


Link to post
Share on other sites

This topic is 4537 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