Archived

This topic is now archived and is closed to further replies.

Evil Steve

Damn SetTextureStageState() (DX9)

Recommended Posts

Ok, I don't even know if this is possible to do efficiently (but to be honest it doesn't really matter). I have these three tiles: (If the image is broken, #1 is a mask (magenta & black), and #2 & #3 are normal textures [grass & sand]). I'd really like to be able to blend the second and third textures using the first as a mask of some sort, but i really don't know how to go about it. At the moment is have this:
m_pDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
m_pDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
m_pDevice->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_CURRENT);

m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAARG2,D3DTA_CURRENT);

m_pDevice->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_ADD);
m_pDevice->SetTextureStageState(1,D3DTSS_COLORARG1,D3DTA_TEXTURE);
m_pDevice->SetTextureStageState(1,D3DTSS_COLORARG2,D3DTA_CURRENT);
Which produces an image like this: (Ignore the window title - its a work in progress ) But i don't know what to do next... Someone suggested something to do with the stencil buffer that sounds over-complicated to me. Is this the only way to do it? How do terrain engines do this? Terrain engines blend 2 textures into one another (e.g. grass & rock), which is what i'm doing - except with only 1 bit of alpha (effectively 0.0 or 1.0) Any suggestions? Cheers, Steve [edited by - Evil Steve on August 12, 2003 8:07:55 AM]

Share this post


Link to post
Share on other sites
If your card supports fancy features like >2 texture stages, temp registers and lerp commands, try something like this:

m_pDevice->SetTexture( 0, m_mask );
m_pDevice->SetTexture( 1, m_sand );
m_pDevice->SetTexture( 2, m_grass );

m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE );
m_pDevice->SetTextureStageState( 0, D3DTSS_RESULTARG1, D3DTA_TEMP );

m_pDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pDevice->SetTextureStageState( 1, D3DTSS_RESULTARG1, D3DTA_CURRENT );

m_pDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_LERP );
m_pDevice->SetTextureStageState( 2, D3DTSS_COLORARG0, D3DTA_TEMP );
m_pDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
m_pDevice->SetTextureStageState( 2, D3DTSS_RESULTARG1, D3DTA_CURRENT );


otherwise go multi-pass:

m_pDevice->SetTexture( 0, m_sand );

m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );

m_pDevice->SetTexture( 0, m_grass );
m_pDevice->SetTexture( 1, m_mask );

m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );

m_pDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
m_pDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
m_pDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );

Share this post


Link to post
Share on other sites
Ok, one more question.
I''ve tried to implement both methods in my game, so that i can use single-pass if its supported. When i did this, i got 950 fps, an increase of 100fps, so i reckon its worthwhile.
Anyway, to determine if the graphics card supports it, i do this:

if((m_theCaps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) &&
(m_theCaps.TextureOpCaps & D3DTEXOPCAPS_LERP))
m_bRenderWithLerp = true;
else
m_bRenderWithLerp = false;

However, i seem to be missing something because although this works on my server (with only onboard graphics), it doesn''t work on my sisters GeForce2. All i get is a black screen. If i skip that step and set m_bRenderWithLerp to false, it works fine. So i guess there must be another cap that i need to test against.
Anyone know what it is?

Cheers,
Steve

Share this post


Link to post
Share on other sites
Although the GeForce2 accepts lerp, it may not support 3 textures. You''ll need to check the maximum number of textures a card supports.

If someone has a link describing all cards feature sets, I''d love to have it, as I''m sure many others would too. If anyone has such a beast, post a new thread (more likely to be seen by interested parties).

Share this post


Link to post
Share on other sites
The GeForce 2 can only handle 2 textures at once.

How to check this value? Is it under (Caps Viewer)

D3D Device Types\HAL\Caps\

"MaxTextureBlendStages" or
"MaxSimultaneousTextures" ?





Share this post


Link to post
Share on other sites
Sorry again, in that "multi-pass" option, isn't the
second "SetTexutre(0, m_grass)" over-writin' the first "SetTexture(0, m_sand)"? Some kind of DrawPrimitive() is
needed in between them, am I right?

m_pDevice->SetTexture( 0, m_sand );
m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );

// Some kind of DrawPrimitive() here...

m_pDevice->SetTexture( 0, m_grass );
m_pDevice->SetTexture( 1, m_mask );

etc...







[edited by - HaywireGuy on August 17, 2003 9:50:59 PM]

Share this post


Link to post
Share on other sites
Q1) I check MaxSimultaneousTextures
Q2) Yes:

m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
m_pDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
// For each tile:

m_theScene.SetTexture(0,m_vTiles[pTile->wTile].pTexture);
m_pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,(y*m_sizeView.cx+x)*4,2);

m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
m_pDevice->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
m_pDevice->SetTextureStageState(1,D3DTSS_COLORARG1,D3DTA_CURRENT);
m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAARG2,D3DTA_TEXTURE);
// For each tile:

m_theScene.SetTexture(0,m_vTiles[pTile->wOverlayTile].pTexture);
m_theScene.SetTexture(1,m_vMasks[pTile->wMask].pTexture);
m_pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,(y*m_sizeView.cx+x)*4,2);


[edited by - Evil Steve on August 19, 2003 10:33:25 AM]

Share this post


Link to post
Share on other sites