PDA

View Full Version : blending decals/particles in a multi-pass renderer



Vexator
04-06-2008, 11:47 AM
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:

http://www.desertsatori.com/vexator/0.jpg http://www.desertsatori.com/vexator/1.jpg

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!

Komat
04-07-2008, 12:40 AM
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 )
}
}

Dark Photon
04-07-2008, 06:09 AM
so, for the first time, I have to handle transparency in a multi-pass environment....with transparency blending enabled ( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) )...there is no lighting where the decal should be transparent...so it seems i have to do more. but what?

Pre-multiplied alpha? For details, look at the Pre-multiplied alpha article in here (http://home.comcast.net/~tom_forsyth/blog.wiki.html), and see this (http://www.gimp.org/docs/plug-in/appendix-alpha.html) 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.

Vexator
04-08-2008, 10:46 AM
it works fine now, thank you! :D

Mikkel Gjoel
04-09-2008, 05:54 AM
vexator - for this community-thingy to make any sense at all, you need to tell everyone what you did to make it work :)

Vexator
04-10-2008, 06:56 AM
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 );
}