Torque3D Documentation / _generateds / matInstance.cpp

matInstance.cpp

Engine/source/materials/matInstance.cpp

More...

Classes:

Public Defines

define
MATINSTPARAMSET(handle, f)     (!mParameters) \
      return; \
   (dynamic_cast<*>(handle), "Invalid handle type!"); \
   MatInstanceParameterHandle* mph = static_cast<*>(handle); \
   mParameters->set(mph->mProcessedHandle, f); \

Detailed Description

Public Defines

MATINSTPARAMSET(handle, f)     (!mParameters) \
      return; \
   (dynamic_cast<*>(handle), "Invalid handle type!"); \
   MatInstanceParameterHandle* mph = static_cast<*>(handle); \
   mParameters->set(mph->mProcessedHandle, f); \
  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "materials/matInstance.h"
 26
 27#include "materials/materialManager.h"
 28#include "materials/customMaterialDefinition.h"
 29#include "materials/processedMaterial.h"
 30#include "materials/processedFFMaterial.h"
 31#include "materials/processedShaderMaterial.h"
 32#include "materials/processedCustomMaterial.h"
 33#include "materials/materialFeatureTypes.h"
 34#include "shaderGen/featureMgr.h"
 35#include "gfx/gfxDevice.h"
 36#include "gfx/sim/cubemapData.h"
 37#include "gfx/gfxCubemap.h"
 38#include "core/util/safeDelete.h"
 39#include "ts/tsShape.h"
 40
 41class MatInstParameters;
 42
 43class MatInstanceParameterHandle : public MaterialParameterHandle
 44{
 45public:
 46   virtual ~MatInstanceParameterHandle() {}
 47   MatInstanceParameterHandle(const String& name);
 48
 49   void loadHandle(ProcessedMaterial* pmat);
 50   
 51   // MaterialParameterHandle interface
 52   const String& getName() const { return mName; }
 53   virtual bool isValid() const; 
 54   virtual S32 getSamplerRegister( U32 pass ) const;
 55private:   
 56   friend class MatInstParameters;
 57   String mName;
 58   MaterialParameterHandle* mProcessedHandle;
 59};
 60
 61MatInstanceParameterHandle::MatInstanceParameterHandle(const String& name)
 62{
 63   mName = name;
 64   mProcessedHandle = NULL;
 65}
 66
 67bool MatInstanceParameterHandle::isValid() const
 68{
 69   return mProcessedHandle && mProcessedHandle->isValid();
 70}
 71
 72S32 MatInstanceParameterHandle::getSamplerRegister( U32 pass ) const
 73{ 
 74   if ( !mProcessedHandle )
 75      return -1;
 76   return mProcessedHandle->getSamplerRegister( pass );
 77}
 78
 79void MatInstanceParameterHandle::loadHandle(ProcessedMaterial* pmat)                                         
 80{
 81   mProcessedHandle = pmat->getMaterialParameterHandle(mName);
 82}
 83
 84MatInstParameters::MatInstParameters() 
 85{ 
 86   mOwnParameters = false; 
 87   mParameters = NULL;
 88}
 89
 90MatInstParameters::MatInstParameters(MaterialParameters* matParams)
 91{
 92   mOwnParameters = false; 
 93   mParameters = matParams;
 94}
 95
 96void MatInstParameters::loadParameters(ProcessedMaterial* pmat)
 97{
 98   mOwnParameters = true; 
 99   mParameters = pmat->allocMaterialParameters();
100}
101
102MatInstParameters::~MatInstParameters()
103{
104   if (mOwnParameters)
105      SAFE_DELETE(mParameters);
106}
107
108const Vector<GFXShaderConstDesc>& MatInstParameters::getShaderConstDesc() const
109{ 
110   return mParameters->getShaderConstDesc(); 
111}
112
113U32 MatInstParameters::getAlignmentValue(const GFXShaderConstType constType)
114{
115   return mParameters->getAlignmentValue(constType);
116}
117
118#define MATINSTPARAMSET(handle, f) \
119   if (!mParameters) \
120      return; \
121   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); \
122   MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); \
123   mParameters->set(mph->mProcessedHandle, f); \
124
125void MatInstParameters::set(MaterialParameterHandle* handle, const F32 f)
126{
127   MATINSTPARAMSET(handle, f);
128}
129
130void MatInstParameters::set(MaterialParameterHandle* handle, const Point2F& fv)
131{
132   MATINSTPARAMSET(handle, fv);
133}
134
135void MatInstParameters::set(MaterialParameterHandle* handle, const Point3F& fv)
136{
137   MATINSTPARAMSET(handle, fv);
138}
139
140void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv)
141{
142   MATINSTPARAMSET(handle, fv);
143}
144
145void MatInstParameters::set(MaterialParameterHandle* handle, const ColorF& fv)
146{
147   MATINSTPARAMSET(handle, fv);
148}
149
150void MatInstParameters::set(MaterialParameterHandle* handle, const S32 f)
151{
152   MATINSTPARAMSET(handle, f);
153}
154
155void MatInstParameters::set(MaterialParameterHandle* handle, const Point2I& fv)
156{
157   MATINSTPARAMSET(handle, fv);
158}
159
160void MatInstParameters::set(MaterialParameterHandle* handle, const Point3I& fv)
161{
162   MATINSTPARAMSET(handle, fv);
163}
164
165void MatInstParameters::set(MaterialParameterHandle* handle, const Point4I& fv)
166{
167   MATINSTPARAMSET(handle, fv);
168}
169
170void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv)
171{
172   MATINSTPARAMSET(handle, fv);
173}
174
175void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv)
176{
177   MATINSTPARAMSET(handle, fv);
178}
179
180void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv)
181{
182   MATINSTPARAMSET(handle, fv);
183}
184
185void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv)
186{
187   MATINSTPARAMSET(handle, fv);
188}
189
190void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv)
191{
192   MATINSTPARAMSET(handle, fv);
193}
194
195void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv)
196{
197   MATINSTPARAMSET(handle, fv);
198}
199
200void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv)
201{
202   MATINSTPARAMSET(handle, fv);
203}
204
205void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv)
206{
207   MATINSTPARAMSET(handle, fv);
208}
209
210void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType)
211{
212   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 
213   MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 
214   mParameters->set(mph->mProcessedHandle, mat, matrixType); 
215}
216
217void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
218{
219   AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); 
220   MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); 
221   mParameters->set(mph->mProcessedHandle, mat, arraySize, matrixType); 
222}
223#undef MATINSTPARAMSET
224
225//****************************************************************************
226// Material Instance
227//****************************************************************************
228MatInstance::MatInstance( Material &mat )
229{
230   VECTOR_SET_ASSOCIATION( mCurrentHandles );
231   VECTOR_SET_ASSOCIATION( mCurrentParameters );
232
233   mMaterial = &mat;
234
235   mCreatedFromCustomMaterial = (dynamic_cast<CustomMaterial *>(&mat) != NULL);
236
237   construct();
238}
239
240//----------------------------------------------------------------------------
241// Construct
242//----------------------------------------------------------------------------
243void MatInstance::construct()
244{
245   mUserObject = NULL;
246   mCurPass = -1;
247   mProcessedMaterial = NULL;
248   mVertexFormat = NULL;
249   mMaxStages = 1;
250   mActiveParameters = NULL;
251   mDefaultParameters = NULL;
252   mHasNormalMaps = false;
253   mUsesHardwareSkinning = false;
254   mIsForwardLit = false;
255   mIsValid = false;
256   mIsHardwareSkinned = false;
257
258   MATMGR->_track(this);
259}
260
261//----------------------------------------------------------------------------
262// Destructor
263//----------------------------------------------------------------------------
264MatInstance::~MatInstance()
265{
266   SAFE_DELETE(mProcessedMaterial);
267   SAFE_DELETE(mDefaultParameters);
268   for (U32 i = 0; i < mCurrentHandles.size(); i++)
269      SAFE_DELETE(mCurrentHandles[i]);   
270
271   MATMGR->_untrack(this);
272}
273
274//----------------------------------------------------------------------------
275// Init
276//----------------------------------------------------------------------------
277bool MatInstance::init( const FeatureSet &features, 
278                        const GFXVertexFormat *vertexFormat ) 
279{
280   AssertFatal( vertexFormat, "MatInstance::init - Got null vertex format!" );
281
282   mFeatureList = features;
283   mVertexFormat = vertexFormat;
284
285   SAFE_DELETE(mProcessedMaterial);   
286   mIsValid = processMaterial();         
287
288   return mIsValid;
289}
290
291
292//----------------------------------------------------------------------------
293// reInitialize
294//----------------------------------------------------------------------------
295bool MatInstance::reInit()
296{
297   if (!mVertexFormat)
298   {
299      mIsValid = false;
300      return mIsValid;
301   }
302
303   SAFE_DELETE(mProcessedMaterial);
304   deleteAllHooks();
305   mIsValid = processMaterial();
306
307   if ( mIsValid )
308   {
309      for (U32 i = 0; i < mCurrentHandles.size(); i++)
310         mCurrentHandles[i]->loadHandle(mProcessedMaterial);
311
312      for (U32 i = 0; i < mCurrentParameters.size(); i++)
313         mCurrentParameters[i]->loadParameters(mProcessedMaterial);
314   }
315
316   return mIsValid;
317}
318
319//----------------------------------------------------------------------------
320// Process stages
321//----------------------------------------------------------------------------
322bool MatInstance::processMaterial()
323{
324   AssertFatal( mMaterial, "MatInstance::processMaterial - Got null material!" );
325   //AssertFatal( mVertexFormat, "MatInstance::processMaterial - Got null vertex format!" );
326   if ( !mMaterial || !mVertexFormat )   
327      return false;   
328
329   SAFE_DELETE(mDefaultParameters);
330
331   CustomMaterial *custMat = NULL;
332
333   if( dynamic_cast<CustomMaterial*>(mMaterial) )
334   {
335      F32 pixVersion = GFX->getPixelShaderVersion();
336      custMat = static_cast<CustomMaterial*>(mMaterial);
337      if ((custMat->mVersion > pixVersion) || (custMat->mVersion == 0.0))
338      {
339         if(custMat->mFallback)
340         {
341            mMaterial = custMat->mFallback;
342            return processMaterial();            
343         }
344         else
345         {            
346            AssertWarn(custMat->mVersion == 0.0f, avar("Can't load CustomMaterial %s for %s, using generic FF fallback", 
347               String(mMaterial->getName()).isEmpty() ? "Unknown" : mMaterial->getName(), custMat->mMapTo.c_str()));
348            mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);
349         }
350      }
351      else 
352         mProcessedMaterial = new ProcessedCustomMaterial(*mMaterial);
353   }
354   else if(GFX->getPixelShaderVersion() > 0.001)
355      mProcessedMaterial = getShaderMaterial();
356   else
357      mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);
358
359   if (mProcessedMaterial)
360   {
361      mProcessedMaterial->addStateBlockDesc( mUserDefinedState );
362      mProcessedMaterial->setShaderMacros( mUserMacros );
363      mProcessedMaterial->setUserObject( mUserObject );
364
365      FeatureSet features( mFeatureList );
366      features.exclude( MATMGR->getExclusionFeatures() );
367
368      if (mVertexFormat->hasBlendIndices() && TSShape::smUseHardwareSkinning)
369      {
370         features.addFeature( MFT_HardwareSkinning );
371      }
372      
373      if( !mProcessedMaterial->init(features, mVertexFormat, mFeaturesDelegate) )
374      {
375         Con::errorf( "Failed to initialize material '%s'", getMaterial()->getName() );
376         SAFE_DELETE( mProcessedMaterial );
377         return false;
378      }
379
380      mDefaultParameters = new MatInstParameters(mProcessedMaterial->getDefaultMaterialParameters());
381      mActiveParameters = mDefaultParameters;
382
383      const FeatureSet &finalFeatures = mProcessedMaterial->getFeatures();
384      mHasNormalMaps = finalFeatures.hasFeature( MFT_NormalMap );
385      mUsesHardwareSkinning = finalFeatures.hasFeature( MFT_HardwareSkinning );
386
387      mIsForwardLit =   (  custMat && custMat->mForwardLit ) || 
388                        (  !finalFeatures.hasFeature( MFT_IsEmissive ) &&
389                           finalFeatures.hasFeature( MFT_ForwardShading ) );
390
391      mIsHardwareSkinned = finalFeatures.hasFeature( MFT_HardwareSkinning );
392
393      return true;
394   }
395   
396   return false;
397}
398
399const MatStateHint& MatInstance::getStateHint() const
400{
401   if ( mProcessedMaterial )
402      return mProcessedMaterial->getStateHint();
403   else
404      return MatStateHint::Default;
405}
406
407ProcessedMaterial* MatInstance::getShaderMaterial()
408{
409   return new ProcessedShaderMaterial(*mMaterial);
410}
411
412void MatInstance::addStateBlockDesc(const GFXStateBlockDesc& desc)
413{   
414   mUserDefinedState = desc;
415}
416
417void MatInstance::updateStateBlocks()
418{
419   if ( mProcessedMaterial )
420      mProcessedMaterial->updateStateBlocks();
421}
422
423void MatInstance::addShaderMacro( const String &name, const String &value )
424{   
425   // Check to see if we already have this macro.
426   Vector<GFXShaderMacro>::iterator iter = mUserMacros.begin();
427   for ( ; iter != mUserMacros.end(); iter++ )
428   {
429      if ( iter->name == name )
430      {
431         iter->value = value;
432         return;
433      }
434   }
435
436   // Add a new macro.
437   mUserMacros.increment();
438   mUserMacros.last().name = name;
439   mUserMacros.last().value = value;
440}
441
442//----------------------------------------------------------------------------
443// Setup pass - needs scenegraph data because the lightmap will change across
444//    several materials.
445//----------------------------------------------------------------------------
446bool MatInstance::setupPass(SceneRenderState * state, const SceneData &sgData )
447{
448   PROFILE_SCOPE( MatInstance_SetupPass );
449   
450   if( !mProcessedMaterial )
451      return false;
452
453   ++mCurPass;
454
455   if ( !mProcessedMaterial->setupPass( state, sgData, mCurPass ) )
456   {
457      mCurPass = -1;
458      return false;
459   }
460
461   return true;
462}
463
464void MatInstance::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state)
465{
466   PROFILE_SCOPE(MatInstance_setTransforms);
467   mProcessedMaterial->setTransforms(matrixSet, state, getCurPass());
468}
469
470void MatInstance::setNodeTransforms(const MatrixF *address, const U32 numTransforms)
471{
472   PROFILE_SCOPE(MatInstance_setNodeTransforms);
473   mProcessedMaterial->setNodeTransforms(address, numTransforms, getCurPass());
474}
475
476void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData)
477{
478   PROFILE_SCOPE(MatInstance_setSceneInfo);
479   mProcessedMaterial->setSceneInfo(state, sgData, getCurPass());
480}
481
482void MatInstance::setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer)
483{
484   mProcessedMaterial->setBuffers(vertBuffer, primBuffer);
485}
486
487void MatInstance::setTextureStages(SceneRenderState * state, const SceneData &sgData )
488{
489   PROFILE_SCOPE(MatInstance_setTextureStages);
490   mProcessedMaterial->setTextureStages(state, sgData, getCurPass());
491}
492
493bool MatInstance::isInstanced() const 
494{
495   return mProcessedMaterial->getFeatures().hasFeature( MFT_UseInstancing );
496}
497
498bool MatInstance::stepInstance()
499{
500   AssertFatal( isInstanced(), "MatInstance::stepInstance - This material isn't instanced!" );
501   AssertFatal( mCurPass >= 0, "MatInstance::stepInstance - Must be within material setup pass!" );
502
503   return mProcessedMaterial->stepInstance();
504}
505
506U32 MatInstance::getCurStageNum()
507{
508   return mProcessedMaterial->getStageFromPass(getCurPass());
509}
510
511RenderPassData* MatInstance::getPass(U32 pass)
512{
513   return mProcessedMaterial->getPass(pass);
514}
515
516bool MatInstance::hasGlow() 
517{ 
518   if( mProcessedMaterial )
519      return mProcessedMaterial->hasGlow(); 
520   else
521      return false;
522}
523
524bool MatInstance::hasAccumulation() 
525{ 
526   if( mProcessedMaterial )
527      return mProcessedMaterial->hasAccumulation(); 
528   else
529      return false;
530}
531
532const FeatureSet& MatInstance::getFeatures() const 
533{
534   return mProcessedMaterial->getFeatures(); 
535}
536
537MaterialParameterHandle* MatInstance::getMaterialParameterHandle(const String& name)
538{
539   AssertFatal(mProcessedMaterial, "Not init'ed!"); 
540   for (U32 i = 0; i < mCurrentHandles.size(); i++)
541   {
542      if (mCurrentHandles[i]->getName().equal(name))
543      {
544         return mCurrentHandles[i];
545      }
546   }
547   MatInstanceParameterHandle* mph = new MatInstanceParameterHandle(name);
548   mph->loadHandle(mProcessedMaterial);
549   mCurrentHandles.push_back(mph);
550   return mph;
551}
552
553MaterialParameters* MatInstance::allocMaterialParameters() 
554{  
555   AssertFatal(mProcessedMaterial, "Not init'ed!"); 
556   MatInstParameters* mip = new MatInstParameters();
557   mip->loadParameters(mProcessedMaterial);
558   mCurrentParameters.push_back(mip);
559   return mip;   
560}
561
562void MatInstance::setMaterialParameters(MaterialParameters* param) 
563{ 
564   AssertFatal(mProcessedMaterial, "Not init'ed!"); 
565   mProcessedMaterial->setMaterialParameters(param, mCurPass);
566   AssertFatal(dynamic_cast<MatInstParameters*>(param), "Incorrect param type!");
567   mActiveParameters = static_cast<MatInstParameters*>(param);
568}
569
570MaterialParameters* MatInstance::getMaterialParameters()
571{ 
572   AssertFatal(mProcessedMaterial, "Not init'ed!"); 
573   return mActiveParameters;
574}
575
576void MatInstance::dumpShaderInfo() const
577{
578   if ( mMaterial == NULL )
579   {
580      Con::errorf( "Trying to get Material information on an invalid MatInstance" );
581      return;
582   }
583
584   Con::printf( "Material Info for object %s - %s", mMaterial->getName(), mMaterial->mMapTo.c_str() );
585
586   if ( mProcessedMaterial == NULL )
587   {
588      Con::printf( "  [no processed material!]" );
589      return;
590   }
591
592   mProcessedMaterial->dumpMaterialInfo();
593}
594