Exemplo n.º 1
0
void SkyBox::_renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi )
{
   GFXDEBUGEVENT_SCOPE( SkyBox_RenderObject, ColorF::WHITE );

   GFXTransformSaver saver;  
   GFX->setVertexBuffer( mVB );         

   MatrixF worldMat = MatrixF::Identity;
   worldMat.setPosition( state->getCameraPosition() );

   SceneData sgData;
   sgData.init( state );
   sgData.objTrans = &worldMat;

   mMatrixSet->restoreSceneViewProjection();
   mMatrixSet->setWorld( worldMat );
   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   while ( mMatInstance->setupPass( state, sgData ) )
   {         
      mMatInstance->setTransforms( *mMatrixSet, state );
      mMatInstance->setSceneInfo( state, sgData );

      GFX->drawPrimitive( GFXTriangleList, 0, mPrimCount );     
   }

   // Draw render band.
   if ( mFogBandHeight > 0 && mFogBandMatInst )
   {
      const FogData &fog = state->getSceneManager()->getFogData();
      if ( mLastFogColor != fog.color )
      {
         mLastFogColor = fog.color;
         _initRender();
      }

      // Just need it to follow the camera... no rotation.
      MatrixF camPosMat( MatrixF::Identity );
      camPosMat.setPosition( worldMat.getPosition() );
      sgData.objTrans = &camPosMat;
      mMatrixSet->setWorld( *sgData.objTrans );

      while ( mFogBandMatInst->setupPass( state, sgData ) )
      {
         mFogBandMatInst->setTransforms( *mMatrixSet, state );
         mFogBandMatInst->setSceneInfo( state, sgData );

         GFX->setVertexBuffer( mFogBandVB );      
         GFX->drawPrimitive( GFXTriangleList, 0, 16 );
      }
   }
}
Exemplo n.º 2
0
void ForcedMaterialMeshMgr::render(SceneRenderState * state)
{
   PROFILE_SCOPE(ForcedMaterialMeshMgr_render);

   if(!mOverrideInstance && mOverrideMaterial.isValid())
   {
      mOverrideInstance = mOverrideMaterial->createMatInstance();
      mOverrideInstance->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<GFXVertexPNTBT>() );
   }

   // Early out if nothing to draw.
   if(!mElementList.size() || !mOverrideInstance)
      return;

   GFXDEBUGEVENT_SCOPE(ForcedMaterialMeshMgr_Render, ColorI::RED);

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

   // init loop data
   SceneData sgData;
   sgData.init( state );

   MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[0].inst);
   setupSGData( ri, sgData );

   while (mOverrideInstance->setupPass(state, sgData))
   {   
      for( U32 j=0; j<mElementList.size(); j++)
      {
         MeshRenderInst* passRI = static_cast<MeshRenderInst*>(mElementList[j].inst);
         if(passRI->primBuff->getPointer()->mPrimitiveArray[passRI->primBuffIndex].numVertices < 1)
            continue;

         getRenderPass()->getMatrixSet().setWorld(*passRI->objectToWorld);
         getRenderPass()->getMatrixSet().setView(*passRI->worldToCamera);
         getRenderPass()->getMatrixSet().setProjection(*passRI->projection);
         mOverrideInstance->setTransforms(getRenderPass()->getMatrixSet(), state, sgData);

         mOverrideInstance->setBuffers(passRI->vertBuff, passRI->primBuff);
         GFX->drawPrimitive( passRI->primBuffIndex );                  
      }
   }
}
Exemplo n.º 3
0
//-----------------------------------------------------------------------------
// render
//-----------------------------------------------------------------------------
void RenderMeshMgr::render(SceneRenderState * state)
{
   PROFILE_SCOPE(RenderMeshMgr_render);

   // Early out if nothing to draw.
   if(!mElementList.size())
      return;


   GFXDEBUGEVENT_SCOPE( RenderMeshMgr_Render, ColorI::GREEN );

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

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

   // init loop data
   GFXTextureObject *lastLM = NULL;
   GFXCubemap *lastCubemap = NULL;
   GFXTextureObject *lastReflectTex = NULL;
   GFXTextureObject *lastMiscTex = NULL;

   SceneData sgData;
   sgData.init( state );

   U32 binSize = mElementList.size();

   for( U32 j=0; j<binSize; )
   {
      MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);

      setupSGData( ri, sgData );
      BaseMatInstance *mat = ri->matInst;

      // If we have an override delegate then give it a 
      // chance to swap the material with another.
      if ( mMatOverrideDelegate )
      {
         mat = mMatOverrideDelegate( mat );
         if ( !mat )
         {
            j++;
            continue;
         }
      }

      if( !mat )
         mat = MATMGR->getWarningMatInstance();


      U32 matListEnd = j;
      lastMiscTex = sgData.miscTex;
      U32 a;

      while( mat && mat->setupPass(state, sgData ) )
      {
         for( a=j; a<binSize; a++ )
         {
            MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);

            // Check to see if we need to break this batch.
            if (  newPassNeeded( ri, passRI ) ||
                  lastMiscTex != passRI->miscTex )
            {
               lastLM = NULL;
               break;
            }

            matrixSet.setWorld(*passRI->objectToWorld);
            matrixSet.setView(*passRI->worldToCamera);
            matrixSet.setProjection(*passRI->projection);
            mat->setTransforms(matrixSet, state);

            setupSGData( passRI, sgData );
            mat->setSceneInfo( state, sgData );

            // If we're instanced then don't render yet.
            if ( mat->isInstanced() )
            {
               // Let the material increment the instance buffer, but
               // break the batch if it runs out of room for more.
               if ( !mat->stepInstance() )
               {
                  a++;
                  break;
               }

               continue;
            }

            // TODO: This could proably be done in a cleaner way.
            //
            // This section of code is dangerous, it overwrites the
            // lightmap values in sgData.  This could be a problem when multiple
            // render instances use the same multi-pass material.  When
            // the first pass is done, setupPass() is called again on
            // the material, but the lightmap data has been changed in
            // sgData to the lightmaps in the last renderInstance rendered.

            // This section sets the lightmap data for the current batch.
            // For the first iteration, it sets the same lightmap data,
            // however the redundancy will be caught by GFXDevice and not
            // actually sent to the card.  This is done for simplicity given
            // the possible condition mentioned above.  Better to set always
            // than to get bogged down into special case detection.
            //-------------------------------------
            bool dirty = false;

            // set the lightmaps if different
            if( passRI->lightmap && passRI->lightmap != lastLM )
            {
               sgData.lightmap = passRI->lightmap;
               lastLM = passRI->lightmap;
               dirty = true;
            }

            // set the cubemap if different.
            if ( passRI->cubemap != lastCubemap )
            {
               sgData.cubemap = passRI->cubemap;
               lastCubemap = passRI->cubemap;
               dirty = true;
            }

            if ( passRI->reflectTex != lastReflectTex )
            {
               sgData.reflectTex = passRI->reflectTex;
               lastReflectTex = passRI->reflectTex;
               dirty = true;
            }

            if ( dirty )
               mat->setTextureStages( state, sgData );

            // Setup the vertex and index buffers.
            mat->setBuffers( passRI->vertBuff, passRI->primBuff );

            // Render this sucker.
            if ( passRI->prim )
               GFX->drawPrimitive( *passRI->prim );
            else
               GFX->drawPrimitive( passRI->primBuffIndex );
         }

         // Draw the instanced batch.
         if ( mat->isInstanced() )
         {
            // Sets the buffers including the instancing stream.
            mat->setBuffers( ri->vertBuff, ri->primBuff );

            // Render the instanced stream.
            if ( ri->prim )
               GFX->drawPrimitive( *ri->prim );
            else
               GFX->drawPrimitive( ri->primBuffIndex );
         }

         matListEnd = a;
      }

      // force increment if none happened, otherwise go to end of batch
      j = ( j == matListEnd ) ? j+1 : matListEnd;
   }
}
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();
}
Exemplo n.º 5
0
void RenderGlowMgr::render( SceneRenderState *state )
{
   PROFILE_SCOPE( RenderGlowMgr_Render );
   
   if ( !isGlowEnabled() )
      return;

   const U32 binSize = mElementList.size();

   // If this is a non-diffuse pass or we have no objects to
   // render then tell the effect to skip rendering.
   if ( !state->isDiffusePass() || binSize == 0 )
   {
      getGlowEffect()->setSkip( true );
      return;
   }

   GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN );

   GFXTransformSaver saver;

   // Tell the superclass we're about to render, preserve contents
   const bool isRenderingToTarget = _onPreRender( state, true );

   // Clear all the buffers to black.
   GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0);

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

   // init loop data
   SceneData sgData;
   sgData.init( state, SceneData::GlowBin );

   for( U32 j=0; j<binSize; )
   {
      MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);

      setupSGData( ri, sgData );

      BaseMatInstance *mat = ri->matInst;
      GlowMaterialHook *hook = mat->getHook<GlowMaterialHook>();
      if ( !hook )
      {
         hook = new GlowMaterialHook( ri->matInst );
         ri->matInst->addHook( hook );
      }
      BaseMatInstance *glowMat = hook->getMatInstance();

      U32 matListEnd = j;

      while( glowMat && glowMat->setupPass( state, sgData ) )
      {
         U32 a;
         for( a=j; a<binSize; a++ )
         {
            MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);

            if ( newPassNeeded( ri, passRI ) )
               break;

            matrixSet.setWorld(*passRI->objectToWorld);
            matrixSet.setView(*passRI->worldToCamera);
            matrixSet.setProjection(*passRI->projection);
            glowMat->setTransforms(matrixSet, state);

            glowMat->setSceneInfo(state, sgData);
            glowMat->setBuffers(passRI->vertBuff, passRI->primBuff);

            if ( passRI->prim )
               GFX->drawPrimitive( *passRI->prim );
            else
               GFX->drawPrimitive( passRI->primBuffIndex );
         }
         matListEnd = a;
         setupSGData( ri, sgData );
      }

      // force increment if none happened, otherwise go to end of batch
      j = ( j == matListEnd ) ? j+1 : matListEnd;
   }

   // Finish up.
   if ( isRenderingToTarget )
      _onPostRender();

   // Make sure the effect is gonna render.
   getGlowEffect()->setSkip( false );
}
void GuiMaterialCtrl::onRender( Point2I offset, const RectI &updateRect )
{
   Parent::onRender( offset, updateRect );

   if ( !mMaterialInst )
      return;

   // Draw a quad with the material assigned
   GFXVertexBufferHandle<GFXVertexPCT> verts( GFX, 4, GFXBufferTypeVolatile );
   verts.lock();

   F32 screenLeft   = updateRect.point.x;
   F32 screenRight  = (updateRect.point.x + updateRect.extent.x);
   F32 screenTop    = updateRect.point.y;
   F32 screenBottom = (updateRect.point.y + updateRect.extent.y);

   const F32 fillConv = GFX->getFillConventionOffset();
   verts[0].point.set( screenLeft  - fillConv, screenTop    - fillConv, 0.f );
   verts[1].point.set( screenRight - fillConv, screenTop    - fillConv, 0.f );
   verts[2].point.set( screenLeft  - fillConv, screenBottom - fillConv, 0.f );
   verts[3].point.set( screenRight - fillConv, screenBottom - fillConv, 0.f );

   verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI( 255, 255, 255, 255 );

   verts[0].texCoord.set( 0.0f, 0.0f );
   verts[1].texCoord.set( 1.0f, 0.0f );
   verts[2].texCoord.set( 0.0f, 1.0f );
   verts[3].texCoord.set( 1.0f, 1.0f );

   verts.unlock();

   GFX->setVertexBuffer( verts );

   MatrixSet matSet;
   matSet.setWorld(GFX->getWorldMatrix());
   matSet.setView(GFX->getViewMatrix());
   matSet.setProjection(GFX->getProjectionMatrix());
   
   MatrixF cameraMatrix( true );
   F32 left, right, top, bottom, nearPlane, farPlane;
   bool isOrtho;
   GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho );
   Frustum frust( isOrtho, left, right, top, bottom, nearPlane, farPlane, cameraMatrix );

   SceneRenderState state
   (
      gClientSceneGraph,
      SPT_Diffuse,
      SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ),
      gClientSceneGraph->getDefaultRenderPass(),
      false
   );

   SceneData sgData;
   sgData.init( &state );
   sgData.wireframe = false; // Don't wireframe this.

   while( mMaterialInst->setupPass( &state, sgData ) )
   {
      mMaterialInst->setSceneInfo( &state, sgData );
      mMaterialInst->setTransforms( matSet, &state );
      GFX->setupGenericShaders();
      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
   }

   // Clean up
   GFX->setShader( NULL );
   GFX->setTexture( 0, NULL );
}
void RenderTranslucentMgr::render( SceneRenderState *state )
{
    PROFILE_SCOPE(RenderTranslucentMgr_render);

    // Early out if nothing to draw.
    if(!mElementList.size())
        return;

    GFXDEBUGEVENT_SCOPE(RenderTranslucentMgr_Render, ColorI::BLUE);

    // Find the particle render manager (if we don't have it)
    if(mParticleRenderMgr == NULL)
    {
        RenderPassManager *rpm = state->getRenderPass();
        for( U32 i = 0; i < rpm->getManagerCount(); i++ )
        {
            RenderBinManager *bin = rpm->getManager(i);
            if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles )
            {
                mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin);
                break;
            }
        }
    }

    GFXTransformSaver saver;

    SceneData sgData;
    sgData.init( state );

    GFXVertexBuffer * lastVB = NULL;
    GFXPrimitiveBuffer * lastPB = NULL;

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

    U32 binSize = mElementList.size();
    for( U32 j=0; j<binSize; )
    {
        RenderInst *baseRI = mElementList[j].inst;

        U32 matListEnd = j;

        // render these separately...
        if ( baseRI->type == RenderPassManager::RIT_ObjectTranslucent )
        {
            ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI);
            objRI->renderDelegate( objRI, state, NULL );

            lastVB = NULL;
            lastPB = NULL;
            j++;
            continue;
        }
        //Volumetric Fog Add
        else if (baseRI->type == RenderPassManager::RIT_VolumetricFog)
        {
            ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI);
            objRI->renderDelegate(objRI,state,NULL);

            lastVB = NULL;
            lastPB = NULL;
            j++;
            continue;
        }
        //Volumetric Fog Add
        else if ( baseRI->type == RenderPassManager::RIT_Particle )
        {
            ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(baseRI);

            // Tell Particle RM to draw the system. (This allows the particle render manager
            // to manage drawing offscreen particle systems, and allows the systems
            // to be composited back into the scene with proper translucent
            // sorting order)
            mParticleRenderMgr->renderInstance(ri, state);

            lastVB = NULL;    // no longer valid, null it
            lastPB = NULL;    // no longer valid, null it

            j++;
            continue;
        }
        else if ( baseRI->type == RenderPassManager::RIT_Translucent )
        {
            MeshRenderInst* ri = static_cast<MeshRenderInst*>(baseRI);
            BaseMatInstance *mat = ri->matInst;

            setupSGData( ri, sgData );

            while( mat->setupPass( state, sgData ) )
            {
                U32 a;
                for( a=j; a<binSize; a++ )
                {
                    RenderInst* nextRI = mElementList[a].inst;
                    if ( nextRI->type != RenderPassManager::RIT_Translucent )
                        break;

                    MeshRenderInst *passRI = static_cast<MeshRenderInst*>(nextRI);

                    // Check to see if we need to break this batch.
                    if ( newPassNeeded( ri, passRI ) )
                        break;

                    // Z sorting and stuff is still not working in this mgr...
                    setupSGData( passRI, sgData );
                    mat->setSceneInfo(state, sgData);
                    matrixSet.setWorld(*passRI->objectToWorld);
                    matrixSet.setView(*passRI->worldToCamera);
                    matrixSet.setProjection(*passRI->projection);
                    mat->setTransforms(matrixSet, state);

                    // If we're instanced then don't render yet.
                    if ( mat->isInstanced() )
                    {
                        // Let the material increment the instance buffer, but
                        // break the batch if it runs out of room for more.
                        if ( !mat->stepInstance() )
                        {
                            a++;
                            break;
                        }

                        continue;
                    }

                    // Setup the vertex and index buffers.
                    mat->setBuffers( passRI->vertBuff, passRI->primBuff );

                    // Render this sucker.
                    if ( passRI->prim )
                        GFX->drawPrimitive( *passRI->prim );
                    else
                        GFX->drawPrimitive( passRI->primBuffIndex );
                }

                // Draw the instanced batch.
                if ( mat->isInstanced() )
                {
                    // Sets the buffers including the instancing stream.
                    mat->setBuffers( ri->vertBuff, ri->primBuff );

                    // Render the instanced stream.
                    if ( ri->prim )
                        GFX->drawPrimitive( *ri->prim );
                    else
                        GFX->drawPrimitive( ri->primBuffIndex );
                }

                matListEnd = a;
            }

            // force increment if none happened, otherwise go to end of batch
            j = ( j == matListEnd ) ? j+1 : matListEnd;
        }
    }
}
Exemplo n.º 8
0
void RenderGlowMgr::render( SceneRenderState *state )
{
   PROFILE_SCOPE( RenderGlowMgr_Render );
   
   if ( !isGlowEnabled() )
      return;

   const U32 binSize = mElementList.size();

   // If this is a non-diffuse pass or we have no objects to
   // render then tell the effect to skip rendering.
   if ( !state->isDiffusePass() || binSize == 0 )
   {
      getGlowEffect()->setSkip( true );
      return;
   }

   GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN );

   GFXTransformSaver saver;

   // Respect the current viewport
   mNamedTarget.setViewport(GFX->getViewport());

   // Tell the superclass we're about to render, preserve contents
   const bool isRenderingToTarget = _onPreRender( state, true );

   // Clear all the buffers to black.
   GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0);

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

   // init loop data
   SceneData sgData;
   sgData.init( state, SceneData::GlowBin );

   for( U32 j=0; j<binSize; )
   {
      RenderInst *_ri = mElementList[j].inst;
      if(_ri->type == RenderPassManager::RIT_Particle)
      {
         // Find the particle render manager (if we don't have it)
         if(mParticleRenderMgr == NULL)
         {
            RenderPassManager *rpm = state->getRenderPass();
            for( U32 i = 0; i < rpm->getManagerCount(); i++ )
            {
               RenderBinManager *bin = rpm->getManager(i);
               if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles )
               {
                  mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin);
                  break;
               }
            }
         }

         ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(_ri);

         GFX->setStateBlock(mParticleRenderMgr->_getHighResStateBlock(ri));
         mParticleRenderMgr->_getShaderConsts().mShaderConsts->setSafe(mParticleRenderMgr->_getShaderConsts().mModelViewProjSC, *ri->modelViewProj);

         mParticleRenderMgr->renderParticle(ri, state);
         j++;
         continue;
      }

      MeshRenderInst *ri = static_cast<MeshRenderInst*>(_ri);

      setupSGData( ri, sgData );

      BaseMatInstance *mat = ri->matInst;
      GlowMaterialHook *hook = mat->getHook<GlowMaterialHook>();
      if ( !hook )
      {
         hook = new GlowMaterialHook( ri->matInst );
         ri->matInst->addHook( hook );
      }
      BaseMatInstance *glowMat = hook->getMatInstance();

      U32 matListEnd = j;

      while( glowMat && glowMat->setupPass( state, sgData ) )
      {
         U32 a;
         for( a=j; a<binSize; a++ )
         {
            if (mElementList[a].inst->type == RenderPassManager::RIT_Particle)
               break;

            MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);

            if ( newPassNeeded( ri, passRI ) )
               break;

            matrixSet.setWorld(*passRI->objectToWorld);
            matrixSet.setView(*passRI->worldToCamera);
            matrixSet.setProjection(*passRI->projection);
            glowMat->setTransforms(matrixSet, state);

            glowMat->setSceneInfo(state, sgData);
            glowMat->setBuffers(passRI->vertBuff, passRI->primBuff);

            if ( passRI->prim )
               GFX->drawPrimitive( *passRI->prim );
            else
               GFX->drawPrimitive( passRI->primBuffIndex );
         }
         matListEnd = a;
         setupSGData( ri, sgData );
      }

      // force increment if none happened, otherwise go to end of batch
      j = ( j == matListEnd ) ? j+1 : matListEnd;
   }

   // Finish up.
   if ( isRenderingToTarget )
      _onPostRender();

   // Make sure the effect is gonna render.
   getGlowEffect()->setSkip( false );
}