lightManager.cpp
Engine/source/lighting/lightManager.cpp
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