Sign in to follow this  
DuckWizard

Yet another multitexturing question

Recommended Posts

I'm having a hard time wrapping my head around all the multitexturing operations and whatnot. I successfully implemented the texture splatting with alpha maps from this article: http://www.gamedev.net/reference/articles/article2238.asp (thanks to the Anonymous Poster who replied to my other thread). My question is, is there anyway I can utilize more texture stages to render the base texture AND a splat texture with alpha map in one pass, rather than rendering the base texture in one pass and each splat texture in subsequent passes? Here are my current texture stage states (lifted vertabim from the article):
	// Alphamap: take the alpha from the alphamap, we don't care about the color
	pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
	pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

	// Texture: take the color from the texture, take the alpha from the previous stage
	pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
	pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
This puts the alpha map in texture stage 0 and then puts texture in texture stage 1, and renders stage 1 with the alpha from stage 0. I guess what I want to do is either a) put a solid texture in stage 0, an alpha map in stage 1, and another texture in stage 2 that gets rendered on top of stage 0 using the alpha from stage 1, OR b) have four stages (alpha, texture, alpha, texture) where each pair of stages renders with its alpha and texture, and the second pair ignores the alpha from the pair before it. I guess it would probably help if I understood what the operations were doing, but I don't :-( Any tips would be most welcome. I hope my description isn't as confusing to you as it is to me. Thanks, -Jeremy

Share this post


Link to post
Share on other sites
Another interesting quirk: when I use the multiple texture stages to get the texture rendered with the alpha map, even when I am using a solid alpha map for the base texture, I seem to lose all my lighting. Any ideas? Is there something I have to do to make sure the lighting doesn't get clobbered by all the texture calculations?

Share this post


Link to post
Share on other sites
Well, I think you were completely clear.

IMO you've got three options here:

1. Stick to the current solution. I don't see how it could be improved while still using alpha-maps. The reason is the lack of additional inputs, or registers to keep the intermediary results.
In this case it would be first texture multiplied with first alpha map. You would need to save it somewhere, compute the second texture*alpha, then add. You could be using D3DTA_TEMP for that, of course. But this entire thing would result in an enormous amount of texture stages needed (not mentioning the 4 texture sampling in one pass to begin with) - as you are using fixed function pipeline, I asume you would want to support older hw, like GeForce2, for example (if not - look at point 2). Those may not be happy about it.

2. Switch to shaders. It's really easy and will spare you many headaches like this one. That would be my first recomendation if you are targeting hws that support shaders.

3. Drop alpha-maps and store coefficients in vertices. I was using this technique a while ago. Here's a snippet:

//effect:
// colorFinal = tex1 * A1 + tex2 * A2;
// alphaFinal = A1 + A2;
//arguments:
// diffuse.a = A1 + A2;
// if ( (A1 + A2) < eps )
// specular.rbg = whatever;
// else
// specular.rbg = A1 / (A1 + A2);

m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );

m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_LERP );
m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG0, D3DTA_SPECULAR );
m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG );
m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );



This combines two textures in one pass.
The two coefficients are A1 and A2. They are stored in diffuse and specular components of the vertices. Not directly, but in a precomputed form, as described in the comments. You should set for the additive bleding at the end, but that you already know.

If something is unclear, I would explain more.
Cheers.
~def

Share this post


Link to post
Share on other sites
Quote:
Original post by DuckWizard
Another interesting quirk: when I use the multiple texture stages to get the texture rendered with the alpha map, even when I am using a solid alpha map for the base texture, I seem to lose all my lighting. Any ideas? Is there something I have to do to make sure the lighting doesn't get clobbered by all the texture calculations?


Oh, oh, I remember now.
Lightning is incorporated in diffuse color AFAIK(R). So if you use only textures, it will be ignored. I was simply premultiplying the alpha coefficients by the premultiplied lighting value for each vertex. So in the end, Alpha did not sum to 1, but to a local light value.

Share this post


Link to post
Share on other sites
Thanks for the reply!

Firstly, I don't really care about hardware support, since I'm just really writing this game for fun and not profit. That said, it does seem a little shoddy to say to people, "This game engine gives you circa 2001 graphics but still needs a cutting-edge GPU because it uses shaders." And I have no illusions about being able to write a graphics engine that delivers impressive visuals :-)

Now then, I wouldn't mind using shaders, except I've no idea how to proceed. I have some generic assembly experience and also some experience writing Renderman shaders, so conceptually I should be okay. But I'm moving to D3D from OpenGL and never really did anything to push the boundaries of OGL; anything beyond drawing geometry with vertex buffers is pretty much over my head at this point.

As for storing the alpha component in the vertex's color field, I am probably going to be using those fields to tint the terrain when it's underwater (this is what I did in my OGL terrain engine and it looked nice and was easy).

So - any tips you can give me on getting started with shaders would be awesome. I guess that's what I'm trying to say :-)

Thanks,
-Jeremy

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Oh, oh, I remember now.
Lightning is incorporated in diffuse color AFAIK(R). So if you use only textures, it will be ignored. I was simply premultiplying the alpha coefficients by the premultiplied lighting value for each vertex. So in the end, Alpha did not sum to 1, but to a local light value.


I see - how do I do this? Add another argument on the second stage of each pass that multiplies the result by the vertex diffuse color?

Share this post


Link to post
Share on other sites
Hm...
For the record, I do not remember why I didn't use diffuse.rgb at all. I briefly recall it being screwed by the hw lighting, but I'm not really sure.

Quote:
I see - how do I do this? Add another argument on the second stage of each pass that multiplies the result by the vertex diffuse color?


Well, it's much, much simplier.
If you have alpha coefficient An, and you know that in this place the light coeff is L, just use An*L instead of An.
Then, in the end:
Sum{0..n}( (An*L)*TEXn ) = L * Sum{0..n}( An*TEXn )


As for the shaders, skip the assembly and go for HLSL at once!
And as a general advice: read DX SDK docs. It's all really there.
Oh, and there are tutorials on HLSL in the SDK as well.

Cheers.
~def

Share this post


Link to post
Share on other sites

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