Torque3D Documentation / _generateds / basicLightManager.cpp

basicLightManager.cpp

Engine/source/lighting/basic/basicLightManager.cpp

More...

Detailed Description

Public Variables

 MODULE_END 
 MODULE_INIT 
 MODULE_SHUTDOWN 

Public Functions

comparePluginScores(const void * a, const void * b)

  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/basic/basicLightManager.h"
 26
 27#include "platform/platformTimer.h"
 28#include "console/simSet.h"
 29#include "console/consoleTypes.h"
 30#include "core/module.h"
 31#include "core/util/safeDelete.h"
 32#include "materials/processedMaterial.h"
 33#include "shaderGen/shaderFeature.h"
 34#include "lighting/basic/basicSceneObjectLightingPlugin.h"
 35#include "shaderGen/shaderGenVars.h"
 36#include "gfx/gfxShader.h"
 37#include "materials/sceneData.h"
 38#include "materials/materialParameters.h"
 39#include "materials/materialManager.h"
 40#include "materials/materialFeatureTypes.h"
 41#include "math/util/frustum.h"
 42#include "scene/sceneObject.h"
 43#include "renderInstance/renderDeferredMgr.h"
 44#include "shaderGen/featureMgr.h"
 45#include "shaderGen/HLSL/shaderFeatureHLSL.h"
 46#include "shaderGen/HLSL/bumpHLSL.h"
 47#include "lighting/basic/blTerrainSystem.h"
 48#include "lighting/common/projectedShadow.h"
 49
 50#if defined( TORQUE_OPENGL )
 51#include "shaderGen/GLSL/shaderFeatureGLSL.h"
 52#include "shaderGen/GLSL/bumpGLSL.h"
 53#endif
 54
 55
 56MODULE_BEGIN( BasicLightManager )
 57
 58   MODULE_SHUTDOWN_AFTER( Scene )
 59
 60   MODULE_INIT
 61   {
 62      ManagedSingleton< BasicLightManager >::createSingleton();
 63   }
 64   
 65   MODULE_SHUTDOWN
 66   {
 67      ManagedSingleton< BasicLightManager >::deleteSingleton();
 68   }
 69
 70MODULE_END;
 71
 72
 73U32 BasicLightManager::smActiveShadowPlugins = 0;
 74U32 BasicLightManager::smShadowsUpdated = 0;
 75U32 BasicLightManager::smElapsedUpdateMs = 0;
 76
 77F32 BasicLightManager::smProjectedShadowFilterDistance = 40.0f;
 78
 79static S32 QSORT_CALLBACK comparePluginScores( const void *a, const void *b )
 80{
 81   const BasicSceneObjectLightingPlugin *A = *((BasicSceneObjectLightingPlugin**)a);
 82   const BasicSceneObjectLightingPlugin *B = *((BasicSceneObjectLightingPlugin**)b);     
 83   
 84   F32 dif = B->getScore() - A->getScore();
 85   return (S32)mFloor( dif );
 86}
 87
 88BasicLightManager::BasicLightManager()
 89   : LightManager( "Basic Lighting", "BLM" ),
 90     mLastShader(NULL),
 91     mLastConstants(NULL)
 92{
 93   mTimer = PlatformTimer::create();
 94   
 95   mTerrainSystem = new blTerrainSystem;
 96   
 97   getSceneLightingInterface()->registerSystem( mTerrainSystem );
 98
 99   Con::addVariable( "$BasicLightManagerStats::activePlugins", 
100      TypeS32, &smActiveShadowPlugins,
101      "The number of active Basic Lighting SceneObjectLightingPlugin objects this frame.\n"
102      "@ingroup BasicLighting\n" );
103
104   Con::addVariable( "$BasicLightManagerStats::shadowsUpdated", 
105      TypeS32, &smShadowsUpdated,
106      "The number of Basic Lighting shadows updated this frame.\n"
107      "@ingroup BasicLighting\n" );
108
109   Con::addVariable( "$BasicLightManagerStats::elapsedUpdateMs", 
110      TypeS32, &smElapsedUpdateMs,
111      "The number of milliseconds spent this frame updating Basic Lighting shadows.\n"
112      "@ingroup BasicLighting\n" );
113
114   Con::addVariable( "$BasicLightManager::shadowFilterDistance", 
115      TypeF32, &smProjectedShadowFilterDistance,
116      "The maximum distance in meters that projected shadows will get soft filtering.\n"
117      "@ingroup BasicLighting\n" );
118
119   Con::addVariable( "$pref::ProjectedShadow::fadeStartPixelSize", 
120      TypeF32, &ProjectedShadow::smFadeStartPixelSize,
121      "A size in pixels at which BL shadows begin to fade out. "
122      "This should be a larger value than fadeEndPixelSize.\n"
123      "@see DecalData\n"
124      "@ingroup BasicLighting\n" );
125
126   Con::addVariable( "$pref::ProjectedShadow::fadeEndPixelSize", 
127      TypeF32, &ProjectedShadow::smFadeEndPixelSize,
128      "A size in pixels at which BL shadows are fully faded out. "
129      "This should be a smaller value than fadeStartPixelSize.\n"
130      "@see DecalData\n"
131      "@ingroup BasicLighting\n" );
132}
133
134BasicLightManager::~BasicLightManager()
135{
136   mLastShader = NULL;
137   mLastConstants = NULL;
138
139   for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
140   {
141      if (i->value)
142         SAFE_DELETE(i->value);
143   }
144   mConstantLookup.clear();
145
146   if (mTimer)
147      SAFE_DELETE( mTimer );
148
149   SAFE_DELETE( mTerrainSystem );
150}
151
152bool BasicLightManager::isCompatible() const
153{
154   // As long as we have some shaders this works.
155   return GFX->getPixelShaderVersion() > 1.0;
156}
157
158void BasicLightManager::activate( SceneManager *sceneManager )
159{
160   Parent::activate( sceneManager );
161
162   if( GFX->getAdapterType() == OpenGL )
163   {
164      #if defined( TORQUE_OPENGL ) 
165         FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatGLSL );
166         FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatGLSL );
167         FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL );
168         FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL );
169         FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL);
170      #endif
171   }
172   else
173   {
174      #if defined( TORQUE_OS_WIN )
175         FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatHLSL );
176         FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatHLSL );
177         FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL );
178         FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL );
179         FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
180      #endif
181   }
182
183   FEATUREMGR->unregisterFeature( MFT_MinnaertShading );
184   FEATUREMGR->unregisterFeature( MFT_SubSurface );
185
186   // First look for the deferred bin...
187   RenderDeferredMgr *deferredBin = _findDeferredRenderBin();
188
189   /*
190   // If you would like to use forward shading, and have a linear depth pre-pass
191   // than un-comment this code block.
192   if ( !deferredBin )
193   {
194      Vector<GFXFormat> formats;
195      formats.push_back( GFXFormatR32F );
196      formats.push_back( GFXFormatR16F );
197      formats.push_back( GFXFormatR8G8B8A8 );
198      GFXFormat linearDepthFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile,
199         formats,
200         true,
201         false );
202
203      // Uncomment this for a no-color-write z-fill pass. 
204      //linearDepthFormat = GFXFormat_COUNT;
205
206      deferredBin = new RenderDeferredMgr( linearDepthFormat != GFXFormat_COUNT, linearDepthFormat );
207      deferredBin->registerObject();
208      rpm->addManager( deferredBin );
209   }
210   */
211   mDeferredRenderBin = deferredBin;
212
213   // If there is a deferred bin
214   MATMGR->setDeferredEnabled( mDeferredRenderBin.isValid() );
215   sceneManager->setPostEffectFog( mDeferredRenderBin.isValid() && mDeferredRenderBin->getTargetChainLength() > 0  );
216
217   // Tell the material manager that we don't use deferred.
218   MATMGR->setDeferredEnabled( false );
219
220   GFXShader::addGlobalMacro( "TORQUE_BASIC_LIGHTING" );
221
222   // Hook into the SceneManager prerender signal.
223   sceneManager->getPreRenderSignal().notify( this, &BasicLightManager::_onPreRender );
224
225   // Last thing... let everyone know we're active.
226   smActivateSignal.trigger( getId(), true );
227}
228
229void BasicLightManager::deactivate()
230{
231   Parent::deactivate();
232
233   mLastShader = NULL;
234   mLastConstants = NULL;
235
236   for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
237   {
238      if (i->value)
239         SAFE_DELETE(i->value);
240   }
241   mConstantLookup.clear();
242
243   if ( mDeferredRenderBin )
244      mDeferredRenderBin->deleteObject();
245   mDeferredRenderBin = NULL;
246
247   GFXShader::removeGlobalMacro( "TORQUE_BASIC_LIGHTING" );
248
249   // Remove us from the prerender signal.
250   getSceneManager()->getPreRenderSignal().remove( this, &BasicLightManager::_onPreRender );
251
252   // Now let everyone know we've deactivated.
253   smActivateSignal.trigger( getId(), false );
254}
255
256void BasicLightManager::_onPreRender( SceneManager *sceneManger, const SceneRenderState *state )
257{
258   // Update all our shadow plugins here!
259   Vector<BasicSceneObjectLightingPlugin*> *pluginInsts = BasicSceneObjectLightingPlugin::getPluginInstances();
260
261   Vector<BasicSceneObjectLightingPlugin*>::const_iterator pluginIter = (*pluginInsts).begin();
262   for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ )
263   {
264      BasicSceneObjectLightingPlugin *plugin = *pluginIter;
265      plugin->updateShadow( (SceneRenderState*)state );
266   }
267
268   U32 pluginCount = (*pluginInsts).size();
269
270   // Sort them by the score.
271   dQsort( (*pluginInsts).address(), pluginCount, sizeof(BasicSceneObjectLightingPlugin*), comparePluginScores );
272
273   mTimer->getElapsedMs();
274   mTimer->reset();
275   U32 numUpdated = 0;
276   U32 targetMs = 5;
277
278   S32 updateMs = 0;
279
280   pluginIter = (*pluginInsts).begin();
281   for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ )
282   {
283      BasicSceneObjectLightingPlugin *plugin = *pluginIter;
284
285      // If we run out of update time then stop.
286      updateMs = mTimer->getElapsedMs();
287      if ( updateMs >= targetMs )
288         break;
289
290      // NOTE! Fix this all up to past const SceneRenderState!
291      plugin->renderShadow( (SceneRenderState*)state );
292      numUpdated++;
293   }
294
295   smShadowsUpdated = numUpdated;
296   smActiveShadowPlugins = pluginCount;
297   smElapsedUpdateMs = updateMs;
298}
299
300BasicLightManager::LightingShaderConstants::LightingShaderConstants()
301   :  mInit( false ),
302      mShader( NULL ),
303      mLightPosition( NULL ),
304      mLightDiffuse( NULL ),
305      mLightAmbient( NULL ),
306      mLightConfigDataSC( NULL ),
307      mLightSpotDir( NULL ),
308      mLightSpotParamsSC( NULL ),
309      mHasVectorLightSC(NULL),
310      mVectorLightDirectionSC(NULL),
311      mVectorLightColorSC(NULL),
312      mVectorLightBrightnessSC(NULL)
313{
314}
315
316BasicLightManager::LightingShaderConstants::~LightingShaderConstants()
317{
318   if (mShader.isValid())
319   {
320      mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
321      mShader = NULL;
322   }
323}
324
325void BasicLightManager::LightingShaderConstants::init(GFXShader* shader)
326{
327   if (mShader.getPointer() != shader)
328   {
329      if (mShader.isValid())
330         mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
331
332      mShader = shader;
333      mShader->getReloadSignal().notify( this, &LightingShaderConstants::_onShaderReload );
334   }
335
336   mLightPosition = shader->getShaderConstHandle( ShaderGenVars::lightPosition );
337   mLightDiffuse = shader->getShaderConstHandle( ShaderGenVars::lightDiffuse);
338   mLightConfigDataSC = shader->getShaderConstHandle( ShaderGenVars::lightConfigData );
339   mLightAmbient = shader->getShaderConstHandle( ShaderGenVars::lightAmbient );   
340   mLightSpotDir = shader->getShaderConstHandle( ShaderGenVars::lightSpotDir );
341   mLightSpotParamsSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotParams );
342
343   mHasVectorLightSC = shader->getShaderConstHandle(ShaderGenVars::hasVectorLight);
344   mVectorLightDirectionSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightDirection);
345   mVectorLightColorSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightColor);
346   mVectorLightBrightnessSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightBrightness);
347
348   mInit = true;
349}
350
351void BasicLightManager::LightingShaderConstants::_onShaderReload()
352{
353   if (mShader.isValid())
354      init( mShader );
355}
356
357void BasicLightManager::setLightInfo(  ProcessedMaterial* pmat, 
358                                       const Material* mat, 
359                                       const SceneData& sgData, 
360                                       const SceneRenderState *state,
361                                       U32 pass, 
362                                       GFXShaderConstBuffer* shaderConsts ) 
363{
364   PROFILE_SCOPE( BasicLightManager_SetLightInfo );
365
366   GFXShader *shader = shaderConsts->getShader();
367
368   // Check to see if this is the same shader.  Since we
369   // sort by material we should get hit repeatedly by the
370   // same one.  This optimization should save us many 
371   // hash table lookups.
372   if ( mLastShader.getPointer() != shader )
373   {
374      LightConstantMap::Iterator iter = mConstantLookup.find(shader);   
375      if ( iter != mConstantLookup.end() )
376      {
377         mLastConstants = iter->value;
378      } 
379      else 
380      {     
381         LightingShaderConstants* lsc = new LightingShaderConstants();
382         mConstantLookup[shader] = lsc;
383
384         mLastConstants = lsc;      
385      }
386
387      // Set our new shader
388      mLastShader = shader;
389   }
390
391   // Make sure that our current lighting constants are initialized
392   if (!mLastConstants->mInit)
393      mLastConstants->init(shader);
394
395   // NOTE: If you encounter a crash from this point forward
396   // while setting a shader constant its probably because the
397   // mConstantLookup has bad shaders/constants in it.
398   //
399   // This is a known crash bug that can occur if materials/shaders
400   // are reloaded and the light manager is not reset.
401   //
402   // We should look to fix this by clearing the table.
403
404   _update4LightConsts( sgData,
405                        mLastConstants->mLightPosition,
406                        mLastConstants->mLightDiffuse,
407                        mLastConstants->mLightAmbient,
408                        mLastConstants->mLightConfigDataSC,
409                        mLastConstants->mLightSpotDir,
410                        mLastConstants->mLightSpotParamsSC,
411                        mLastConstants->mHasVectorLightSC,
412                        mLastConstants->mVectorLightDirectionSC,
413                        mLastConstants->mVectorLightColorSC,
414                        mLastConstants->mVectorLightBrightnessSC,
415                        shaderConsts );
416}
417