TGE bug: use of getLight(0) as sunlight
by John Kabus (BobTheCBuilder) · in Torque Game Engine · 05/16/2004 (11:23 am) · 9 replies
I recently ran into this issue with the Lighting Pack and have identified the same problem in stock TGE. The problem is this:
FxSunLight and WaterBlock both attempt to use LightManager's first registered light as the sun, however this is not always the case. In some instances I've seen fxLight::onAdd called before Sun::onAdd, placing fxLights before the sun in the LightSet and ultimately before the sun in the registered light list. Also the registered light list is resorted by any object that calls installLights and is left in the new sort order going into the next object, which could potentially be fxSunLight or WaterBlock neither of which will resort before assuming that the sun is at index 0.
To resolve this I've added the ability to trap vector lights being registered by LightManager to be used as the sun.
In fxSunLight.cc approximately line 1688 change:
To
In fluidRender.cc approximately line 810 change:
To
FxSunLight and WaterBlock both attempt to use LightManager's first registered light as the sun, however this is not always the case. In some instances I've seen fxLight::onAdd called before Sun::onAdd, placing fxLights before the sun in the LightSet and ultimately before the sun in the registered light list. Also the registered light list is resorted by any object that calls installLights and is left in the new sort order going into the next object, which could potentially be fxSunLight or WaterBlock neither of which will resort before assuming that the sun is at index 0.
To resolve this I've added the ability to trap vector lights being registered by LightManager to be used as the sun.
In fxSunLight.cc approximately line 1688 change:
// Do we have any lights?
if ( gClientSceneGraph->getLightManager()->getNumLights() > 0 )
{
// Yes, so fetch sunlight ( always first light ).
LightInfo sunLight = gClientSceneGraph->getLightManager()->getLight(0);
VectorF sunVector = -sunLight.mDirection;
// Calculate Pitch/Yaw.
F32 Yaw, Pitch;
MathUtils::getAnglesFromVector(sunVector, Yaw, Pitch);To
[b] LightInfo *sunLight;
if((sunLight = gClientSceneGraph->getLightManager()->getSunLight()) != NULL)
[/b] {
[b] VectorF sunVector = -sunLight->mDirection;[/b]
// Calculate Pitch/Yaw.
F32 Yaw, Pitch;
MathUtils::getAnglesFromVector(sunVector, Yaw, Pitch);In fluidRender.cc approximately line 810 change:
// Do we have any lights?
if ( gClientSceneGraph->getLightManager()->getNumLights() > 0 )
{
// Yes, so fetch sunlight ( always first light ).
// calculate real sun elevation/azimuth.
LightInfo sunLight = gClientSceneGraph->getLightManager()->getLight(0);
lightDir = sunLight.mDirection; //first light is always sun
}To
[b] LightInfo *sunLight;
if((sunLight = gClientSceneGraph->getLightManager()->getSunLight()) != NULL)[/b]
{
// calculate real sun elevation/azimuth.
[b] lightDir = sunLight->mDirection;[/b]
}
#2
Change terrRender.cc line 1790:
To
Change lightManager.cc line 338:
To
-John
05/16/2004 (11:54 am)
Quick update:Change terrRender.cc line 1790:
Point3F sTangent,tTangent;
static Vector<LightInfo*> lights;
lights.clear();
gClientSceneGraph->getLightManager()->getLights(lights);
VectorF sunVector = -lights[0]->mDirection; //first light is always sunTo
Point3F sTangent,tTangent;
[b] VectorF sunVector;
LightInfo *sunLight = gClientSceneGraph->getLightManager()->getSunLight();
if(sunLight)
sunVector = sunLight->mDirection;
else
sunVector = VectorF(-0.57735f, -0.57735f, -0.57735f);[/b]Change lightManager.cc line 338:
const Point3F LightManager::getShadowLightDirection() const
{
if(getNumLights() > 0)
return mLights[0]->mDirection;
else
// Do a lame default...
return Point3F(0.573, 0.573, -0.573);
}To
const Point3F LightManager::getShadowLightDirection() const
{
[b] if(mSunLight)
return mSunLight->mDirection;[/b]
else
// Do a lame default...
return Point3F(0.573, 0.573, -0.573);
}-John
#3
Heh, nice changes john, I guess this was causing problems with weird shadows appearing right?
05/16/2004 (3:16 pm)
W00t, the second code post of yours has a comment by me :P (XA)Heh, nice changes john, I guess this was causing problems with weird shadows appearing right?
#4
That would definitely be a side effect too, but the original issue I had was flickering fxSunLights and WaterBlock specular highlights. This would appear under certain conditions in TGE. Some of the lighting options in the Lighting Pack exaggerated the problem making it appear more frequently, that's how I was able to track it down quickly.
This should make things less hairy, personally the light0 == sun concept always made me a little nervous. :)
-John
05/16/2004 (3:28 pm)
Hi Xavier,That would definitely be a side effect too, but the original issue I had was flickering fxSunLights and WaterBlock specular highlights. This would appear under certain conditions in TGE. Some of the lighting options in the Lighting Pack exaggerated the problem making it appear more frequently, that's how I was able to track it down quickly.
This should make things less hairy, personally the light0 == sun concept always made me a little nervous. :)
-John
#5
Regards,
Xavier.
05/16/2004 (4:27 pm)
Hehe, yeah, hard coding stuff like that isn't nice really, plus you need to know that 0 is the sun (if that was even true), having it with a special method to get the sun is a much better solution. Guess this will be rolled into CVS after it's tested, maybe you could make a patch and submit this as a patch resource so it gets in quicker!Regards,
Xavier.
#6
05/16/2004 (5:38 pm)
I came up across same problem when adjusting particle colour according to sun ambient color. :p A dedicated functiob would be nice :)
#7
05/23/2004 (11:19 am)
Might also want to look in ShapeBase.cc for the shadow render. I know in stock torque the shadows on shapebase objects don't change position based on the sun vector.
#8
05/24/2004 (8:51 am)
That has been fixed in the HEAD
#9
05/24/2004 (9:26 am)
John, this works. I tested it out this weekend with my current HEAD release (the one where I was seeing the flickery sun flares). Blammo! That got it. You da man!
Torque Owner John Kabus (BobTheCBuilder)
// XA: Moved to public for access via ConsoleMethod void resetGL(); private: U32 installGLLights(); void installGLLight(LightInfo *); void fillLightList(LightInfoList&, U32); void scoreLight(LightInfo *, const SphereF &) const; void scoreLight(LightInfo *, const PlaneF *, const U32, const Point3F &) const; static S32 QSORT_CALLBACK compareLights(const void *, const void *); LightInfoList mLights; U32 mMaxGLLights; U32 mGLLightCount; bool mGLLightsInstalled; bool mGLInitialized; bool mVectorLightsEnabled; F32 mVectorLightsAttenuation; ColorF mAmbientLightColor; };To
// XA: Moved to public for access via ConsoleMethod void resetGL(); [b] LightInfo *getSunLight() {return mSunLight;}[/b] private: U32 installGLLights(); void installGLLight(LightInfo *); void fillLightList(LightInfoList&, U32); void scoreLight(LightInfo *, const SphereF &) const; void scoreLight(LightInfo *, const PlaneF *, const U32, const Point3F &) const; static S32 QSORT_CALLBACK compareLights(const void *, const void *); LightInfoList mLights; U32 mMaxGLLights; U32 mGLLightCount; bool mGLLightsInstalled; bool mGLInitialized; bool mVectorLightsEnabled; F32 mVectorLightsAttenuation; ColorF mAmbientLightColor; [b] LightInfo *mSunLight;[/b] };In lightManager.cc approximately line 48 change:
LightManager::LightManager() { mGLInitialized = false; mGLLightsInstalled = false; mGLLightCount = 0; mAmbientLightColor.set(0.f,0.f,0.f); mVectorLightsAttenuation = 1.f; mVectorLightsEnabled = true;To
LightManager::LightManager() { mGLInitialized = false; mGLLightsInstalled = false; mGLLightCount = 0; mAmbientLightColor.set(0.f,0.f,0.f); mVectorLightsAttenuation = 1.f; mVectorLightsEnabled = true; [b] mSunLight = NULL;[/b]In lightManager.cc approximately line 128 change:
void LightManager::addLight(LightInfo * light) { mLights.push_back(light); } void LightManager::removeLight(LightInfo * light) { for(U32 i = 0; i < mLights.size(); i++) { if(mLights[i] == light) { mLights.erase_fast(i); break; } } }To
void LightManager::addLight(LightInfo * light) { mLights.push_back(light); [b] if(light->mType == LightInfo::Vector) mSunLight = light;[/b] } void LightManager::removeLight(LightInfo * light) { for(U32 i = 0; i < mLights.size(); i++) { if(mLights[i] == light) { mLights.erase_fast(i); break; } } [b] if(mSunLight == light) mSunLight = NULL;[/b] }If anyone discovers any issues with this fix please let me know so I can resolve them.
-John Kabus