Problem with transparent textures, when clipped

Hello guys.
Please be a bit patient with me as I am still a big OpenGL noob.

I am playing around with the DESCENT engine - maybe someone remembers. I managed to get textures filtered using mipmap and also using alpha for things like explosions.

This ONLY happens if the bitmap has it’s center coordinates BEHIND (from my point of view) such a wall.

Problem is: If an explosion bitmap (always aligned to viewer) is clipped “through” a wall (while the coordinates of the bitmap are BEHIND the wall texture), I the wall becomes invisible on the clipped part.

I have a hard time to explain this so I made a scheme:

  • The black line represents a wall texture (yes, only one texture)
  • The dotted line represents the FOV of the viewer/player
  • The red line represents an explosion bitmap which is located “behind” the wall but tru alignment to player is clipped through the wall
  • The green line now represents the part of the wall I SHOULD see behind the explosion part which came tru the wall… but it isn’t there.

Here is also a shot from the ectual engine:

I know it’s hard to see on this shot as there is a lot of red (explosion and lava behind the fence). Problem is: Behind that explosion slash bitmap, the fence is not visible…

I think this might be a problem with GL_BLEND? Or is it impossible to “fix” this, when such a clipping is happening? I hope it’s not. :frowning:

Here are some hopefully important function I set for the rendering:

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GEQUAL,0.02);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

Sorry for asking that stupid… but I hope anyone can help me. :slight_smile:

thanks in advance
Chris

Depth testing is draw order-independent.
Blending with a non-commutative blend function is draw order-dependent.

Therefore, blending and depth testing are incompatible.
You need to sort translucent objects manually.

It is like your engine determines that your fire sprite is in front of the wall from the view point thus, the sprite is drawn with depth writing enabled then the wall is drawn. But since the wall is behind the sprite in the green protion, it will not be drawn and the fire will be blended with the scene behind the wall.
If you disable depth writing when drawing the sprite this would not work either because the wall is not transparent and because of what arekkusu said about blending.

The only solution, is to draw all opaque objects in your scene. Then draw translucent objects (which should be z-sorted) with depth comparison enabled but depth writing disabled (since you sort geometry this depth writing is useless).

Yes, the sprite normally is “behind” that wall … but as my viewer has a bit different angle, the fire sprite rotates to the viewer. This way there is the clipping. And sure… I thought already: as the sprite normally is BEHIND the wall, Depth test does not count it in while drawing.

Hmmm as said I am a bit of a noob.
The game engine normally gives the segments from far to near to the opengl drawing functions. When done with a segment, it draws the objects in it. However this does not always correspond to the actual FOV but also follows the level structure a bit.

So I ask myself: Do I need to rewrite all that code when to render which segment and objects OR
do I have a possibility to manually sort the elements in the buffer (as depth test would do).
(Sorry, if this sounds stupid, but please see: the OpenGL stuff in this engine is just an overlay, so the actual game engine is pretty abstracted from the OpenGL part).

So I do not really understand what you guys mean with “first draw X then Y” or “sort manually”. I am dumb I guess. :slight_smile:
If I have to align all functions of how the level structure wants to “show” objects, this means a lot of work… especially because the coordinates of such a level are not relative to the viewer.
However if I can just sort objects by their Z-values on the opengl buffer, then I would be lucky and I just need to know how to do that. :slight_smile: (maybe hints to functions I need to use and/or pseudo code?)

Thanks again for all your patience.
It’s really nice you are really willing to help me to bring some light in the dark for me. Thanks so much. :slight_smile:

The only solution, is to draw all opaque objects in your scene. Then draw translucent objects (which should be z-sorted) with depth comparison enabled but depth writing disabled (since you sort geometry this depth writing is useless).

After thinking about this much further and reading I think I found my solution.
So first I now render the opaque objects like the walls, etc, normal polygon objects, all with depth test enabled.
Then I draw those sprites (while drawing the sides of the segment it’s located in) together with
glDepthMask(GL_FALSE).
This seems to give me pretty good results. The invisible-wall effects are gone. The sprite even stays “behind” the wall textures - where it belongs. :slight_smile:

I really hope I understood and realized it correctly so I will continue testing that and reading much more.

Thanks again for the help. :slight_smile:

Sounds correct.
However, in your above shot from the engine, the explosion texture has an annoying whitish outline. There certainly ways to improve this.
Can you share the data inputs to the engine, how the original descent interpreted it, how does your engine interprets it ?
Especially blend modes, alpha testing parameters, do you rebuild the alpha channel, etc ?

Hmm that outline around the explosion also seems to be happening only when it’s clipped through the wall. This effect also disappears with glDepthMask.

I’ve made a new screenshot, with a better visible explosion:

Sure this also doesn’t look very cool, but that’s what you get with 64x64 textures.

Great, that looks better indeed! :slight_smile:

BTW, if the engine has MSAA, you can utilize the Alpha-To-Coverage to get rid of the annoying alpha sorting.

You can get some example pics from here.(Just ignore the chinese, look at the pics. :slight_smile: )