lightManager.cpp 17 KB

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