Torque3D Documentation / _generateds / advancedLightManager.cpp

advancedLightManager.cpp

Engine/source/lighting/advanced/advancedLightManager.cpp

More...

Public Defines

define
ADD_LIGHT_FIELD(field, type, var, desc)    ( field, type, 0,                       \
      &Dummy::_set##var##Field, &Dummy::_get##var##Field, desc )
define
DEFINE_LIGHT_FIELD(var, type, enum_)    static inline  char* _get##var##Field(  *obj,  char *data )  \
   {                                                                          \
       *p = _getShadowMapParams( obj );                        \
       ( p )                                                                \
         return ( type, &p->var, 0, enum_ );                      \
      else                                                                    \
         return "";                                                           \
   }                                                                          \
                                                                              \
   static inline bool _set##var##Field(  *object,  char *index,  char *data )  \
   {                                                                                         \
       *p = _getShadowMapParams( object );                     \
       ( p )                                                                \
      {                                                                       \
         ( type, &p->var, 0, 1, &data, enum_ );                   \
         p->_validate();                                                      \
      }                                                                       \
      return false;                                                           \
   }
define
DEFINE_LIGHTMAP_FIELD(var, type, enum_)    static inline  char* _get##var##Field(  *obj,  char *data )  \
   {                                                                          \
       *p = _getLightMapParams( obj );                          \
       ( p )                                                                \
         return ( type, &p->var, 0, enum_ );                      \
      else                                                                    \
         return "";                                                           \
   }                                                                          \
   \
   static inline bool _set##var##Field(  *object,  char *index,  char *data )  \
   {                                                                                         \
       *p = _getLightMapParams( object );                       \
       ( p )                                                                \
      {                                                                       \
         ( type, &p->var, 0, 1, &data, enum_ );                   \
      }                                                                       \
      return false;                                                           \
   }

Public Variables

Public Functions

DefineEngineFunction(setShadowVizLight , const char * , (const char *name) , ("") , "" )
ImplementEnumType(ShadowType , "\n\n" "@ingroup AdvancedLighting" )

Detailed Description

Public Defines

ADD_LIGHT_FIELD(field, type, var, desc)    ( field, type, 0,                       \
      &Dummy::_set##var##Field, &Dummy::_get##var##Field, desc )
DEFINE_LIGHT_FIELD(var, type, enum_)    static inline  char* _get##var##Field(  *obj,  char *data )  \
   {                                                                          \
       *p = _getShadowMapParams( obj );                        \
       ( p )                                                                \
         return ( type, &p->var, 0, enum_ );                      \
      else                                                                    \
         return "";                                                           \
   }                                                                          \
                                                                              \
   static inline bool _set##var##Field(  *object,  char *index,  char *data )  \
   {                                                                                         \
       *p = _getShadowMapParams( object );                     \
       ( p )                                                                \
      {                                                                       \
         ( type, &p->var, 0, 1, &data, enum_ );                   \
         p->_validate();                                                      \
      }                                                                       \
      return false;                                                           \
   }
DEFINE_LIGHTMAP_FIELD(var, type, enum_)    static inline  char* _get##var##Field(  *obj,  char *data )  \
   {                                                                          \
       *p = _getLightMapParams( obj );                          \
       ( p )                                                                \
         return ( type, &p->var, 0, enum_ );                      \
      else                                                                    \
         return "";                                                           \
   }                                                                          \
   \
   static inline bool _set##var##Field(  *object,  char *index,  char *data )  \
   {                                                                                         \
       *p = _getLightMapParams( object );                       \
       ( p )                                                                \
      {                                                                       \
         ( type, &p->var, 0, 1, &data, enum_ );                   \
      }                                                                       \
      return false;                                                           \
   }

Public Variables

 EndImplementEnumType 

Public Functions

DefineEngineFunction(setShadowVizLight , const char * , (const char *name) , ("") , "" )

ImplementEnumType(ShadowType , "\n\n" "@ingroup AdvancedLighting" )

  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/advanced/advancedLightManager.h"
 26
 27#include "lighting/advanced/advancedLightBinManager.h"
 28#include "lighting/advanced/advancedLightingFeatures.h"
 29#include "lighting/shadowMap/shadowMapManager.h"
 30#include "lighting/shadowMap/lightShadowMap.h"
 31#include "lighting/common/sceneLighting.h"
 32#include "lighting/common/lightMapParams.h"
 33#include "core/util/safeDelete.h"
 34#include "renderInstance/renderDeferredMgr.h"
 35#include "materials/materialManager.h"
 36#include "math/util/sphereMesh.h"
 37#include "console/consoleTypes.h"
 38#include "console/engineAPI.h"
 39#include "scene/sceneRenderState.h"
 40#include "gfx/gfxCardProfile.h"
 41#include "gfx/gfxTextureProfile.h"
 42
 43#ifndef TORQUE_BASIC_LIGHTING
 44F32 AdvancedLightManager::smProjectedShadowFilterDistance = 40.0f;
 45#endif
 46
 47ImplementEnumType( ShadowType,
 48   "\n\n"
 49   "@ingroup AdvancedLighting" )
 50   { ShadowType_Spot,                     "Spot" },
 51   { ShadowType_PSSM,                     "PSSM" },
 52   { ShadowType_DualParaboloidSinglePass, "DualParaboloidSinglePass" },
 53   { ShadowType_DualParaboloid,           "DualParaboloid" },
 54   { ShadowType_CubeMap,                  "CubeMap" },
 55EndImplementEnumType;
 56
 57
 58AdvancedLightManager AdvancedLightManager::smSingleton;
 59
 60
 61AdvancedLightManager::AdvancedLightManager()
 62   :  LightManager( "Advanced Lighting", "ADVLM" )
 63{
 64   mLightBinManager = NULL;
 65   mLastShader = NULL;
 66   mLastConstants = NULL;
 67   mSpherePrimitiveCount = 0;
 68   mConePrimitiveCount = 0;
 69   mAvailableSLInterfaces = NULL;
 70}
 71
 72AdvancedLightManager::~AdvancedLightManager()
 73{
 74   mLastShader = NULL;
 75   mLastConstants = NULL;
 76
 77   for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
 78   {
 79      if (i->value)
 80         SAFE_DELETE(i->value);
 81   }
 82   mConstantLookup.clear();
 83}
 84
 85bool AdvancedLightManager::isCompatible() const
 86{
 87   // TODO: We need at least 3.0 shaders at the moment
 88   // but this should be relaxed to 2.0 soon.
 89   if ( GFX->getPixelShaderVersion() < 3.0 )
 90      return false;
 91
 92   // TODO: Test for the necessary texture formats!
 93   bool autoMips;
 94   if(!GFX->getCardProfiler()->checkFormat(GFXFormatR16F, &GFXRenderTargetProfile, autoMips))
 95      return false;
 96
 97   return true;
 98}
 99
100void AdvancedLightManager::activate( SceneManager *sceneManager )
101{
102   Parent::activate( sceneManager );
103
104   GFXShader::addGlobalMacro( "TORQUE_ADVANCED_LIGHTING" );
105
106   sceneManager->setPostEffectFog( true );
107
108   SHADOWMGR->activate();
109
110   // Find a target format that supports blending... 
111   // we prefer the floating point format if it works.
112   Vector<GFXFormat> formats;
113   formats.push_back( GFXFormatR16G16B16A16F );
114   //formats.push_back( GFXFormatR16G16B16A16 );
115   GFXFormat blendTargetFormat = GFX->selectSupportedFormat( &GFXRenderTargetProfile,
116                                                         formats,
117                                                         true,
118                                                         true,
119                                                         false );
120
121   // First look for the deferred bin...
122   RenderDeferredMgr *deferredBin = _findDeferredRenderBin();
123
124   // If we didn't find the deferred bin then add one.
125   if (!deferredBin)
126   {
127      deferredBin = new RenderDeferredMgr(true, blendTargetFormat);
128      deferredBin->assignName("AL_DeferredBin");
129      deferredBin->registerObject();
130      getSceneManager()->getDefaultRenderPass()->addManager(deferredBin);
131      mDeferredRenderBin = deferredBin;
132   }
133
134   mLightBinManager = new AdvancedLightBinManager( this, SHADOWMGR, blendTargetFormat );
135   mLightBinManager->assignName( "AL_LightBinMgr" );
136
137   // Tell the material manager that deferred is enabled.
138   MATMGR->setDeferredEnabled( true );
139
140   // Insert our light bin manager.
141   mLightBinManager->setRenderOrder( deferredBin->getRenderOrder() + 0.01f );
142   getSceneManager()->getDefaultRenderPass()->addManager( mLightBinManager );
143
144   AdvancedLightingFeatures::registerFeatures(mDeferredRenderBin->getTargetFormat(), blendTargetFormat);
145
146   // Last thing... let everyone know we're active.
147   smActivateSignal.trigger( getId(), true );
148}
149
150void AdvancedLightManager::deactivate()
151{
152   Parent::deactivate();
153
154   GFXShader::removeGlobalMacro( "TORQUE_ADVANCED_LIGHTING" );
155
156   // Release our bin manager... it will take care of
157   // removing itself from the render passes.
158   if( mLightBinManager )
159   {
160      mLightBinManager->MRTLightmapsDuringDeferred(false);
161      mLightBinManager->deleteObject();
162   }
163   mLightBinManager = NULL;
164
165   if ( mDeferredRenderBin )
166      mDeferredRenderBin->deleteObject();
167   mDeferredRenderBin = NULL;
168
169   SHADOWMGR->deactivate();
170
171   mLastShader = NULL;
172   mLastConstants = NULL;
173
174   for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
175   {
176      if (i->value)
177         SAFE_DELETE(i->value);
178   }
179   mConstantLookup.clear();
180
181   mSphereGeometry = NULL;
182   mSphereIndices = NULL;
183   mConeGeometry = NULL;
184   mConeIndices = NULL;
185
186   AdvancedLightingFeatures::unregisterFeatures();
187
188   // Now let everyone know we've deactivated.
189   smActivateSignal.trigger( getId(), false );
190}
191
192void AdvancedLightManager::_addLightInfoEx( LightInfo *lightInfo )
193{
194   lightInfo->addExtended( new ShadowMapParams( lightInfo ) );
195   lightInfo->addExtended( new LightMapParams( lightInfo ) );
196}
197
198
199void AdvancedLightManager::_initLightFields()
200{
201   #define DEFINE_LIGHT_FIELD( var, type, enum_ )                             \
202   static inline const char* _get##var##Field( void *obj, const char *data )  \
203   {                                                                          \
204      ShadowMapParams *p = _getShadowMapParams( obj );                        \
205      if ( p )                                                                \
206         return Con::getData( type, &p->var, 0, enum_ );                      \
207      else                                                                    \
208         return "";                                                           \
209   }                                                                          \
210                                                                              \
211   static inline bool _set##var##Field( void *object, const char *index, const char *data )  \
212   {                                                                                         \
213      ShadowMapParams *p = _getShadowMapParams( object );                     \
214      if ( p )                                                                \
215      {                                                                       \
216         Con::setData( type, &p->var, 0, 1, &data, enum_ );                   \
217         p->_validate();                                                      \
218      }                                                                       \
219      return false;                                                           \
220   }
221
222   #define DEFINE_LIGHTMAP_FIELD( var, type, enum_ )                          \
223   static inline const char* _get##var##Field( void *obj, const char *data )  \
224   {                                                                          \
225      LightMapParams *p = _getLightMapParams( obj );                          \
226      if ( p )                                                                \
227         return Con::getData( type, &p->var, 0, enum_ );                      \
228      else                                                                    \
229         return "";                                                           \
230   }                                                                          \
231   \
232   static inline bool _set##var##Field( void *object, const char *index, const char *data )  \
233   {                                                                                         \
234      LightMapParams *p = _getLightMapParams( object );                       \
235      if ( p )                                                                \
236      {                                                                       \
237         Con::setData( type, &p->var, 0, 1, &data, enum_ );                   \
238      }                                                                       \
239      return false;                                                           \
240   }
241
242   #define ADD_LIGHT_FIELD( field, type, var, desc )                       \
243   ConsoleObject::addProtectedField( field, type, 0,                       \
244      &Dummy::_set##var##Field, &Dummy::_get##var##Field, desc )
245
246   // Our dummy adaptor class which we hide in here
247   // to keep from poluting the global namespace.
248   class Dummy
249   {
250   protected:
251
252      static inline ShadowMapParams* _getShadowMapParams( void *obj )
253      {
254         ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( (SimObject*)obj );
255         if ( sceneLight )
256         {
257            LightInfo *lightInfo = sceneLight->getLight();                           
258            if ( lightInfo )
259               return lightInfo->getExtended<ShadowMapParams>();
260         }
261         return NULL;
262      }
263
264      static inline LightMapParams* _getLightMapParams( void *obj )
265      {
266         ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( (SimObject*)obj );
267         if ( sceneLight )
268         {
269            LightInfo *lightInfo = sceneLight->getLight();                           
270            if ( lightInfo )
271               return lightInfo->getExtended<LightMapParams>();
272         }
273         return NULL;
274      }
275
276   public:
277
278      DEFINE_LIGHT_FIELD( attenuationRatio, TypePoint3F, NULL );
279      DEFINE_LIGHT_FIELD( shadowType, TYPEID< ShadowType >(), ConsoleBaseType::getType( TYPEID< ShadowType >() )->getEnumTable() );
280      DEFINE_LIGHT_FIELD( texSize, TypeS32, NULL );
281      DEFINE_LIGHT_FIELD( cookie, TypeStringFilename, NULL );      
282      DEFINE_LIGHT_FIELD( numSplits, TypeS32, NULL );
283      DEFINE_LIGHT_FIELD( logWeight, TypeF32, NULL );
284      DEFINE_LIGHT_FIELD( overDarkFactor, TypePoint4F, NULL);
285      DEFINE_LIGHT_FIELD( shadowDistance, TypeF32, NULL );
286      DEFINE_LIGHT_FIELD( shadowSoftness, TypeF32, NULL );
287      DEFINE_LIGHT_FIELD( fadeStartDist, TypeF32, NULL );
288      DEFINE_LIGHT_FIELD( lastSplitTerrainOnly, TypeBool, NULL );     
289
290      DEFINE_LIGHTMAP_FIELD( representedInLightmap, TypeBool, NULL );
291      DEFINE_LIGHTMAP_FIELD( shadowDarkenColor, TypeColorF, NULL );
292      DEFINE_LIGHTMAP_FIELD( includeLightmappedGeometryInShadow, TypeBool, NULL );
293   };
294
295   ConsoleObject::addGroup( "Advanced Lighting" );
296
297      ADD_LIGHT_FIELD( "attenuationRatio", TypePoint3F, attenuationRatio,
298         "The proportions of constant, linear, and quadratic attenuation to use for "
299         "the falloff for point and spot lights." );
300
301      ADD_LIGHT_FIELD( "shadowType", TYPEID< ShadowType >(), shadowType,
302         "The type of shadow to use on this light." );
303
304      ADD_LIGHT_FIELD( "cookie", TypeStringFilename, cookie,
305         "A custom pattern texture which is projected from the light." );
306
307      ADD_LIGHT_FIELD( "texSize", TypeS32, texSize,
308         "The texture size of the shadow map." );
309
310      ADD_LIGHT_FIELD( "overDarkFactor", TypePoint4F, overDarkFactor,
311         "The ESM shadow darkening factor");
312
313      ADD_LIGHT_FIELD( "shadowDistance", TypeF32, shadowDistance,
314         "The distance from the camera to extend the PSSM shadow." );
315
316      ADD_LIGHT_FIELD( "shadowSoftness", TypeF32, shadowSoftness,
317         "" );
318
319      ADD_LIGHT_FIELD( "numSplits", TypeS32, numSplits,
320         "The logrithmic PSSM split distance factor." );
321
322      ADD_LIGHT_FIELD( "logWeight", TypeF32, logWeight,
323         "The logrithmic PSSM split distance factor." );      
324
325      ADD_LIGHT_FIELD( "fadeStartDistance", TypeF32, fadeStartDist,
326         "Start fading shadows out at this distance.  0 = auto calculate this distance.");
327
328      ADD_LIGHT_FIELD( "lastSplitTerrainOnly", TypeBool, lastSplitTerrainOnly,
329         "This toggles only terrain being rendered to the last split of a PSSM shadow map.");
330
331   ConsoleObject::endGroup( "Advanced Lighting" );
332
333   ConsoleObject::addGroup( "Advanced Lighting Lightmap" );
334
335      ADD_LIGHT_FIELD( "representedInLightmap", TypeBool, representedInLightmap,
336         "This light is represented in lightmaps (static light, default: false)");
337
338      ADD_LIGHT_FIELD( "shadowDarkenColor", TypeColorF, shadowDarkenColor,
339         "The color that should be used to multiply-blend dynamic shadows onto lightmapped geometry (ignored if 'representedInLightmap' is false)");
340
341      ADD_LIGHT_FIELD( "includeLightmappedGeometryInShadow", TypeBool, includeLightmappedGeometryInShadow,
342         "This light should render lightmapped geometry during its shadow-map update (ignored if 'representedInLightmap' is false)");
343
344   ConsoleObject::endGroup( "Advanced Lighting Lightmap" );
345
346   #undef DEFINE_LIGHT_FIELD
347   #undef ADD_LIGHT_FIELD
348}
349
350void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat, 
351                                          const Material *mat, 
352                                          const SceneData &sgData,
353                                          const SceneRenderState *state,
354                                          U32 pass, 
355                                          GFXShaderConstBuffer *shaderConsts)
356{
357   // Skip this if we're rendering from the deferred bin.
358   if ( sgData.binType == SceneData::DeferredBin )
359      return;
360
361   PROFILE_SCOPE(AdvancedLightManager_setLightInfo);
362
363   LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);
364
365   LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();
366
367   LightInfo *light;
368   if (lsm)
369      light = lsm->getLightInfo();
370   else
371   {
372      light = sgData.lights[0];
373      if ( !light )
374         light = getDefaultLight();
375   }
376
377   // NOTE: If you encounter a crash from this point forward
378   // while setting a shader constant its probably because the
379   // mConstantLookup has bad shaders/constants in it.
380   //
381   // This is a known crash bug that can occur if materials/shaders
382   // are reloaded and the light manager is not reset.
383   //
384   // We should look to fix this by clearing the table.
385
386   // Update the forward shading light constants.
387   _update4LightConsts( sgData,
388                        lsc->mLightPositionSC,
389                        lsc->mLightDiffuseSC,
390                        lsc->mLightAmbientSC,
391                        lsc->mLightConfigDataSC,
392                        lsc->mLightSpotDirSC,
393                        lsc->mLightSpotParamsSC,
394                        lsc->mHasVectorLightSC,
395                        lsc->mVectorLightDirectionSC,
396                        lsc->mVectorLightColorSC,
397                        lsc->mVectorLightBrightnessSC,
398                        shaderConsts );
399
400   // Static
401   if (lsm && light->getCastShadows())
402   {
403      if (  lsc->mWorldToLightProjSC->isValid() )
404         shaderConsts->set(   lsc->mWorldToLightProjSC, 
405                              lsm->getWorldToLightProj(), 
406                              lsc->mWorldToLightProjSC->getType() );
407
408      if (  lsc->mViewToLightProjSC->isValid() )
409      {
410         // TODO: Should probably cache these results and 
411         // not do this mul here on every material that needs
412         // this transform.
413
414         shaderConsts->set(   lsc->mViewToLightProjSC, 
415                              lsm->getWorldToLightProj() * state->getCameraTransform(), 
416                              lsc->mViewToLightProjSC->getType() );
417      }
418
419      shaderConsts->setSafe( lsc->mShadowMapSizeSC, 1.0f / (F32)lsm->getTexSize() );
420
421      // Do this last so that overrides can properly override parameters previously set
422      lsm->setShaderParameters(shaderConsts, lsc);
423   }
424   else
425   {
426      if ( lsc->mViewToLightProjSC->isValid() )
427      {
428         // TODO: Should probably cache these results and 
429         // not do this mul here on every material that needs
430         // this transform.
431         MatrixF proj;
432         light->getWorldToLightProj( &proj );
433
434         shaderConsts->set(   lsc->mViewToLightProjSC, 
435                              proj * state->getCameraTransform(), 
436                              lsc->mViewToLightProjSC->getType() );
437      }
438   }
439}
440
441void AdvancedLightManager::registerGlobalLight(LightInfo *light, SimObject *obj)
442{
443   Parent::registerGlobalLight( light, obj );
444
445   // Pass the volume lights to the bin manager.
446   if (  mLightBinManager &&
447         (  light->getType() == LightInfo::Point ||
448            light->getType() == LightInfo::Spot ) )
449      mLightBinManager->addLight( light );
450}
451
452void AdvancedLightManager::unregisterAllLights()
453{
454   Parent::unregisterAllLights();
455
456   if ( mLightBinManager )
457      mLightBinManager->clearAllLights();
458}
459
460bool AdvancedLightManager::setTextureStage(  const SceneData &sgData,
461                                             const U32 currTexFlag,
462                                             const U32 textureSlot, 
463                                             GFXShaderConstBuffer *shaderConsts, 
464                                             ShaderConstHandles *handles )
465{
466   LightShadowMap* lsm = SHADOWMGR->getCurrentShadowMap();
467
468   // Assign Shadowmap, if it exists
469   LightingShaderConstants* lsc = getLightingShaderConstants(shaderConsts);
470   if ( !lsc )
471      return false;
472
473   if ( currTexFlag == Material::DynamicLight )
474   {
475      // Static
476      if ( lsm && lsm->getLightInfo()->getCastShadows() )
477         return lsm->setTextureStage( currTexFlag, lsc );
478
479      S32 reg = lsc->mShadowMapSC->getSamplerRegister();
480      if ( reg != -1 )
481         GFX->setTexture( reg, GFXTexHandle::ONE );
482
483      return true;
484   } 
485   else if ( currTexFlag == Material::DynamicLightMask )
486   {
487      S32 reg = lsc->mCookieMapSC->getSamplerRegister();
488      if ( reg != -1 && sgData.lights[0] )
489      {
490         ShadowMapParams *p = sgData.lights[0]->getExtended<ShadowMapParams>();
491
492         if ( lsc->mCookieMapSC->getType() == GFXSCT_SamplerCube )
493            GFX->setCubeTexture( reg, p->getCookieCubeTex() );
494         else
495            GFX->setTexture( reg, p->getCookieTex() );
496      }
497
498      return true;
499   }
500
501   return false;
502}
503
504LightingShaderConstants* AdvancedLightManager::getLightingShaderConstants(GFXShaderConstBuffer* buffer)
505{
506   if ( !buffer )
507      return NULL;
508
509   PROFILE_SCOPE( AdvancedLightManager_GetLightingShaderConstants );
510
511   GFXShader* shader = buffer->getShader();
512
513   // Check to see if this is the same shader, we'll get hit repeatedly by
514   // the same one due to the render bin loops.
515   if ( mLastShader.getPointer() != shader )
516   {
517      LightConstantMap::Iterator iter = mConstantLookup.find(shader);   
518      if ( iter != mConstantLookup.end() )
519      {
520         mLastConstants = iter->value;
521      } 
522      else 
523      {     
524         LightingShaderConstants* lsc = new LightingShaderConstants();
525         mConstantLookup[shader] = lsc;
526
527         mLastConstants = lsc;      
528      }
529
530      // Set our new shader
531      mLastShader = shader;
532   }
533
534   // Make sure that our current lighting constants are initialized
535   if (!mLastConstants->mInit)
536      mLastConstants->init(shader);
537
538   return mLastConstants;
539}
540
541GFXVertexBufferHandle<AdvancedLightManager::LightVertex> AdvancedLightManager::getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives)
542{
543   static SphereMesh sSphereMesh;
544
545   if( mSphereGeometry.isNull() )
546   {
547      const SphereMesh::TriangleMesh * sphereMesh = sSphereMesh.getMesh(3);
548      S32 numPoly = sphereMesh->numPoly;
549      mSpherePrimitiveCount = 0;
550      mSphereGeometry.set(GFX, numPoly*3, GFXBufferTypeStatic);
551      mSphereGeometry.lock();
552      S32 vertexIndex = 0;
553      
554      for (S32 i=0; i<numPoly; i++)
555      {
556         mSpherePrimitiveCount++;
557
558         mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[0];
559         mSphereGeometry[vertexIndex].color = ColorI::WHITE;
560         vertexIndex++;
561
562         mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[1];
563         mSphereGeometry[vertexIndex].color = ColorI::WHITE;
564         vertexIndex++;
565
566         mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[2];
567         mSphereGeometry[vertexIndex].color = ColorI::WHITE;
568         vertexIndex++;
569      }
570      mSphereGeometry.unlock();
571   }
572
573   outNumPrimitives = mSpherePrimitiveCount;
574   outPrimitives = NULL; // For now
575   return mSphereGeometry;
576}
577
578GFXVertexBufferHandle<AdvancedLightManager::LightVertex> AdvancedLightManager::getConeMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives )
579{
580   static const Point2F circlePoints[] = 
581   {
582      Point2F(0.707107f, 0.707107f),
583      Point2F(0.923880f, 0.382683f),
584      Point2F(1.000000f, 0.000000f),
585      Point2F(0.923880f, -0.382684f),
586      Point2F(0.707107f, -0.707107f),
587      Point2F(0.382683f, -0.923880f),
588      Point2F(0.000000f, -1.000000f),
589      Point2F(-0.382683f, -0.923880f),
590      Point2F(-0.707107f, -0.707107f),
591      Point2F(-0.923880f, -0.382684f),
592      Point2F(-1.000000f, 0.000000f),
593      Point2F(-0.923879f, 0.382684f),
594      Point2F(-0.707107f, 0.707107f),
595      Point2F(-0.382683f, 0.923880f),
596      Point2F(0.000000f, 1.000000f),
597      Point2F(0.382684f, 0.923879f)
598   };
599   const S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
600
601   if ( mConeGeometry.isNull() )
602   {
603      mConeGeometry.set(GFX, numPoints + 1, GFXBufferTypeStatic);
604      mConeGeometry.lock();
605
606      mConeGeometry[0].point = Point3F(0.0f,0.0f,0.0f);
607
608      for (S32 i=1; i<numPoints + 1; i++)
609      {
610         S32 imod = (i - 1) % numPoints;
611         mConeGeometry[i].point = Point3F(circlePoints[imod].x*1.1,circlePoints[imod].y*1.1, -1.0f);
612         mConeGeometry[i].color = ColorI::WHITE;
613      }
614      mConeGeometry.unlock();
615
616      mConePrimitiveCount = numPoints * 2 - 1;
617
618      // Now build the index buffer
619      mConeIndices.set(GFX, mConePrimitiveCount * 3, mConePrimitiveCount, GFXBufferTypeStatic);
620
621      U16 *idx = NULL;
622      mConeIndices.lock( &idx );
623      // Build the cone
624      U32 idxIdx = 0;
625      for( U32 i = 1; i < numPoints + 1; i++ )
626      {
627         idx[idxIdx++] = 0; // Triangles on cone start at top point
628         idx[idxIdx++] = i;
629         idx[idxIdx++] = ( i + 1 > numPoints ) ? 1 : i + 1;
630      }
631
632      // Build the bottom of the cone (reverse winding order)
633      for( U32 i = 1; i < numPoints - 1; i++ )
634      {
635         idx[idxIdx++] = 1;
636         idx[idxIdx++] = i + 2;
637         idx[idxIdx++] = i + 1;
638      }
639      mConeIndices.unlock();
640   }
641
642   outNumPrimitives = mConePrimitiveCount;
643   outPrimitives = mConeIndices.getPointer();
644   return mConeGeometry;
645}
646
647LightShadowMap* AdvancedLightManager::findShadowMapForObject( SimObject *object )
648{
649   if ( !object )
650      return NULL;
651
652   ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( object );
653   if ( !sceneLight || !sceneLight->getLight() )
654      return NULL;
655
656   return sceneLight->getLight()->getExtended<ShadowMapParams>()->getShadowMap();
657}
658
659DefineEngineFunction( setShadowVizLight, const char*, (const char* name), (""), "")
660{
661   static const String DebugTargetName( "AL_ShadowVizTexture" );
662
663   NamedTexTarget *target = NamedTexTarget::find( DebugTargetName );
664   if ( target )
665      target->unregister();
666
667   AdvancedLightManager *lm = dynamic_cast<AdvancedLightManager*>( LIGHTMGR );
668   if ( !lm )
669      return 0;
670
671   SimObject *object;
672   Sim::findObject( name, object );
673   LightShadowMap *lightShadowMap = lm->findShadowMapForObject( object );
674   if ( !lightShadowMap || !lightShadowMap->getTexture() )
675      return 0;
676
677   lightShadowMap->setDebugTarget( DebugTargetName );
678
679   GFXTextureObject *texObject = lightShadowMap->getTexture();
680   const Point3I &size = texObject->getSize();
681   F32 aspect = (F32)size.x / (F32)size.y;
682
683   static const U32 bufSize = 64;
684   char *result = Con::getReturnBuffer( bufSize );
685   dSprintf( result, bufSize, "%d %d %g", size.x, size.y, aspect ); 
686   return result;
687}
688
689