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 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; */ }