Single-pass Texture Splatting

Started by
21 comments, last by Jiia 18 years, 10 months ago
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]
Advertisement
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 ;)
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



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]
"TEMP" is D3DTA_TEMP.

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

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.
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.

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.
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
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..
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!

This topic is closed to new replies.

Advertisement