0

I'm trying to translate an OpenGL renderer into DirectX9. It mostly seems to work, but the two don't seem to agree on the settings for alpha blending. In OpenGL, I'm using:

glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

and never actually setting the GL_DEST_ALPHA, so it's whatever the default is. This works fine. Translating to DirectX, I get:

device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);

which should do about the same thing, but totally doesn't. The closest I can get is:

device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);

which is almost right, but if the geometry overlaps itself, the alpha in front overrides the alpha in back, and makes the more distant faces invisible. For the record, the other potentially related render states I've got going on are:

device->SetRenderState(D3DRS_LIGHTING, FALSE);
device->SetRenderState(D3DRS_ZENABLE, TRUE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);

At this point, I feel like I'm just changing states at random to see which combination gives the best results, but nothing is working as well as it did in OpenGL. Not sure what I'm missing here...

Darrel Hoffman
  • 4,436
  • 6
  • 29
  • 41
  • 1
    How about `device->SetRenderSate( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );`? – Ylisar Jul 31 '12 at 19:26
  • I think that's what I tried first, looking at the sample code I was working from. Doesn't work though. The alpha on the front faces always overrides the alpha on faces further away, which makes those faces invisible. Is there some other setting I need to make it so that the alpha maps can be multi-layered in the same draw-call? (I'm making a particle engine, but all quads are drawn in one call, rather than one at a time, to increase performance.) – Darrel Hoffman Jul 31 '12 at 20:06
  • Could you post screenshots of what you want vs what you're getting? – Ani Jul 31 '12 at 20:30
  • I'll try - never posted an image here before, let's see if this works: http://darrelhoffman.com/?attachment_id=190 Eh, just click the link. – Darrel Hoffman Jul 31 '12 at 20:35
  • 1
    That does not look like an alpha blending problem. Try to turn off ZWriteEnable or turn on alpha testing. – Nico Schertler Aug 01 '12 at 15:43
  • Turning off ZWriteEnable worked for the particles, but now any other geometry created after the particle system is rendered on top of the particles even when it should be behind. Only solution I can think of for that is maybe to make sure that all particles are always drawn last, which would require a little refactoring. – Darrel Hoffman Aug 01 '12 at 16:32
  • Actually, that wasn't quite so bad - my objects were all in a std::list, so I just changed "push_front" to "push_back" for particle systems, and it works perfectly. If you post this as an answer, I'll mark it as accepted. – Darrel Hoffman Aug 01 '12 at 16:40

1 Answers1

1

The alpha blending itself is performed correctly. Otherwise, every particle would look strange. The reason why some parts of some particles are not drawn, is that they are behind the transparent parts of some other particles.

To solve this problem you have two options:

  1. Turn off ZWriteEnable for the particles. With that, every object drawn after the particle will be in front of it. This could lead to problems, if you have objects that should actually behind the particles and are drawn afterwards.

  2. Enable alpha testing for the particles. Alpha testing is a technique to remove transparent pixels (given a certain threshold) from the target. This includes the ZBuffer.

Btw. when rendering transparent objects, it is almost always necessary to sort the objects to solve ZBuffer issues. The above solutions work for some special cases.

Nico Schertler
  • 32,049
  • 4
  • 39
  • 70