processedShaderMaterial.cpp
Engine/source/materials/processedShaderMaterial.cpp
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