6
\$\begingroup\$

I'm working on a game in a 3D world with elements 2D only (Like Don't starve game) for Android and IOS.

Currently, I've managed "Sprite" without alpha blending, I've just put a condition in the pixel shader to test if pixel alpha channel is null:

if ( texture.a < 0.5 ) discard;

Everything working here. (On old devies like an HTC desire mobile, this condition destroy framerate but it's another problem :/)

But recently, I've tried to had another Sprite with AlphaBlending activated:

glCheck( glEnable(GL_BLEND) );
glCheck( glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ) );
glCheck( glDisable(GL_DEPTH_TEST) );

My sprite transparency is ok but it is now in front of everything in the scene. (Probably due to glDisable(GL_DEPTH_TEST)).

How can I handle depth with alpha blending activated?

EDIT: A video to show the problem: http://www.youtube.com/watch?v=W0gpBekEwW8&feature=youtu.be

\$\endgroup\$
5
\$\begingroup\$

Alpha blending in 3D is tricky, simply due to the fact that you're (usually) still rendering the quad (or polygon) to the depth buffer using the depth buffer, even if your visible texture is just a tiny part of that.

To achieve proper rendering you'll have to render everything in the correct order, essentially from back to front. If you don't use the correct order you'll get weird things like objects disappearing behind otherwise transparent surfaces (e.g. water or something like the thing you experienced).

For example, assume you'd like to render a scene with a sphere sitting in shallow water:

  • Without transparency you're able to render these in any order and it will look good.
  • But if you're making the water transparent, you'll have to render the sphere first (as it's partially "behind" the water surface).
  • Otherwise the sphere won't be drawn underwater (simply due to the depth test failing there).

The problem is the same if you're drawing something with varying levels of transparency (like a texture with 100% transparent parts).

I don't know your actual scene, but I'd say you've got a 3D world with 2D sprites?

That case I'd say render your 3D world first, then all your sprites from back to front (far to close). If you've got transparent surfaces (like windows or water), you'll have to render that together with your sprites and in correct order rather than with your 3D world.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your response! I've tried to draw all the scenes and my transparent character at last but it didn't work, I've tried to draw character first and world after, but the problem is here again :/. I've made a video to show the problem in my first message :). \$\endgroup\$ – user34026 Aug 14 '13 at 10:02
  • 1
    \$\begingroup\$ @user34026 you can render it back to front. So, if there's 3 trees behind your character then you need to render those first, then render the character and after that render all the trees that are in-front of your character. If early Z-culling is not enabled you can also just use depth-testing normally, since you use discard and for those pixels nothing is written to the depth buffer. But if you ever want to use actual blending with alpha values other than 0.0 or 1.0 then you should do the view-sorting. Which shouldn't e difficult if the camera doesn't rotate and your surfaces are flat. \$\endgroup\$ – PeterT Aug 14 '13 at 13:45
  • \$\begingroup\$ Thanks that work! I'm ordering the scene back to front with the result of my FrustumCuller (~50 elements currently). In my algorithm, I take in account object's depth and his position. Thanks again! \$\endgroup\$ – user34026 Aug 14 '13 at 14:28
  • \$\begingroup\$ @user34026 you can then remove the discard from your shader if you use glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); which should help the mobile GPU drivers to re-enable the optimizations. \$\endgroup\$ – PeterT Aug 14 '13 at 16:33
  • \$\begingroup\$ @PeterT Thanks, I've changed that earlier and it's work perfectly. But I have another question: How can I handle alpha and order when I work with batching? (I "merge" all my similar meshes to have only one draw call) \$\endgroup\$ – user34026 Aug 14 '13 at 19:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.