Torque3D Documentation / _generateds / processedShaderMaterial.cpp

processedShaderMaterial.cpp

Engine/source/materials/processedShaderMaterial.cpp

More...

Detailed Description

   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/processedShaderMaterial.h"
  26
  27#include "core/util/safeDelete.h"
  28#include "gfx/sim/cubemapData.h"
  29#include "gfx/gfxShader.h"
  30#include "gfx/genericConstBuffer.h"
  31#include "gfx/gfxPrimitiveBuffer.h"
  32#include "scene/sceneRenderState.h"
  33#include "shaderGen/shaderFeature.h"
  34#include "shaderGen/shaderGenVars.h"
  35#include "shaderGen/featureMgr.h"
  36#include "shaderGen/shaderGen.h"
  37#include "materials/sceneData.h"
  38#include "materials/materialFeatureTypes.h"
  39#include "materials/materialManager.h"
  40#include "materials/shaderMaterialParameters.h"
  41#include "materials/matTextureTarget.h"
  42#include "gfx/util/screenspace.h"
  43#include "math/util/matrixSet.h"
  44
  45#include "renderInstance/renderProbeMgr.h"
  46
  47#include "ts/tsRenderState.h"
  48
  49// We need to include customMaterialDefinition for ShaderConstHandles::init
  50#include "materials/customMaterialDefinition.h"
  51
  52#include "gui/controls/guiTreeViewCtrl.h"
  53#include "ts/tsShape.h"
  54
  55///
  56/// ShaderConstHandles
  57///
  58void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/)
  59{
  60   mDiffuseColorSC = shader->getShaderConstHandle("$diffuseMaterialColor");
  61   mTexMatSC = shader->getShaderConstHandle(ShaderGenVars::texMat);
  62   mToneMapTexSC = shader->getShaderConstHandle(ShaderGenVars::toneMap);
  63   mORMConfigSC = shader->getShaderConstHandle(ShaderGenVars::ormConfig);
  64   mRoughnessSC = shader->getShaderConstHandle(ShaderGenVars::roughness);
  65   mMetalnessSC = shader->getShaderConstHandle(ShaderGenVars::metalness);
  66   mGlowMulSC = shader->getShaderConstHandle(ShaderGenVars::glowMul);
  67   mAccuScaleSC = shader->getShaderConstHandle("$accuScale");
  68   mAccuDirectionSC = shader->getShaderConstHandle("$accuDirection");
  69   mAccuStrengthSC = shader->getShaderConstHandle("$accuStrength");
  70   mAccuCoverageSC = shader->getShaderConstHandle("$accuCoverage");
  71   mAccuSpecularSC = shader->getShaderConstHandle("$accuSpecular");
  72   mParallaxInfoSC = shader->getShaderConstHandle("$parallaxInfo");
  73   mFogDataSC = shader->getShaderConstHandle(ShaderGenVars::fogData);
  74   mFogColorSC = shader->getShaderConstHandle(ShaderGenVars::fogColor);
  75   mDetailScaleSC = shader->getShaderConstHandle(ShaderGenVars::detailScale);
  76   mVisiblitySC = shader->getShaderConstHandle(ShaderGenVars::visibility);
  77   mColorMultiplySC = shader->getShaderConstHandle(ShaderGenVars::colorMultiply);
  78   mAlphaTestValueSC = shader->getShaderConstHandle(ShaderGenVars::alphaTestValue);
  79   mModelViewProjSC = shader->getShaderConstHandle(ShaderGenVars::modelview);
  80   mWorldViewOnlySC = shader->getShaderConstHandle(ShaderGenVars::worldViewOnly);
  81   mWorldToCameraSC = shader->getShaderConstHandle(ShaderGenVars::worldToCamera);
  82   mCameraToWorldSC = shader->getShaderConstHandle(ShaderGenVars::cameraToWorld);
  83   mWorldToObjSC = shader->getShaderConstHandle(ShaderGenVars::worldToObj);
  84   mViewToObjSC = shader->getShaderConstHandle(ShaderGenVars::viewToObj);
  85   mInvCameraTransSC = shader->getShaderConstHandle(ShaderGenVars::invCameraTrans);
  86   mCameraToScreenSC = shader->getShaderConstHandle(ShaderGenVars::cameraToScreen);
  87   mScreenToCameraSC = shader->getShaderConstHandle(ShaderGenVars::screenToCamera);
  88   mCubeTransSC = shader->getShaderConstHandle(ShaderGenVars::cubeTrans);
  89   mCubeMipsSC = shader->getShaderConstHandle(ShaderGenVars::cubeMips);
  90   mObjTransSC = shader->getShaderConstHandle(ShaderGenVars::objTrans);
  91   mCubeEyePosSC = shader->getShaderConstHandle(ShaderGenVars::cubeEyePos);
  92   mEyePosSC = shader->getShaderConstHandle(ShaderGenVars::eyePos);
  93   mEyePosWorldSC = shader->getShaderConstHandle(ShaderGenVars::eyePosWorld);
  94   m_vEyeSC = shader->getShaderConstHandle(ShaderGenVars::vEye);
  95   mEyeMatSC = shader->getShaderConstHandle(ShaderGenVars::eyeMat);
  96   mOneOverFarplane = shader->getShaderConstHandle(ShaderGenVars::oneOverFarplane);
  97   mAccumTimeSC = shader->getShaderConstHandle(ShaderGenVars::accumTime);
  98   mMinnaertConstantSC = shader->getShaderConstHandle(ShaderGenVars::minnaertConstant);
  99   mSubSurfaceParamsSC = shader->getShaderConstHandle(ShaderGenVars::subSurfaceParams);
 100   mDiffuseAtlasParamsSC = shader->getShaderConstHandle(ShaderGenVars::diffuseAtlasParams);
 101   mDiffuseAtlasTileSC = shader->getShaderConstHandle(ShaderGenVars::diffuseAtlasTileParams);
 102   mBumpAtlasParamsSC = shader->getShaderConstHandle(ShaderGenVars::bumpAtlasParams);
 103   mBumpAtlasTileSC = shader->getShaderConstHandle(ShaderGenVars::bumpAtlasTileParams);
 104   mRTSizeSC = shader->getShaderConstHandle( "$targetSize" );
 105   mOneOverRTSizeSC = shader->getShaderConstHandle( "$oneOverTargetSize" );
 106   mDetailBumpStrength = shader->getShaderConstHandle( "$detailBumpStrength" );
 107   mViewProjSC = shader->getShaderConstHandle( "$viewProj" );
 108
 109   // MFT_ImposterVert
 110   mImposterUVs = shader->getShaderConstHandle( "$imposterUVs" );
 111   mImposterLimits = shader->getShaderConstHandle( "$imposterLimits" );
 112
 113   for (S32 i = 0; i < GFX_TEXTURE_STAGE_COUNT; ++i)
 114      mRTParamsSC[i] = shader->getShaderConstHandle( String::ToString( "$rtParams%d", i ) );
 115
 116   // MFT_HardwareSkinning
 117   mNodeTransforms = shader->getShaderConstHandle( "$nodeTransforms" );
 118
 119   // Clear any existing texture handles.
 120   dMemset( mTexHandlesSC, 0, sizeof( mTexHandlesSC ) );
 121   if(mat)
 122   {
 123      for (S32 i = 0; i < Material::MAX_TEX_PER_PASS; ++i)
 124         mTexHandlesSC[i] = shader->getShaderConstHandle(mat->mSamplerNames[i]);
 125   }
 126
 127   // Deferred Shading
 128   mMatInfoFlagsSC = shader->getShaderConstHandle(ShaderGenVars::matInfoFlags);
 129}
 130
 131///
 132/// ShaderRenderPassData
 133///
 134void ShaderRenderPassData::reset()
 135{
 136   Parent::reset();
 137
 138   shader = NULL;
 139
 140   for ( U32 i=0; i < featureShaderHandles.size(); i++ )
 141      delete featureShaderHandles[i];
 142
 143   featureShaderHandles.clear();
 144}
 145
 146String ShaderRenderPassData::describeSelf() const
 147{
 148   // First write the shader identification.
 149   String desc = String::ToString( "%s\n", shader->describeSelf().c_str() );
 150
 151   // Let the parent get the rest.
 152   desc += Parent::describeSelf();
 153
 154   return desc;
 155}
 156
 157///
 158/// ProcessedShaderMaterial
 159///
 160ProcessedShaderMaterial::ProcessedShaderMaterial()
 161   :  mDefaultParameters( NULL ),
 162      mInstancingState( NULL )
 163{
 164   VECTOR_SET_ASSOCIATION( mShaderConstDesc );
 165   VECTOR_SET_ASSOCIATION( mParameterHandles );
 166}
 167
 168ProcessedShaderMaterial::ProcessedShaderMaterial(Material &mat)
 169   :  mDefaultParameters( NULL ),
 170      mInstancingState( NULL )
 171{
 172   VECTOR_SET_ASSOCIATION( mShaderConstDesc );
 173   VECTOR_SET_ASSOCIATION( mParameterHandles );
 174   mMaterial = &mat;
 175}
 176
 177ProcessedShaderMaterial::~ProcessedShaderMaterial()
 178{
 179   SAFE_DELETE(mInstancingState);
 180   SAFE_DELETE(mDefaultParameters);
 181   for (U32 i = 0; i < mParameterHandles.size(); i++)
 182      SAFE_DELETE(mParameterHandles[i]);
 183}
 184
 185//
 186// Material init
 187//
 188bool ProcessedShaderMaterial::init( const FeatureSet &features, 
 189                                    const GFXVertexFormat *vertexFormat,
 190                                    const MatFeaturesDelegate &featuresDelegate )
 191{
 192   // Load our textures
 193   _setStageData();
 194
 195   // Determine how many stages we use
 196   mMaxStages = getNumStages(); 
 197   mVertexFormat = vertexFormat;
 198   mFeatures.clear();
 199   mStateHint.clear();
 200   SAFE_DELETE(mInstancingState);
 201
 202   for( U32 i=0; i<mMaxStages; i++ )
 203   {
 204      MaterialFeatureData fd;
 205
 206      // Determine the features of this stage
 207      _determineFeatures( i, fd, features );
 208   
 209      // Let the delegate poke at the features.
 210      if ( featuresDelegate )
 211         featuresDelegate( this, i, fd, features );
 212
 213      // Create the passes for this stage
 214      if ( fd.features.isNotEmpty() )
 215         if( !_createPasses( fd, i, features ) )
 216            return false;
 217   }
 218
 219   _initRenderPassDataStateBlocks();
 220   _initMaterialParameters();
 221   mDefaultParameters =  allocMaterialParameters();
 222   setMaterialParameters( mDefaultParameters, 0 );
 223   mStateHint.init( this );   
 224
 225   // Enable instancing if we have it.
 226   if ( mFeatures.hasFeature( MFT_UseInstancing ) )
 227   {
 228      mInstancingState = new InstancingState();
 229      mInstancingState->setFormat( _getRPD( 0 )->shader->getInstancingFormat(), mVertexFormat );
 230   }
 231   if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr(0, 1).equal("#"))
 232   {
 233      String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1);
 234      NamedTexTarget *texTarget = NamedTexTarget::find(texTargetBufferName);
 235      RenderPassData* rpd = getPass(0);
 236
 237      if (rpd)
 238      {
 239         rpd->mTexSlot[0].texTarget = texTarget;
 240         rpd->mTexType[0] = Material::TexTarget;
 241         rpd->mSamplerNames[0] = "diffuseMap";
 242      }
 243   }
 244   return true;
 245}
 246
 247U32 ProcessedShaderMaterial::getNumStages()
 248{
 249   // Loops through all stages to determine how many 
 250   // stages we actually use.  
 251   // 
 252   // The first stage is always active else we shouldn't be
 253   // creating the material to begin with.
 254   U32 numStages = 1;
 255
 256   U32 i;
 257   for( i=1; i<Material::MAX_STAGES; i++ )
 258   {
 259      // Assume stage is inactive
 260      bool stageActive = false;
 261
 262      // Cubemaps only on first stage
 263      if( i == 0 )
 264      {
 265         // If we have a cubemap the stage is active
 266         if( mMaterial->mCubemapData || mMaterial->mDynamicCubemap )
 267         {
 268            numStages++;
 269            continue;
 270         }
 271      }
 272
 273      // If we have a texture for the a feature the 
 274      // stage is active.
 275      if ( mStages[i].hasValidTex() )
 276         stageActive = true;
 277      
 278      // If this stage has diffuse color, it's active
 279      if (  mMaterial->mDiffuse[i].alpha > 0 &&
 280            mMaterial->mDiffuse[i] != LinearColorF::WHITE )
 281         stageActive = true;
 282
 283      // If we have a Material that is vertex lit
 284      // then it may not have a texture
 285      if( mMaterial->mVertLit[i] )
 286         stageActive = true;
 287
 288      // Increment the number of active stages
 289      numStages += stageActive;
 290   }
 291
 292   return numStages;
 293}
 294
 295void ProcessedShaderMaterial::_determineFeatures(  U32 stageNum, 
 296                                                   MaterialFeatureData &fd, 
 297                                                   const FeatureSet &features )
 298{
 299   PROFILE_SCOPE( ProcessedShaderMaterial_DetermineFeatures );
 300
 301   const F32 shaderVersion = GFX->getPixelShaderVersion();
 302   AssertFatal(shaderVersion > 0.0 , "Cannot create a shader material if we don't support shaders");
 303
 304   bool lastStage = stageNum == (mMaxStages-1);
 305
 306   // First we add all the features which the 
 307   // material has defined.
 308   if (mMaterial->mInvertRoughness[stageNum])
 309      fd.features.addFeature(MFT_InvertRoughness);
 310
 311   if ( mMaterial->isTranslucent() )
 312   {
 313      // Note: This is for decal blending into the deferred
 314      // for AL... it probably needs to be made clearer.
 315      if (  mMaterial->mTranslucentBlendOp == Material::LerpAlpha &&
 316            mMaterial->mTranslucentZWrite )
 317         fd.features.addFeature( MFT_IsTranslucentZWrite );
 318      else
 319      {
 320         fd.features.addFeature( MFT_IsTranslucent );
 321         fd.features.addFeature( MFT_ForwardShading );
 322      }
 323   }
 324
 325   // TODO: This sort of sucks... BL should somehow force this
 326   // feature on from the outside and not this way.
 327   if (String::compare(LIGHTMGR->getId(), "BLM") == 0)
 328   {
 329      fd.features.addFeature(MFT_ForwardShading);
 330      fd.features.addFeature(MFT_ReflectionProbes);
 331   }
 332
 333   // Disabling the InterlacedDeferred feature for now. It is not ready for prime-time
 334   // and it should not be triggered off of the DoubleSided parameter. [2/5/2010 Pat]
 335   /*if ( mMaterial->isDoubleSided() )
 336   {
 337      fd.features.addFeature( MFT_InterlacedDeferred );
 338   }*/
 339
 340   // Allow instancing if it was requested and the card supports
 341   // SM 3.0 or above.
 342   //
 343   // We also disable instancing for non-single pass materials
 344   // and glowing materials because its untested/unimplemented.
 345   //
 346   if (  features.hasFeature( MFT_UseInstancing ) &&
 347         mMaxStages == 1 &&
 348         !mMaterial->mGlow[0] &&
 349         shaderVersion >= 3.0f )
 350      fd.features.addFeature( MFT_UseInstancing );
 351
 352   if ( mMaterial->mAlphaTest )
 353      fd.features.addFeature( MFT_AlphaTest );
 354
 355   if (mMaterial->mEmissive[stageNum])
 356   {
 357      fd.features.addFeature(MFT_IsEmissive);
 358   }
 359   else
 360   {
 361      fd.features.addFeature(MFT_RTLighting);
 362     if (mMaterial->isTranslucent())
 363        fd.features.addFeature(MFT_ReflectionProbes);
 364   }
 365
 366   if ( mMaterial->mAnimFlags[stageNum] )
 367      fd.features.addFeature( MFT_TexAnim );  
 368
 369   if ( mMaterial->mVertLit[stageNum] )
 370      fd.features.addFeature( MFT_VertLit );
 371   
 372   // cubemaps only available on stage 0 for now - bramage   
 373   if ( stageNum < 1 && mMaterial->isTranslucent() &&
 374         (  (  mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) ||
 375               mMaterial->mDynamicCubemap ) && !features.hasFeature(MFT_ReflectionProbes))
 376   {
 377       fd.features.addFeature( MFT_CubeMap );
 378   }
 379
 380   fd.features.addFeature( MFT_Visibility );
 381
 382   if (  lastStage && 
 383         (  !gClientSceneGraph->usePostEffectFog() ||
 384            fd.features.hasFeature( MFT_IsTranslucent ) ||
 385            fd.features.hasFeature( MFT_ForwardShading )) )
 386      fd.features.addFeature( MFT_Fog );
 387
 388   if ( mMaterial->mMinnaertConstant[stageNum] > 0.0f )
 389      fd.features.addFeature( MFT_MinnaertShading );
 390
 391   if ( mMaterial->mSubSurface[stageNum] )
 392      fd.features.addFeature( MFT_SubSurface );
 393
 394   if ( !mMaterial->mCellLayout[stageNum].isZero() )
 395   {
 396      fd.features.addFeature( MFT_DiffuseMapAtlas );
 397
 398      if ( mMaterial->mNormalMapAtlas )
 399         fd.features.addFeature( MFT_NormalMapAtlas );
 400   }
 401
 402   if (!fd.features.hasFeature(MFT_ForwardShading))
 403   {
 404      fd.features.removeFeature(MFT_DebugViz);
 405   }
 406
 407   // Grab other features like normal maps, base texture, etc.
 408   FeatureSet mergeFeatures;
 409   mStages[stageNum].getFeatureSet( &mergeFeatures );
 410   fd.features.merge( mergeFeatures );
 411   
 412   if ( fd.features[ MFT_NormalMap ] )   
 413   {   
 414      if (  mStages[stageNum].getTex( MFT_NormalMap )->mFormat == GFXFormatBC3 &&   
 415           !mStages[stageNum].getTex( MFT_NormalMap )->mHasTransparency )   
 416         fd.features.addFeature( MFT_IsBC3nm );
 417      else if ( mStages[stageNum].getTex(MFT_NormalMap)->mFormat == GFXFormatBC5 &&
 418            !mStages[stageNum].getTex(MFT_NormalMap)->mHasTransparency )
 419         fd.features.addFeature( MFT_IsBC5nm );
 420   }
 421
 422   // Now for some more advanced features that we 
 423   // cannot do on SM 2.0 and below.
 424   if ( shaderVersion > 2.0f )
 425   {
 426
 427      if (  mMaterial->mParallaxScale[stageNum] > 0.0f &&
 428         fd.features[ MFT_NormalMap ] )
 429         fd.features.addFeature( MFT_Parallax );
 430   }
 431
 432   // Deferred Shading : PBR Config
 433   if (mStages[stageNum].getTex(MFT_OrmMap))
 434   {
 435      fd.features.addFeature(MFT_OrmMap);
 436   }
 437   else
 438      fd.features.addFeature(MFT_ORMConfigVars);
 439
 440   // Deferred Shading : Material Info Flags
 441   fd.features.addFeature(MFT_MatInfoFlags);
 442
 443   if (features.hasFeature(MFT_isBackground))
 444   {
 445      fd.features.addFeature(MFT_isBackground);
 446   }
 447   if (features.hasFeature(MFT_SkyBox))
 448   {
 449      fd.features.addFeature(MFT_StaticCubemap);
 450      fd.features.addFeature(MFT_CubeMap);
 451      fd.features.addFeature(MFT_SkyBox);
 452
 453      fd.features.removeFeature(MFT_ReflectionProbes);
 454      fd.features.removeFeature(MFT_ORMConfigVars);
 455      fd.features.removeFeature(MFT_MatInfoFlags);
 456   }
 457
 458   if ( mMaterial->mAccuEnabled[stageNum] )
 459   {
 460      mHasAccumulation = true;
 461   }
 462
 463   // we need both diffuse and normal maps + sm3 to have an accu map
 464   if(   fd.features[ MFT_AccuMap ] && 
 465       ( !fd.features[ MFT_DiffuseMap ] || 
 466         !fd.features[ MFT_NormalMap ] ||
 467         GFX->getPixelShaderVersion() < 3.0f ) ) {
 468      AssertWarn(false, "SAHARA: Using an Accu Map requires SM 3.0 and a normal map.");
 469      fd.features.removeFeature( MFT_AccuMap );
 470      mHasAccumulation = false;
 471   }
 472   
 473   // Without a base texture use the diffuse color
 474   // feature to ensure some sort of output.
 475   if (!fd.features[MFT_DiffuseMap])
 476   {
 477      fd.features.addFeature( MFT_DiffuseColor );
 478
 479      // No texture coords... no overlay.
 480      fd.features.removeFeature( MFT_OverlayMap );
 481   }
 482
 483   // If we have a diffuse map and the alpha on the diffuse isn't
 484   // zero and the color isn't pure white then multiply the color.
 485   else if (   mMaterial->mDiffuse[stageNum].alpha > 0.0f && 
 486               mMaterial->mDiffuse[stageNum] != LinearColorF::WHITE )
 487      fd.features.addFeature( MFT_DiffuseColor );
 488
 489   // If lightmaps or tonemaps are enabled or we 
 490   // don't have a second UV set then we cannot 
 491   // use the overlay texture.
 492   if (  fd.features[MFT_LightMap] || 
 493         fd.features[MFT_ToneMap] || 
 494         mVertexFormat->getTexCoordCount() < 2 )
 495      fd.features.removeFeature( MFT_OverlayMap );
 496
 497   // If tonemaps are enabled don't use lightmap
 498   if ( fd.features[MFT_ToneMap] || mVertexFormat->getTexCoordCount() < 2 )
 499      fd.features.removeFeature( MFT_LightMap );
 500
 501   // Don't allow tonemaps if we don't have a second UV set
 502   if ( mVertexFormat->getTexCoordCount() < 2 )
 503      fd.features.removeFeature( MFT_ToneMap );
 504
 505   // Always add the HDR output feature.  
 506   //
 507   // It will be filtered out if it was disabled 
 508   // for this material creation below.
 509   //
 510   // Also the shader code will evaluate to a nop
 511   // if HDR is not enabled in the scene.
 512   //
 513   fd.features.addFeature( MFT_HDROut );
 514
 515   fd.features.addFeature(MFT_DebugViz);
 516
 517   // If vertex color is enabled on the material's stage and
 518   // color is present in vertex format, add diffuse vertex
 519   // color feature.
 520   
 521   if (  mMaterial->mVertColor[ stageNum ] &&
 522         mVertexFormat->hasColor() )
 523      fd.features.addFeature( MFT_DiffuseVertColor );
 524
 525   // Allow features to add themselves.
 526   for ( U32 i = 0; i < FEATUREMGR->getFeatureCount(); i++ )
 527   {
 528      const FeatureInfo &info = FEATUREMGR->getAt( i );
 529      info.feature->determineFeature(  mMaterial, 
 530                                       mVertexFormat, 
 531                                       stageNum, 
 532                                       *info.type, 
 533                                       features, 
 534                                       &fd );
 535   }
 536
 537   // Need to add the Hardware Skinning feature if its used
 538   if ( features.hasFeature( MFT_HardwareSkinning ) )
 539   {
 540      fd.features.addFeature( MFT_HardwareSkinning );
 541   }
 542
 543   // Now disable any features that were 
 544   // not part of the input feature handle.
 545   fd.features.filter( features );
 546}
 547
 548bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, U32 stageNum, const FeatureSet &features )
 549{
 550   // Creates passes for the given stage
 551   ShaderRenderPassData passData;
 552   U32 texIndex = 0;
 553
 554   for( U32 featureIDx=0; featureIDx < FEATUREMGR->getFeatureCount(); featureIDx++ )
 555   {
 556      const FeatureInfo &info = FEATUREMGR->getAt(featureIDx);
 557      if ( !stageFeatures.features.hasFeature( *info.type ) ) 
 558         continue;
 559
 560      U32 numTexReg = info.feature->getResources( stageFeatures ).numTexReg;
 561
 562      // adds pass if blend op changes for feature
 563      _setPassBlendOp( info.feature, passData, texIndex, stageFeatures, stageNum, features );
 564
 565      // Add pass if num tex reg is going to be too high
 566      if( passData.mNumTexReg + numTexReg > GFX->getNumSamplers() )
 567      {
 568         if( !_addPass( passData, texIndex, stageFeatures, stageNum, features ) )
 569            return false;
 570         _setPassBlendOp( info.feature, passData, texIndex, stageFeatures, stageNum, features );
 571      }
 572
 573      passData.mNumTexReg += numTexReg;
 574      passData.mFeatureData.features.addFeature( *info.type );
 575
 576#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
 577      U32 oldTexNumber = texIndex;
 578#endif
 579
 580      info.feature->setTexData( mStages[stageNum], stageFeatures, passData, texIndex );
 581
 582#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
 583      if(oldTexNumber != texIndex)
 584      {
 585         for(int texNum = oldTexNumber; texNum < texIndex; texNum++)
 586         {
 587            AssertFatal(passData.mSamplerNames[ oldTexNumber ].isNotEmpty(), avar( "ERROR: ShaderGen feature %s don't set used sampler name", info.feature->getName().c_str()) );
 588         }
 589      }
 590#endif
 591
 592      // Add pass if tex units are maxed out
 593      if( texIndex > GFX->getNumSamplers() )
 594      {
 595         if( !_addPass( passData, texIndex, stageFeatures, stageNum, features ) )
 596            return false;
 597         _setPassBlendOp( info.feature, passData, texIndex, stageFeatures, stageNum, features );
 598      }
 599   }
 600
 601#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
 602   for(int samplerIDx = 0; samplerIDx < texIndex; samplerIDx++)
 603   {
 604      AssertFatal(passData.mSamplerNames[samplerIDx].isNotEmpty(),"");
 605   }
 606#endif
 607
 608   const FeatureSet &passFeatures = passData.mFeatureData.codify();
 609   if ( passFeatures.isNotEmpty() )
 610   {
 611      mFeatures.merge( passFeatures );
 612      if(  !_addPass( passData, texIndex, stageFeatures, stageNum, features ) )
 613      {
 614         mFeatures.clear();
 615         return false;
 616      }
 617   }
 618
 619   return true;
 620} 
 621
 622void ProcessedShaderMaterial::_initMaterialParameters()
 623{   
 624   // Cleanup anything left first.
 625   SAFE_DELETE( mDefaultParameters );
 626   for ( U32 i = 0; i < mParameterHandles.size(); i++ )
 627      SAFE_DELETE( mParameterHandles[i] );
 628
 629   // Gather the shaders as they all need to be 
 630   // passed to the ShaderMaterialParameterHandles.
 631   Vector<GFXShader*> shaders;
 632   shaders.setSize( mPasses.size() );
 633   for ( U32 i = 0; i < mPasses.size(); i++ )
 634      shaders[i] = _getRPD(i)->shader;
 635
 636   // Run through each shader and prepare its constants.
 637   for ( U32 i = 0; i < mPasses.size(); i++ )
 638   {
 639      const Vector<GFXShaderConstDesc>& desc = shaders[i]->getShaderConstDesc();
 640
 641      Vector<GFXShaderConstDesc>::const_iterator p = desc.begin();
 642      for ( ; p != desc.end(); p++ )
 643      {
 644         // Add this to our list of shader constants
 645         GFXShaderConstDesc d(*p);
 646         mShaderConstDesc.push_back(d);
 647
 648         ShaderMaterialParameterHandle* smph = new ShaderMaterialParameterHandle(d.name, shaders);
 649         mParameterHandles.push_back(smph);
 650      }
 651   }
 652}
 653
 654bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd, 
 655                                       U32 &texIndex, 
 656                                       MaterialFeatureData &fd,
 657                                       U32 stageNum,
 658                                       const FeatureSet &features )
 659{
 660   // Set number of textures, stage, glow, etc.
 661   rpd.mNumTex = texIndex;
 662   rpd.mStageNum = stageNum;
 663   rpd.mGlow |= mMaterial->mGlow[stageNum];
 664
 665   // Copy over features
 666   rpd.mFeatureData.materialFeatures = fd.features;
 667
 668   Vector<String> samplers;
 669   samplers.setSize(Material::MAX_TEX_PER_PASS);
 670   for(int i = 0; i < Material::MAX_TEX_PER_PASS; ++i)
 671   {
 672      samplers[i] = (rpd.mSamplerNames[i].isEmpty() || rpd.mSamplerNames[i][0] == '$') ? rpd.mSamplerNames[i] : "$" + rpd.mSamplerNames[i];
 673   }
 674
 675   // Generate shader
 676   GFXShader::setLogging( true, true );
 677   rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros, samplers );
 678   if( !rpd.shader )
 679      return false;
 680   rpd.shaderHandles.init( rpd.shader );
 681
 682   // If a pass glows, we glow
 683   if( rpd.mGlow )
 684      mHasGlow = true;
 685 
 686   ShaderRenderPassData *newPass = new ShaderRenderPassData( rpd );
 687   mPasses.push_back( newPass );
 688
 689   //initSamplerHandles
 690   ShaderConstHandles *handles = _getShaderConstHandles( mPasses.size()-1 );
 691   AssertFatal(handles,"");
 692   for(int i = 0; i < rpd.mNumTex; i++)
 693   { 
 694      if(rpd.mSamplerNames[i].isEmpty())
 695      {
 696         handles->mTexHandlesSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString );
 697         handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString );
 698         continue;
 699      }
 700
 701      String samplerName = rpd.mSamplerNames[i];
 702      if( !samplerName.startsWith("$"))
 703         samplerName.insert(0, "$");
 704
 705      GFXShaderConstHandle *handle = newPass->shader->getShaderConstHandle( samplerName ); 
 706
 707      handles->mTexHandlesSC[i] = handle;
 708      handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::ToString( "$rtParams%s", samplerName.c_str()+1 ) ); 
 709      
 710      AssertFatal( handle,"");
 711   }
 712
 713   // Give each active feature a chance to create specialized shader consts.
 714   for( U32 i=0; i < FEATUREMGR->getFeatureCount(); i++ )
 715   {
 716      const FeatureInfo &info = FEATUREMGR->getAt( i );
 717      if ( !fd.features.hasFeature( *info.type ) ) 
 718         continue;
 719
 720      ShaderFeatureConstHandles *fh = info.feature->createConstHandles( rpd.shader, mUserObject );
 721      if ( fh )
 722         newPass->featureShaderHandles.push_back( fh );
 723   }
 724
 725   rpd.reset();
 726   texIndex = 0;
 727   
 728   return true;
 729}
 730
 731void ProcessedShaderMaterial::_setPassBlendOp( ShaderFeature *sf,
 732                                              ShaderRenderPassData &passData,
 733                                              U32 &texIndex,
 734                                              MaterialFeatureData &stageFeatures,
 735                                              U32 stageNum,
 736                                              const FeatureSet &features )
 737{
 738   if( sf->getBlendOp() == Material::None )
 739   {
 740      return;
 741   }
 742
 743   // set up the current blend operation for multi-pass materials
 744   if( mPasses.size() > 0)
 745   {
 746      // If passData.numTexReg is 0, this is a brand new pass, so set the
 747      // blend operation to the first feature.
 748      if( passData.mNumTexReg == 0 )
 749      {
 750         passData.mBlendOp = sf->getBlendOp();
 751      }
 752      else
 753      {
 754         // numTegReg is more than zero, if this feature
 755         // doesn't have the same blend operation, then
 756         // we need to create yet another pass 
 757         if( sf->getBlendOp() != passData.mBlendOp && mPasses[mPasses.size()-1]->mStageNum == stageNum)
 758         {
 759            _addPass( passData, texIndex, stageFeatures, stageNum, features );
 760            passData.mBlendOp = sf->getBlendOp();
 761         }
 762      }
 763   }
 764} 
 765
 766//
 767// Runtime / rendering
 768//
 769bool ProcessedShaderMaterial::setupPass( SceneRenderState *state, const SceneData &sgData, U32 pass )
 770{
 771   PROFILE_SCOPE( ProcessedShaderMaterial_SetupPass );
 772
 773   // Make sure we have the pass
 774   if(pass >= mPasses.size())
 775   {
 776      // If we were rendering instanced data tell
 777      // the device to reset that vb stream.
 778      if ( mInstancingState )
 779         GFX->setVertexBuffer( NULL, 1 );
 780
 781      return false;
 782   }
 783
 784   _setRenderState( state, sgData, pass );
 785
 786   // Set shaders
 787   ShaderRenderPassData* rpd = _getRPD(pass);
 788   if( rpd->shader )
 789   {
 790      GFX->setShader( rpd->shader );
 791      GFX->setShaderConstBuffer(_getShaderConstBuffer(pass));      
 792      _setShaderConstants(state, sgData, pass);      
 793
 794      // If we're instancing then do the initial step to get
 795      // set the vb pointer to the const buffer.
 796      if ( mInstancingState )
 797         stepInstance();
 798   }
 799   else
 800   {
 801      GFX->setupGenericShaders();
 802      GFX->setShaderConstBuffer(NULL);
 803   } 
 804
 805   // Set our textures
 806   setTextureStages( state, sgData, pass );
 807   _setTextureTransforms(pass);
 808
 809   return true;
 810}
 811
 812void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const SceneData &sgData, U32 pass )
 813{
 814   PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages );
 815
 816   ShaderConstHandles *handles = _getShaderConstHandles(pass);
 817   AssertFatal(handles,"");
 818
 819   // Set all of the textures we need to render the give pass.
 820#ifdef TORQUE_DEBUG
 821   AssertFatal( pass<mPasses.size(), "Pass out of bounds" );
 822#endif
 823
 824   RenderPassData *rpd = mPasses[pass];
 825   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
 826   NamedTexTarget *texTarget;
 827   GFXTextureObject *texObject; 
 828
 829   for( U32 i=0; i<rpd->mNumTex; i++ )
 830   {
 831      U32 currTexFlag = rpd->mTexType[i];
 832      if (!LIGHTMGR || !LIGHTMGR->setTextureStage(sgData, currTexFlag, i, shaderConsts, handles))
 833      {
 834         switch( currTexFlag )
 835         {
 836         // If the flag is unset then assume its just
 837         // a regular texture to set... nothing special.
 838         case 0:
 839         default:
 840            GFX->setTexture(i, rpd->mTexSlot[i].texObject);
 841            break;
 842
 843         case Material::NormalizeCube:
 844            GFX->setCubeTexture(i, Material::GetNormalizeCube());
 845            break;
 846
 847         case Material::Lightmap:
 848            GFX->setTexture( i, sgData.lightmap );
 849            break;
 850
 851         case Material::ToneMapTex:
 852            shaderConsts->setSafe(handles->mToneMapTexSC, (S32)i);
 853            GFX->setTexture(i, rpd->mTexSlot[i].texObject);
 854            break;
 855
 856         case Material::Cube:
 857            GFX->setCubeTexture( i, rpd->mCubeMap );
 858            break;
 859
 860         case Material::SGCube:
 861            GFX->setCubeTexture( i, sgData.cubemap );
 862            break;
 863
 864         case Material::BackBuff:
 865            GFX->setTexture( i, sgData.backBuffTex );
 866            break;
 867
 868         case Material::AccuMap:
 869            if ( sgData.accuTex )
 870               GFX->setTexture( i, sgData.accuTex );
 871            else
 872               GFX->setTexture( i, GFXTexHandle::ZERO );
 873            break;
 874            
 875         case Material::TexTarget:
 876            {
 877               texTarget = rpd->mTexSlot[i].texTarget;
 878               if ( !texTarget )
 879               {
 880                  GFX->setTexture( i, NULL );
 881                  break;
 882               }
 883            
 884               texObject = texTarget->getTexture();
 885
 886               // If no texture is available then map the default 2x2
 887               // black texture to it.  This at least will ensure that
 888               // we get consistant behavior across GPUs and platforms.
 889               if ( !texObject )
 890                  texObject = GFXTexHandle::ZERO;
 891
 892               if ( handles->mRTParamsSC[i]->isValid() && texObject )
 893               {
 894                  const Point3I &targetSz = texObject->getSize();
 895                  const RectI &targetVp = texTarget->getViewport();
 896                  Point4F rtParams;
 897
 898                  ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
 899
 900                  shaderConsts->set(handles->mRTParamsSC[i], rtParams);
 901               }
 902
 903               GFX->setTexture( i, texObject );
 904               break;
 905            }
 906         }
 907      }
 908   }
 909}
 910
 911void ProcessedShaderMaterial::_setTextureTransforms(const U32 pass)
 912{
 913   PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureTransforms );
 914
 915   ShaderConstHandles* handles = _getShaderConstHandles(pass);
 916   if (handles->mTexMatSC->isValid())
 917   {   
 918      MatrixF texMat( true );
 919
 920      mMaterial->updateTimeBasedParams();
 921      F32 waveOffset = _getWaveOffset( pass ); // offset is between 0.0 and 1.0
 922
 923      // handle scroll anim type
 924      if(  mMaterial->mAnimFlags[pass] & Material::Scroll )
 925      {
 926         if( mMaterial->mAnimFlags[pass] & Material::Wave )
 927         {
 928            Point3F scrollOffset;
 929            scrollOffset.x = mMaterial->mScrollDir[pass].x * waveOffset;
 930            scrollOffset.y = mMaterial->mScrollDir[pass].y * waveOffset;
 931            scrollOffset.z = 1.0;
 932
 933            texMat.setColumn( 3, scrollOffset );
 934         }
 935         else
 936         {
 937            Point3F offset( mMaterial->mScrollOffset[pass].x, 
 938               mMaterial->mScrollOffset[pass].y, 
 939               1.0 );
 940
 941            texMat.setColumn( 3, offset );
 942         }
 943
 944      }
 945
 946      // handle rotation
 947      if( mMaterial->mAnimFlags[pass] & Material::Rotate )
 948      {
 949         if( mMaterial->mAnimFlags[pass] & Material::Wave )
 950         {
 951            F32 rotPos = waveOffset * M_2PI;
 952            texMat.set( EulerF( 0.0, 0.0, rotPos ) );
 953            texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) );
 954
 955            MatrixF test( true );
 956            test.setColumn( 3, Point3F( mMaterial->mRotPivotOffset[pass].x, 
 957               mMaterial->mRotPivotOffset[pass].y,
 958               0.0 ) );
 959            texMat.mul( test );
 960         }
 961         else
 962         {
 963            texMat.set( EulerF( 0.0, 0.0, mMaterial->mRotPos[pass] ) );
 964
 965            texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) );
 966
 967            MatrixF test( true );
 968            test.setColumn( 3, Point3F( mMaterial->mRotPivotOffset[pass].x, 
 969               mMaterial->mRotPivotOffset[pass].y,
 970               0.0 ) );
 971            texMat.mul( test );
 972         }
 973      }
 974
 975      // Handle scale + wave offset
 976      if(  mMaterial->mAnimFlags[pass] & Material::Scale &&
 977         mMaterial->mAnimFlags[pass] & Material::Wave )
 978      {
 979         F32 wOffset = fabs( waveOffset );
 980
 981         texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) );
 982
 983         MatrixF temp( true );
 984         temp.setRow( 0, Point3F( wOffset,  0.0,  0.0 ) );
 985         temp.setRow( 1, Point3F( 0.0,  wOffset,  0.0 ) );
 986         temp.setRow( 2, Point3F( 0.0,  0.0,  wOffset ) );
 987         temp.setColumn( 3, Point3F( -wOffset * 0.5, -wOffset * 0.5, 0.0 ) );
 988         texMat.mul( temp );
 989      }
 990
 991      // handle sequence
 992      if( mMaterial->mAnimFlags[pass] & Material::Sequence )
 993      {
 994         U32 frameNum = (U32)(MATMGR->getTotalTime() * mMaterial->mSeqFramePerSec[pass]);
 995         F32 offset = frameNum * mMaterial->mSeqSegSize[pass];
 996
 997         if ( mMaterial->mAnimFlags[pass] & Material::Scale )
 998            texMat.scale( Point3F( mMaterial->mSeqSegSize[pass], 1.0f, 1.0f ) );
 999
1000         Point3F texOffset = texMat.getPosition();
1001         texOffset.x += offset;
1002         texMat.setPosition( texOffset );
1003      }
1004
1005      GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1006      shaderConsts->setSafe(handles->mTexMatSC, texMat);
1007   }
1008}
1009
1010//--------------------------------------------------------------------------
1011// Get wave offset for texture animations using a wave transform
1012//--------------------------------------------------------------------------
1013F32 ProcessedShaderMaterial::_getWaveOffset( U32 stage )
1014{
1015   switch( mMaterial->mWaveType[stage] )
1016   {
1017   case Material::Sin:
1018      {
1019         return mMaterial->mWaveAmp[stage] * mSin( M_2PI * mMaterial->mWavePos[stage] );
1020         break;
1021      }
1022
1023   case Material::Triangle:
1024      {
1025         F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] );
1026         if( frac > 0.0 && frac <= 0.25 )
1027         {
1028            return mMaterial->mWaveAmp[stage] * frac * 4.0;
1029         }
1030
1031         if( frac > 0.25 && frac <= 0.5 )
1032         {
1033            return mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.25)*4.0) );
1034         }
1035
1036         if( frac > 0.5 && frac <= 0.75 )
1037         {
1038            return mMaterial->mWaveAmp[stage] * (frac-0.5) * -4.0;
1039         }
1040
1041         if( frac > 0.75 && frac <= 1.0 )
1042         {
1043            return -mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.75)*4.0) );
1044         }
1045
1046         break;
1047      }
1048
1049   case Material::Square:
1050      {
1051         F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] );
1052         if( frac > 0.0 && frac <= 0.5 )
1053         {
1054            return 0.0;
1055         }
1056         else
1057         {
1058            return mMaterial->mWaveAmp[stage];
1059         }
1060         break;
1061      }
1062
1063   }
1064
1065   return 0.0;
1066}
1067
1068void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, const SceneData &sgData, U32 pass)
1069{
1070   PROFILE_SCOPE( ProcessedShaderMaterial_SetShaderConstants );
1071
1072   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1073   ShaderConstHandles* handles = _getShaderConstHandles(pass);
1074   U32 stageNum = getStageFromPass(pass);
1075
1076   // First we do all the constants which are not
1077   // controlled via the material... we have to
1078   // set these all the time as they could change.
1079
1080   if ( handles->mFogDataSC->isValid() )
1081   {
1082      Point3F fogData;
1083      fogData.x = sgData.fogDensity;
1084      fogData.y = sgData.fogDensityOffset;
1085      fogData.z = sgData.fogHeightFalloff;     
1086      shaderConsts->set( handles->mFogDataSC, fogData );
1087   }
1088
1089   shaderConsts->setSafe(handles->mFogColorSC, sgData.fogColor);
1090
1091   if( handles->mOneOverFarplane->isValid() )
1092   {
1093      const F32 &invfp = 1.0f / state->getFarPlane();
1094      Point4F oneOverFP(invfp, invfp, invfp, invfp);
1095      shaderConsts->set( handles->mOneOverFarplane, oneOverFP );
1096   }
1097
1098   shaderConsts->setSafe( handles->mAccumTimeSC, MATMGR->getTotalTime() );
1099
1100   // If the shader constants have not been lost then
1101   // they contain the content from a previous render pass.
1102   //
1103   // In this case we can skip updating the material constants
1104   // which do not change frame to frame.
1105   //
1106   // NOTE: This assumes we're not animating material parameters
1107   // in a way that doesn't cause a shader reload... this isn't
1108   // being done now, but it could change in the future.
1109   // 
1110   if ( !shaderConsts->wasLost() )
1111      return;
1112
1113   shaderConsts->setSafe(handles->mRoughnessSC, mMaterial->mRoughness[stageNum]);
1114   shaderConsts->setSafe(handles->mMetalnessSC, mMaterial->mMetalness[stageNum]);
1115   shaderConsts->setSafe(handles->mGlowMulSC, mMaterial->mGlowMul[stageNum]);
1116
1117   shaderConsts->setSafe(handles->mParallaxInfoSC, mMaterial->mParallaxScale[stageNum]);   
1118   shaderConsts->setSafe(handles->mMinnaertConstantSC, mMaterial->mMinnaertConstant[stageNum]);
1119
1120   if ( handles->mSubSurfaceParamsSC->isValid() )
1121   {
1122      Point4F subSurfParams;
1123      dMemcpy( &subSurfParams, &mMaterial->mSubSurfaceColor[stageNum], sizeof(LinearColorF) );
1124      subSurfParams.w = mMaterial->mSubSurfaceRolloff[stageNum];
1125      shaderConsts->set(handles->mSubSurfaceParamsSC, subSurfParams);
1126   }
1127
1128   if ( handles->mRTSizeSC->isValid() )
1129   {
1130      const Point2I &resolution = GFX->getActiveRenderTarget()->getSize();
1131      Point2F pixelShaderConstantData;
1132
1133      pixelShaderConstantData.x = resolution.x;
1134      pixelShaderConstantData.y = resolution.y;
1135
1136      shaderConsts->set( handles->mRTSizeSC, pixelShaderConstantData );
1137   }
1138
1139   if ( handles->mOneOverRTSizeSC->isValid() )
1140   {
1141      const Point2I &resolution = GFX->getActiveRenderTarget()->getSize();
1142      Point2F oneOverTargetSize( 1.0f / (F32)resolution.x, 1.0f / (F32)resolution.y );
1143
1144      shaderConsts->set( handles->mOneOverRTSizeSC, oneOverTargetSize );
1145   }
1146
1147   // set detail scale
1148   shaderConsts->setSafe(handles->mDetailScaleSC, mMaterial->mDetailScale[stageNum]);
1149   shaderConsts->setSafe(handles->mDetailBumpStrength, mMaterial->mDetailNormalMapStrength[stageNum]);
1150
1151   // MFT_ImposterVert
1152   if ( handles->mImposterUVs->isValid() )
1153   {
1154      U32 uvCount = getMin( mMaterial->mImposterUVs.size(), 64 ); // See imposter.hlsl   
1155      AlignedArray<Point4F> imposterUVs( uvCount, sizeof( Point4F ), (U8*)mMaterial->mImposterUVs.address(), false );
1156      shaderConsts->set( handles->mImposterUVs, imposterUVs );
1157   }
1158   shaderConsts->setSafe( handles->mImposterLimits, mMaterial->mImposterLimits );
1159
1160   // Diffuse
1161   shaderConsts->setSafe(handles->mDiffuseColorSC, mMaterial->mDiffuse[stageNum]);
1162
1163   shaderConsts->setSafe( handles->mAlphaTestValueSC, mClampF( (F32)mMaterial->mAlphaRef / 255.0f, 0.0f, 1.0f ) );      
1164
1165   if(handles->mDiffuseAtlasParamsSC)
1166   {
1167      Point4F atlasParams(1.0f / mMaterial->mCellLayout[stageNum].x, // 1 / num_horizontal
1168         1.0f / mMaterial->mCellLayout[stageNum].y, // 1 / num_vertical
1169         mMaterial->mCellSize[stageNum],            // tile size in pixels
1170         getBinLog2(mMaterial->mCellSize[stageNum]) );    // pow of 2 of tile size in pixels 2^9 = 512, 2^10=1024 etc
1171      shaderConsts->setSafe(handles->mDiffuseAtlasParamsSC, atlasParams);
1172   }
1173
1174   if(handles->mBumpAtlasParamsSC)
1175   {
1176      Point4F atlasParams(1.0f / mMaterial->mCellLayout[stageNum].x, // 1 / num_horizontal
1177         1.0f / mMaterial->mCellLayout[stageNum].y, // 1 / num_vertical
1178         mMaterial->mCellSize[stageNum],            // tile size in pixels
1179         getBinLog2(mMaterial->mCellSize[stageNum]) );    // pow of 2 of tile size in pixels 2^9 = 512, 2^10=1024 etc
1180      shaderConsts->setSafe(handles->mBumpAtlasParamsSC, atlasParams);
1181   }
1182
1183   if(handles->mDiffuseAtlasTileSC)
1184   {
1185      // Sanity check the wrap flags
1186      //AssertWarn(mMaterial->mTextureAddressModeU == mMaterial->mTextureAddressModeV, "Addresing mode mismatch, texture atlasing will be confused");
1187      Point4F atlasTileParams( mMaterial->mCellIndex[stageNum].x, // Tile co-ordinate, ie: [0, 3]
1188         mMaterial->mCellIndex[stageNum].y, 
1189         0.0f, 0.0f ); // TODO: Wrap mode flags?
1190      shaderConsts->setSafe(handles->mDiffuseAtlasTileSC, atlasTileParams);
1191   }
1192
1193   if(handles->mBumpAtlasTileSC)
1194   {
1195      // Sanity check the wrap flags
1196      //AssertWarn(mMaterial->mTextureAddressModeU == mMaterial->mTextureAddressModeV, "Addresing mode mismatch, texture atlasing will be confused");
1197      Point4F atlasTileParams( mMaterial->mCellIndex[stageNum].x, // Tile co-ordinate, ie: [0, 3]
1198         mMaterial->mCellIndex[stageNum].y, 
1199         0.0f, 0.0f ); // TODO: Wrap mode flags?
1200      shaderConsts->setSafe(handles->mBumpAtlasTileSC, atlasTileParams);
1201   }
1202
1203   // Deferred Shading: Determine Material Info Flags
1204   S32 matInfoFlags = 
1205            (mMaterial->mEmissive[stageNum] ? 1 : 0) | //emissive
1206            (mMaterial->mSubSurface[stageNum] ? 2 : 0); //subsurface
1207   mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f;
1208   shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]);   
1209   if( handles->mAccuScaleSC->isValid() )
1210      shaderConsts->set( handles->mAccuScaleSC, mMaterial->mAccuScale[stageNum] );
1211   if( handles->mAccuDirectionSC->isValid() )
1212      shaderConsts->set( handles->mAccuDirectionSC, mMaterial->mAccuDirection[stageNum] );
1213   if( handles->mAccuStrengthSC->isValid() )
1214      shaderConsts->set( handles->mAccuStrengthSC, mMaterial->mAccuStrength[stageNum] );
1215   if( handles->mAccuCoverageSC->isValid() )
1216      shaderConsts->set( handles->mAccuCoverageSC, mMaterial->mAccuCoverage[stageNum] );
1217   if( handles->mAccuSpecularSC->isValid() )
1218      shaderConsts->set( handles->mAccuSpecularSC, mMaterial->mAccuSpecular[stageNum] );
1219}
1220
1221bool ProcessedShaderMaterial::_hasCubemap(U32 pass)
1222{
1223   // Only support cubemap on the first stage
1224   if( mPasses[pass]->mStageNum > 0 )
1225      return false;
1226
1227   if( mPasses[pass]->mCubeMap )
1228      return true;
1229
1230   return false;
1231}
1232
1233void ProcessedShaderMaterial::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass)
1234{
1235   PROFILE_SCOPE( ProcessedShaderMaterial_setTransforms );
1236
1237   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1238   ShaderConstHandles* handles = _getShaderConstHandles(pass);
1239
1240   // The MatrixSet will lazily generate a matrix under the
1241   // various 'get' methods, so inline the test for a valid
1242   // shader constant handle to avoid that work when we can.
1243   if ( handles->mModelViewProjSC->isValid() )
1244      shaderConsts->set( handles->mModelViewProjSC, matrixSet.getWorldViewProjection() );
1245   if ( handles->mObjTransSC->isValid() )
1246      shaderConsts->set( handles->mObjTransSC, matrixSet.getObjectToWorld() );      
1247   if ( handles->mWorldToObjSC->isValid() )
1248      shaderConsts->set( handles->mWorldToObjSC, matrixSet.getWorldToObject() );
1249   if ( handles->mWorldToCameraSC->isValid() )
1250      shaderConsts->set( handles->mWorldToCameraSC, matrixSet.getWorldToCamera() );
1251   if (handles->mCameraToWorldSC->isValid())
1252      shaderConsts->set(handles->mCameraToWorldSC, matrixSet.getCameraToWorld());
1253   if ( handles->mWorldViewOnlySC->isValid() )
1254      shaderConsts->set( handles->mWorldViewOnlySC, matrixSet.getObjectToCamera() );
1255   if ( handles->mViewToObjSC->isValid() )
1256      shaderConsts->set( handles->mViewToObjSC, matrixSet.getCameraToObject() );
1257   if ( handles->mViewProjSC->isValid() )
1258      shaderConsts->set( handles->mViewProjSC, matrixSet.getWorldToScreen() );
1259
1260   if (  handles->mCubeTransSC->isValid() &&
1261         ( _hasCubemap(pass) || mMaterial->mDynamicCubemap ) )
1262   {
1263      // TODO: Could we not remove this constant?  Use mObjTransSC and cast to float3x3 instead?
1264      shaderConsts->set(handles->mCubeTransSC, matrixSet.getObjectToWorld(), GFXSCT_Float3x3);
1265   }
1266
1267   if ( handles->m_vEyeSC->isValid() )
1268      shaderConsts->set( handles->m_vEyeSC, state->getVectorEye() );
1269}
1270
1271void ProcessedShaderMaterial::setNodeTransforms(const MatrixF *transforms, const U32 transformCount, const U32 pass)
1272{
1273   PROFILE_SCOPE( ProcessedShaderMaterial_setNodeTransforms );
1274
1275   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1276   ShaderConstHandles* handles = _getShaderConstHandles(pass);
1277
1278   if ( handles->mNodeTransforms->isValid() )
1279   {
1280      S32 realTransformCount = getMin( transformCount, TSShape::smMaxSkinBones );
1281      shaderConsts->set( handles->mNodeTransforms, transforms, realTransformCount, GFXSCT_Float4x3 );
1282   }
1283}
1284
1285void ProcessedShaderMaterial::setCustomShaderData(Vector<CustomShaderBindingData> &shaderData, const U32 pass)
1286{
1287   PROFILE_SCOPE(ProcessedShaderMaterial_setCustomShaderData);
1288
1289   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1290   ShaderConstHandles* handles = _getShaderConstHandles(pass);
1291
1292   for (U32 i = 0; i < shaderData.size(); i++)
1293   {
1294      for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
1295      {
1296         StringTableEntry handleName = shaderData[i].getHandleName();
1297         bool tmp = true;
1298      }
1299      //roll through and try setting our data!
1300      for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
1301      {
1302         StringTableEntry handleName = shaderData[i].getHandleName();
1303         StringTableEntry rpdHandleName = handles->mCustomHandles[h].handleName;
1304         if (handles->mCustomHandles[h].handleName == shaderData[i].getHandleName())
1305         {
1306            if (handles->mCustomHandles[h].handle->isValid())
1307            {
1308               CustomShaderBindingData::UniformType type = shaderData[i].getType();
1309
1310               if (type == CustomShaderBindingData::Float)
1311                  shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat());
1312               else if (type == CustomShaderBindingData::Float2)
1313                  shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat2());
1314               else if (type == CustomShaderBindingData::Float3)
1315                  shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat3());
1316               else if (type == CustomShaderBindingData::Float4)
1317                  shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat4());
1318               break;
1319            }
1320         }
1321      }
1322   }
1323}
1324
1325void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass)
1326{
1327   PROFILE_SCOPE(ProcessedShaderMaterial_setSceneInfo);
1328
1329   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
1330   ShaderConstHandles* handles = _getShaderConstHandles(pass);
1331
1332   // Set cubemap stuff here (it's convenient!)
1333   const Point3F &eyePosWorld = state->getCameraPosition();
1334   if (_hasCubemap(pass) || mMaterial->mDynamicCubemap)
1335   {
1336      if (handles->mCubeEyePosSC->isValid())
1337      {
1338         Point3F cubeEyePos = eyePosWorld - sgData.objTrans->getPosition();
1339         shaderConsts->set(handles->mCubeEyePosSC, cubeEyePos);
1340      }
1341   }
1342   if (sgData.cubemap)
1343      shaderConsts->setSafe(handles->mCubeMipsSC, (F32)sgData.cubemap->getMipMapLevels());
1344   else
1345      shaderConsts->setSafe(handles->mCubeMipsSC, 1.0f);
1346
1347   shaderConsts->setSafe(handles->mVisiblitySC, sgData.visibility);
1348
1349   shaderConsts->setSafe(handles->mEyePosWorldSC, eyePosWorld);   
1350
1351   if ( handles->mEyePosSC->isValid() )
1352   {
1353      MatrixF tempMat( *sgData.objTrans );
1354      tempMat.inverse();
1355      Point3F eyepos;
1356      tempMat.mulP( eyePosWorld, &eyepos );
1357      shaderConsts->set(handles->mEyePosSC, eyepos);   
1358   }
1359
1360   shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform());
1361
1362   ShaderRenderPassData *rpd = _getRPD(pass);
1363   for (U32 i = 0; i < rpd->featureShaderHandles.size(); i++)
1364      rpd->featureShaderHandles[i]->setConsts(state, sgData, shaderConsts);
1365
1366   LIGHTMGR->setLightInfo(this, mMaterial, sgData, state, pass, shaderConsts);
1367
1368   PROBEMGR->setProbeInfo(this, mMaterial, sgData, state, pass, shaderConsts);
1369}
1370
1371void ProcessedShaderMaterial::setBuffers( GFXVertexBufferHandleBase *vertBuffer, GFXPrimitiveBufferHandle *primBuffer )
1372{
1373   PROFILE_SCOPE(ProcessedShaderMaterial_setBuffers);
1374
1375   // If we're not instanced then just call the parent.
1376   if ( !mInstancingState )
1377   {
1378      Parent::setBuffers( vertBuffer, primBuffer );
1379      return;
1380   }
1381
1382   PROFILE_SCOPE(ProcessedShaderMaterial_setBuffers_instancing);
1383
1384   const S32 instCount = mInstancingState->getCount();
1385   AssertFatal( instCount > 0,
1386      "ProcessedShaderMaterial::setBuffers - No instances rendered!" );
1387
1388   // Nothing special here.
1389   GFX->setPrimitiveBuffer( *primBuffer );
1390
1391   // Set the first stream the the normal VB and set the
1392   // correct frequency for the number of instances to render.
1393   GFX->setVertexBuffer( *vertBuffer, 0, instCount );
1394
1395   // Get a volatile VB and fill it with the vertex data.
1396   const GFXVertexFormat *instFormat = mInstancingState->getFormat();
1397   GFXVertexBufferDataHandle instVB;
1398   instVB.set( GFX, instFormat->getSizeInBytes(), instFormat, instCount, GFXBufferTypeVolatile );
1399   U8 *dest = instVB.lock();
1400   if(!dest) return;
1401   dMemcpy( dest, mInstancingState->getBuffer(), instFormat->getSizeInBytes() * instCount );
1402   instVB.unlock();
1403
1404   // Set the instance vb for streaming.
1405   GFX->setVertexBuffer( instVB, 1, 1 );
1406
1407   // Finally set the vertex format which defines
1408   // both of the streams.
1409   GFX->setVertexFormat( mInstancingState->getDeclFormat() );
1410
1411   // Done... reset the count.
1412   mInstancingState->resetStep();
1413}
1414
1415bool ProcessedShaderMaterial::stepInstance()
1416{
1417   PROFILE_SCOPE(ProcessedShaderMaterial_stepInstance);
1418   AssertFatal( mInstancingState, "ProcessedShaderMaterial::stepInstance - This material isn't instanced!" );  
1419   return mInstancingState->step( &_getShaderConstBuffer( 0 )->mInstPtr );
1420}
1421
1422MaterialParameters* ProcessedShaderMaterial::allocMaterialParameters()
1423{
1424   ShaderMaterialParameters* smp = new ShaderMaterialParameters();
1425   Vector<GFXShaderConstBufferRef> buffers( __FILE__, __LINE__ );
1426   buffers.setSize(mPasses.size());
1427   for (U32 i = 0; i < mPasses.size(); i++)
1428      buffers[i] = _getRPD(i)->shader->allocConstBuffer();
1429   // smp now owns these buffers.
1430   smp->setBuffers(mShaderConstDesc, buffers);
1431   return smp;   
1432}
1433
1434MaterialParameterHandle* ProcessedShaderMaterial::getMaterialParameterHandle(const String& name)
1435{
1436   // Search our list
1437   for (U32 i = 0; i < mParameterHandles.size(); i++)
1438   {
1439      if (mParameterHandles[i]->getName().equal(name))
1440         return mParameterHandles[i];
1441   }
1442   
1443   // If we didn't find it, we have to add it to support shader reloading.
1444
1445   Vector<GFXShader*> shaders;
1446   shaders.setSize(mPasses.size());
1447   for (U32 i = 0; i < mPasses.size(); i++)
1448      shaders[i] = _getRPD(i)->shader;
1449
1450   ShaderMaterialParameterHandle* smph = new ShaderMaterialParameterHandle( name, shaders );
1451   mParameterHandles.push_back(smph);
1452
1453   return smph;
1454}
1455
1456/// This is here to deal with the differences between ProcessedCustomMaterials and ProcessedShaderMaterials.
1457GFXShaderConstBuffer* ProcessedShaderMaterial::_getShaderConstBuffer( const U32 pass )
1458{   
1459   if (mCurrentParams && pass < mPasses.size())
1460   {
1461      return static_cast<ShaderMaterialParameters*>(mCurrentParams)->getBuffer(pass);
1462   }
1463   return NULL;
1464}
1465
1466ShaderConstHandles* ProcessedShaderMaterial::_getShaderConstHandles(const U32 pass)
1467{
1468   if (pass < mPasses.size())
1469   {
1470      return &_getRPD(pass)->shaderHandles;
1471   }
1472   return NULL;
1473}
1474
1475void ProcessedShaderMaterial::dumpMaterialInfo()
1476{
1477   for ( U32 i = 0; i < getNumPasses(); i++ )
1478   {
1479      const ShaderRenderPassData *passData = _getRPD( i );
1480
1481      if ( passData == NULL )
1482         continue;
1483
1484      const GFXShader      *shader = passData->shader;
1485
1486      if ( shader == NULL )
1487         Con::printf( "  [%i] [NULL shader]", i );
1488      else
1489         Con::printf( "  [%i] %s", i, shader->describeSelf().c_str() );
1490   }
1491}
1492
1493void ProcessedShaderMaterial::getMaterialInfo(GuiTreeViewCtrl* tree, U32 item)
1494{
1495   for (U32 i = 0; i < getNumPasses(); i++)
1496   {
1497      const ShaderRenderPassData* passData = _getRPD(i);
1498
1499      if (passData == NULL)
1500         continue;
1501
1502      char passStr[64];
1503      dSprintf(passStr, 64, "Pass Number: %i", i);
1504
1505      U32 passItem = tree->insertItem(item, passStr);
1506
1507      const GFXShader * shader = passData->shader;
1508
1509      if (shader == NULL)
1510         tree->insertItem(passItem, "[NULL shader]");
1511      else
1512         tree->insertItem(passItem, shader->describeSelf().c_str());
1513   }
1514}
1515