Game Development Community

Dts ambient lighting bug fix...

by John Kabus (BobTheCBuilder) · in Torque Game Engine · 12/06/2003 (7:04 pm) · 11 replies

Ok, mystery solved:

The 'fix' I posted a few days ago is clearly wrong. I don't know how I ever convinced myself that the mac/pc code was swapped. I realized tonight as soon as I looked at the code how completely wrong it was (how embarrassing).

Anyway the real issue is that the terrain lightmap is in BGRA format and getColor is expecting RGBA.

So to make a long story short:

-my fix is bunk, so ignore it.
-the c++ blender is bunk, so I'll fix it.
-getColor doesn't work with BGRA textures, so I'll fix it.

I'll get back in a little while with the blender/getColor fixes.

Sorry for the inconvenience...

John.

Btw: So far the second half of my post (using the interior ambient model when on the terrain) still works fine. Just steer clear of the getColor/setColor changes.


Original post:
Quote:
Dts ambient lighting bug fix...

Ok, I've got two fixes. One is a bug fix the other is personal preference.

First the bug:

GBitmap.cc line getColor() (580) the following pc/mac code is reversed:

#if defined(TORQUE_OS_MAC)
      rColor.red   = (*((U16*)pLoc) >> 0) & 0x1F;
      rColor.green = (*((U16*)pLoc) >> 5) & 0x1F;
      rColor.blue  = (*((U16*)pLoc) >> 10) & 0x1F;  
      rColor.alpha = ((*((U16*)pLoc) >> 15) & 0x01) ? 255 : 0;
#else
      rColor.red   =  *((U16*)pLoc) >> 11;
      rColor.green = (*((U16*)pLoc) >> 6) & 0x1f;
      rColor.blue  = (*((U16*)pLoc) >> 1) & 0x1f;  
      rColor.alpha = (*((U16*)pLoc) & 1) ? 255 : 0;
#endif

should be:

#if defined(TORQUE_OS_MAC)
 [b]     rColor.red   =  *((U16*)pLoc) >> 11;
      rColor.green = (*((U16*)pLoc) >> 6) & 0x1f;
      rColor.blue  = (*((U16*)pLoc) >> 1) & 0x1f;  
      rColor.alpha = (*((U16*)pLoc) & 1) ? 255 : 0;[/b]
#else
[b]      rColor.red   = (*((U16*)pLoc) >> 0) & 0x1F;
      rColor.green = (*((U16*)pLoc) >> 5) & 0x1F;
      rColor.blue  = (*((U16*)pLoc) >> 10) & 0x1F;  
      rColor.alpha = ((*((U16*)pLoc) >> 15) & 0x01) ? 255 : 0;[/b]
#endif

and setColor() (line 637):

#if defined(TORQUE_OS_MAC)
      *((U16*)pLoc) = (((rColor.alpha>0) ? 1 : 0)<<15) | (rColor.blue << 10) | (rColor.green << 5) | (rColor.red << 0);
#else
      *((U16*)pLoc) = (rColor.blue << 1) | (rColor.green << 6) | (rColor.red << 11) | ((rColor.alpha>0) ? 1 : 0);
#endif

should be:

#if defined(TORQUE_OS_MAC)
 [b]     *((U16*)pLoc) = (rColor.blue << 1) | (rColor.green << 6) | (rColor.red << 11) | ((rColor.alpha>0) ? 1 : 0);[/b]
#else
[b]      *((U16*)pLoc) = (((rColor.alpha>0) ? 1 : 0)<<15) | (rColor.blue << 10) | (rColor.green << 5) | (rColor.red << 0);[/b]
#endif

now this works on pc, but I would appreciate it if someone could verify that it works on mac.

...

#1
12/06/2003 (7:05 pm)
Next the preference issue:

If you create a mission with any kind of colored lighting (anything other than white or gray) you my notice that the lighting affecting the dts's is off when you're on the terrain.

The code in Torque collects the lighting info off of the terrain lightmap only to convert it into a grayscale and then sets the new value as the ambient lighting contribution.

My personal preference is to use the same code method for ambient lighting that the interiors are using. The actual lighting color info is used for the ambient lighting and the transition from terrain to interior is much less noticeable.

To see what I mean you can change SceneObject.cc installLights() (approximately line 1726) from:

if(getLightingAmbientColor(&ambientColor))
   {
      switch(mLightingInfo.mLightSource)
      {
         case LightingInfo::Interior:
         {
            // ambient/directional contributions
            const F32 directionalFactor = 0.3f;
            const F32 ambientFactor = 0.7f;

            LightInfo & light = mLightingInfo.smAmbientLight;

            light.mType = LightInfo::Ambient;
      		light.mDirection = VectorF(0.57735f, 0.57735f, -0.57735f);
            light.mColor = ambientColor * directionalFactor;
            light.mAmbient = ambientColor * ambientFactor;

            lightManager->addLight(&mLightingInfo.smAmbientLight);
            lightManager->setVectorLightsEnabled(false);

            break;
         }

         case LightingInfo::Terrain:
         {
            F32 factor = mClampF((ambientColor.red + ambientColor.green + ambientColor.blue) / 3.f, 0.f, 1.f);
            lightManager->setVectorLightsAttenuation(factor);
            break;
         }
      }
   }

to:

if(getLightingAmbientColor(&ambientColor))
   {
    [b]  //switch(mLightingInfo.mLightSource)
      //{
      //   case LightingInfo::Interior:
      //   {[/b]
            // ambient/directional contributions
            const F32 directionalFactor = 0.3f;
            const F32 ambientFactor = 0.7f;

            LightInfo & light = mLightingInfo.smAmbientLight;

            light.mType = LightInfo::Ambient;
      		light.mDirection = VectorF(0.57735f, 0.57735f, -0.57735f);
            light.mColor = ambientColor * directionalFactor;
            light.mAmbient = ambientColor * ambientFactor;

            lightManager->addLight(&mLightingInfo.smAmbientLight);
            lightManager->setVectorLightsEnabled(false);

    [b]  //      break;
      //   }

      //   case LightingInfo::Terrain:
      //   {
      //      F32 factor = mClampF((ambientColor.red + ambientColor.green + ambientColor.blue) / 3.f, 0.f, 1.f);
      //      lightManager->setVectorLightsAttenuation(factor);
      //      break;
      //   }
      //}[/b]
   }

Any comments? I'm curious as to what everyone's thoughts may be.

John.
#2
12/07/2003 (2:23 am)
Thanks, I like your way better too.
#3
12/09/2003 (10:18 am)
Hey Mark,

Have you noticed any weird lighting on your guy when you're on the terrain?

Sometimes the information coming from getColor is totally inconsistent with the lighting on the terrain under your guy. It looks like the code that translates the player position into the lightmap uv may be broken (inferred based on the code that is known to be working).

Anyway I'll take a look at this as soon as I get the chance. Let me know if you are having problems...

Thanks...

John.
#4
12/09/2003 (10:20 am)
Btw: I only noticed this yesterday in the 1.2 demo mission (stronghold?). If you watch the bot running around sometimes he will turn purple.
#5
12/09/2003 (10:35 am)
John,

I've fooled around in that code before. If you comment out the Interior vs Terrain check you'll notice some strange 'flickering' of the player when they are near but not totally inside an interior. There are also some other strange problems, just fyi.

Also the getAmbientLight function is .. really screwed up. It casts a ray 100 units down to pick the light and is dependant on whether it struck an interior or a terrain.

I wish there was a better way of doing that, so if you have any ideas let me know.
#6
12/09/2003 (11:18 am)
Robert,

Yes, unfortunately I've dealt with getLightingAmbient before. It's a real mess and hate that it uses the interior's vertex lighting (grrr...).

Anyway I'll take a look at it tonight. I really think that the lm uv's fall outside of the actual texture buffer (at least for the purple). If the calculations are off that would also explain why the lighting is off (when it's working). I'll keep what you've said in mind; in fact the issue may have to do with the rayCast not hitting anything at all.

Oh well, technically this is not a new issue. I've always noticed the player randomly (and briefly) becoming a little too dark when on the terrain in Torque. Clearly this was the same issue, but Torque's processing on the lm color (gray scaled and blended with the directional lighting) minimizes it greatly.

Thanks for the input and I'll let you know what I come up with...

John.
#7
12/09/2003 (6:31 pm)
Ok, mystery solved:

The 'fix' I posted a few days ago is clearly wrong. I don't know how I ever convinced myself that the mac/pc code was swapped. I realized tonight as soon as I looked at the code how completely wrong it was (how embarrassing).

Anyway the real issue is that the terrain lightmap is in BGRA format and getColor is expecting RGBA.

So to make a long story short:

-my fix is bunk, so ignore it.
-the c++ blender is bunk, so I'll fix it.
-getColor doesn't work with BGRA textures, so I'll fix it.

I'll get back in a little while with the blender/getColor fixes.

Sorry for the inconvenience...

John.

Btw: So far the second half of my post (using the interior ambient model when on the terrain) still works fine. Just steer clear of the getColor/setColor changes.
#8
12/09/2003 (8:05 pm)
Blender fix (blender.cc line 721) change:

U32 i;
                  for(i = 0; i < 4; i++)
                  {
                     // dc - leave this alone on mac, as seem to be have lightmaps as 5551 RGBA (pc format)
                     col[0][i] = (lumels[i])      & (0x1f << 11);
                     col[1][i] = (lumels[i] << 5)   & (0x1f << 11);
                     col[2][i] = (lumels[i] << 10)   & (0x1f << 11);
                  }

to:

U32 i;
                  for(i = 0; i < 4; i++)
                  {
#if defined(TORQUE_OS_MAC)
                     // dc - leave this alone on mac, as seem to be have lightmaps as 5551 RGBA (pc format)
                     col[0][i] = (lumels[i])      & (0x1f << 11);
                     col[1][i] = (lumels[i] << 5)   & (0x1f << 11);
                     col[2][i] = (lumels[i] << 10)   & (0x1f << 11);
#else
                     col[[b]2[/b]][i] = (lumels[i])      & (0x1f << 11);
                     col[1][i] = (lumels[i] << 5)   & (0x1f << 11);
                     col[[b]0[/b]][i] = (lumels[i] << 10)   & (0x1f << 11);
#endif
                  }

This assumes that the existing code works on mac.

Next the getColor fix (gBitmap.cc line 542) add:

/**
 * jk - Will properly get a pixel from a BGRA texture
 *      with an RGBA color object and vice versa.
 */
bool GBitmap::getColorBGRA(const U32 x, const U32 y, ColorI& rColor) const
{
	if(!getColor(x, y, rColor))
		return false;
	//jk - swap red and blue...
	U8 r = rColor.red;
	rColor.red = rColor.blue;
	rColor.blue = r;
	return true;
}

/**
 * jk - Will properly set a pixel in a BGRA texture
 *      with an RGBA color object and vice versa.
 */
bool GBitmap::setColorBGRA(const U32 x, const U32 y, ColorI& rColor)
{
	//jk - copy then swap red and blue...
	//jk - using a copy so the color object provided by the caller isn't swapped...
	ColorI temp = rColor;

	U8 r = temp.red;
	temp.red = temp.blue;
	temp.blue = r;

	return setColor(x, y, temp);
}

and (gBitmap.h line 87) add:

bool        getColorBGRA(const U32 x, const U32 y, ColorI& rColor) const;
   bool        setColorBGRA(const U32 x, const U32 y, ColorI& rColor);

and (sceneObject.cc line 2016) change:

ColorI terrCol;
            if(lightmap->getColor(pos.x, pos.y, terrCol))
            {
               const F32 scale = 255.f / 31.f;

to:

ColorI terrCol;
            if(lightmap->getColorBGRA(pos.x, pos.y, terrCol))
            {
               const F32 scale = 255.f / 31.f;
#9
12/09/2003 (8:42 pm)
Cool. I thanks you guys.
#10
12/10/2003 (9:43 am)
Is this only beneficial to Mac OS?
#11
12/10/2003 (10:12 am)
Good question:

- The blender issue only pops up when using the c++ blender on a pc (as far as I can tell).
- The getColor/setColor issue should be broken on both platforms.
- The change to installLights is really a preference thing.

If anyone is having a problem please let me know.

Thanks...

John.