Beispiel #1
0
void RenderGlowMgr::addElement( RenderInst *inst )
{
   // Skip out if we don't have the glow post 
   // effect enabled at this time.
   if ( !isGlowEnabled() )
      return;

   // TODO: We need to get the scene state here in a more reliable
   // manner so we can skip glow in a non-diffuse render pass.
   //if ( !mParentManager->getSceneManager()->getSceneState()->isDiffusePass() )
      //return RenderBinManager::arSkipped;
   ParticleRenderInst *particleInst = NULL;
   if(inst->type == RenderPassManager::RIT_Particle)
      particleInst = static_cast<ParticleRenderInst*>(inst);
   if(particleInst && particleInst->glow)
   {
      internalAddElement(inst);
      return;
   }

   // Skip it if we don't have a glowing material.
   BaseMatInstance *matInst = getMaterial( inst );
   if ( !matInst || !matInst->hasGlow() )   
      return;

   internalAddElement(inst);
}
void TSForestCellBatch::_render( const SceneRenderState *state )
{
   if (  !mVB.isValid() || 
         ( state->isShadowPass() && !TSLastDetail::smCanShadow ) )
      return;

   // Make sure we have a material to render with.
   BaseMatInstance *mat = state->getOverrideMaterial( mDetail->getMatInstance() );
   if ( mat == NULL )
      return;

   // We don't really render here... we submit it to
   // the render manager which collects all the batches
   // in the scene, sorts them by texture, sets up the
   // shader, and then renders them all at once.

   ImposterBatchRenderInst *inst = state->getRenderPass()->allocInst<ImposterBatchRenderInst>();
   inst->mat = mat;
   inst->vertBuff = &mVB;

   // We sort by the imposter type first so that RIT_Imposter and 
   // RIT_ImposterBatches do not get mixed together.
   //
   // We then sort by material.
   //
   inst->defaultKey = 0;
   inst->defaultKey2 = mat->getStateHint();

   state->getRenderPass()->addInst( inst );
}
BaseMatInstance* InstancingMaterialHook::getInstancingMat( BaseMatInstance *matInst )
{
   PROFILE_SCOPE( InstancingMaterialHook_GetInstancingMat );

   if ( matInst == NULL )
      return NULL;

   InstancingMaterialHook *hook = matInst->getHook<InstancingMaterialHook>();
   if ( hook == NULL )
   {
      hook = new InstancingMaterialHook();
      matInst->addHook( hook );

      BaseMatInstance *instMat = matInst->getMaterial()->createMatInstance();
      FeatureSet features( matInst->getRequestedFeatures() );
      features.addFeature( MFT_UseInstancing ); 

      if ( !instMat->init( features, matInst->getVertexFormat() ) )
         SAFE_DELETE( instMat );

      hook->mMatInst = instMat;
   }

   return hook->mMatInst;
}
Beispiel #4
0
BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const ColorF &meshColor)
{
   String  meshDebugStr = String::ToString( "Torque_MeshDebug_%d", meshColor.getRGBAPack() );

   Material *debugMat;
   if (!Sim::findObject(meshDebugStr,debugMat))
   {
      debugMat = allocateAndRegister( meshDebugStr );

      debugMat->mDiffuse[0] = meshColor;
      debugMat->mEmissive[0] = true;
   }

   BaseMatInstance   *debugMatInstance = NULL;

   if( debugMat != NULL )
   {
      debugMatInstance = debugMat->createMatInstance();

      GFXStateBlockDesc desc;
      desc.setCullMode(GFXCullNone);
      desc.fillMode = GFXFillWireframe;
      debugMatInstance->addStateBlockDesc(desc);

      // Disable fog and other stuff.
      FeatureSet debugFeatures;
      debugFeatures.addFeature( MFT_DiffuseColor );
      debugMatInstance->init( debugFeatures, getGFXVertexFormat<GFXVertexPCN>() );
   }

   return debugMatInstance;
}
void ImposterCaptureMaterialHook::init( BaseMatInstance *inMat )
{
   // We cannot capture impostors on custom materials
   // as we don't know how to get just diffuse and just
   // normals rendering.
   if ( dynamic_cast<CustomMaterial*>( inMat->getMaterial() ) )
      return;

   // Tweak the feature data to include just what we need.
   FeatureSet features;
   features.addFeature( MFT_VertTransform );
   features.addFeature( MFT_DiffuseMap );
   features.addFeature( MFT_OverlayMap );
   features.addFeature( MFT_DetailMap );
   features.addFeature( MFT_DiffuseColor );
   features.addFeature( MFT_AlphaTest );
   features.addFeature( MFT_IsTranslucent );

   const String &matName = inMat->getMaterial()->getName();

   mDiffuseMatInst = MATMGR->createMatInstance( matName );
   mDiffuseMatInst->getFeaturesDelegate().bind( &ImposterCaptureMaterialHook::_overrideFeatures );
   mDiffuseMatInst->init( features, inMat->getVertexFormat() );
   
   features.addFeature( MFT_IsDXTnm );
   features.addFeature( MFT_NormalMap );
   features.addFeature( MFT_NormalsOut );
   mNormalsMatInst = MATMGR->createMatInstance( matName );
   mNormalsMatInst->getFeaturesDelegate().bind( &ImposterCaptureMaterialHook::_overrideFeatures );
   mNormalsMatInst->init( features, inMat->getVertexFormat() );
}
void RenderTranslucentMgr::addElement( RenderInst *inst )
{
    // Right off the bat if its not translucent skip it.
    if ( !inst->translucentSort )
        return;

    // What type of instance is this.
    const bool isMeshInst = inst->type == RenderPassManager::RIT_Translucent;

    // Get its material if its a mesh.
    BaseMatInstance* matInst = NULL;
    if ( isMeshInst )
        matInst = static_cast<MeshRenderInst*>( inst )->matInst;

    // If the material isn't translucent the skip it.
    if ( matInst && !matInst->getMaterial()->isTranslucent() )
        return;

    // We made it this far, add the instance.
    mElementList.increment();
    MainSortElem& elem = mElementList.last();
    elem.inst = inst;

    // Override the instances default key to be the sort distance. All
    // the pointer dereferencing is in there to prevent us from losing
    // information when converting to a U32.
    elem.key = *((U32*)&inst->sortDistSq);

    AssertFatal( inst->defaultKey != 0, "RenderTranslucentMgr::addElement() - Got null sort key... did you forget to set it?" );

    // Then use the instances primary key as our secondary key
    elem.key2 = inst->defaultKey;
}
// Returns true is the shape contains any materials with accumulation enabled.
bool TSShapeInstance::hasAccumulation()
{
   bool result = false;
   for ( U32 i = 0; i < mMaterialList->size(); ++i )
   {
      BaseMatInstance* mat = mMaterialList->getMaterialInst(i);
      if ( mat->hasAccumulation() )
         result = true;
   }
   return result;
}
void GroundPlane::prepRenderImage( SceneRenderState* state )
{
   PROFILE_SCOPE( GroundPlane_prepRenderImage );
   
   // TODO: Should we skip rendering the ground plane into
   // the shadows?  Its not like you can ever get under it.

   if ( !mMaterial )
      return;

   // If we don't have a material instance after the override then 
   // we can skip rendering all together.
   BaseMatInstance *matInst = state->getOverrideMaterial( mMaterial );
   if ( !matInst )
      return;

   PROFILE_SCOPE( GroundPlane_prepRender );

   // Update the geometry.
   createGeometry( state->getCullingFrustum() );
   if( mVertexBuffer.isNull() )
      return;

   // Add a render instance.

   RenderPassManager*   pass  = state->getRenderPass();
   MeshRenderInst*      ri    = pass->allocInst< MeshRenderInst >();

   ri->type                   = RenderPassManager::RIT_Mesh;
   ri->vertBuff               = &mVertexBuffer;
   ri->primBuff               = &mPrimitiveBuffer;
   ri->prim                   = &mPrimitive;
   ri->matInst                = matInst;
   ri->objectToWorld          = pass->allocUniqueXform( MatrixF::Identity );
   ri->worldToCamera          = pass->allocSharedXform( RenderPassManager::View );
   ri->projection             = pass->allocSharedXform( RenderPassManager::Projection );
   ri->visibility             = 1.0f;
   ri->translucentSort        = matInst->getMaterial()->isTranslucent();
   ri->defaultKey             = matInst->getStateHint();

   if( ri->translucentSort )
      ri->type = RenderPassManager::RIT_Translucent;

	// If we need lights then set them up.
   if ( matInst->isForwardLit() )
   {
      LightQuery query;
      query.init( getWorldSphere() );
		query.getLights( ri->lights, 8 );
   }

   pass->addInst( ri );
}
Beispiel #9
0
BaseMatInstance* MaterialManager::createMatInstance(  const String &matName, 
                                                      const FeatureSet& features, 
                                                      const GFXVertexFormat *vertexFormat )
{
   BaseMatInstance* mat = createMatInstance(matName);
   if (mat)
   {
      mat->init( features, vertexFormat );
      return mat;
   }

   return NULL;
}
void PxCloth::prepRenderImage( SceneRenderState *state )
{  
   if ( mIsVBDirty )
      _updateVBIB();

   // Recreate the material if we need to.
   if ( !mMatInst )
      _initMaterial();

   // If we don't have a material instance after the override then 
   // we can skip rendering all together.
   BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst );
   if ( !matInst )
      return;

   MeshRenderInst *ri = state->getRenderPass()->allocInst<MeshRenderInst>();

	// If we need lights then set them up.
   if ( matInst->isForwardLit() )
   {
      LightQuery query;
      query.init( getWorldSphere() );
		query.getLights( ri->lights, 8 );
   }

   ri->projection = state->getRenderPass()->allocSharedXform(RenderPassManager::Projection);
   ri->objectToWorld = &MatrixF::Identity;

   ri->worldToCamera = state->getRenderPass()->allocSharedXform(RenderPassManager::View);   
   ri->type = RenderPassManager::RIT_Mesh;

   ri->primBuff = &mPrimBuffer;
   ri->vertBuff = &mVB;

   ri->matInst = matInst;
   ri->prim = state->getRenderPass()->allocPrim();
   ri->prim->type = GFXTriangleList;
   ri->prim->minIndex = 0;
   ri->prim->startIndex = 0;
   ri->prim->numPrimitives = mNumIndices / 3;

   ri->prim->startVertex = 0;
   ri->prim->numVertices = mNumVertices;

   ri->defaultKey = matInst->getStateHint();
   ri->defaultKey2 = (U32)ri->vertBuff;

   state->getRenderPass()->addInst( ri );
}
Beispiel #11
0
void AtlasClipMapBatcher::renderClipMap( SceneGraphData& sgData, BaseMatInstance* overrideMat )
{
   PROFILE_START(AtlasClipMapBatcher_renderClipMap);

   for(S32 curBin=1; curBin<4; curBin++)
   {
      // If bin is empty, skip.
      if(mRenderList[curBin].size() == 0)
         continue;

      for(S32 i=0; i<mRenderList[curBin].size(); i++)
      {
         // Grab the render note.
         const RenderNote *rn = mRenderList[curBin][i];

         // Set up clipmap levels.
         if( !mFixedFunction )
         {
            BaseMatInstance* material = overrideMat;
            if( !material )
               switch( rn->levelCount )
               {
               case 2:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart, -1, -1, false ); break;
               case 3:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 1, rn->levelStart, -1, false ); break;
               case 4:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 2, rn->levelStart + 1, rn->levelStart, false ); break;
               default:    material = MaterialManager::get()->getWarningMatInstance();
               }

            while( material->setupPass( mState, sgData ) )
               rn->chunk->render();
         }
         else
         {
            Point4F clipmapMapping;
            for( U32 curLayer = rn->levelEnd; curLayer >= rn->levelStart; -- curLayer )
            {
               BaseMatInstance* material = overrideMat;
               if( !material )
                  material = mClipMap->bindTexturesFF( curLayer, clipmapMapping, curLayer == rn->levelEnd, false );

               while( material->setupPass( mState, sgData ) )
                  rn->chunk->render();
            }
         }
      }
   }

   PROFILE_END();
}
Beispiel #12
0
BaseMatInstance* TerrainCellMaterial::getShadowMat()
{
   // Find our material which has some settings
   // defined on it in script.
   Material *mat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );

   // Create the material instance adding the feature which
   // handles rendering terrain cut outs.
   FeatureSet features = MATMGR->getDefaultFeatures();
   BaseMatInstance *matInst = mat->createMatInstance();
   if ( !matInst->init( features, getGFXVertexFormat<TerrVertex>() ) )
   {
      delete matInst;
      matInst = NULL;
   }

   return matInst;
}
Beispiel #13
0
bool WaterObject::initMaterial( S32 idx )
{
   // We must return false for any case which it is NOT safe for the caller
   // to use the indexed material.
   
   if ( idx < 0 || idx > NumMatTypes )
      return false;

   BaseMatInstance *mat = mMatInstances[idx];
   WaterMatParams &matParams = mMatParamHandles[idx];
   
   // Is it already initialized?

   if ( mat && mat->isValid() )
      return true;

   // Do we need to allocate anything?

   if ( mSurfMatName[idx].isNotEmpty() )
   {      
      if ( mat )
         SAFE_DELETE( mat );

      CustomMaterial *custMat;
      if ( Sim::findObject( mSurfMatName[idx], custMat ) && custMat->mShaderData )
         mat = custMat->createMatInstance();
      else
         mat = MATMGR->createMatInstance( mSurfMatName[idx] );

      const GFXVertexFormat *flags = getGFXVertexFormat<GFXVertexPC>();

      if ( mat && mat->init( MATMGR->getDefaultFeatures(), flags ) )
      {      
         mMatInstances[idx] = mat;
         matParams.init( mat );         
         return true;
      }
            
      SAFE_DELETE( mat );      
   }

   return false;
}
Beispiel #14
0
BaseMatInstance  * MaterialManager::createWarningMatInstance()
{
   Material *warnMat = static_cast<Material*>(Sim::findObject("WarningMaterial"));

   BaseMatInstance   *warnMatInstance = NULL;

   if( warnMat != NULL )
   {
      warnMatInstance = warnMat->createMatInstance();

      GFXStateBlockDesc desc;
      desc.setCullMode(GFXCullNone);
      warnMatInstance->addStateBlockDesc(desc);

      warnMatInstance->init(  getDefaultFeatures(), 
                              getGFXVertexFormat<GFXVertexPNTTB>() );
   }

   return warnMatInstance;
}
Beispiel #15
0
void MaterialManager::dumpMaterialInstances( BaseMaterialDefinition *target ) const
{
   if ( !mMatInstanceList.size() )
      return;

   if ( target )
      Con::printf( "--------------------- %s MatInstances ---------------------", target->getName() );
   else
      Con::printf( "--------------------- MatInstances %d ---------------------", mMatInstanceList.size() );

   for( U32 i=0; i<mMatInstanceList.size(); i++ )
   {
      BaseMatInstance *inst = mMatInstanceList[i];
      
      if ( target && inst->getMaterial() != target )
         continue;

      inst->dumpShaderInfo();

      Con::printf( "" );
   }

   Con::printf( "---------------------- Dump complete ----------------------");
}
void MaterialList::initMatInstances(   const FeatureSet &features, 
                                       const GFXVertexFormat *vertexFormat )
{
   for( U32 i=0; i < mMatInstList.size(); i++ )
   {
      BaseMatInstance *matInst = mMatInstList[i];
      if ( !matInst )
         continue;

      if ( !matInst->init( features, vertexFormat ) )
      {
         Con::errorf( "MaterialList::initMatInstances - failed to initialize material instance for '%s'",
            matInst->getMaterial()->getName() );

         // Fall back to warning material.

         SAFE_DELETE( matInst );
         matInst = MATMGR->createMatInstance( "WarningMaterial" );
         matInst->init( MATMGR->getDefaultFeatures(), vertexFormat );
         mMatInstList[ i ] = matInst;
      }
   }

}
Beispiel #17
0
BaseMatInstance* ClipMap::getMaterialAndTextures( U32 level1, U32 level2, U32 level3/*=-1*/, U32 level4/*=-1*/, bool doTerrainRenderHack )
{
   // Figure out how many layers we have.
   U32 levelCount = 2;
   if(level3 != -1) levelCount++;
   if(level4 != -1) levelCount++;

   GRAPHIC->clearSamplerOverrides();   

   mMapInfoConst.setSize(levelCount);
   // Set up constants, bind textures.
   for(S32 i=0; i<levelCount; i++)
   {
      U32 curLevel = -1;
      switch(i)
      {
      case 0: curLevel = level1; break;
      case 1: curLevel = level2; break;
      case 2: curLevel = level3; break;
      case 3: curLevel = level4; break;
      }

      AssertFatal(curLevel != -1, "ClipMap::bindShaderAndTextures - tried to draw an unspecified layer!");
      AssertFatal(curLevel < mLevels.size(), "ClipMap::bindShaderAndTextures - out of range level specified!");

      // Grab references to relevant data.
      Point4F &pt = mMapInfoConst[i];
      ClipMap::ClipStackEntry &cse = mLevels[curLevel];

      // Bind debug or real textures, depending on flag.
      if(smDebugTextures)
         GRAPHIC->setTexture(i, cse.mDebugTex);
      else
         GRAPHIC->setTexture(i, cse.mTex);

      // Note the offset and center for this level as well.
      pt.x = cse.mClipCenter.x * cse.mScale;
      pt.y = cse.mClipCenter.y * cse.mScale;
      pt.z = cse.mScale;
      pt.w = 0.f;

      if (doTerrainRenderHack && TerrainRender::mCurrentBlock && !TerrainRender::mCurrentBlock->isTiling())
      {
         // At scale 1.0 we can clamp the UV edges avoiding edge bleed between terrain blocks
         if (cse.mScale == 1.0f)
         {            
            GRAPHIC->setSamplerAddressModeOverride(i, true, GAddressClamp);
         }

         // Ideally, we want to clamp at scale 2.0 as well.
         // however, we can't clamp as the shader is scaling the UV coords
         // edge bleed is caused by mipmaps wrapping, so let's bias the mipmap selection
         // out a little bit, this is only necessary for level 2 of the clip map
         if (cse.mScale == 2.0f)
         {
            
            GRAPHIC->setSamplerMipLODBiasOverride(i, true, -1.0f);
         }
         else
         {
            GRAPHIC->setSamplerMipLODBiasOverride(i, true, 0.0f);
         }
      }

   }

   S32 idx = levelCount - 1;
   BaseMatInstance* ret = mClipmapMat[idx];
   MaterialParameters* params = ret->getMaterialParameters();
   
   // We do not use the morph target in the shader, but
   // we also cannot assume it will be cleared for us.     
   params->set(mMorphTSC[idx], 0.0f);   

   // Set all the constants in one go.   
   params->set(mMapInfoTC[idx], mMapInfoConst);
   
   params->set(mDiffuseMap0TC[idx], (S32)0);
   params->set(mDiffuseMap1TC[idx], (S32)1);
   params->set(mDiffuseMap2TC[idx], (S32)2);
   params->set(mDiffuseMap3TC[idx], (S32)3);

   
   GRAPHIC->updateStates(true);
   
   // Ok - all bound!
   return ret;
}
Beispiel #18
0
void ClipMap::initClipStack()
{
   PROFILE_START(ClipMap_initClipStack);

   // Clear out all the levels.
   while(mLevels.size())
   {
      mLevels.last().mDebugTex = NULL;
      mLevels.last().mTex = NULL;
      mLevels.pop_back();
   }

   // What texture profile are we going to be using?
   AssertFatal(mImageCache, "ClipMap::initClipStack - must have image cache by this point.");
   GTextureProfile *texProfile = mImageCache->isRenderToTargetCache() 
                                    ? &ClipMapTextureRTProfile : &ClipMapTextureProfile;

   // Figure out how many clipstack textures we'll have.
   mClipStackDepth = getBinLog2(mTextureSize) - getBinLog2(mClipMapSize) + 1;
   mLevels.setSize(mClipStackDepth);

   // Print a little report on our allocation.
   Con::printf("Allocating a %d px clipmap for a %dpx source texture.", mClipMapSize, mTextureSize);
   Con::printf("   - %d base clipstack entries, + 1 cap.", mClipStackDepth - 1);

   U32 baseTexSize = (mClipMapSize * mClipMapSize * 4);
   Con::printf("   - Using approximately %fMB of texture memory.", 
      (F32(baseTexSize * mClipStackDepth) * 1.33) / (1024.0*1024.0));

   // First do our base textures - they are not mipped.
   // We rely on auto-mipmapping, but if the device/card doesn't support it, we should just not ask for it.
   U32 numMips = GRAPHIC->getCardProfiler()->queryProfile("autoMipMapLevel", true) ? 0 : 1;
   for(S32 i=0; i<mClipStackDepth; i++)
   {
      mLevels[i].mScale = (F32)BIT(mClipStackDepth - (1 + i));
      mLevels[i].mTex.set(mClipMapSize, mClipMapSize, GFormatR8G8B8X8, texProfile, avar("%s() - mLevels[%d].mTex (line %d)", __FUNCTION__, i, __LINE__), numMips);
   }

   // Some stuff can get skipped once we're set up.
   if(mTexCallbackHandle != -1)
      return;

   // Don't forget to allocate our debug textures...

   for(S32 i=0; i<mClipStackDepth; i++)
      mLevels[i].initDebugTexture(i);

   GAtlasVert2* vert = NULL;

   if (GRAPHIC->getPixelShaderVersion() > 0)
   {   
      // Do shader lookup for 2,3,4 level shaders.
      for(S32 i=2; i<5; i++)
      {
         // Init materials
         const String matname = String::ToString("AtlasMaterial%d", i);
         const U32 arrayOffset = i-1;
         mClipmapMat[arrayOffset] = MaterialManager::get()->createMatInstance(matname, (GVertexFlags)getGVertFlags(vert));
         if (!mClipmapMat[arrayOffset])
         {
            Con::errorf("Could not find material: %s", matname.c_str());
            continue;
         }
         else
         {
            if (mMapInfoConst.getElementSize() == 0)
               mMapInfoConst.setCapacity(4, mClipmapMat[arrayOffset]->getMaterialParameters()->getAlignmentValue(GSCT_Float4));
         }
         BaseMatInstance* matParams = mClipmapMat[arrayOffset];
         mMorphTSC[arrayOffset] = matParams->getMaterialParameterHandle("$morphT");
         mMapInfoTC[arrayOffset] = matParams->getMaterialParameterHandle("$mapInfo");
         mDiffuseMap0TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap0");
         mDiffuseMap1TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap1");
         mDiffuseMap2TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap2");
         mDiffuseMap3TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap3");
      }
   } else {
      mClipmapMatBasePassFF = MaterialManager::get()->createMatInstance("AtlasMaterialFFBasePass", (GVertexFlags)getGVertFlags(vert));
      mClipmapMatAddPassFF = MaterialManager::get()->createMatInstance("AtlasMaterialFFAddPass", (GVertexFlags)getGVertFlags(vert));
   }
   
   // Grab a callback from the texture manager to deal with zombification.
   GRAPHIC->getTextureManager()->registerTexCallback(texCB, this, mTexCallbackHandle);

   // Ok, everything is ready to go.
   PROFILE_END();
}
void ShadowMaterialHook::init( BaseMatInstance *inMat )
{
   if( !inMat->isValid() )
      return;

   // Tweak the feature data to include just what we need.
   FeatureSet features;
   features.addFeature( MFT_VertTransform );
   features.addFeature( MFT_DiffuseMap );
   features.addFeature( MFT_TexAnim );
   features.addFeature( MFT_AlphaTest );
   features.addFeature( MFT_Visibility );

   // Actually we want to include features from the inMat
   // if they operate on the preTransform verts so things
   // like wind/deformation effects will also affect the shadow.
   const FeatureSet &inFeatures = inMat->getFeatures();
   for ( U32 i = 0; i < inFeatures.getCount(); i++ )
   {      
      const FeatureType& ft = inFeatures.getAt(i);
      
      if ( ft.getGroup() == MFG_PreTransform )
         features.addFeature( ft );
   }

   // Do instancing in shadows if we can.
   if ( inFeatures.hasFeature( MFT_UseInstancing ) )
      features.addFeature( MFT_UseInstancing );

   Material *shadowMat = (Material*)inMat->getMaterial();
   if ( dynamic_cast<CustomMaterial*>( shadowMat ) )
   {
      // This is a custom material... who knows what it really does, but
      // if it wasn't already filtered out of the shadow render then just
      // give it some default depth out material.
      shadowMat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );
   }

   // By default we want to disable some states
   // that the material might enable for us.
   GFXStateBlockDesc forced;
   forced.setBlend( false );
   forced.setAlphaTest( false );

   // We should force on zwrite as the prepass
   // will disable it by default.
   forced.setZReadWrite( true, true );
   
   // TODO: Should we render backfaces for 
   // shadows or does the ESM take care of 
   // all our acne issues?
   //forced.setCullMode( GFXCullCW );

   // Vector, and spotlights use the same shadow material.
   BaseMatInstance *newMat = new ShadowMatInstance( shadowMat );
   newMat->setUserObject( inMat->getUserObject() );
   newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
   newMat->addStateBlockDesc( forced );
   if( !newMat->init( features, inMat->getVertexFormat() ) )
   {
      SAFE_DELETE( newMat );
      newMat = MATMGR->createWarningMatInstance();
   }
   
   mShadowMat[ShadowType_Spot] = newMat;

   newMat = new ShadowMatInstance( shadowMat );
   newMat->setUserObject( inMat->getUserObject() );
   newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
   forced.setCullMode( GFXCullCW );   
   newMat->addStateBlockDesc( forced );
   forced.cullDefined = false;
   newMat->addShaderMacro( "CUBE_SHADOW_MAP", "" );
   newMat->init( features, inMat->getVertexFormat() );
   mShadowMat[ShadowType_CubeMap] = newMat;
   
   // A dual paraboloid shadow rendered in a single draw call.
   features.addFeature( MFT_ParaboloidVertTransform );
   features.addFeature( MFT_IsSinglePassParaboloid );
   features.removeFeature( MFT_VertTransform );
   newMat = new ShadowMatInstance( shadowMat );
   newMat->setUserObject( inMat->getUserObject() );
   GFXStateBlockDesc noCull( forced );
   noCull.setCullMode( GFXCullNone );
   newMat->addStateBlockDesc( noCull );
   newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
   newMat->init( features, inMat->getVertexFormat() );
   mShadowMat[ShadowType_DualParaboloidSinglePass] = newMat;

   // Regular dual paraboloid shadow.
   features.addFeature( MFT_ParaboloidVertTransform );
   features.removeFeature( MFT_IsSinglePassParaboloid );
   features.removeFeature( MFT_VertTransform );
   newMat = new ShadowMatInstance( shadowMat );
   newMat->setUserObject( inMat->getUserObject() );
   newMat->addStateBlockDesc( forced );
   newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
   newMat->init( features, inMat->getVertexFormat() );
   mShadowMat[ShadowType_DualParaboloid] = newMat;

   /*
   // A single paraboloid shadow.
   newMat = new ShadowMatInstance( startMatInstance );
   GFXStateBlockDesc noCull;
   noCull.setCullMode( GFXCullNone );
   newMat->addStateBlockDesc( noCull );
   newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
   newMat->init( features, globalFeatures, inMat->getVertexFormat() );
   mShadowMat[ShadowType_DualParaboloidSinglePass] = newMat;
   */
}
Beispiel #20
0
void RenderMeshExample::prepRenderImage( SceneRenderState *state )
{
   // Do a little prep work if needed
   if ( mVertexBuffer.isNull() )
      createGeometry();

   // If we have no material then skip out.
   if ( !mMaterialInst )
      return;

   // If we don't have a material instance after the override then 
   // we can skip rendering all together.
   BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst );
   if ( !matInst )
      return;

   // Get a handy pointer to our RenderPassmanager
   RenderPassManager *renderPass = state->getRenderPass();

   // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
   MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();

   // Set our RenderInst as a standard mesh render
   ri->type = RenderPassManager::RIT_Mesh;

   // Calculate our sorting point
   if ( state )
   {
      // Calculate our sort point manually.
      const Box3F& rBox = getRenderWorldBox();
      ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );      
   } 
   else 
      ri->sortDistSq = 0.0f;

   // Set up our transforms
   MatrixF objectToWorld = getRenderTransform();
   objectToWorld.scale( getScale() );

   ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld );
   ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
   ri->projection    = renderPass->allocSharedXform(RenderPassManager::Projection);

	// If our material needs lights then fill the RIs 
   // light vector with the best lights.
   if ( matInst->isForwardLit() )
   {
      LightQuery query;
      query.init( getWorldSphere() );
		query.getLights( ri->lights, 8 );
   }

   // Make sure we have an up-to-date backbuffer in case
   // our Material would like to make use of it
   // NOTICE: SFXBB is removed and refraction is disabled!
   //ri->backBuffTex = GFX->getSfxBackBuffer();

   // Set our Material
   ri->matInst = matInst;

   // Set up our vertex buffer and primitive buffer
   ri->vertBuff = &mVertexBuffer;
   ri->primBuff = &mPrimitiveBuffer;

   ri->prim = renderPass->allocPrim();
   ri->prim->type = GFXTriangleList;
   ri->prim->minIndex = 0;
   ri->prim->startIndex = 0;
   ri->prim->numPrimitives = 12;
   ri->prim->startVertex = 0;
   ri->prim->numVertices = 36;

   // We sort by the material then vertex buffer
   ri->defaultKey = matInst->getStateHint();
   ri->defaultKey2 = (U32)ri->vertBuff; // Not 64bit safe!

   // Submit our RenderInst to the RenderPassManager
   state->getRenderPass()->addInst( ri );
}
Beispiel #21
0
void WaterPlane::innerRender( SceneRenderState *state )
{
   GFXDEBUGEVENT_SCOPE( WaterPlane_innerRender, ColorI( 255, 0, 0 ) );

   const Point3F &camPosition = state->getCameraPosition();

   Point3F rvec, fvec, uvec, pos;

   const MatrixF &objMat = getTransform(); //getRenderTransform();
   const MatrixF &camMat = state->getCameraTransform();

   MatrixF renderMat( true );

   camMat.getColumn( 1, &fvec );
   uvec.set( 0, 0, 1 );
   rvec = mCross( fvec, uvec );
   rvec.normalize();   
   fvec = mCross( uvec, rvec );
   pos = camPosition;
   pos.z = objMat.getPosition().z;      

   renderMat.setColumn( 0, rvec );
   renderMat.setColumn( 1, fvec );
   renderMat.setColumn( 2, uvec );
   renderMat.setColumn( 3, pos );

   setRenderTransform( renderMat );

   // Setup SceneData
   SceneData sgData = setupSceneGraphInfo( state );   

   // set the material
   S32 matIdx = getMaterialIndex( camPosition );
   
   if ( !initMaterial( matIdx ) )
      return;

   BaseMatInstance *mat = mMatInstances[matIdx];
   WaterMatParams matParams = mMatParamHandles[matIdx];

   // render the geometry
   if ( mat )
   {      
      // setup proj/world transform
      mMatrixSet->restoreSceneViewProjection();
      mMatrixSet->setWorld(getRenderTransform());

      setShaderParams( state, mat, matParams );     

      while( mat->setupPass( state, sgData ) )
      {    
         mat->setSceneInfo(state, sgData);
         mat->setTransforms(*mMatrixSet, state, sgData);
         setCustomTextures( matIdx, mat->getCurPass(), matParams );

         // set vert/prim buffer
         GFX->setVertexBuffer( mVertBuff );
         GFX->setPrimitiveBuffer( mPrimBuff );
         GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount );
      }
   }
}
Beispiel #22
0
void ConvexShape::prepRenderImage( SceneRenderState *state )
{   
   /*
   if ( state->isDiffusePass() )
   {
      ObjectRenderInst *ri2 = state->getRenderPass()->allocInst<ObjectRenderInst>();
      ri2->renderDelegate.bind( this, &ConvexShape::_renderDebug );
      ri2->type = RenderPassManager::RIT_Editor;
      state->getRenderPass()->addInst( ri2 );
   }
   */

   if ( mVertexBuffer.isNull() )
      return;

   // If we don't have a material instance after the override then 
   // we can skip rendering all together.
   BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst ? mMaterialInst : MATMGR->getWarningMatInstance() );
   if ( !matInst )
      return;

   // Get a handy pointer to our RenderPassmanager
   RenderPassManager *renderPass = state->getRenderPass();

   // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
   MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();

   // Set our RenderInst as a standard mesh render
   ri->type = RenderPassManager::RIT_Mesh;

   // Calculate our sorting point
   if ( state )
   {
      // Calculate our sort point manually.
      const Box3F& rBox = getRenderWorldBox();
      ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );      
   } 
   else 
      ri->sortDistSq = 0.0f;

   // Set up our transforms
   MatrixF objectToWorld = getRenderTransform();
   objectToWorld.scale( getScale() );

   ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld );
   ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
   ri->projection    = renderPass->allocSharedXform(RenderPassManager::Projection);

	// If we need lights then set them up.
   if ( matInst->isForwardLit() )
   {
      LightQuery query;
      query.init( getWorldSphere() );
		query.getLights( ri->lights, 8 );
   }

   // Make sure we have an up-to-date backbuffer in case
   // our Material would like to make use of it
   // NOTICE: SFXBB is removed and refraction is disabled!
   //ri->backBuffTex = GFX->getSfxBackBuffer();

   // Set our Material
   ri->matInst = matInst;
   if ( matInst->getMaterial()->isTranslucent() )
   {
      ri->translucentSort = true;
      ri->type = RenderPassManager::RIT_Translucent;
   }

   // Set up our vertex buffer and primitive buffer
   ri->vertBuff = &mVertexBuffer;
   ri->primBuff = &mPrimitiveBuffer;

   ri->prim = renderPass->allocPrim();
   ri->prim->type = GFXTriangleList;
   ri->prim->minIndex = 0;
   ri->prim->startIndex = 0;
   ri->prim->numPrimitives = mPrimCount;
   ri->prim->startVertex = 0;
   ri->prim->numVertices = mVertCount;

   // We sort by the material then vertex buffer.
   ri->defaultKey = matInst->getStateHint();
   ri->defaultKey2 = (U32)ri->vertBuff; // Not 64bit safe!

   // Submit our RenderInst to the RenderPassManager
   state->getRenderPass()->addInst( ri );
}
Beispiel #23
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 );
}
Beispiel #24
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 );
}
Beispiel #25
0
void DecalRoad::prepRenderImage( SceneRenderState* state )
{
   PROFILE_SCOPE( DecalRoad_prepRenderImage );

   if (  mNodes.size() <= 1 || 
         mBatches.size() == 0 ||
         !mMatInst ||
         state->isShadowPass() )
      return;

   // If we don't have a material instance after the override then 
   // we can skip rendering all together.
   BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst );
   if ( !matInst )
      return;
      
   RenderPassManager *renderPass = state->getRenderPass();

   // Debug RenderInstance
   // Only when editor is open.
   if ( smEditorOpen )
   {
      ObjectRenderInst *ri = renderPass->allocInst<ObjectRenderInst>();
      ri->type = RenderPassManager::RIT_Editor;
      ri->renderDelegate.bind( this, &DecalRoad::_debugRender );
      state->getRenderPass()->addInst( ri );
   }

   // Normal Road RenderInstance
   // Always rendered when the editor is not open
   // otherwise obey the smShowRoad flag
   if ( !smShowRoad && smEditorOpen )
      return;

   const Frustum &frustum = state->getCameraFrustum();

   MeshRenderInst coreRI;
   coreRI.clear();
   coreRI.objectToWorld = &MatrixF::Identity;
   coreRI.worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
   
   MatrixF *tempMat = renderPass->allocUniqueXform( MatrixF( true ) );   
   MathUtils::getZBiasProjectionMatrix( gDecalBias, frustum, tempMat );
   coreRI.projection = tempMat;

   coreRI.type = RenderPassManager::RIT_Decal;
   coreRI.vertBuff = &mVB;
   coreRI.primBuff = &mPB;
   coreRI.matInst = matInst;

   // Make it the sort distance the max distance so that 
   // it renders after all the other opaque geometry in 
   // the prepass bin.
   coreRI.sortDistSq = F32_MAX;

	// If we need lights then set them up.
   if ( matInst->isForwardLit() )
   {
      LightQuery query;
      query.init( getWorldSphere() );
		query.getLights( coreRI.lights, 8 );
   }
   
   U32 startBatchIdx = -1;
   U32 endBatchIdx = 0;

   for ( U32 i = 0; i < mBatches.size(); i++ )   
   {
      const RoadBatch &batch = mBatches[i];
      const bool isVisible = !frustum.isCulled( batch.bounds );         
      if ( isVisible )
      {
         // If this is the start of a set of batches.
         if ( startBatchIdx == -1 )
            endBatchIdx = startBatchIdx = i;

         // Else we're extending the end batch index.
         else
            ++endBatchIdx; 

         // If this isn't the last batch then continue.
         if ( i < mBatches.size()-1 )
            continue;
      }

      // We we still don't have a start batch, so skip.
      if ( startBatchIdx == -1 )
         continue;

      // Render this set of batches.
      const RoadBatch &startBatch = mBatches[startBatchIdx];
      const RoadBatch &endBatch = mBatches[endBatchIdx]; 

      U32 startVert = startBatch.startVert;
      U32 startIdx = startBatch.startIndex;
      U32 vertCount = endBatch.endVert - startVert;
      U32 idxCount = ( endBatch.endIndex - startIdx ) + 1;
      U32 triangleCount = idxCount / 3;

      AssertFatal( startVert + vertCount <= mVertCount, "DecalRoad, bad draw call!" );
      AssertFatal( startIdx + triangleCount < mTriangleCount * 3, "DecalRoad, bad draw call!" );

      MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();

      *ri = coreRI;

      ri->prim = renderPass->allocPrim();
      ri->prim->type = GFXTriangleList;
      ri->prim->minIndex = 0;
      ri->prim->startIndex = startIdx;
      ri->prim->numPrimitives = triangleCount;
      ri->prim->startVertex = 0;
      ri->prim->numVertices = endBatch.endVert + 1;

      // For sorting we first sort by render priority
      // and then by objectId. 
      //
      // Since a road can submit more than one render instance, we want all 
      // draw calls for a single road to occur consecutively, since they
      // could use the same vertex buffer.
      ri->defaultKey =  mRenderPriority << 0 | mId << 16;
      ri->defaultKey2 = 0;

      renderPass->addInst( ri );

      // Reset the batching.
      startBatchIdx = -1;
   }   
}
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;
        }
    }
}
//-----------------------------------------------------------------------------
// 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;
   }
}
Beispiel #28
0
void TSMesh::innerRender( TSMaterialList *materials, const TSRenderState &rdata, TSVertexBufferHandle &vb, GFXPrimitiveBufferHandle &pb )
{
   PROFILE_SCOPE( TSMesh_InnerRender );

   if( vertsPerFrame <= 0 ) 
      return;

   F32 meshVisibility = rdata.getFadeOverride() * mVisibility;
   if ( meshVisibility < VISIBILITY_EPSILON )
      return;

   const SceneRenderState *state = rdata.getSceneState();
   RenderPassManager *renderPass = state->getRenderPass();

   MeshRenderInst *coreRI = renderPass->allocInst<MeshRenderInst>();
   coreRI->type = RenderPassManager::RIT_Mesh;

   const MatrixF &objToWorld = GFX->getWorldMatrix();

   // Sort by the center point or the bounds.
   if ( rdata.useOriginSort() )
      coreRI->sortDistSq = ( objToWorld.getPosition() - state->getCameraPosition() ).lenSquared();
   else
   {
      Box3F rBox = mBounds;
      objToWorld.mul( rBox );
      coreRI->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );      
   }

   if (getFlags(Billboard))
   {
      Point3F camPos = state->getDiffuseCameraPosition();
      Point3F objPos;
      objToWorld.getColumn(3, &objPos);
      Point3F targetVector = camPos - objPos;
      if(getFlags(BillboardZAxis))
         targetVector.z = 0.0f;
      targetVector.normalize();
      MatrixF orient = MathUtils::createOrientFromDir(targetVector);
      orient.setPosition(objPos);
      orient.scale(objToWorld.getScale());

      coreRI->objectToWorld = renderPass->allocUniqueXform( orient );
   }
   else
      coreRI->objectToWorld = renderPass->allocUniqueXform( objToWorld );

   coreRI->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
   coreRI->projection = renderPass->allocSharedXform(RenderPassManager::Projection);

   AssertFatal( vb.isValid(), "TSMesh::innerRender() - Got invalid vertex buffer!" );
   AssertFatal( pb.isValid(), "TSMesh::innerRender() - Got invalid primitive buffer!" );

   coreRI->vertBuff = &vb;
   coreRI->primBuff = &pb;
   coreRI->defaultKey2 = (U32) coreRI->vertBuff;

   coreRI->materialHint = rdata.getMaterialHint();

   coreRI->visibility = meshVisibility;  
   coreRI->cubemap = rdata.getCubemap();

   // NOTICE: SFXBB is removed and refraction is disabled!
   //coreRI->backBuffTex = GFX->getSfxBackBuffer();

   for ( S32 i = 0; i < primitives.size(); i++ )
   {
      const TSDrawPrimitive &draw = primitives[i];

      // We need to have a material.
      if ( draw.matIndex & TSDrawPrimitive::NoMaterial )
         continue;

#ifdef TORQUE_DEBUG
      // for inspection if you happen to be running in a debugger and can't do bit 
      // operations in your head.
      S32 triangles = draw.matIndex & TSDrawPrimitive::Triangles;
      S32 strip = draw.matIndex & TSDrawPrimitive::Strip;
      S32 fan = draw.matIndex & TSDrawPrimitive::Fan;
      S32 indexed = draw.matIndex & TSDrawPrimitive::Indexed;
      S32 type = draw.matIndex & TSDrawPrimitive::TypeMask;
      TORQUE_UNUSED(triangles);
      TORQUE_UNUSED(strip);
      TORQUE_UNUSED(fan);
      TORQUE_UNUSED(indexed);
      TORQUE_UNUSED(type);
#endif

      const U32 matIndex = draw.matIndex & TSDrawPrimitive::MaterialMask;
      BaseMatInstance *matInst = materials->getMaterialInst( matIndex );

#ifndef TORQUE_OS_MAC

      // Get the instancing material if this mesh qualifies.
      if ( meshType != SkinMeshType && pb->mPrimitiveArray[i].numVertices < smMaxInstancingVerts )
         matInst = InstancingMaterialHook::getInstancingMat( matInst );

#endif

      // If we don't have a material instance after the overload then
      // there is nothing to render... skip this primitive.
      matInst = state->getOverrideMaterial( matInst );
      if ( !matInst || !matInst->isValid())
         continue;

      // If the material needs lights then gather them
      // here once and set them on the core render inst.
      if ( matInst->isForwardLit() && !coreRI->lights[0] && rdata.getLightQuery() )
         rdata.getLightQuery()->getLights( coreRI->lights, 8 );

      MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
      *ri = *coreRI;

      ri->matInst = matInst;
      ri->defaultKey = matInst->getStateHint();
      ri->primBuffIndex = i;

      // Translucent materials need the translucent type.
      if ( matInst->getMaterial()->isTranslucent() )
      {
         ri->type = RenderPassManager::RIT_Translucent;
         ri->translucentSort = true;
      }

      renderPass->addInst( ri );
   }
}