What is the best way to render a mixture point sprites and 3D objects?
Say for example, I wanted to model "space dust" particles as point sprites. In space I could have large asteroid objects (cubes for simplicity) and the space dust particles could be in front of or behind the asteroid cubes.
I am stuck with 2 scenarios:
- I render the space dust point sprites first, use
gl_DepthMask(GL_TRUE)
and then render the asteroid cubes (space dust is always behind the asteroids) - I render the asteroid cubes first, use
gl_DepthMask(GL_FALSE)
, render the space dust point sprites and setgl_DepthMask(GL_TRUE)
(space dust always appears in front of the asteroids)
I am currently using a single particle emitter vertex shader that draws a load of particles with gl_DrawArrays()
at random (x,y,z) positions.
How can I render a load of particles so that they will appear both in front of and behind the asteroid cubes?
If my particles were individual quads then I could sort the order of Z rendering but I have no idea how to achieve this behaviour using gl_DrawArrays()
, GL_POINT
s and my vertex shader.
Should I perhaps be splitting up the particles into sets of arrays - for example would I have to do something like this:
- draw an array of particles that are behind all asteroids
- draw asteroid furthest away
- draw another array of particles that appear in front of the above asteroid but behind the next closest asteroid
- draw front-most asteroid
If I have a lot of asteroids, wouldn't this be terribly inefficient?
Surely OpenGL has a better way of achieving this than what I am suggesting above?
Update: Trying Thomas' suggestion:
My cube and particles are rendered with the following blend/depth calls:
// First render opaque object(s)
glEnable( GL_DEPTH_TEST );
glDepthMask( true );
g_ObjCube1.Render();
// Now render sprites with particle emitter - sprites should appear
// behind and in front of above cube
glEnable( GL_POINT_SPRITE );
// Stop overlapping particles from interfering with each other
//glDisable( GL_DEPTH_TEST ); <- NO! Must leave depth test enabled
glDepthMask( false );
glEnable( GL_BLEND );
//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBlendFunc( GL_SRC_ALPHA, GL_ONE ); // Doing the same as above
glBlendEquation( GL_FUNC_ADD );
...
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
...
glDepthMask( true );