Game Development Community

SgDecalProjector != distance culling

by Caylo Gypsyblood · in Torque Game Engine · 02/26/2007 (9:37 pm) · 6 replies

Some time ago i was on a quest to have my decal projectors occlude with the view fog.

I finally got back to it, and have found this solution to work great.
This is from 1.42TLK, i expect it should work with 1.5 just fine.

Find bool DecalManager::prepRenderImage and copy this over it.
bool DecalManager::prepRenderImage(SceneState* state, const U32 stateKey,
                                   const U32 /*startZone*/, const bool /*modifyBaseState*/)
{
   if (!smDecalsOn) return false;
   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);
   if (mDecalQueue.size() == 0)
      return false;

   // This should be sufficient for most objects that don't manage zones, and
   //  don't need to return a specialized RenderImage...
   SceneRenderImage* image = new SceneRenderImage;
   image->obj = this;
   image->isTranslucent = true;
   image->sortType      = SceneRenderImage::BeginSort;
   state->insertRenderImage(image);
   U32 currMs = Platform::getVirtualMilliseconds();

   for (S32 i = mDecalQueue.size() - 1; i >= 0; i--)
   {
//////QUICK&DIRY OCCLUSION
	////// get the VIEWer object and the render OBJECT
	Point3F endloc;
        endloc = mDecalQueue[i]->point[0];//mDecalQueue THIS decal's point from '0' poly
	endloc -= state->getCameraPosition();
	F32   Ddist = endloc.len();
	//////calc the amount of FOG it have
	F32 fogAmount = state->getHazeAndFog(Ddist, endloc.z);
	////// The following 0.90 is sorta a % of fog cover to consider occlusion.
	if (fogAmount  > 0.90 ) 	return false;
//////QUICK&DIRY OCCLUSION

      U32 age = currMs - mDecalQueue[i]->allocTime;
     
	  U32 timeout = mDecalQueue[i]->decalData->sgDecalData.sgLifeSpan;
      if (age > timeout)
      {
         freeDecalInstance(mDecalQueue[i]);
         mDecalQueue.erase(i);
      }
      else if (age > ((3 * timeout) / 4))
      {
         mDecalQueue[i]->fade = (1.00f-fogAmount) - (F32(age - ((3 * timeout) / 4)) / F32(timeout / 4));
      }
      else
      {
         mDecalQueue[i]->fade = (1.00f-fogAmount);
      }
   }
   if (mQueueDirty == true)
   {
      // Sort the decals based on the data pointers...
      dQsort(mDecalQueue.address(),
             mDecalQueue.size(),
             sizeof(DecalInstance*),
             cmpDecalInstance);
      mQueueDirty = false;
   }
   return false;
}

Take note the reversion date, and following reply are out of context.

#1
03/02/2007 (1:26 pm)
Awesome! Is the fog automatically applied during rendering, or did you have to alter the rendering code too?
#2
03/02/2007 (5:33 pm)
I actually did not hook fog INTO the decal, just made it so the decal can disappear in the fog. It just POP out of view.

I do notice mDecalQueue[i]->fade and expect one could easily add mDecalQueue[i]->fade = fogAmount; and then it WILL fade with distance- but have not tried it yet.

Ok, it works, not truly FOGGING but it do FADE according to the fog.

find the bit like this:
if (age > timeout)
      {
         freeDecalInstance(mDecalQueue[i]);
         mDecalQueue.erase(i);
      }
and change the 2 line that say mDecalQueue[i]->fade = into this
else if (age > ((3 * timeout) / 4))
      {
         mDecalQueue[i]->fade = (1.0f-fogAmount) - (F32(age - ((3 * timeout) / 4)) / F32(timeout / 4));
      }
      else
      {
         mDecalQueue[i]->fade = (1.0f-fogAmount);
      }
#3
03/02/2007 (6:46 pm)
Ah well, shoot. I only had tested this with ONE SgDecalProjector, oddly enough placed in the middle of my test map. So the testing turned out TRUE, but its still wrong.
mObjToWorld seems to be the middle of the world, i must find a way to get the location of each SgDecalProjector- same problem i had last time i took this on....
#4
03/03/2007 (10:32 am)
OK, i fixed it. Im putting the GOOD code in my original post; with the FADE for FOG bit... ^^^
#5
03/03/2007 (10:56 am)
Nice work, thanks for posting this!
#6
09/27/2009 (6:12 pm)
OK, I just installed this resource and I'm having some minor problems...

I know this is somewhat a resurrection, but considering the nature still very relevant!

I'm using the DecalProjector for Roads and I have multiple sections and from some angles it seems that sometimes it doesnt fade all the decal textures, from others it seems like it works perfectly.

Edit: BTW (for TGE1.5.2) Line#36 in the resource had to be replaced with:
U32 timeout = mDecalQueue[i]->decalData->lifeSpan;

Either way thanks for the resource!