How do people handle alpha in d3d?

Started by
8 comments, last by Namethatnobodyelsetook 19 years, 3 months ago
From what i understand, alpha blending in d3d is a world of trouble. What is the common approach to handeling it? I read that there were some trick you could use so that an object never realy becomes 100% transparent and then it would almost work without z-sorting. But really, that dosnt sound like the intended way, so how do people manage it? Do you sort all objects in z? Even that approach wont be perfect when some objects are both behind and infront of others (like arcs). Or do you sort triangles? I have a hard time seeing how that would be done in d3d.. Please enlighten me to what the common solution to the z + alpha problem is. :-) Thanks in advance!
Shields up! Rrrrred alert!
Advertisement
I read somewhere that you have to draw your opaque triangles first (using for example the zbuffer) then disable z-sort and draw transparent triangles in back-to-front order. I hope I'm right.
Fil (il genio)
Just ss Fil wrote you have to render all your solid (non-blended) tris first and then without z-handling draw all blended tris in some manually sorted back-to-front order. It isn't perfect but for a scene with not too much blended tris it should be fairly enough...

While thinking about it just now I wonder if you cannot get around the problem by having an additional target buffer; one for the solid pixels' color with a z-buffer attached, and one for the blended pixels' solid colors with an additional target "blend value", and then blend them together before presenting... hmm. I'm going to look into this one further.

/Staffan
Hack my projects! Oh Yeah! Use an SVN client to check them out.BlockStacker
Hi,

There's no problem and no trick at all, just common sense.

a. Enable ZWrites, enable Color Write. Disable alpha blend. Draw all your opaque tris.
b. Disable ZWrites, enable colow writes, enable alpha blend. Draw all your alpha polys.

Its really easy. No need for Z sorting.

The idea behind it is that all the opaque objects fill the z buffer as you can't see anything behind (thats why tey are opaque). So you enable the Z writes and draw your opaque polys. No need for Z sort because the ZBuffer will discard unseen pixels.

After that you should write your transparent polys. But being transparent they shouldn't fill the z buffer so other polys can be drawn 'behind' (note that ZTesting is still enabled so opaque objects will still be opaque and wont be overwritten). Again no need for Z sorting because alpha is enabled, so any color write will be blended with the current frame color. So if you render poly A and then poly B will be the same than rendering first poly B and then poly A because colors will just blend.

Luck!
Guimo


It is easier when you work with the D3DXEffect Framework as you stop thinking in terms of states and start thinking in terms of effects.

Luck!
Guimo

Quote:Original post by Guimo
But being transparent they shouldn't fill the z buffer so other polys can be drawn 'behind' (note that ZTesting is still enabled so opaque objects will still be opaque and wont be overwritten).

That's incorrect. Alpha blended polys will write the z-buffer unless you use alpha testing as well. So either you can't have gradient alpha or you do have to sort the polys back-to-front.
Use alphatest when you want boolean alpha. This causes visible pixels to write to Z, and invisible pixels to not write to Z. This should cover most cases. Mixed with multisampling, you'll still get some softness to the edges.

Alphablending though, yeah, what everyone else said. Z order doesn't matter if you're doing additive blending:

The ordering here doesn't matter. As long as DESTBLEND is D3DBLEND_ONE, you're just adding to the existing values. If SRCBLEND is D3DBLEND_ONE, you're adding color without alpha. If SRCBLEND is D3DBLEND_SRCALPHA, you're adding color times alpha.

SRCBLEND = ONE, DESTBLEND = ONE
color = color.rgb + tri1.rgb
color = color.rgb + tri2.rgb

SRCBLEND = SRCALPHA, DESTBLEND = ONE
color = color.rgb + tri1.rgb * tri1.a
color = color.rgb + tri2.rgb * tri2.a

You can swap the two triangles order, and nothing changes.

If you're doing proper standard alphablending, you'll have SRCBLEND = SRCALPHA and DESTBLEND = INVSRCALPHA. This translates as:
color = color.rgb * (1-tri1.a) + tri1.rgb * tri1.a
color = color.rgb * (1-tri2.a) + tri2.rgb * tri2.a

In this case, the order definately matters. Lets say you're drawing a red box on a green background, 90% solid. You'll end up with 90% red, 10% green, 0% blue. Next we draw a 50% solid blue box in front of it. 45% red, 5% green 50% blue should be the result. Now lets ignore the order we draw these items as Guimo suggests. Lets draw blue box then red box on our green background. First we get 0% red, 50% green 50% blue, then mixing in the red box, we get 90% red, 95% green, and 45% blue.

45% red is not 90% red
5% green is not 95% green, and
50% blue is not 45% blue.

The order matters.
Hey, read all my post, turn off zwrites before drawing alpha polys.

Luck!
Guimo
Quote:Original post by Guimo
Hey, read all my post, turn off zwrites before drawing alpha polys.

Hey, read all my post. ;) Yes, without Z writes you allow the transparent items to be drawn behind other previously drawn transparent items. For additive blending this works great... I suppose modulate style blending works out too. But for standard alpha blending, if you change the order you draw things, the math simply does not work out. The order is vital.
so in short Namethatnobodyelsetook, i need to sort all objects along the cameras z axis? But even this approach cant be perfect, what about objects that are partialy infront and partialy behind objects? Because i mean you dont really sort triangles in d3d but rather think in the terms of meshes, since DrawPrimative likes to draw large chunks of triangles and not single ones.. right?
Shields up! Rrrrred alert!
And that's the biggest dilema of using alpha blending. There is no "good" solution right now. You can break the mesh into pieces, but that implies you know how the objects will be placed, not two dynamic objects. There is research being done in "order independant transparency". Until someone comes up with a fix, you'll have some buggy visuals where two transparent objects overlap.

Try to eliminate as much alphablending by alphatesting as you can. Then just sort the alphablended objects by camera space Z, and hope for the best. This is all most games do (I don't know any that does more, but I'm not going to claim that nobody does more).

You could sort the individual polys, which would be slow, but possibly more accurate. When two poly intersect though, you'll need to break both into more polys. It just quickly becomes a mess.

Sorry it's not an ideal world. ;)

This topic is closed to new replies.

Advertisement