Per-vertex alpha blending

Started by
9 comments, last by kosmon_x 18 years, 10 months ago
Is it possible to blend 2 textures together on the same quad in one pass using per-vertex alpha blending with the fixed function pipeline? I can do it easy enough in two passes, just by swapping SRC/DEST blends. It looks something like this:

// I have 4 verts with a diffuse component. 2 of the verts have 0 alpha for diffuse, 2 of them have 255 alpha for the diffuse.

                pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
		pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
		pd3dDevice->SetTexture( 0, m_Texture1 );
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

		// pass 2
		pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA );
		pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
		pd3dDevice->SetTexture( 0, m_Texture2 );
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );




But, can it be done in one pass? Thanks :) [Edited by - kosmon_x on June 17, 2005 9:49:49 PM]
Advertisement
Why not render the first opaque, then the second with it's transparency?

You can combine two textures with texture stage states and render one quad in one draw call combining both textures. But I don't know how you would go about doing it with vertex alpha, or why you would want to use vertex alpha?
Well, I'm trying to nail something down for some terrain. Ideally, I'd want to be able to render 3 textures to one quad (in 2 passes). However, I'm not sure how I'd do this with one diffuse component per vertex.. I'd probably have to change it for the 2nd pass.

How does everyone else do this with the fixed function pipeline?
Using texture stage states
stage, colorop, colorarg1, colorarg2
0, top_selectarg1, ta_texture, ta_diffuse
1, top_blenddiffusealpha, ta_texture, ta_current
2, top_modulate, ta_diffuse, ta_current
3, top_disable

What this does is:
stage 0, first texture 100%
stage 1, mix between texture and stage 0 by diffuse alpha
stage 2, multiply stage 1 by lighting or vertex color
stage 3, end

you'll likely also want

d3drs_colorvertexenable, true
d3drs_diffusematerialsource, d3dmcs_color1

which informs D3D to use vertex rather than material colors.
Most people use an alpha map. But I think it elludes them that the alpha map usually costs more memory than giving each layer it's own vertex buffer.

I just render a vertex colored non-textured layer of terrain over the whole map first. The colors are based on mip level 1x1 from the mixed terrain textures. Then each layer is rendered with a seperate draw call with it's own buffer. So each layer has it's own vertex value. Having them equal to one will not make them completely opaque, though. Which is what the base color layer is for.

You can see some bad examples of my terrain engine here or here. There's not much blending going on. Sorry, I'm a bit tied between engine changes or I would wip up a better example.

edit: Ah, I dug up a better example here.
Hmmm sounds like an interesting approach.. How many layers are being rendered in the screenshots you posted? And is it using shaders or the FFP?
In my engine, it's using a vertex shader. But the only reason it uses one is to reduce the size of a vertex. There's no need to store texture coordinates in these vertices. So they only consist of a vector and color, and end up only 16 bytes. Other than that, the fixed pipeline could easily dish it out.

As for the number of layers, there's no limit. In my screen shots, what you see is what you get. If you see three textures, it's three layers. I limited the maximum to 32 layers for the sake of simplifying my editor, but as far as I know, there's no other real reason to do so.
Quote:Original post by Jiia
In my engine, it's using a vertex shader. But the only reason it uses one is to reduce the size of a vertex. There's no need to store texture coordinates in these vertices. So they only consist of a vector and color, and end up only 16 bytes. Other than that, the fixed pipeline could easily dish it out.

As for the number of layers, there's no limit. In my screen shots, what you see is what you get. If you see three textures, it's three layers. I limited the maximum to 32 layers for the sake of simplifying my editor, but as far as I know, there's no other real reason to do so.


Ooh ok... So let me get your technique right: You have a set of 4 vertices for each layer of each quad on the terrain, in addition to one base layer of vertices. So, if one quad has 3 textures blended over it, that quad will essentially be represented by 12 vertices (a set of 4 for each texture), and it will be rendered by 3 draw calls (using a vertex buffer for each layer). (And before all that happens, the base layer of colored verts is rendered). Is that right?

Thanks for all the help... definite rating+++ :)


P.S.: How did you make those light rays? They look great :)
Quote:Original post by Namethatnobodyelsetook
Using texture stage states
stage, colorop, colorarg1, colorarg2
0, top_selectarg1, ta_texture, ta_diffuse
1, top_blenddiffusealpha, ta_texture, ta_current
2, top_modulate, ta_diffuse, ta_current
3, top_disable

What this does is:
stage 0, first texture 100%
stage 1, mix between texture and stage 0 by diffuse alpha
stage 2, multiply stage 1 by lighting or vertex color
stage 3, end

you'll likely also want

d3drs_colorvertexenable, true
d3drs_diffusematerialsource, d3dmcs_color1

which informs D3D to use vertex rather than material colors.


Thank you! This works perfectly :) One question: why do you need "stage 2, multiply stage 1 by lighting or vertex color" and setting the d3drs_colorvertex to true? It seems to work without them.. just curious.
If lighting is disabled, stage 2 it will multiply by the vertex color. Try disabling lighting, and changing your vertex color to some extreme color like bright red. Everything should render bright red. Now disable stage 2, and it should remain a blend of textures but without being tinted by your vertex color.

If lighting is enabled, stage 2 will take into account lighting from the fixed pipeline lights. If you disable stage 2 you'll get blended textures but absolutely no effect from lights. The value of lighting goes into D3DTA_DIFFUSE. Try changing the light's color to make the effects of including this stage more obvious.

If you have lighting enabled with a full white ambient, or lighting disabled with white vertex diffuse, then you won't see any effect if you enable or disable stage 2.

COLORVERTEX, TRUE, and DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 are likely defaults. It's best not to rely on defaults as some drivers don't default everything correctly. Also, if one effect changes these settings, you'll need to set them back. It's best to set everything you need.

If COLORVERTEX is false, D3D's fixed pipeline lighting uses material colors.

If COLORVERTEX is true, D3D's fixed pipeline lighting may use material or vertex colors. DIFFUSEMATERIALSOURCE, SPECULARMATERIALSOURCE, EMISSIVEMATERIALSOURCE, and AMBIENTMATERIALSOURCE are used to choose where the lighting system should look for values. Your choices are MATERIAL, COLOR1, and COLOR2. MATERIAL will choose the matching part of a D3DMATERIAL9 that you've SetMaterial()'d into the device. COLOR1 will choose vertex diffuse color. COLOR2 will choose vertex specular color.

Since you require vertex diffuse alpha for your blending, I included the settings that would ensure you're getting diffuse color from the vertex diffuse.

This topic is closed to new replies.

Advertisement