void AdvancedLightBinManager::render( SceneRenderState *state )
{
   PROFILE_SCOPE( AdvancedLightManager_Render );

   // Take a look at the SceneRenderState and see if we should skip drawing the pre-pass
   if( state->disableAdvancedLightingBins() )
      return;

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   if( !mLightManager )
      return;

   // Get the sunlight. If there's no sun, and no lights in the bins, no draw
   LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType );
   if( !sunLight && mLightBin.empty() )
      return;

   GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render, ColorI::RED );

   // Tell the superclass we're about to render
   if ( !_onPreRender( state ) )
      return;

   // Clear as long as there isn't MRT population of light buffer with lightmap data
   if ( !MRTLightmapsDuringPrePass() )
      GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);

   // Restore transforms
   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
   matrixSet.restoreSceneViewProjection();

   const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();

   // Set up the SG Data
   SceneData sgData;
   sgData.init( state );

   // There are cases where shadow rendering is disabled.
   const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;

   // Pick the right material for rendering the sunlight... we only
   // cast shadows when its enabled and we're not in a reflection.
   LightMaterialInfo *vectorMatInfo;
   if (  sunLight &&
         sunLight->getCastShadows() &&
         !disableShadows &&
         sunLight->getExtended<ShadowMapParams>() )
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM, false );
   else
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None, false );

   // Initialize and set the per-frame parameters after getting
   // the vector light material as we use lazy creation.
   _setupPerFrameParameters( state );
   
   // Draw sunlight/ambient
   if ( sunLight && vectorMatInfo )
   {
      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Sunlight, ColorI::RED );

      // Set up SG data
      setupSGData( sgData, state, sunLight );
      vectorMatInfo->setLightParameters( sunLight, state, worldToCameraXfm );

      // Set light holds the active shadow map.       
      mShadowManager->setLightShadowMapForLight( sunLight );

      // Set geometry
      GFX->setVertexBuffer( mFarFrustumQuadVerts );
      GFX->setPrimitiveBuffer( NULL );

      // Render the material passes
      while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
      {
         vectorMatInfo->matInstance->setSceneInfo( state, sgData );
         vectorMatInfo->matInstance->setTransforms( matrixSet, state );
         GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
      }
   }

   // Blend the lights in the bin to the light buffer
   for( LightBinIterator itr = mLightBin.begin(); itr != mLightBin.end(); itr++ )
   {
      LightBinEntry& curEntry = *itr;
      LightInfo *curLightInfo = curEntry.lightInfo;
      LightMaterialInfo *curLightMat = curEntry.lightMaterial;
      const U32 numPrims = curEntry.numPrims;
      const U32 numVerts = curEntry.vertBuffer->mNumVerts;

      // Skip lights which won't affect the scene.
      if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f )
         continue;

      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Light, ColorI::RED );

      setupSGData( sgData, state, curLightInfo );
      curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
      mShadowManager->setLightShadowMap( curEntry.shadowMap );

      // Let the shadow know we're about to render from it.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->preLightRender();

      // Set geometry
      GFX->setVertexBuffer( curEntry.vertBuffer );
      GFX->setPrimitiveBuffer( curEntry.primBuffer );

      // Render the material passes
      while( curLightMat->matInstance->setupPass( state, sgData ) )
      {
         // Set transforms
         matrixSet.setWorld(*sgData.objTrans);
         curLightMat->matInstance->setTransforms(matrixSet, state);
         curLightMat->matInstance->setSceneInfo(state, sgData);

         if(curEntry.primBuffer)
            GFX->drawIndexedPrimitive(GFXTriangleList, 0, 0, numVerts, 0, numPrims);
         else
            GFX->drawPrimitive(GFXTriangleList, 0, numPrims);
      }

      // Tell it we're done rendering.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->postLightRender();
   }

   // Set NULL for active shadow map (so nothing gets confused)
   mShadowManager->setLightShadowMap(NULL);
   GFX->setVertexBuffer( NULL );
   GFX->setPrimitiveBuffer( NULL );

   // Fire off a signal to let others know that light-bin rendering is ending now
   getRenderSignal().trigger(state, this);

   // Finish up the rendering
   _onPostRender();
}
void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat, 
                                          const Material *mat, 
                                          const SceneData &sgData,
                                          const SceneRenderState *state,
                                          U32 pass, 
                                          GFXShaderConstBuffer *shaderConsts)
{
   // Skip this if we're rendering from the prepass bin.
   if ( sgData.binType == SceneData::PrePassBin )
      return;

   PROFILE_SCOPE(AdvancedLightManager_setLightInfo);

   LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);

   LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();

   LightInfo *light;
   if ( lsm )
      light = lsm->getLightInfo();
   else
   {
      light = sgData.lights[0];
      if ( !light )
         light = getDefaultLight();
   }

   // NOTE: If you encounter a crash from this point forward
   // while setting a shader constant its probably because the
   // mConstantLookup has bad shaders/constants in it.
   //
   // This is a known crash bug that can occur if materials/shaders
   // are reloaded and the light manager is not reset.
   //
   // We should look to fix this by clearing the table.

   // Update the forward shading light constants.
   _update4LightConsts( sgData,
                        lsc->mLightPositionSC,
                        lsc->mLightDiffuseSC,
                        lsc->mLightAmbientSC,
                        lsc->mLightInvRadiusSqSC,
                        lsc->mLightSpotDirSC,
                        lsc->mLightSpotAngleSC,
						lsc->mLightSpotFalloffSC,
                        shaderConsts );

   if ( lsm && light->getCastShadows() )
   {
      if (  lsc->mWorldToLightProjSC->isValid() )
         shaderConsts->set(   lsc->mWorldToLightProjSC, 
                              lsm->getWorldToLightProj(), 
                              lsc->mWorldToLightProjSC->getType() );

      if (  lsc->mViewToLightProjSC->isValid() )
      {
         // TODO: Should probably cache these results and 
         // not do this mul here on every material that needs
         // this transform.

         shaderConsts->set(   lsc->mViewToLightProjSC, 
                              lsm->getWorldToLightProj() * state->getCameraTransform(), 
                              lsc->mViewToLightProjSC->getType() );
      }

      shaderConsts->setSafe( lsc->mShadowMapSizeSC, 1.0f / (F32)lsm->getTexSize() );

      // Do this last so that overrides can properly override parameters previously set
      lsm->setShaderParameters(shaderConsts, lsc);
   }
   else
   {
      if ( lsc->mViewToLightProjSC->isValid() )
      {
         // TODO: Should probably cache these results and 
         // not do this mul here on every material that needs
         // this transform.
         MatrixF proj;
         light->getWorldToLightProj( &proj );

         shaderConsts->set(   lsc->mViewToLightProjSC, 
                              proj * state->getCameraTransform(), 
                              lsc->mViewToLightProjSC->getType() );
      }
   }
}