Game Development Community

Distortion effects, the backbuffer, and particles

by Max Robinson · in Torque Game Engine Advanced · 09/06/2005 (1:15 pm) · 8 replies

I've been trying to create a sort of compression wave/ripple or "shockwave" sort of effect by creating a shader (mostly just a refract) and by creating an object to attach to an explosion that will use a material that has this shader. There's one big problem though, and that is that most things are not in the backbuffer. Projectiles, particles, and water aren't there, and I suppose for a small refracting object usually used in an indoor area, this wouldn't usually be a problem. But I'm looking to create an object that will overlap particles in every case it is used.

So first question: is it intended that particles not be in the backbuffer? Is it for performance reasons?

Whether it's intended or not - how would I go about making sure they are in the backbuffer? Sticking in a renderImage with the Refraction sortType didn't do it, so what's the real way?

If there's another way to do a sort of area-based pixel offset or something similar to what I'm talking about, but it won't need to use the backbuffer or something more costly to performance, please tell me! I'm new at this stuff, and am very willing to learn.

And on particles: is the current particle implementation "complete" or is it due for some major changes? I can imagine a lot of re-organizations, and I've already modified it a lot to do some things I need it to do, but I would like to go farther. I'm curious, because if major changes are slated for the particles, then I'd like to hold off on modifications until they are "done."

#1
09/06/2005 (4:43 pm)
The particles don't refract because all translucent objects are drawn after refractive objects. This is because translucent objects don't write to the zbuffer and therefore wouldn't sort right if you drew refractive objects first.

This can be solved by rendering translucent obects twice - once before refractive objects, and then once afterwards. But this is not very efficient.

To play with this ordering yourself look in SceneState::renderCurrentImages().



The current particle implementation is pretty much set other than added support for shaders to the particles. A vertex shader may be added to handle particle rotations, etc.
#2
10/07/2005 (7:27 pm)
Woot!

It looks better in motion. (may have to save it and play)
0.5 mb xvid video

www.echelon5.net/max/sw1.jpgwww.echelon5.net/max/sw2.jpgwww.echelon5.net/max/sw3.jpg
#3
10/13/2005 (7:57 pm)
Very cool effect Max. Party on dude!
#4
04/08/2007 (12:03 am)
Hello,

I am also running into this problem with meshes that are rendered with translucency (I guess its the same issue you were having with projectiles)... It is quite noticeable when you look out from under-water and notice that there are no tree-tops... :(

How did you solve this issue Max? By double-rendering translucent objects? Is there really no better way than that?

Thanks in advance for any help you may be able to provice...

Stephane
#5
04/08/2007 (12:45 am)
Alright, I've found a way to solve this. It seems like it might be an elegant way to fix this issue (and probably this glow buffer issue among others). It does not require double rendering translucent objects and allows a user to decide on a per-material basis which translucent things should be allowed to be refracted.

All you need to do is add another render bin type (I called mine TranslucentZWrite):
enum RenderBinTypes
   {
      Sky = 0,
      Begin,
      Interior,
      InteriorDynamicLighting,
      Mesh,
      MiscObject,
      Shadow,
      Decal,
      TranslucentZWrite,
      Refraction,
      Water,
      Glow,
      Foliage,
      Translucent,
      NumRenderBins
   };
Make sure that the new render bin type is before the refraction bin type.

Next, modify the top of the
void RenderInstManager::addInst( RenderInst *inst )
function to be like so:

AssertISV( mInitialized, "RenderInstManager not initialized - call console function 'initRenderInstManager()'" );
// handle special cases that don't require insertion into multiple bins
if( inst->translucent || (inst->matInst && inst->matInst->getMaterial()->translucent ) )
{
    if (inst->matInst && inst->matInst->getMaterial()->translucentZWrite)
        mRenderBins[ TranslucentZWrite ]->addElement( inst );
    else
        mRenderBins[ Translucent ]->addElement( inst );
    return;
}

Now, any material that you flag as 'translucent' and 'translucentZWrite' will get added to the TranslucentZWrite render manager and get rendered before the back buffer is copied... which means it will be included in the refracted buffer and be visible in shaders using refraction. Since 'translucentZWrite' also draws the translucent material to the z-buffer, translucent objects drawn this way should be sorted properly... Preliminary tests show that things seem to work fine.

Please let me know if you have any trouble using this... I will send an e-mail to Brian to let him know about this possible work-around.

Cheers,

Stephane
#6
04/08/2007 (3:33 am)
Can anyone create a resource on how you're getting this effect? :-/
#7
04/10/2007 (4:09 pm)
Ya, this should be a resource. Like I said above this is not efficient and could significantly affect performance on low-end cards.
#8
04/10/2007 (10:07 pm)
Thank you for checking out this post Brian.

Writing many translucent objects to the z-buffer will certainly incur a performance hit, but as long as you are very selective with which objects have translucentZWrite enabled you should be alright.