blending decals/particles in a multi-pass renderer

i have recently switched from deferred rendering to classic multi-pass forward rendering and added decals and particle systems, so, for the first time, I have to handle transparency in a multi-pass environment.

i have read numerous threads both here and on the gamedev forums, but didn’t get a satisfying answer. they all agree that it’s not a simple task, but while some say it’s possible to do using blending alone, others talk about using a separate frame buffer for translucent meshes… etc.

keep in mind that i only need transparency for decals and particles, i. e. simple quads that are already sorted from back to front. in all other cases like water and glass, i have to use separate buffers anyway to store what’s behind.

this is what i do so far:
in the initial pass i render depth and ambient light; first come opaque meshes with blending disabled, then come decals and particles sorted back to front with transparency blending enabled ( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ). then i enable additive blending ( glBlendFunc(GL_ONE, GL_ONE) )and render my lighting passes.

this obviously is wrong or insufficent:

if no lights are enabled, the decal blends fine (left picture), but if i enable a light source then there is no lighting where the decal should be transparent (compare the box’s shadow in the top right).
i have tried any possible blend mode combination without success, so it seems i have to do more. but what?

thanks!

You need to first render all opaque meshes with all lighting. Then you need to render the decals. If the decals are lit and can overlap then you need something like.


opaque_ambient_pass() ;
for each light {
    for each opaque_object {
        lit_render( ONE, ONE )
    }
}

for each decal {
    ambient_render( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ) ;    
    for each light {
         lit_render( SRC_ALPHA, ONE )
    }
}

Pre-multiplied alpha? For details, look at the Pre-multiplied alpha article in here, and see this for a GIMP/Photoshop-centric overview. Not using this is the most common cause of problems I’ve seen when blending multi-layered particle systems together.

it works fine now, thank you! :smiley:

vexator - for this community-thingy to make any sense at all, you need to tell everyone what you did to make it work :slight_smile:

just the way they told me: using premultiplied alpha and rendering ambience and lighting passes per mesh:

for every mesh
{
	if( mesh->HasAlpha() )
	{
		// alpha blending
		glEnable( GL_BLEND );
		glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
	}

	mesh->Render( AMBIENT_PASS );

	if( mesh->HasAlpha() )
	{
		// alpha-additive blending
		glBlendFunc( GL_SRC_ALPHA, GL_ONE );
	}
	else
	{
		// additive blending
		glEnable( GL_BLEND );
		glBlendFunc( GL_ONE, GL_ONE );
	}

	mesh->Render( LIGHTING_PASSES );

	glDisable( GL_BLEND );
}