| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------#include "platform/platform.h"#include "materials/matInstance.h"#include "materials/materialManager.h"#include "materials/customMaterialDefinition.h"#include "materials/processedMaterial.h"#include "materials/processedFFMaterial.h"#include "materials/processedShaderMaterial.h"#include "materials/processedCustomMaterial.h"#include "materials/materialFeatureTypes.h"#include "shaderGen/featureMgr.h"#include "gfx/gfxDevice.h"#include "gfx/sim/cubemapData.h"#include "gfx/gfxCubemap.h"#include "core/util/safeDelete.h"class MatInstParameters;class MatInstanceParameterHandle : public MaterialParameterHandle{public:   virtual ~MatInstanceParameterHandle() {}   MatInstanceParameterHandle(const String& name);   void loadHandle(ProcessedMaterial* pmat);      // MaterialParameterHandle interface   const String& getName() const { return mName; }   virtual bool isValid() const;    virtual S32 getSamplerRegister( U32 pass ) const;private:      friend class MatInstParameters;   String mName;   MaterialParameterHandle* mProcessedHandle;};MatInstanceParameterHandle::MatInstanceParameterHandle(const String& name){   mName = name;   mProcessedHandle = NULL;}bool MatInstanceParameterHandle::isValid() const{   return mProcessedHandle && mProcessedHandle->isValid();}S32 MatInstanceParameterHandle::getSamplerRegister( U32 pass ) const{    if ( !mProcessedHandle )      return -1;   return mProcessedHandle->getSamplerRegister( pass );}void MatInstanceParameterHandle::loadHandle(ProcessedMaterial* pmat)                                         {   mProcessedHandle = pmat->getMaterialParameterHandle(mName);}MatInstParameters::MatInstParameters() {    mOwnParameters = false;    mParameters = NULL;}MatInstParameters::MatInstParameters(MaterialParameters* matParams){   mOwnParameters = false;    mParameters = matParams;}void MatInstParameters::loadParameters(ProcessedMaterial* pmat){   mOwnParameters = true;    mParameters = pmat->allocMaterialParameters();}MatInstParameters::~MatInstParameters(){   if (mOwnParameters)      SAFE_DELETE(mParameters);}const Vector<GFXShaderConstDesc>& MatInstParameters::getShaderConstDesc() const{    return mParameters->getShaderConstDesc(); }U32 MatInstParameters::getAlignmentValue(const GFXShaderConstType constType){   return mParameters->getAlignmentValue(constType);}#define MATINSTPARAMSET(handle, f) \   if (!mParameters) \      return; \   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); \   MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); \   mParameters->set(mph->mProcessedHandle, f); \void MatInstParameters::set(MaterialParameterHandle* handle, const F32 f){   MATINSTPARAMSET(handle, f);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point2F& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point3F& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const ColorF& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const S32 f){   MATINSTPARAMSET(handle, f);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point2I& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point3I& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const Point4I& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv){   MATINSTPARAMSET(handle, fv);}void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType){   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!");    MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle);    mParameters->set(mph->mProcessedHandle, mat, matrixType); }void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType){   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!");    MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle);    mParameters->set(mph->mProcessedHandle, mat, arraySize, matrixType); }#undef MATINSTPARAMSET//****************************************************************************// Material Instance//****************************************************************************MatInstance::MatInstance( Material &mat ){   VECTOR_SET_ASSOCIATION( mCurrentHandles );   VECTOR_SET_ASSOCIATION( mCurrentParameters );   mMaterial = &mat;   mCreatedFromCustomMaterial = (dynamic_cast<CustomMaterial *>(&mat) != NULL);   construct();}//----------------------------------------------------------------------------// Construct//----------------------------------------------------------------------------void MatInstance::construct(){   mUserObject = NULL;   mCurPass = -1;   mProcessedMaterial = NULL;   mVertexFormat = NULL;   mMaxStages = 1;   mActiveParameters = NULL;   mDefaultParameters = NULL;   mHasNormalMaps = false;   mIsForwardLit = false;   mIsValid = false;   MATMGR->_track(this);}//----------------------------------------------------------------------------// Destructor//----------------------------------------------------------------------------MatInstance::~MatInstance(){   SAFE_DELETE(mProcessedMaterial);   SAFE_DELETE(mDefaultParameters);   for (U32 i = 0; i < mCurrentHandles.size(); i++)      SAFE_DELETE(mCurrentHandles[i]);      MATMGR->_untrack(this);}//----------------------------------------------------------------------------// Init//----------------------------------------------------------------------------bool MatInstance::init( const FeatureSet &features,                         const GFXVertexFormat *vertexFormat ) {   AssertFatal( vertexFormat, "MatInstance::init - Got null vertex format!" );   mFeatureList = features;   mVertexFormat = vertexFormat;   SAFE_DELETE(mProcessedMaterial);      mIsValid = processMaterial();            return mIsValid;}//----------------------------------------------------------------------------// reInitialize//----------------------------------------------------------------------------bool MatInstance::reInit(){   SAFE_DELETE(mProcessedMaterial);   deleteAllHooks();   mIsValid = processMaterial();   if ( mIsValid )   {      for (U32 i = 0; i < mCurrentHandles.size(); i++)         mCurrentHandles[i]->loadHandle(mProcessedMaterial);      for (U32 i = 0; i < mCurrentParameters.size(); i++)         mCurrentParameters[i]->loadParameters(mProcessedMaterial);   }   return mIsValid;}//----------------------------------------------------------------------------// Process stages//----------------------------------------------------------------------------bool MatInstance::processMaterial(){   AssertFatal( mMaterial, "MatInstance::processMaterial - Got null material!" );   //AssertFatal( mVertexFormat, "MatInstance::processMaterial - Got null vertex format!" );   if ( !mMaterial || !mVertexFormat )         return false;      SAFE_DELETE(mDefaultParameters);   CustomMaterial *custMat = NULL;   if( dynamic_cast<CustomMaterial*>(mMaterial) )   {      F32 pixVersion = GFX->getPixelShaderVersion();      custMat = static_cast<CustomMaterial*>(mMaterial);      if ((custMat->mVersion > pixVersion) || (custMat->mVersion == 0.0))      {         if(custMat->mFallback)         {            mMaterial = custMat->mFallback;            return processMaterial();                     }         else         {                        AssertWarn(custMat->mVersion == 0.0f, avar("Can't load CustomMaterial %s for %s, using generic FF fallback",                String(mMaterial->getName()).isEmpty() ? "Unknown" : mMaterial->getName(), custMat->mMapTo.c_str()));            mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);         }      }      else          mProcessedMaterial = new ProcessedCustomMaterial(*mMaterial);   }   else if(GFX->getPixelShaderVersion() > 0.001)      mProcessedMaterial = getShaderMaterial();   else      mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);   if (mProcessedMaterial)   {      mProcessedMaterial->addStateBlockDesc( mUserDefinedState );      mProcessedMaterial->setShaderMacros( mUserMacros );      mProcessedMaterial->setUserObject( mUserObject );      FeatureSet features( mFeatureList );      features.exclude( MATMGR->getExclusionFeatures() );            if( !mProcessedMaterial->init(features, mVertexFormat, mFeaturesDelegate) )      {         Con::errorf( "Failed to initialize material '%s'", getMaterial()->getName() );         SAFE_DELETE( mProcessedMaterial );         return false;      }      mDefaultParameters = new MatInstParameters(mProcessedMaterial->getDefaultMaterialParameters());      mActiveParameters = mDefaultParameters;      const FeatureSet &finalFeatures = mProcessedMaterial->getFeatures();      mHasNormalMaps = finalFeatures.hasFeature( MFT_NormalMap );      mIsForwardLit =   (  custMat && custMat->mForwardLit ) ||                         (  !finalFeatures.hasFeature( MFT_IsEmissive ) &&                           finalFeatures.hasFeature( MFT_ForwardShading ) );      return true;   }      return false;}const MatStateHint& MatInstance::getStateHint() const{   if ( mProcessedMaterial )      return mProcessedMaterial->getStateHint();   else      return MatStateHint::Default;}ProcessedMaterial* MatInstance::getShaderMaterial(){   return new ProcessedShaderMaterial(*mMaterial);}void MatInstance::addStateBlockDesc(const GFXStateBlockDesc& desc){      mUserDefinedState = desc;}void MatInstance::updateStateBlocks(){   if ( mProcessedMaterial )      mProcessedMaterial->updateStateBlocks();}void MatInstance::addShaderMacro( const String &name, const String &value ){      // Check to see if we already have this macro.   Vector<GFXShaderMacro>::iterator iter = mUserMacros.begin();   for ( ; iter != mUserMacros.end(); iter++ )   {      if ( iter->name == name )      {         iter->value = value;         return;      }   }   // Add a new macro.   mUserMacros.increment();   mUserMacros.last().name = name;   mUserMacros.last().value = value;}//----------------------------------------------------------------------------// Setup pass - needs scenegraph data because the lightmap will change across//    several materials.//----------------------------------------------------------------------------bool MatInstance::setupPass(SceneRenderState * state, const SceneData &sgData ){   PROFILE_SCOPE( MatInstance_SetupPass );      if( !mProcessedMaterial )      return false;   ++mCurPass;   if ( !mProcessedMaterial->setupPass( state, sgData, mCurPass ) )   {      mCurPass = -1;      return false;   }   return true;}void MatInstance::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state){   PROFILE_SCOPE(MatInstance_setTransforms);   mProcessedMaterial->setTransforms(matrixSet, state, getCurPass());}void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData){   PROFILE_SCOPE(MatInstance_setSceneInfo);   mProcessedMaterial->setSceneInfo(state, sgData, getCurPass());}void MatInstance::setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer){   mProcessedMaterial->setBuffers(vertBuffer, primBuffer);}void MatInstance::setTextureStages(SceneRenderState * state, const SceneData &sgData ){   PROFILE_SCOPE(MatInstance_setTextureStages);   mProcessedMaterial->setTextureStages(state, sgData, getCurPass());}bool MatInstance::isInstanced() const {   return mProcessedMaterial->getFeatures().hasFeature( MFT_UseInstancing );}bool MatInstance::stepInstance(){   AssertFatal( isInstanced(), "MatInstance::stepInstance - This material isn't instanced!" );   AssertFatal( mCurPass >= 0, "MatInstance::stepInstance - Must be within material setup pass!" );   return mProcessedMaterial->stepInstance();}U32 MatInstance::getCurStageNum(){   return mProcessedMaterial->getStageFromPass(getCurPass());}RenderPassData* MatInstance::getPass(U32 pass){   return mProcessedMaterial->getPass(pass);}bool MatInstance::hasGlow() {    if( mProcessedMaterial )      return mProcessedMaterial->hasGlow();    else      return false;}bool MatInstance::hasAccumulation() {    if( mProcessedMaterial )      return mProcessedMaterial->hasAccumulation();    else      return false;}const FeatureSet& MatInstance::getFeatures() const {   return mProcessedMaterial->getFeatures(); }MaterialParameterHandle* MatInstance::getMaterialParameterHandle(const String& name){   AssertFatal(mProcessedMaterial, "Not init'ed!");    for (U32 i = 0; i < mCurrentHandles.size(); i++)   {      if (mCurrentHandles[i]->getName().equal(name))      {         return mCurrentHandles[i];      }   }   MatInstanceParameterHandle* mph = new MatInstanceParameterHandle(name);   mph->loadHandle(mProcessedMaterial);   mCurrentHandles.push_back(mph);   return mph;}MaterialParameters* MatInstance::allocMaterialParameters() {     AssertFatal(mProcessedMaterial, "Not init'ed!");    MatInstParameters* mip = new MatInstParameters();   mip->loadParameters(mProcessedMaterial);   mCurrentParameters.push_back(mip);   return mip;   }void MatInstance::setMaterialParameters(MaterialParameters* param) {    AssertFatal(mProcessedMaterial, "Not init'ed!");    mProcessedMaterial->setMaterialParameters(param, mCurPass);   AssertFatal(dynamic_cast<MatInstParameters*>(param), "Incorrect param type!");   mActiveParameters = static_cast<MatInstParameters*>(param);}MaterialParameters* MatInstance::getMaterialParameters(){    AssertFatal(mProcessedMaterial, "Not init'ed!");    return mActiveParameters;}void MatInstance::dumpShaderInfo() const{   if ( mMaterial == NULL )   {      Con::errorf( "Trying to get Material information on an invalid MatInstance" );      return;   }   Con::printf( "Material Info for object %s - %s", mMaterial->getName(), mMaterial->mMapTo.c_str() );   if ( mProcessedMaterial == NULL )   {      Con::printf( "  [no processed material!]" );      return;   }   mProcessedMaterial->dumpMaterialInfo();}
 |