Search code examples
c#opengltransparencyopengl-3

Render particles in the transparent parts of other particles


Problem

I am rendering a 3D cube, and this works fine. Afterwards, I render particles as an array of points, which a geometry shader transforms to quads (2 triangles). The problem I have is that the transparent part from my particle texture is not replaced with the non-transparent color from a particle "behind" it:

enter image description here

As the image shows, the grey/orange textured cube behind it is shown correctly "through" the transparent parts of the particles. However, where particles textures overlap, the "bottom" one is not shown through the "top" one, even in the supposedly transparent parts.

Before rendering the cube, I call

gl.Enable(EnableCap.DepthTest);
gl.DepthMask(true);
gl.Disable(EnableCap.Blend);

and before I render the particles,

gl.Enable(EnableCap.Blend);
gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

(method names are slightly different than original openGL because I'm using Silk.NET, a thin wrapper for openGL)

What I've tried

Now, I found a possibly similar question. I can't quite confirm, because the images are gone there, but I tried the advice there nonetheless. However, doing

gl.DepthMask(false);
gl.Enable(EnableCap.Blend);
gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

before rendering the particles, the blending of the particles among each other works mostly fine. However, I first thought the cube behind it has vanished - but while I move the camera, I see glitchy fragments of it (it took me several tries to get this on a screenshot)

enter image description here


Solution

  • OK I found it and if you know it, it feels semi-obvious.

    When rendering the particles, I set gl.DepthMask(false);, but the particles were the last openGL thing I did per frame. So when the next frame started, the depth mask was still off. Apparently this also influences glClear(), so the depth buffer was not cleared at all then.