Torque3D Documentation / _generateds / lightManager.cpp

lightManager.cpp

Engine/source/lighting/lightManager.cpp

More...

Public Functions

DefineEngineFunction(getActiveLightManager , const char * , () , "Returns the active light manager <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
DefineEngineFunction(getLightManagerNames , String , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tab seperated list of light manager <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">names.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
DefineEngineFunction(lightScene , bool , (const char *completeCallbackFn, const char *mode) , (nullAsType< const char * >(), nullAsType< const char * >()) , "Will generate static lighting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the scene <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> supported by the active light <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manager.\n\n</a>" "If <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> is \"forceAlways\" , the lightmaps will be regenerated regardless of whether " "lighting cache files can be written to. If <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> is \"forceWritable\" , then the lightmaps " "will be regenerated only <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the lighting cache files can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">written.\n</a>" " @param completeCallbackFn The name of the function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> execute when the lighting is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">complete.\n</a>" " @param <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> One of \"forceAlways\" , \"forceWritable\" or \"loadOnly\".\n" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the scene lighting process was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">started.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
DefineEngineFunction(resetLightManager , void , () , "@brief Deactivates and then activates the currently active light manager." "This causes most shaders <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be regenerated and is often used when global " "rendering changes have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occured.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
DefineEngineFunction(setLightManager , bool , (const char *name) , "Finds and activates the named light <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manager.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the light manager is found and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
IMPLEMENT_GLOBAL_CALLBACK(onLightManagerActivate , void , (const char *name) , (name) , "A callback called by the engine when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> light manager is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param name The name of the light manager being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )
IMPLEMENT_GLOBAL_CALLBACK(onLightManagerDeactivate , void , (const char *name) , (name) , "A callback called by the engine when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> light manager is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deactivated.\n</a>" "@param name The name of the light manager being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deactivated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

Detailed Description

Public Functions

DefineEngineFunction(getActiveLightManager , const char * , () , "Returns the active light manager <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

DefineEngineFunction(getLightManagerNames , String , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tab seperated list of light manager <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">names.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

DefineEngineFunction(lightScene , bool , (const char *completeCallbackFn, const char *mode) , (nullAsType< const char * >(), nullAsType< const char * >()) , "Will generate static lighting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the scene <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> supported by the active light <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manager.\n\n</a>" "If <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> is \"forceAlways\" , the lightmaps will be regenerated regardless of whether " "lighting cache files can be written to. If <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> is \"forceWritable\" , then the lightmaps " "will be regenerated only <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the lighting cache files can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">written.\n</a>" " @param completeCallbackFn The name of the function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> execute when the lighting is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">complete.\n</a>" " @param <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> One of \"forceAlways\" , \"forceWritable\" or \"loadOnly\".\n" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the scene lighting process was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">started.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

DefineEngineFunction(resetLightManager , void , () , "@brief Deactivates and then activates the currently active light manager." "This causes most shaders <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be regenerated and is often used when global " "rendering changes have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occured.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

DefineEngineFunction(setLightManager , bool , (const char *name) , "Finds and activates the named light <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manager.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the light manager is found and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

IMPLEMENT_GLOBAL_CALLBACK(onLightManagerActivate , void , (const char *name) , (name) , "A callback called by the engine when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> light manager is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param name The name of the light manager being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

IMPLEMENT_GLOBAL_CALLBACK(onLightManagerDeactivate , void , (const char *name) , (name) , "A callback called by the engine when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> light manager is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deactivated.\n</a>" "@param name The name of the light manager being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deactivated.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "lighting/lightManager.h"
 26
 27#include "console/console.h"
 28#include "console/consoleTypes.h"
 29#include "core/util/safeDelete.h"
 30#include "console/sim.h"
 31#include "console/simSet.h"
 32#include "scene/sceneManager.h"
 33#include "materials/materialManager.h"
 34#include "materials/sceneData.h"
 35#include "lighting/lightInfo.h"
 36#include "lighting/lightingInterfaces.h"
 37#include "T3D/gameBase/gameConnection.h"
 38#include "gfx/gfxStringEnumTranslate.h"
 39#include "console/engineAPI.h"
 40#include "renderInstance/renderDeferredMgr.h"
 41
 42
 43Signal<void(const char*,bool)> LightManager::smActivateSignal;
 44LightManager *LightManager::smActiveLM = NULL;
 45
 46
 47LightManager::LightManager( const char *name, const char *id )
 48   :  mName( name ),
 49      mId( id ),
 50      mIsActive( false ),
 51      mDefaultLight( NULL ),
 52      mSceneManager( NULL ),
 53      mCullPos( Point3F::Zero ),
 54      mAvailableSLInterfaces( NULL )
 55{ 
 56   _getLightManagers().insert( mName, this );
 57
 58   dMemset( &mSpecialLights, 0, sizeof( mSpecialLights ) );
 59}
 60
 61LightManager::~LightManager() 
 62{
 63   _getLightManagers().erase( mName );
 64   SAFE_DELETE( mAvailableSLInterfaces );
 65   SAFE_DELETE( mDefaultLight );
 66}
 67
 68LightManagerMap& LightManager::_getLightManagers()
 69{
 70   static LightManagerMap lightManagerMap;
 71   return lightManagerMap;
 72}
 73
 74LightManager* LightManager::findByName( const char *name )
 75{
 76   LightManagerMap &lightManagers = _getLightManagers();
 77
 78   LightManagerMap::Iterator iter = lightManagers.find( name );
 79   if ( iter != lightManagers.end() )
 80      return iter->value;
 81
 82   return NULL;
 83}
 84
 85void LightManager::getLightManagerNames( String *outString )
 86{
 87   LightManagerMap &lightManagers = _getLightManagers();
 88   LightManagerMap::Iterator iter = lightManagers.begin();
 89   for ( ; iter != lightManagers.end(); iter++ )
 90      *outString += iter->key + "\t";
 91
 92   // TODO!
 93   //outString->rtrim();
 94}
 95
 96LightInfo* LightManager::createLightInfo(LightInfo* light /* = NULL */)
 97{
 98   LightInfo *outLight = (light != NULL) ? light : new LightInfo;
 99
100   LightManagerMap &lightManagers = _getLightManagers();
101   LightManagerMap::Iterator iter = lightManagers.begin();
102   for ( ; iter != lightManagers.end(); iter++ )
103   {
104      LightManager *lm = iter->value;
105      lm->_addLightInfoEx( outLight );
106   }
107
108   return outLight;
109}
110
111void LightManager::initLightFields()
112{
113   LightManagerMap &lightManagers = _getLightManagers();
114
115   LightManagerMap::Iterator iter = lightManagers.begin();
116   for ( ; iter != lightManagers.end(); iter++ )
117   {
118      LightManager *lm = iter->value;
119      lm->_initLightFields();
120   }
121}
122
123IMPLEMENT_GLOBAL_CALLBACK( onLightManagerActivate, void, ( const char *name ), ( name ),
124   "A callback called by the engine when a light manager is activated.\n"
125   "@param name The name of the light manager being activated.\n"
126   "@ingroup Lighting\n" );
127
128void LightManager::activate( SceneManager *sceneManager )
129{
130   AssertFatal( sceneManager, "LightManager::activate() - Got null scene manager!" );
131   AssertFatal( mIsActive == false, "LightManager::activate() - Already activated!" );
132   AssertFatal( smActiveLM == NULL, "LightManager::activate() - A previous LM is still active!" );
133
134   mIsActive = true;
135   mSceneManager = sceneManager;
136   smActiveLM = this;
137
138   onLightManagerActivate_callback( getName() );
139}
140
141IMPLEMENT_GLOBAL_CALLBACK( onLightManagerDeactivate, void, ( const char *name ), ( name ),
142   "A callback called by the engine when a light manager is deactivated.\n"
143   "@param name The name of the light manager being deactivated.\n"
144   "@ingroup Lighting\n" );
145
146void LightManager::deactivate()
147{
148   AssertFatal( mIsActive == true, "LightManager::deactivate() - Already deactivated!" );
149   AssertFatal( smActiveLM == this, "LightManager::activate() - This isn't the active light manager!" );
150
151   if( Sim::getRootGroup() ) // To protect against shutdown.
152      onLightManagerDeactivate_callback( getName() );
153
154   mIsActive = false;
155   mSceneManager = NULL;
156   smActiveLM = NULL;
157
158   // Just in case... make sure we're all clear.
159   unregisterAllLights();
160}
161
162LightInfo* LightManager::getDefaultLight()
163{
164   // The sun is always our default light when
165   // when its registered.
166   if ( mSpecialLights[ LightManager::slSunLightType ] )
167      return mSpecialLights[ LightManager::slSunLightType ];
168
169   // Else return a dummy special light.
170   if ( !mDefaultLight )
171      mDefaultLight = createLightInfo();
172   return mDefaultLight;
173}
174
175LightInfo* LightManager::getSpecialLight( LightManager::SpecialLightTypesEnum type, bool useDefault )
176{
177   if ( mSpecialLights[type] )
178      return mSpecialLights[type];
179
180   if ( useDefault )
181      return getDefaultLight();
182
183   return NULL;
184}
185
186void LightManager::setSpecialLight( LightManager::SpecialLightTypesEnum type, LightInfo *light )
187{
188   if ( light && type == slSunLightType )
189   {
190      // The sun must be specially positioned and ranged
191      // so that it can be processed like a point light 
192      // in the stock light shader used by Basic Lighting.
193      
194      light->setPosition( mCullPos - ( light->getDirection() * 10000.0f ) );
195      light->setRange( 2000000.0f );
196   }
197
198   mSpecialLights[type] = light;
199   registerGlobalLight( light, NULL );
200}
201
202void LightManager::registerGlobalLights( const Frustum *frustum, bool staticLighting, bool enableZoneLightCulling)
203{
204   PROFILE_SCOPE( LightManager_RegisterGlobalLights );
205
206   // TODO: We need to work this out...
207   //
208   // 1. Why do we register and unregister lights on every 
209   //    render when they don't often change... shouldn't we
210   //    just register once and keep them?
211   // 
212   // 2. If we do culling of lights should this happen as part
213   //    of registration or somewhere else?
214   //
215
216   // Grab the lights to process.
217   Vector<SceneObject*> activeLights;
218   const U32 lightMask = LightObjectType;
219   
220   if ( staticLighting || !frustum )
221   {
222      // We're processing static lighting or want all the lights
223      // in the container registerd...  so no culling.
224      getSceneManager()->getContainer()->findObjectList( lightMask, &activeLights );
225   }
226   else
227   {
228      // Cull the lights using the frustum.
229      getSceneManager()->getContainer()->findObjectList(*frustum, lightMask, &activeLights);
230      /*
231      for (U32 i = 0; i < activeLights.size(); ++i)
232      {
233         for (U32 i = 0; i < activeLights.size(); ++i)
234         {
235            if (!getSceneManager()->mRenderedObjectsList.contains(activeLights[i]))
236            {
237               activeLights.erase(i);
238               --i;
239            }
240         }
241      }
242      */
243      // Store the culling position for sun placement
244      // later... see setSpecialLight.
245      mCullPos = frustum->getPosition();
246
247      // HACK: Make sure the control object always gets 
248      // processed as lights mounted to it don't change
249      // the shape bounds and can often get culled.
250
251      GameConnection *conn = GameConnection::getConnectionToServer();
252      if (conn->getControlObject())
253      {
254         GameBase *conObject = conn->getControlObject();
255         activeLights.push_back_unique(conObject);
256      }
257   }
258
259   // Let the lights register themselves.
260   for ( U32 i = 0; i < activeLights.size(); i++ )
261   {
262      ISceneLight *lightInterface = dynamic_cast<ISceneLight*>( activeLights[i] );
263      if ( lightInterface )
264         lightInterface->submitLights( this, staticLighting );
265   }
266}
267
268void LightManager::registerGlobalLight( LightInfo *light, SimObject *obj )
269{
270   AssertFatal( !mRegisteredLights.contains( light ), 
271      "LightManager::registerGlobalLight - This light is already registered!" );
272
273   mRegisteredLights.push_back( light );
274}
275
276void LightManager::unregisterGlobalLight( LightInfo *light )
277{
278   mRegisteredLights.unregisterLight( light );
279
280   // If this is the sun... clear the special light too.
281   if ( light == mSpecialLights[slSunLightType] )
282      dMemset( mSpecialLights, 0, sizeof( mSpecialLights ) );
283}
284
285void LightManager::registerLocalLight( LightInfo *light )
286{
287   // TODO: What should we do here?
288}
289
290void LightManager::unregisterLocalLight( LightInfo *light )
291{
292   // TODO: What should we do here?
293}
294
295void LightManager::unregisterAllLights()
296{
297   dMemset( mSpecialLights, 0, sizeof( mSpecialLights ) );
298   mRegisteredLights.clear();
299}
300
301void LightManager::getAllUnsortedLights( Vector<LightInfo*> *list ) const
302{
303   list->merge( mRegisteredLights );
304}
305
306void LightManager::_update4LightConsts(   const SceneData &sgData,
307                                          GFXShaderConstHandle *lightPositionSC,
308                                          GFXShaderConstHandle *lightDiffuseSC,
309                                          GFXShaderConstHandle *lightAmbientSC,
310                                          GFXShaderConstHandle *lightConfigDataSC,
311                                          GFXShaderConstHandle *lightSpotDirSC,
312                                          GFXShaderConstHandle *lightSpotParamsSC,
313                                          GFXShaderConstHandle* hasVectorLightSC,
314                                          GFXShaderConstHandle* vectorLightDirectionSC,
315                                          GFXShaderConstHandle* vectorLightColorSC,
316                                          GFXShaderConstHandle* vectorLightBrightnessSC,
317                                          GFXShaderConstBuffer *shaderConsts )
318{
319   PROFILE_SCOPE( LightManager_Update4LightConsts );
320
321   // Skip over gathering lights if we don't have to!
322   if (  lightPositionSC->isValid() || 
323         lightDiffuseSC->isValid() ||
324         lightConfigDataSC->isValid() ||
325         lightSpotDirSC->isValid() ||
326         lightSpotParamsSC->isValid() )
327   {
328      PROFILE_SCOPE( LightManager_Update4LightConsts_setLights );
329
330      //new setup
331      const U32 MAX_FORWARD_LIGHTS = 4;
332
333      static AlignedArray<Point4F> lightPositions(MAX_FORWARD_LIGHTS, sizeof(Point4F));
334      static AlignedArray<Point4F> lightSpotDirs(MAX_FORWARD_LIGHTS, sizeof(Point4F));
335      static AlignedArray<Point4F> lightColors(MAX_FORWARD_LIGHTS, sizeof(Point4F));
336      static AlignedArray<Point4F> lightConfigData(MAX_FORWARD_LIGHTS, sizeof(Point4F)); //type, brightness, range, invSqrRange : rgba
337      static AlignedArray<Point2F> lightSpotParams(MAX_FORWARD_LIGHTS, sizeof(Point2F));
338
339      dMemset(lightPositions.getBuffer(), 0, lightPositions.getBufferSize());
340      dMemset(lightSpotDirs.getBuffer(), 0, lightSpotDirs.getBufferSize());
341      dMemset(lightColors.getBuffer(), 0, lightColors.getBufferSize());
342      dMemset(lightConfigData.getBuffer(), 0, lightConfigData.getBufferSize());
343      dMemset(lightSpotParams.getBuffer(), 0, lightSpotParams.getBufferSize());
344
345      //sun-only
346      F32 vectorLightBrightness;
347      static Point4F vectorLightDirection;
348      static Point4F vectorLightColor;
349      static Point4F vectorLightAmbientColor;
350      int hasVectorLight = 0;
351
352      vectorLightBrightness = 0;
353      vectorLightDirection = Point4F::Zero;
354      vectorLightColor = Point4F::Zero;
355      vectorLightAmbientColor = Point4F::Zero;
356
357      // Gather the data for the first 4 lights.
358      const LightInfo* light;
359      for (U32 i = 0; i < MAX_FORWARD_LIGHTS; i++)
360      {
361         light = sgData.lights[i];
362         if (!light)
363            break;
364
365         if (light->getType() == LightInfo::Vector)
366         {
367            if (hasVectorLight != 0)
368               continue;
369
370            vectorLightBrightness = light->getBrightness();
371            vectorLightDirection = light->getDirection();
372            vectorLightColor = Point4F(light->getColor());
373            vectorLightAmbientColor = Point4F(light->getAmbient());
374            hasVectorLight = 1;
375            continue;
376         }
377
378         // The light positions and spot directions are 
379         // in SoA order to make optimal use of the GPU.
380         const Point3F& lightPos = light->getPosition();
381         lightPositions[i].x = lightPos.x;
382         lightPositions[i].y = lightPos.y;
383         lightPositions[i].z = lightPos.z;
384         lightPositions[i].w = 0;
385
386         const VectorF& lightDir = light->getDirection();
387         lightSpotDirs[i].x = lightDir.x;
388         lightSpotDirs[i].y = lightDir.y;
389         lightSpotDirs[i].z = lightDir.z;
390         lightSpotDirs[i].w = 0;
391
392         lightColors[i] = Point4F(light->getColor());
393
394         if (light->getType() == LightInfo::Point)
395         {
396            lightConfigData[i].x = 0;
397         }
398         else if (light->getType() == LightInfo::Spot)
399         {
400            lightConfigData[i].x = 1;
401
402            const F32 outerCone = light->getOuterConeAngle();
403            const F32 innerCone = getMin(light->getInnerConeAngle(), outerCone);
404            const F32 outerCos = mCos(mDegToRad(outerCone / 2.0f));
405            const F32 innerCos = mCos(mDegToRad(innerCone / 2.0f));
406            Point2F spotParams(outerCos, innerCos - outerCos);
407
408            lightSpotParams[i].x = spotParams.x;
409            lightSpotParams[i].y = spotParams.y;
410         }
411
412         lightConfigData[i].y = light->getBrightness();
413
414         F32 range = light->getRange().x;
415         lightConfigData[i].z = range;
416         lightConfigData[i].w = 1.0f / (range * range);
417      }
418
419      shaderConsts->setSafe(lightPositionSC, lightPositions);
420      shaderConsts->setSafe(lightDiffuseSC, lightColors);
421      shaderConsts->setSafe(lightSpotDirSC, lightSpotDirs);
422      shaderConsts->setSafe(lightConfigDataSC, lightConfigData);
423      shaderConsts->setSafe(lightSpotParamsSC, lightSpotParams);
424
425      shaderConsts->setSafe(hasVectorLightSC, (int)hasVectorLight);
426      shaderConsts->setSafe(vectorLightDirectionSC, vectorLightDirection);
427      shaderConsts->setSafe(vectorLightColorSC, vectorLightColor);
428      shaderConsts->setSafe(vectorLightBrightnessSC, vectorLightBrightness);
429
430      //================================================================
431      //old setup
432      /*static AlignedArray<Point4F> lightPositions( 3, sizeof( Point4F ) );
433      static AlignedArray<Point4F> lightSpotDirs( 3, sizeof( Point4F ) );
434      static AlignedArray<Point4F> lightColors( 4, sizeof( Point4F ) );
435      static Point4F lightInvRadiusSq;
436      static Point4F lightSpotAngle;
437      static Point4F lightSpotFalloff;
438      F32 range;
439      
440      // Need to clear the buffers so that we don't leak
441      // lights from previous passes or have NaNs.
442      dMemset( lightPositions.getBuffer(), 0, lightPositions.getBufferSize() );
443      dMemset( lightSpotDirs.getBuffer(), 0, lightSpotDirs.getBufferSize() );
444      dMemset( lightColors.getBuffer(), 0, lightColors.getBufferSize() );
445      lightInvRadiusSq = Point4F::Zero;
446      lightSpotAngle.set( -1.0f, -1.0f, -1.0f, -1.0f );
447      lightSpotFalloff.set( F32_MAX, F32_MAX, F32_MAX, F32_MAX );
448
449      // Gather the data for the first 4 lights.
450      const LightInfo *light;
451      for ( U32 i=0; i < MAX_FORWARD_LIGHTS; i++ )
452      {
453         light = sgData.lights[i];
454         if ( !light )            
455            break;
456
457            // The light positions and spot directions are 
458            // in SoA order to make optimal use of the GPU.
459            const Point3F &lightPos = light->getPosition();
460            lightPositions[0][i] = lightPos.x;
461            lightPositions[1][i] = lightPos.y;
462            lightPositions[2][i] = lightPos.z;
463
464            const VectorF &lightDir = light->getDirection();
465            lightSpotDirs[0][i] = lightDir.x;
466            lightSpotDirs[1][i] = lightDir.y;
467            lightSpotDirs[2][i] = lightDir.z;
468            
469            if ( light->getType() == LightInfo::Spot )
470         {
471               lightSpotAngle[i] = mCos( mDegToRad( light->getOuterConeAngle() / 2.0f ) ); 
472            lightSpotFalloff[i] = 1.0f / getMax( F32_MIN, mCos( mDegToRad( light->getInnerConeAngle() / 2.0f ) ) - lightSpotAngle[i] );
473         }
474
475         // Prescale the light color by the brightness to 
476         // avoid doing this in the shader.
477         lightColors[i] = Point4F(light->getColor()) * light->getBrightness();
478
479         // We need 1 over range^2 here.
480         range = light->getRange().x;
481         lightInvRadiusSq[i] = 1.0f / ( range * range );
482      }
483
484      shaderConsts->setSafe( lightPositionSC, lightPositions );   
485      shaderConsts->setSafe( lightDiffuseSC, lightColors );
486      shaderConsts->setSafe( lightInvRadiusSqSC, lightInvRadiusSq );
487
488      shaderConsts->setSafe( lightSpotDirSC, lightSpotDirs );
489      shaderConsts->setSafe( lightSpotAngleSC, lightSpotAngle );
490      shaderConsts->setSafe( lightSpotFalloffSC, lightSpotFalloff );*/
491   }
492
493   // Setup the ambient lighting from the first 
494   // light which is the directional light if 
495   // one exists at all in the scene.
496   if ( lightAmbientSC->isValid() )
497      shaderConsts->set( lightAmbientSC, sgData.ambientLightColor );
498}
499
500AvailableSLInterfaces* LightManager::getSceneLightingInterface()
501{
502   if ( !mAvailableSLInterfaces )
503      mAvailableSLInterfaces = new AvailableSLInterfaces();
504
505   return mAvailableSLInterfaces;
506}
507
508bool LightManager::lightScene( const char* callback, const char* param )
509{
510   BitSet32 flags = 0;
511
512   if ( param )
513   {
514      if ( !dStricmp( param, "forceAlways" ) )
515         flags.set( SceneLighting::ForceAlways );
516      else if ( !dStricmp(param, "forceWritable" ) )
517         flags.set( SceneLighting::ForceWritable );
518      else if ( !dStricmp(param, "loadOnly" ) )
519         flags.set( SceneLighting::LoadOnly );
520   }
521
522   // The SceneLighting object will delete itself 
523   // once the lighting process is complete.   
524   SceneLighting* sl = new SceneLighting( getSceneLightingInterface() );
525   return sl->lightScene( callback, flags );
526}
527
528RenderDeferredMgr* LightManager::_findDeferredRenderBin()
529{
530   RenderPassManager* rpm = getSceneManager()->getDefaultRenderPass();
531   for( U32 i = 0; i < rpm->getManagerCount(); i++ )
532   {
533      RenderBinManager *bin = rpm->getManager( i );
534      if( bin->getRenderInstType() == RenderDeferredMgr::RIT_Deferred )
535      {
536         return ( RenderDeferredMgr* ) bin;
537      }
538   }
539
540   return NULL;
541}
542
543DefineEngineFunction( setLightManager, bool, ( const char *name ),,
544   "Finds and activates the named light manager.\n"
545   "@return Returns true if the light manager is found and activated.\n"
546   "@ingroup Lighting\n" )
547{
548   return gClientSceneGraph->setLightManager( name );
549}
550
551DefineEngineFunction( lightScene, bool, ( const char *completeCallbackFn, const char *mode ), ( nullAsType<const char*>(), nullAsType<const char*>() ),
552   "Will generate static lighting for the scene if supported by the active light manager.\n\n"
553   "If mode is \"forceAlways\", the lightmaps will be regenerated regardless of whether "
554   "lighting cache files can be written to. If mode is \"forceWritable\", then the lightmaps "
555   "will be regenerated only if the lighting cache files can be written.\n"
556   "@param completeCallbackFn The name of the function to execute when the lighting is complete.\n"
557   "@param mode One of \"forceAlways\",  \"forceWritable\" or \"loadOnly\".\n"
558   "@return Returns true if the scene lighting process was started.\n"
559   "@ingroup Lighting\n" )
560{
561   if ( !LIGHTMGR )
562      return false;
563
564   return LIGHTMGR->lightScene( completeCallbackFn, mode );
565}
566
567DefineEngineFunction( getLightManagerNames, String, (),,
568   "Returns a tab seperated list of light manager names.\n"
569   "@ingroup Lighting\n" )
570{
571   String names;
572   LightManager::getLightManagerNames( &names );
573   return names;
574}
575
576DefineEngineFunction( getActiveLightManager, const char*, (),,
577   "Returns the active light manager name.\n"
578   "@ingroup Lighting\n" )
579{
580   if ( !LIGHTMGR )
581      return NULL;
582
583   return LIGHTMGR->getName();
584}
585
586DefineEngineFunction( resetLightManager, void, (),,
587   "@brief Deactivates and then activates the currently active light manager."
588   "This causes most shaders to be regenerated and is often used when global "
589   "rendering changes have occured.\n"
590   "@ingroup Lighting\n" )
591{
592   LightManager *lm = LIGHTMGR;
593   if ( !lm )
594      return;
595
596   SceneManager *sm = lm->getSceneManager();
597   lm->deactivate();
598   lm->activate( sm );
599}
600