processedFFMaterial.cpp
Engine/source/materials/processedFFMaterial.cpp
Classes:
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/processedFFMaterial.h" 26 27#include "gfx/sim/cubemapData.h" 28#include "materials/sceneData.h" 29#include "materials/customMaterialDefinition.h" 30#include "materials/materialFeatureTypes.h" 31#include "gfx/sim/gfxStateBlockData.h" 32#include "gfx/gfxDevice.h" 33#include "gfx/genericConstBuffer.h" 34#include "materials/materialParameters.h" 35#include "lighting/lightInfo.h" 36#include "scene/sceneRenderState.h" 37#include "core/util/safeDelete.h" 38#include "math/util/matrixSet.h" 39 40class FFMaterialParameterHandle : public MaterialParameterHandle 41{ 42public: 43 virtual ~FFMaterialParameterHandle() {} 44 virtual const String& getName() const { return mName; } 45 virtual bool isValid() const { return false; } 46 virtual S32 getSamplerRegister( U32 pass ) const { return -1; } 47private: 48 String mName; 49}; 50 51ProcessedFFMaterial::ProcessedFFMaterial() 52{ 53 VECTOR_SET_ASSOCIATION( mParamDesc ); 54 55 _construct(); 56} 57 58ProcessedFFMaterial::ProcessedFFMaterial(Material &mat, const bool isLightingMaterial) 59{ 60 VECTOR_SET_ASSOCIATION( mParamDesc ); 61 62 _construct(); 63 mMaterial = &mat; 64 mIsLightingMaterial = isLightingMaterial; 65} 66 67void ProcessedFFMaterial::_construct() 68{ 69 mHasSetStageData = false; 70 mHasGlow = false; 71 mHasAccumulation = false; 72 mIsLightingMaterial = false; 73 mDefaultHandle = new FFMaterialParameterHandle(); 74 mDefaultParameters = new MaterialParameters(); 75 mCurrentParams = mDefaultParameters; 76} 77 78ProcessedFFMaterial::~ProcessedFFMaterial() 79{ 80 SAFE_DELETE(mDefaultParameters); 81 SAFE_DELETE( mDefaultHandle ); 82} 83 84void ProcessedFFMaterial::_createPasses( U32 stageNum, const FeatureSet &features ) 85{ 86 FixedFuncFeatureData featData; 87 _determineFeatures(stageNum, featData, features); 88 // Just create a simple pass! 89 _addPass(0, featData); 90 91 mFeatures.clear(); 92 if ( featData.features[FixedFuncFeatureData::DiffuseMap] ) 93 mFeatures.addFeature( MFT_DiffuseMap ); 94 if ( featData.features[FixedFuncFeatureData::LightMap] ) 95 mFeatures.addFeature( MFT_LightMap ); 96 if ( featData.features[FixedFuncFeatureData::ToneMap] ) 97 mFeatures.addFeature( MFT_ToneMap ); 98 99} 100 101void ProcessedFFMaterial::_determineFeatures( U32 stageNum, 102 FixedFuncFeatureData& featData, 103 const FeatureSet &features ) 104{ 105 if ( mStages[stageNum].getTex( MFT_DiffuseMap ) ) 106 featData.features[FixedFuncFeatureData::DiffuseMap] = true; 107 108 if ( features.hasFeature( MFT_LightMap ) ) 109 featData.features[FixedFuncFeatureData::LightMap] = true; 110 if ( features.hasFeature( MFT_ToneMap )) 111 featData.features[FixedFuncFeatureData::ToneMap] = true; 112} 113 114U32 ProcessedFFMaterial::getNumStages() 115{ 116 // Loops through all stages to determine how many stages we actually use 117 U32 numStages = 0; 118 119 U32 i; 120 for( i=0; i<Material::MAX_STAGES; i++ ) 121 { 122 // Assume stage is inactive 123 bool stageActive = false; 124 125 // Cubemaps only on first stage 126 if( i == 0 ) 127 { 128 // If we have a cubemap the stage is active 129 if( mMaterial->mCubemapData || mMaterial->mDynamicCubemap ) 130 { 131 numStages++; 132 continue; 133 } 134 } 135 136 // If we have a texture for the a feature the 137 // stage is active. 138 if ( mStages[i].hasValidTex() ) 139 stageActive = true; 140 141 // If this stage has specular lighting, it's active 142 if ( mMaterial->mPixelSpecular[i] ) 143 stageActive = true; 144 145 // If we have a Material that is vertex lit 146 // then it may not have a texture 147 if( mMaterial->mVertLit[i] ) 148 { 149 stageActive = true; 150 } 151 152 // Increment the number of active stages 153 numStages += stageActive; 154 } 155 156 157 return numStages; 158} 159 160bool ProcessedFFMaterial::setupPass( SceneRenderState *state, const SceneData &sgData, U32 pass ) 161{ 162 PROFILE_SCOPE( ProcessedFFMaterial_SetupPass ); 163 164 // Make sure we have a pass 165 if(pass >= mPasses.size()) 166 return false; 167 168 _setRenderState( state, sgData, pass ); 169 170 // Bind our textures 171 setTextureStages( state, sgData, pass ); 172 return true; 173} 174 175void ProcessedFFMaterial::setTextureStages(SceneRenderState * state, const SceneData& sgData, U32 pass) 176{ 177 // We may need to do some trickery in here for fixed function, this is just copy/paste from MatInstance 178#ifdef TORQUE_DEBUG 179 AssertFatal( pass<mPasses.size(), "Pass out of bounds" ); 180#endif 181 RenderPassData *rpd = mPasses[pass]; 182 for( U32 i=0; i<rpd->mNumTex; i++ ) 183 { 184 U32 currTexFlag = rpd->mTexType[i]; 185 if (!LIGHTMGR || !LIGHTMGR->setTextureStage(sgData, currTexFlag, i, NULL, NULL)) 186 { 187 switch( currTexFlag ) 188 { 189 case Material::NoTexture: 190 if (rpd->mTexSlot[i].texObject) 191 GFX->setTexture( i, rpd->mTexSlot[i].texObject ); 192 break; 193 194 case Material::NormalizeCube: 195 GFX->setCubeTexture(i, Material::GetNormalizeCube()); 196 break; 197 198 case Material::Lightmap: 199 GFX->setTexture( i, sgData.lightmap ); 200 break; 201 202 case Material::Cube: 203 // TODO: Is this right? 204 GFX->setTexture( i, rpd->mTexSlot[0].texObject ); 205 break; 206 207 case Material::SGCube: 208 // No cubemap support just yet 209 //GFX->setCubeTexture( i, sgData.cubemap ); 210 GFX->setTexture( i, rpd->mTexSlot[0].texObject ); 211 break; 212 213 case Material::BackBuff: 214 GFX->setTexture( i, sgData.backBuffTex ); 215 break; 216 } 217 } 218 } 219} 220 221MaterialParameters* ProcessedFFMaterial::allocMaterialParameters() 222{ 223 return new MaterialParameters(); 224} 225 226MaterialParameters* ProcessedFFMaterial::getDefaultMaterialParameters() 227{ 228 return mDefaultParameters; 229} 230 231MaterialParameterHandle* ProcessedFFMaterial::getMaterialParameterHandle(const String& name) 232{ 233 return mDefaultHandle; 234} 235 236void ProcessedFFMaterial::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass) 237{ 238 GFX->setWorldMatrix(matrixSet.getObjectToWorld()); 239 GFX->setViewMatrix(matrixSet.getWorldToCamera()); 240 GFX->setProjectionMatrix(matrixSet.getCameraToScreen()); 241} 242 243void ProcessedFFMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass) 244{ 245 _setPrimaryLightInfo(*sgData.objTrans, sgData.lights[0], pass); 246 _setSecondaryLightInfo(*sgData.objTrans, sgData.lights[1]); 247} 248 249void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightInfo* light, U32 pass) 250{ 251 // Just in case 252 GFX->setGlobalAmbientColor(ColorF(0.0f, 0.0f, 0.0f, 1.0f)); 253 if ( light->getType() == LightInfo::Ambient ) 254 { 255 // Ambient light 256 GFX->setGlobalAmbientColor( light->getAmbient() ); 257 return; 258 } 259 260 GFX->setLight(0, NULL); 261 GFX->setLight(1, NULL); 262 // This is a quick hack that lets us use FF lights 263 GFXLightMaterial lightMat; 264 lightMat.ambient = ColorF(1.0f, 1.0f, 1.0f, 1.0f); 265 lightMat.diffuse = ColorF(1.0f, 1.0f, 1.0f, 1.0f); 266 lightMat.emissive = ColorF(0.0f, 0.0f, 0.0f, 0.0f); 267 lightMat.specular = ColorF(0.0f, 0.0f, 0.0f, 0.0f); 268 lightMat.shininess = 128.0f; 269 GFX->setLightMaterial(lightMat); 270 271 // set object transform 272 MatrixF objTrans = _objTrans; 273 objTrans.inverse(); 274 275 // fill in primary light 276 //------------------------- 277 GFXLightInfo xlatedLight; 278 light->setGFXLight(&xlatedLight); 279 Point3F lightPos = light->getPosition(); 280 Point3F lightDir = light->getDirection(); 281 objTrans.mulP(lightPos); 282 objTrans.mulV(lightDir); 283 284 xlatedLight.mPos = lightPos; 285 xlatedLight.mDirection = lightDir; 286 287 GFX->setLight(0, &xlatedLight); 288} 289 290void ProcessedFFMaterial::_setSecondaryLightInfo(const MatrixF &_objTrans, LightInfo* light) 291{ 292 // set object transform 293 MatrixF objTrans = _objTrans; 294 objTrans.inverse(); 295 296 // fill in secondary light 297 //------------------------- 298 GFXLightInfo xlatedLight; 299 light->setGFXLight(&xlatedLight); 300 301 Point3F lightPos = light->getPosition(); 302 Point3F lightDir = light->getDirection(); 303 objTrans.mulP(lightPos); 304 objTrans.mulV(lightDir); 305 306 xlatedLight.mPos = lightPos; 307 xlatedLight.mDirection = lightDir; 308 309 GFX->setLight(1, &xlatedLight); 310} 311 312bool ProcessedFFMaterial::init( const FeatureSet &features, 313 const GFXVertexFormat *vertexFormat, 314 const MatFeaturesDelegate &featuresDelegate ) 315{ 316 TORQUE_UNUSED( vertexFormat ); 317 TORQUE_UNUSED( featuresDelegate ); 318 319 _setStageData(); 320 321 // Just create a simple pass 322 _createPasses(0, features); 323 _initRenderPassDataStateBlocks(); 324 mStateHint.init( this ); 325 326 return true; 327} 328 329void ProcessedFFMaterial::_addPass(U32 stageNum, FixedFuncFeatureData& featData) 330{ 331 U32 numTex = 0; 332 333 // Just creates a simple pass, but it can still glow! 334 RenderPassData rpd; 335 336 // Base texture, texunit 0 337 if(featData.features[FixedFuncFeatureData::DiffuseMap]) 338 { 339 rpd.mTexSlot[0].texObject = mStages[stageNum].getTex( MFT_DiffuseMap ); 340 rpd.mTexType[0] = Material::NoTexture; 341 numTex++; 342 } 343 344 // lightmap, texunit 1 345 if(featData.features[FixedFuncFeatureData::LightMap]) 346 { 347 rpd.mTexType[1] = Material::Lightmap; 348 numTex++; 349 } 350 351 rpd.mNumTex = numTex; 352 rpd.mStageNum = stageNum; 353 rpd.mGlow = false; 354 355 mPasses.push_back( new RenderPassData(rpd) ); 356} 357 358void ProcessedFFMaterial::_setPassBlendOp() 359{ 360 361} 362 363void ProcessedFFMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc &result ) 364{ 365 Parent::_initPassStateBlock( rpd, result ); 366 367 if ( mIsLightingMaterial ) 368 { 369 result.ffLighting = true; 370 result.blendDefined = true; 371 result.blendEnable = true; 372 result.blendSrc = GFXBlendOne; 373 result.blendDest = GFXBlendZero; 374 } 375 376 // This is here for generic FF shader fallbacks. 377 CustomMaterial* custmat = dynamic_cast<CustomMaterial*>(mMaterial); 378 if (custmat && custmat->getStateBlockData() ) 379 result.addDesc(custmat->getStateBlockData()->getState()); 380} 381
