Multitexturing - 2 textures, more alpha aches and pains

Started by
8 comments, last by SpiralGuru3d 22 years, 1 month ago
Hey guys If you read my other multi-texturing mail, you''ll see eRAZOR helped me out real well, my hassle there was multi-texturing, with alpha in the *texture*. Now, I want to use the alpha channel from the *diffuse* component of each vertex. Trouble is, it seems vertices can only have one diffuse component in their FVF, not different ones for each blend stage. So, how do I do this? The point is, from rock on stage 0 say, up to grass on stage 1, I want each vetex in the grass layer to have a different alpha...just per-vertex...which I can read from an alpha map from that layer on the terrain. I can''t open the vertex buffer and change alpha values between texture stage states can I? =) So, have I finally hit the point where I need a shader? * Am I right in thinking the diffuse cannot change, per blend stage...if it''s being take from the vertices diffuse components? -Scott -- Give me a hard copy right there ---
-- Give me a hard copy right there ---
Advertisement
I'm not quite sure what you're trying to do.. but I can honestly say that no, there is no way to change what your diffuse value in between texture stages. Once you send your geometry to to the renderer it just gets renderered.

That said you have access to the specular component just as you do to the diffuse if you only need two different values (and unless you're targeting geforce 3 systems as your minimum then you probably can't do more than two texture blends anyways)...

If you clarify what exactly it is you want to do I might be better able to help.

Edited by - Sorrow on February 23, 2002 1:42:08 AM
Hi there,

Wow! 2 texture blends on anything less than a Geforce 3? Damn it, I hadn''t checked the caps for that...I take it MaxBlendStages isn''t the same thing then, as I *did* check that?

What I''m trying to do is layered terrain, without multi-pass. So, you have a texture and alpha map, for each layer. One for rock, and then for grass (so, your alpha for rock is totally opaque, then for grass, to dictate where the rock shows through etc.) Up to say, maybe 4 layers in places.

With multipass, I can do it with a dynamic vertex buffer. Lock it, set the rock texture, copy the alpha for that layer in...and draw..then, set the grass texture, lock the VB, copy alpha into the diffuse for *that* layer...and so we go on...

*But*, I''m killing myself trying to figure how to do this with multi-texturing, or a shader, and thus avoid multi-pass. With multi-pass, I''m drawing big primitives multiple times, and locking/altering big VBs...I want to avoid that.

The only improvements I can lean on with multi-pass is switching off terrain layers occluded by opaques quad meshes in a higher layer, and culling tiles by AABB...ofcourse.

Just want to avoid multi-pass if I can...

Any ideas?

-Spiral

-- Give me a hard copy right there ---
-- Give me a hard copy right there ---
yah.. that threw me off too... I can''t figure out exactly why the MaxTextureBlendStages is set to 8, as trying to use anything more than 2 kills me dead. If you check around you''ll find that there is also a value for MaxSimultaneousTextures, and that it is only 2.

As far as I know there''s only 2 blend stages PER PIXEL.. on a gf2. That said It can concurrently work on several pixels or something (I''m guessings). If anyone knows the real answer there I''d be just as curious to know. Trying to set the third blend stage turns everything black (but doesn''t return an error.)

As a note, gf3 does, if memory serve, allow you to set 8 deep blending stages when using a pixel shader (but I still don''t think it allows you more than 2 if you aren''t using pixel shaders.) You can also use more textures when using the pixel shader (again.. I think. I haven''t got a gf3 so this is just from stuff I''ve read.)

I think the best you''ll do without a pixel shader is 2 passes with 2 textures each, except that I''m not sure how you plan to do alpha blending before the final combiner (which alpha blends to the screen.) That said I''m no expert on the texture stages(combiners) so for all I know there might be an easy way to do it of which I am unaware. (question, why not just store the alpha value in the textures for each layer? Do you plan to alter the alpha values per vertex between frames to create an effect?)

If you need one alpha value per stage just use both the diffuse and specular components.


Sorrow
Hmm...MaxSimultaneousTextures seems to be the value to cap then.

Without a pixel shader then it looks like this:

* With multi-texturing, each pair of layers would take a single pass on a Geforce 2, yes?

Does the pass count increase if I''m referencing anything in the alpha cascade? Aside from cap''ing things like MaxSimultaneousTextures, is there any way of profiling passes being used, or is it down to knowing the card and drawing conclusions from profiling?

* With multi-pass, each layer would take one whole pass. Adjsuting the alpha for each layer, between passes, would requite a lock/recreation of vertices with altered alpha. Yes?

For Geforce3 support, I will use a pixel shader for sure, ofcourse. It''s just the right thing. For older cards though, I need a good combination of multi-texture (if available - say, Geforce2) and multi-pass (where necessary).

As you say, with multi-texturing, I can do the layers a pair at a time, the specular component of the vertices diffuse can be hijacked for the alpha in the second layer of each pair. I can do this with the multi-pass do, thus requring a lock/recreaction only every other layer...see?

I take it:

STSS(1, D3DTSS_ALPHAARG1, D3DTA_SPECULAR); - is going to work just like STSS(1, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE) - it goes straight for the A in ARGB when it''s an ALPHAARG doesn''t it?

---

I''m not entirely sure what you mean by this:

"except that I''m not sure how you plan to do alpha blending before the final combiner (which alpha blends to the screen)"

Can you clarify? I am under the impression that alpha is resolved at each stage...is this not the case? If it''s not, there are some things working this end that shouldn''t! =)

There it is again:

"That said I''m no expert on the texture stages(combiners)" - what''s a "combiner"? Is it just a blend op, do I know what you''re talking about here really? =p

[Answer: For each terrain layer (256x256 verts) I want a single 256x256 alpha map - so, alpha per vertex is perfect, and the values blend and smooth the layers into one another.

Referencing an alpha texture per quad (poly pair) would be crazy, and referencing an opaque/transparent texture per pair would give blocky alpha...(or circular/weird with filtering on) so I need it per vertex. Does this answer your question?]

Thanks for the feedback Sorrow, keep it coming!

-Spiral

-- Give me a hard copy right there ---
-- Give me a hard copy right there ---
I''m not sure what youre asking... for each texture you get one texture stage consisting of an alpha portion and a color portion. That should be consistant for all video cards under directx. Just check the caps... if it says two simultaneous textures then you''re capped at two texture blending stages. The only other thing to do is check and see if the operations you need are supported by the card.

If you REALLY want to get more out of your hardware check out opengl... it doesn''t give you more textures but if you use the NVidia extentions it does let you access two in a single blend stage, or so it seems from the articles I''ve read. The DirectX format is a bit neutered for conformancy''s sake.

I''m not sure what "STSS(1, D3DTSS_ALPHAARG1, D3DTA_SPECULAR)" is, but diffuse and specular seem perfectly interchangable as constants in the texture stages and get used identically.

To be honest I''m not sure about the alphaarg either as I haven''t actually needed it for anything yet. I THINK everything stays coherent in the alpha portions until you reach the blending stage, at which point the only output you get from the alpha stages is the alpha component of the final result. Don''t quote me on that though.

Could you post a code snippet showing how you are setting up your texture stages and blend stage? I''ve got the basic idea of what you''re trying to do, but i''m still fuzzy on your method. You might easily be using a blending method that hasn''t even occred to me. Are you using ops like D3DTOP_BLENDDIFFUSEALPHA ? Or simply combining your textures and alpha values seperatly and then putting them back together (which wouldn''t work properly I don''t believe)? If you''re using D3DTOP_BLENDDIFFUSEALPHA then I think your''e sol on the specular, there''s no identicaly op for specular.

A combiner, is just another name for a texture stage. When I read gl docs they call them combiners. I''ve heard the blend stage referenced as the final "special" combiner but that may be an eroneous use of the term, beats me.






Hmm, ok, so what is the difference between this:

[Note: STSS == SetTextureStageState]

// Alpha in stage 0 comes from the texture
STSS( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
STSS( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

// why these _BLEND* tex ops work, I don't know!
STSS( 1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );

// opaque pixels stack up and occlude clear ones that come before
STSS( 1, D3DTSS_ALPHAOP, D3DTOP_ADD );
STSS( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
STSS( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);

and this:

STSS( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
STSS( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

// colour in stage 1 from texture too please - but whatta ya know? If I do this instead of _BLEND*, the texture in stage 0 reads from the texture in stage 1!!!!
STSS( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
STSS( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );

STSS( 1, D3DTSS_ALPHAOP, D3DTOP_ADD );
STSS( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
STSS( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);

---

They *do* have different effects, notably, that second approach *not* doing what I expect!

What *is* the point of these D3DTOP_BLEND* ops, and *do they* have an equivalent in terms of D3DTOP_COLOROP / _ALPHAOP?

-Spiral

-- Give me a hard copy right there ---

Edited by - SpiralGuru3d on February 24, 2002 7:25:08 PM
-- Give me a hard copy right there ---
ok.. sorry it took me so long to reply.

your first set :

// Alpha in stage 0 comes from the texture
STSS( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
STSS( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

// why these _BLEND* tex ops work, I don''t know!
STSS( 1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );

// opaque pixels stack up and occlude clear ones that come before
STSS( 1, D3DTSS_ALPHAOP, D3DTOP_ADD );
STSS( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
STSS( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);

It looks like you''re accumulating the alpha from the texture for blending with the screen at the end. I thought you wanted to blend from the vertices?

Your one call to BLENDTEXTUREALPHA is hard to evaluate as I don''t know what the arguments are (colorarg1 colorarg2) ? I''m guessing that you used something like

STSS(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
STSS(0,D3DTSS_COLOROP,SELECT_ARG1);

STSS(1,D3DTSS_COLORARG1,D3DTA_CURRENT);
STSS(1,D3DTSS_COLORARG2,D3DTA_TEXTURE);

In which case you''re blending the values from the first texture and the second texture... unfortunatly the only deciding factor on how they are blended is the alpha value from the second texture. The BLENDDIFFUSEALPHA on the other hand would use the interpolated alpha values from the DIFFUSE values at the vertices to weight the blend of the two textures. That of course doesn''t get you a blending alpha to combine everything to the screen, just the value for combining the two textures.

So why not specifiy them seperatly? You can use the diffuse value for blending the two textures together, and then put the alpha value from the specular color into the alpha portion of the second stage. You use the specular to blend the final result to the screen, the diffuse to blend the two textures together. The specular at each vertex contains the summed alpha for the two textures, and the diffuse contains the alpha ratio between the two textures.

Should work I think... assuming you still want to blend from the alpha values at the vertices. Something like that shoudl work I think.


The Second Set :

STSS( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
STSS( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

// colour in stage 1 from texture too please - but whatta ya know? If I do this instead of _BLEND*, the texture in stage 0 reads from the texture in stage 1!!!!
STSS( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
STSS( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );

STSS( 1, D3DTSS_ALPHAOP, D3DTOP_ADD );
STSS( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
STSS( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);

umm... still accumulating the alpha values from the two textures... and then just passing forward the value from the second texture.

:: blinks :: Of COURSE setting the texture in stage 0 doesn''t do anything, you''ve got a "SELECTARG1" in texture stage 1. Long story short that just sends the value from the second texture stage to the screen.

Texture Stage 0 does it''s calcluation and stores the result in D3DTA_CURRENT. Texture Stage 1 does it''s calcluation and stores the result in D3DTA_CURRENT.

After the last texture stage the value in D3DTA_CURRENT is the one that''s applied to the screen (based ont he alpha blending settings.)

As you haven''t referenced D3DTA_CURRENT in texture stage 1 the value from texture stage 0 is lost.


---

>> They *do* have different effects, notably, that second
>> approach *not* doing what I expect!

What do you expect it to do?

>> What *is* the point of these D3DTOP_BLEND* ops, and
>> *do they* have an equivalent in terms of D3DTOP_COLOROP /
>> _ALPHAOP?

If you want to blend the value from both stages, there''s only two ways to do it. With D3DTOP_MODULATE, which is an unweighted blend, combining both colors equally, and with the BLEND commands which allow you to weight the blending from the two values. THAT''S the point of the ops, without them I don''t know how you expect to get the values from both textures combined in any fasion.

After all the talk of using the alpha values from the vertices, I''m confused to see no reference to the diffuse or specular values what so ever.

You''ve also made no mention of what your destination and source blend values are for the actual write to the screen.

Sorrow
test

Sorrow
Discord -- Work in Progress
I don't know if you're still interested spiral.. but I've since discovered WHY the caps for geforce/geforce2 list 8 texture blend stages and only 2 simultaneous textures. It's not an arbitrary setup. There is a second "mode" you can program the blend stages for geforce cards in, which actually bears little to no resemblance to the standard d3d blend stages. It basically highjacks the blend stages for use in representing the full functionality of the texture combiners.

the basic setup lets you do :

((A*B) + (C*D)) in a single combiner (you get two per pass + a final combiner stage which is different)

You can have multiple textures used in that equation, there's no restriction on which variables are what ( you could take the texture color Tc and do : ((Tc* Tc) + (Tc*Tc)) if you wanted to. Or with two textures Tc and Td you could have : ( ((Tc*Td)+(Td*A)) or whatever you want. Much more flexible than the texture stages.

To do this you have to set up all EIGHT blend stages... it's very funky. I've currently only found the details on how this works for TNT, I'm trying to track down the specs for Geforce as the geforce combiners have extended functionality (dotproduct3, spare0 register, spare1 register, 2 color constants...) and I'm assuming they've been given the same kind of support (:: crosses his fingers :. The same method they use to hijack the basic functionality of the combiners would easily carry over to dotproduct3, two tfactors, two temp values, you get the idea.

As soon as you set the third stage to anything other than D3DTOP_DISABLE it thinks you're trying to use the alternate mode (combiners) instead of the stages. But if you haven't defined ALL the blend stages according to the new mode format it doesn't work properly, the reason things just seemed to die when I attempted to use a third stage in the normal d3d fasion.



Sorrow
Discord -- Work in Progress

Edited by - sorrow on March 3, 2002 12:16:22 PM

This topic is closed to new replies.

Advertisement