terrCellMaterial.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "terrain/terrCellMaterial.h"
  24. #include "terrain/terrData.h"
  25. #include "terrain/terrCell.h"
  26. #include "materials/materialFeatureTypes.h"
  27. #include "materials/materialManager.h"
  28. #include "terrain/terrFeatureTypes.h"
  29. #include "terrain/terrMaterial.h"
  30. #include "renderInstance/renderDeferredMgr.h"
  31. #include "shaderGen/shaderGen.h"
  32. #include "shaderGen/featureMgr.h"
  33. #include "scene/sceneRenderState.h"
  34. #include "materials/sceneData.h"
  35. #include "gfx/util/screenspace.h"
  36. #include "lighting/advanced/advancedLightBinManager.h"
  37. S32 sgMaxTerrainMaterialsPerPass = 3;
  38. AFTER_MODULE_INIT( MaterialManager )
  39. {
  40. Con::NotifyDelegate callabck( &TerrainCellMaterial::_updateDefaultAnisotropy );
  41. Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
  42. }
  43. Vector<TerrainCellMaterial*> TerrainCellMaterial::smAllMaterials;
  44. Vector<String> _initSamplerNames()
  45. {
  46. Vector<String> samplerNames;
  47. samplerNames.push_back("$baseTexMap");
  48. samplerNames.push_back("$layerTex");
  49. samplerNames.push_back("$macrolayerTex");
  50. samplerNames.push_back("$lightMapTex");
  51. samplerNames.push_back("$lightInfoBuffer");
  52. for(int i = 0; i < 3; ++i)
  53. {
  54. samplerNames.push_back(avar("$normalMap%d",i));
  55. samplerNames.push_back(avar("$detailMap%d",i));
  56. samplerNames.push_back(avar("$macroMap%d", i));
  57. samplerNames.push_back(avar("$compositeMap%d", i));
  58. }
  59. return samplerNames;
  60. }
  61. const Vector<String> TerrainCellMaterial::mSamplerNames = _initSamplerNames();
  62. TerrainCellMaterial::TerrainCellMaterial()
  63. : mTerrain( NULL ),
  64. mCurrPass( 0 ),
  65. mDeferredMat( NULL ),
  66. mReflectMat( NULL )
  67. {
  68. smAllMaterials.push_back( this );
  69. }
  70. TerrainCellMaterial::~TerrainCellMaterial()
  71. {
  72. SAFE_DELETE( mDeferredMat );
  73. SAFE_DELETE( mReflectMat );
  74. smAllMaterials.remove( this );
  75. }
  76. void TerrainCellMaterial::_updateDefaultAnisotropy()
  77. {
  78. // TODO: We need to split the stateblock initialization
  79. // from the shader constant lookup and pass setup in a
  80. // future version of terrain materials.
  81. //
  82. // For now use some custom code in a horrible loop to
  83. // change the anisotropy directly and fast.
  84. //
  85. const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy();
  86. Vector<TerrainCellMaterial*>::iterator iter = smAllMaterials.begin();
  87. for ( ; iter != smAllMaterials.end(); iter++ )
  88. {
  89. for ( U32 p=0; p < (*iter)->mPasses.size(); p++ )
  90. {
  91. Pass &pass = (*iter)->mPasses[p];
  92. // Start from the existing state block.
  93. GFXStateBlockDesc desc = pass.stateBlock->getDesc();
  94. for ( U32 m=0; m < pass.materials.size(); m++ )
  95. {
  96. const MaterialInfo *matInfo = pass.materials[m];
  97. if ( matInfo->detailTexConst->isValid() )
  98. {
  99. const S32 sampler = matInfo->detailTexConst->getSamplerRegister();
  100. if ( maxAnisotropy > 1 )
  101. {
  102. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  103. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  104. }
  105. else
  106. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  107. }
  108. if ( matInfo->macroTexConst->isValid() )
  109. {
  110. const S32 sampler = matInfo->macroTexConst->getSamplerRegister();
  111. if ( maxAnisotropy > 1 )
  112. {
  113. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  114. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  115. }
  116. else
  117. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  118. }
  119. if ( matInfo->normalTexConst->isValid() )
  120. {
  121. const S32 sampler = matInfo->normalTexConst->getSamplerRegister();
  122. if ( maxAnisotropy > 1 )
  123. {
  124. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  125. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  126. }
  127. else
  128. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  129. }
  130. if (matInfo->compositeTexConst->isValid())
  131. {
  132. const S32 sampler = matInfo->compositeTexConst->getSamplerRegister();
  133. if (maxAnisotropy > 1)
  134. {
  135. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  136. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  137. }
  138. else
  139. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  140. }
  141. } // for ( U32 m=0; m < pass.materials.size(); m++ )
  142. // Set the updated stateblock.
  143. desc.setCullMode( GFXCullCCW );
  144. pass.stateBlock = GFX->createStateBlock( desc );
  145. //reflection
  146. desc.setCullMode( GFXCullCW );
  147. pass.reflectionStateBlock = GFX->createStateBlock(desc);
  148. // Create the wireframe state blocks.
  149. GFXStateBlockDesc wireframe( desc );
  150. wireframe.fillMode = GFXFillWireframe;
  151. wireframe.setCullMode( GFXCullCCW );
  152. pass.wireframeStateBlock = GFX->createStateBlock( wireframe );
  153. } // for ( U32 p=0; i < (*iter)->mPasses.size(); p++ )
  154. }
  155. }
  156. void TerrainCellMaterial::setTransformAndEye( const MatrixF &modelXfm,
  157. const MatrixF &viewXfm,
  158. const MatrixF &projectXfm,
  159. F32 farPlane )
  160. {
  161. PROFILE_SCOPE( TerrainCellMaterial_SetTransformAndEye );
  162. MatrixF modelViewProj = projectXfm * viewXfm * modelXfm;
  163. MatrixF invViewXfm( viewXfm );
  164. invViewXfm.inverse();
  165. Point3F eyePos = invViewXfm.getPosition();
  166. MatrixF invModelXfm( modelXfm );
  167. invModelXfm.inverse();
  168. Point3F objEyePos = eyePos;
  169. invModelXfm.mulP( objEyePos );
  170. VectorF vEye = invViewXfm.getForwardVector();
  171. vEye.normalize( 1.0f / farPlane );
  172. for ( U32 i=0; i < mPasses.size(); i++ )
  173. {
  174. Pass &pass = mPasses[i];
  175. pass.consts->setSafe( pass.modelViewProjConst, modelViewProj );
  176. if( pass.viewToObj->isValid() || pass.worldViewOnly->isValid() )
  177. {
  178. MatrixF worldViewOnly = viewXfm * modelXfm;
  179. pass.consts->setSafe( pass.worldViewOnly, worldViewOnly );
  180. if( pass.viewToObj->isValid() )
  181. {
  182. worldViewOnly.affineInverse();
  183. pass.consts->set( pass.viewToObj, worldViewOnly);
  184. }
  185. }
  186. pass.consts->setSafe( pass.eyePosWorldConst, eyePos );
  187. pass.consts->setSafe( pass.eyePosConst, objEyePos );
  188. pass.consts->setSafe( pass.objTransConst, modelXfm );
  189. pass.consts->setSafe( pass.worldToObjConst, invModelXfm );
  190. pass.consts->setSafe( pass.vEyeConst, vEye );
  191. }
  192. }
  193. TerrainCellMaterial* TerrainCellMaterial::getDeferredMat()
  194. {
  195. if ( !mDeferredMat )
  196. {
  197. mDeferredMat = new TerrainCellMaterial();
  198. mDeferredMat->init( mTerrain, mMaterials, true, false, mMaterials == 0 );
  199. }
  200. return mDeferredMat;
  201. }
  202. TerrainCellMaterial* TerrainCellMaterial::getReflectMat()
  203. {
  204. if ( !mReflectMat )
  205. {
  206. mReflectMat = new TerrainCellMaterial();
  207. mReflectMat->init( mTerrain, mMaterials, false, true, true );
  208. }
  209. return mReflectMat;
  210. }
  211. void TerrainCellMaterial::init( TerrainBlock *block,
  212. U64 activeMaterials,
  213. bool deferredMat,
  214. bool reflectMat,
  215. bool baseOnly )
  216. {
  217. // This isn't allowed for now.
  218. AssertFatal( !( deferredMat && reflectMat ), "TerrainCellMaterial::init - We shouldn't get deferred and reflection in the same material!" );
  219. mTerrain = block;
  220. mMaterials = activeMaterials;
  221. Vector<MaterialInfo*> materials;
  222. for ( U32 i = 0; i < 64; i++ )
  223. {
  224. if ( !( mMaterials & ((U64)1 << i ) ) )
  225. continue;
  226. TerrainMaterial *mat = block->getMaterial( i );
  227. MaterialInfo *info = new MaterialInfo();
  228. info->layerId = i;
  229. info->mat = mat;
  230. materials.push_back( info );
  231. }
  232. mCurrPass = 0;
  233. mPasses.clear();
  234. // Ok... loop till we successfully generate all
  235. // the shader passes for the materials.
  236. while ( materials.size() > 0 || baseOnly )
  237. {
  238. mPasses.increment();
  239. if ( !_createPass( &materials,
  240. &mPasses.last(),
  241. mPasses.size() == 1,
  242. deferredMat,
  243. reflectMat,
  244. baseOnly ) )
  245. {
  246. Con::errorf( "TerrainCellMaterial::init - Failed to create pass!" );
  247. // The pass failed to be generated... give up.
  248. mPasses.last().materials.clear();
  249. mPasses.clear();
  250. T3D::for_each( materials.begin(), materials.end(), T3D::delete_pointer() );
  251. return;
  252. }
  253. if ( baseOnly )
  254. break;
  255. }
  256. // Cleanup any remaining matinfo.
  257. T3D::for_each( materials.begin(), materials.end(), T3D::delete_pointer() );
  258. // If we have attached mats then update them too.
  259. if ( mDeferredMat )
  260. mDeferredMat->init( mTerrain, mMaterials, true, false, baseOnly );
  261. if ( mReflectMat )
  262. mReflectMat->init( mTerrain, mMaterials, false, true, baseOnly );
  263. }
  264. bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
  265. Pass *pass,
  266. bool firstPass,
  267. bool deferredMat,
  268. bool reflectMat,
  269. bool baseOnly )
  270. {
  271. if ( GFX->getPixelShaderVersion() < 3.0f )
  272. baseOnly = true;
  273. // NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials
  274. // into a single pass. This is sub-optimal for the simplest
  275. // cases, but the most common case results in much fewer
  276. // shader generation failures and permutations leading to
  277. // faster load time and less hiccups during gameplay.
  278. U32 matCount = getMin( sgMaxTerrainMaterialsPerPass, materials->size() );
  279. Vector<GFXTexHandle> normalMaps;
  280. // See if we're currently running under the
  281. // basic lighting manager.
  282. //
  283. // TODO: This seems ugly... we should trigger
  284. // features like this differently in the future.
  285. //
  286. bool useBLM = dStrcmp( LIGHTMGR->getId(), "BLM" ) == 0;
  287. // Do we need to disable normal mapping?
  288. const bool disableNormalMaps = MATMGR->getExclusionFeatures().hasFeature( MFT_NormalMap ) || useBLM;
  289. // How about parallax?
  290. const bool disableParallaxMaps = GFX->getPixelShaderVersion() < 3.0f ||
  291. MATMGR->getExclusionFeatures().hasFeature( MFT_Parallax );
  292. // Has advanced lightmap support been enabled for deferred.
  293. bool advancedLightmapSupport = false;
  294. if ( deferredMat )
  295. {
  296. // This sucks... but it works.
  297. AdvancedLightBinManager *lightBin;
  298. if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
  299. advancedLightmapSupport = lightBin->MRTLightmapsDuringDeferred();
  300. }
  301. // Loop till we create a valid shader!
  302. while( true )
  303. {
  304. FeatureSet features;
  305. features.addFeature( MFT_VertTransform );
  306. features.addFeature( MFT_TerrainBaseMap );
  307. if ( deferredMat )
  308. {
  309. features.addFeature( MFT_EyeSpaceDepthOut );
  310. features.addFeature( MFT_DeferredConditioner );
  311. features.addFeature(MFT_isDeferred);
  312. if ( advancedLightmapSupport )
  313. features.addFeature( MFT_RenderTarget3_Zero );
  314. }
  315. else
  316. {
  317. features.addFeature( MFT_RTLighting );
  318. // The HDR feature is always added... it will compile out
  319. // if HDR is not enabled in the engine.
  320. features.addFeature( MFT_HDROut );
  321. }
  322. features.addFeature(MFT_DeferredTerrainBlankInfoMap);
  323. // Enable lightmaps and fogging if we're in BL.
  324. if ( reflectMat || useBLM )
  325. {
  326. features.addFeature( MFT_Fog );
  327. features.addFeature( MFT_ForwardShading );
  328. }
  329. if ( useBLM )
  330. features.addFeature( MFT_TerrainLightMap );
  331. // The additional passes need to be lerp blended into the
  332. // target to maintain the results of the previous passes.
  333. if (!firstPass && deferredMat)
  334. features.addFeature( MFT_TerrainAdditive );
  335. normalMaps.clear();
  336. pass->materials.clear();
  337. // Now add all the material layer features.
  338. for ( U32 i=0; i < matCount && !baseOnly; i++ )
  339. {
  340. TerrainMaterial *mat = (*materials)[i]->mat;
  341. if ( mat == NULL )
  342. continue;
  343. // We only include materials that
  344. // have more than a base texture.
  345. if ( mat->getDetailSize() <= 0 ||
  346. mat->getDetailDistance() <= 0 ||
  347. mat->getDetailMap().isEmpty() )
  348. continue;
  349. S32 featureIndex = pass->materials.size();
  350. // check for macro detail texture
  351. if ( !(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap().isEmpty() ) )
  352. {
  353. if(deferredMat)
  354. features.addFeature(MFT_isDeferred, featureIndex);
  355. features.addFeature( MFT_TerrainMacroMap, featureIndex );
  356. }
  357. if(deferredMat)
  358. features.addFeature(MFT_isDeferred, featureIndex);
  359. features.addFeature( MFT_TerrainDetailMap, featureIndex );
  360. if (!(mat->getCompositeMap().isEmpty()))
  361. {
  362. if (deferredMat)
  363. features.addFeature(MFT_isDeferred, featureIndex);
  364. features.addFeature(MFT_TerrainCompositeMap, featureIndex);
  365. features.removeFeature(MFT_DeferredTerrainBlankInfoMap);
  366. }
  367. if (mat->getInvertSmoothness())
  368. features.addFeature(MFT_InvertSmoothness);
  369. pass->materials.push_back( (*materials)[i] );
  370. normalMaps.increment();
  371. // Skip normal maps if we need to.
  372. if ( !disableNormalMaps && mat->getNormalMap().isNotEmpty() )
  373. {
  374. features.addFeature( MFT_TerrainNormalMap, featureIndex );
  375. normalMaps.last().set( mat->getNormalMap(),
  376. &GFXNormalMapProfile, "TerrainCellMaterial::_createPass() - NormalMap" );
  377. GFXFormat normalFmt = normalMaps.last().getFormat();
  378. if ( normalFmt == GFXFormatBC3 )
  379. features.addFeature( MFT_IsBC3nm, featureIndex );
  380. else if ( normalFmt == GFXFormatBC5)
  381. features.addFeature( MFT_IsBC5nm, featureIndex);
  382. // Do we need and can we do parallax mapping?
  383. if ( !disableParallaxMaps &&
  384. mat->getParallaxScale() > 0.0f &&
  385. !mat->useSideProjection() )
  386. features.addFeature( MFT_TerrainParallaxMap, featureIndex );
  387. }
  388. // Is this layer got side projection?
  389. if ( mat->useSideProjection() )
  390. features.addFeature( MFT_TerrainSideProject, featureIndex );
  391. }
  392. MaterialFeatureData featureData;
  393. featureData.features = features;
  394. featureData.materialFeatures = features;
  395. Vector<CustomShaderFeatureData*> customFeatures;
  396. // Check to see how many vertex shader output
  397. // registers we're gonna need.
  398. U32 numTex = 0;
  399. U32 numTexReg = 0;
  400. for ( U32 i=0; i < features.getCount(); i++ )
  401. {
  402. S32 index;
  403. const FeatureType &type = features.getAt( i, &index );
  404. ShaderFeature* sf = FEATUREMGR->getByType( type );
  405. if ( !sf )
  406. continue;
  407. sf->setProcessIndex( index );
  408. ShaderFeature::Resources res = sf->getResources( featureData );
  409. numTex += res.numTex;
  410. numTexReg += res.numTexReg;
  411. }
  412. // Can we build the shader?
  413. //
  414. // NOTE: The 10 is sort of an abitrary SM 3.0
  415. // limit. Its really supposed to be 11, but that
  416. // always fails to compile so far.
  417. //
  418. if ( numTex < GFX->getNumSamplers() &&
  419. numTexReg <= 10 )
  420. {
  421. // NOTE: We really shouldn't be getting errors building the shaders,
  422. // but we can generate more instructions than the ps_2_x will allow.
  423. //
  424. // There is no way to deal with this case that i know of other than
  425. // letting the compile fail then recovering by trying to build it
  426. // with fewer materials.
  427. //
  428. // We normally disable the shader error logging so that the user
  429. // isn't fooled into thinking there is a real bug. That is until
  430. // we get down to a single material. If a single material case
  431. // fails it means it cannot generate any passes at all!
  432. const bool logErrors = true;// matCount == 1;
  433. GFXShader::setLogging( logErrors, true );
  434. pass->shader = SHADERGEN->getShader( featureData, customFeatures, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
  435. }
  436. // If we got a shader then we can continue.
  437. if ( pass->shader )
  438. break;
  439. // If the material count is already 1 then this
  440. // is a real shader error... give up!
  441. if ( matCount <= 1 )
  442. return false;
  443. // If we failed we next try half the input materials
  444. // so that we can more quickly arrive at a valid shader.
  445. matCount -= matCount / 2;
  446. }
  447. // Setup the constant buffer.
  448. pass->consts = pass->shader->allocConstBuffer();
  449. // Prepare the basic constants.
  450. pass->modelViewProjConst = pass->shader->getShaderConstHandle( "$modelview" );
  451. pass->worldViewOnly = pass->shader->getShaderConstHandle( "$worldViewOnly" );
  452. pass->viewToObj = pass->shader->getShaderConstHandle( "$viewToObj" );
  453. pass->eyePosWorldConst = pass->shader->getShaderConstHandle( "$eyePosWorld" );
  454. pass->eyePosConst = pass->shader->getShaderConstHandle( "$eyePos" );
  455. pass->vEyeConst = pass->shader->getShaderConstHandle( "$vEye" );
  456. pass->layerSizeConst = pass->shader->getShaderConstHandle( "$layerSize" );
  457. pass->objTransConst = pass->shader->getShaderConstHandle( "$objTrans" );
  458. pass->worldToObjConst = pass->shader->getShaderConstHandle( "$worldToObj" );
  459. pass->lightInfoBufferConst = pass->shader->getShaderConstHandle( "$lightInfoBuffer" );
  460. pass->baseTexMapConst = pass->shader->getShaderConstHandle( "$baseTexMap" );
  461. pass->layerTexConst = pass->shader->getShaderConstHandle( "$layerTex" );
  462. pass->fogDataConst = pass->shader->getShaderConstHandle( "$fogData" );
  463. pass->fogColorConst = pass->shader->getShaderConstHandle( "$fogColor" );
  464. pass->lightMapTexConst = pass->shader->getShaderConstHandle( "$lightMapTex" );
  465. pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" );
  466. pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" );
  467. pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParamslightInfoBuffer" );
  468. // Now prepare the basic stateblock.
  469. GFXStateBlockDesc desc;
  470. if ( !firstPass )
  471. {
  472. desc.setBlend( true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha );
  473. // If this is the deferred then we don't want to
  474. // write to the last two color channels (where
  475. // depth is usually encoded).
  476. //
  477. // This trick works in combination with the
  478. // MFT_TerrainAdditive feature to lerp the
  479. // output normal with the previous pass.
  480. //
  481. if ( deferredMat )
  482. desc.setColorWrites( true, true, true, false );
  483. }
  484. // We write to the zbuffer if this is a deferred
  485. // material or if the deferred is disabled.
  486. desc.setZReadWrite( true, !MATMGR->getDeferredEnabled() ||
  487. deferredMat ||
  488. reflectMat );
  489. desc.samplersDefined = true;
  490. if ( pass->baseTexMapConst->isValid() )
  491. desc.samplers[pass->baseTexMapConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
  492. if ( pass->layerTexConst->isValid() )
  493. desc.samplers[pass->layerTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
  494. if ( pass->lightInfoBufferConst->isValid() )
  495. desc.samplers[pass->lightInfoBufferConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
  496. if ( pass->lightMapTexConst->isValid() )
  497. desc.samplers[pass->lightMapTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
  498. const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy();
  499. // Finally setup the material specific shader
  500. // constants and stateblock state.
  501. //
  502. // NOTE: If this changes be sure to check TerrainCellMaterial::_updateDefaultAnisotropy
  503. // to see if it needs the same changes.
  504. //
  505. for ( U32 i=0; i < pass->materials.size(); i++ )
  506. {
  507. MaterialInfo *matInfo = pass->materials[i];
  508. matInfo->detailInfoVConst = pass->shader->getShaderConstHandle( avar( "$detailScaleAndFade%d", i ) );
  509. matInfo->detailInfoPConst = pass->shader->getShaderConstHandle( avar( "$detailIdStrengthParallax%d", i ) );
  510. matInfo->detailTexConst = pass->shader->getShaderConstHandle( avar( "$detailMap%d", i ) );
  511. if ( matInfo->detailTexConst->isValid() )
  512. {
  513. const S32 sampler = matInfo->detailTexConst->getSamplerRegister();
  514. desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
  515. desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
  516. desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
  517. if ( maxAnisotropy > 1 )
  518. {
  519. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  520. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  521. }
  522. else
  523. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  524. matInfo->detailTex.set( matInfo->mat->getDetailMap(),
  525. &GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - DetailMap" );
  526. }
  527. matInfo->compositeTexConst = pass->shader->getShaderConstHandle(avar("$compositeMap%d", i));
  528. if (matInfo->compositeTexConst->isValid())
  529. {
  530. GFXTextureProfile* profile = &GFXStaticTextureProfile;
  531. if (matInfo->mat->getIsSRGB())
  532. profile = &GFXStaticTextureSRGBProfile;
  533. matInfo->compositeTex.set(matInfo->mat->getCompositeMap(),
  534. profile, "TerrainCellMaterial::_createPass() - CompositeMap");
  535. const S32 sampler = matInfo->compositeTexConst->getSamplerRegister();
  536. desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
  537. desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
  538. desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
  539. if (maxAnisotropy > 1)
  540. {
  541. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  542. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  543. }
  544. else
  545. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  546. }
  547. matInfo->macroInfoVConst = pass->shader->getShaderConstHandle( avar( "$macroScaleAndFade%d", i ) );
  548. matInfo->macroInfoPConst = pass->shader->getShaderConstHandle( avar( "$macroIdStrengthParallax%d", i ) );
  549. matInfo->macroTexConst = pass->shader->getShaderConstHandle( avar( "$macroMap%d", i ) );
  550. if ( matInfo->macroTexConst->isValid() )
  551. {
  552. const S32 sampler = matInfo->macroTexConst->getSamplerRegister();
  553. desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
  554. desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
  555. desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
  556. if ( maxAnisotropy > 1 )
  557. {
  558. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  559. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  560. }
  561. else
  562. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  563. matInfo->macroTex.set( matInfo->mat->getMacroMap(),
  564. &GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - MacroMap" );
  565. }
  566. //end macro texture
  567. matInfo->normalTexConst = pass->shader->getShaderConstHandle( avar( "$normalMap%d", i ) );
  568. if ( matInfo->normalTexConst->isValid() )
  569. {
  570. const S32 sampler = matInfo->normalTexConst->getSamplerRegister();
  571. desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
  572. desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
  573. desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
  574. if ( maxAnisotropy > 1 )
  575. {
  576. desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
  577. desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
  578. }
  579. else
  580. desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
  581. matInfo->normalTex = normalMaps[i];
  582. }
  583. }
  584. // Remove the materials we processed and leave the
  585. // ones that remain for the next pass.
  586. for ( U32 i=0; i < matCount; i++ )
  587. {
  588. MaterialInfo *matInfo = materials->first();
  589. if ( baseOnly || pass->materials.find_next( matInfo ) == -1 )
  590. delete matInfo;
  591. materials->pop_front();
  592. }
  593. // If we're doing deferred it requires some
  594. // special stencil settings for it to work.
  595. if ( deferredMat )
  596. desc.addDesc( RenderDeferredMgr::getOpaqueStenciWriteDesc( false ) );
  597. desc.setCullMode( GFXCullCCW );
  598. pass->stateBlock = GFX->createStateBlock(desc);
  599. //reflection stateblock
  600. desc.setCullMode( GFXCullCW );
  601. pass->reflectionStateBlock = GFX->createStateBlock(desc);
  602. // Create the wireframe state blocks.
  603. GFXStateBlockDesc wireframe( desc );
  604. wireframe.fillMode = GFXFillWireframe;
  605. wireframe.setCullMode( GFXCullCCW );
  606. pass->wireframeStateBlock = GFX->createStateBlock( wireframe );
  607. return true;
  608. }
  609. void TerrainCellMaterial::_updateMaterialConsts( Pass *pass )
  610. {
  611. PROFILE_SCOPE( TerrainCellMaterial_UpdateMaterialConsts );
  612. for ( U32 j=0; j < pass->materials.size(); j++ )
  613. {
  614. MaterialInfo *matInfo = pass->materials[j];
  615. F32 detailSize = matInfo->mat->getDetailSize();
  616. F32 detailScale = 1.0f;
  617. if ( !mIsZero( detailSize ) )
  618. detailScale = mTerrain->getWorldBlockSize() / detailSize;
  619. // Scale the distance by the global scalar.
  620. const F32 distance = mTerrain->smDetailScale * matInfo->mat->getDetailDistance();
  621. // NOTE: The negation of the y scale is to make up for
  622. // my mistake early in development and passing the wrong
  623. // y texture coord into the system.
  624. //
  625. // This negation fixes detail, normal, and parallax mapping
  626. // without harming the layer id blending code.
  627. //
  628. // Eventually we should rework this to correct this little
  629. // mistake, but there isn't really a hurry to.
  630. //
  631. Point4F detailScaleAndFade( detailScale,
  632. -detailScale,
  633. distance,
  634. 0 );
  635. if ( !mIsZero( distance ) )
  636. detailScaleAndFade.w = 1.0f / distance;
  637. Point3F detailIdStrengthParallax( matInfo->layerId,
  638. matInfo->mat->getDetailStrength(),
  639. matInfo->mat->getParallaxScale() );
  640. pass->consts->setSafe( matInfo->detailInfoVConst, detailScaleAndFade );
  641. pass->consts->setSafe( matInfo->detailInfoPConst, detailIdStrengthParallax );
  642. // macro texture info
  643. F32 macroSize = matInfo->mat->getMacroSize();
  644. F32 macroScale = 1.0f;
  645. if ( !mIsZero( macroSize ) )
  646. macroScale = mTerrain->getWorldBlockSize() / macroSize;
  647. // Scale the distance by the global scalar.
  648. const F32 macroDistance = mTerrain->smDetailScale * matInfo->mat->getMacroDistance();
  649. Point4F macroScaleAndFade( macroScale,
  650. -macroScale,
  651. macroDistance,
  652. 0 );
  653. if ( !mIsZero( macroDistance ) )
  654. macroScaleAndFade.w = 1.0f / macroDistance;
  655. Point3F macroIdStrengthParallax( matInfo->layerId,
  656. matInfo->mat->getMacroStrength(),
  657. 0 );
  658. pass->consts->setSafe( matInfo->macroInfoVConst, macroScaleAndFade );
  659. pass->consts->setSafe( matInfo->macroInfoPConst, macroIdStrengthParallax );
  660. }
  661. }
  662. bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
  663. const SceneData &sceneData )
  664. {
  665. PROFILE_SCOPE( TerrainCellMaterial_SetupPass );
  666. if ( mCurrPass >= mPasses.size() )
  667. {
  668. mCurrPass = 0;
  669. return false;
  670. }
  671. Pass &pass = mPasses[mCurrPass];
  672. _updateMaterialConsts( &pass );
  673. if ( pass.baseTexMapConst->isValid() )
  674. GFX->setTexture( pass.baseTexMapConst->getSamplerRegister(), mTerrain->mBaseTex.getPointer() );
  675. if ( pass.layerTexConst->isValid() )
  676. GFX->setTexture( pass.layerTexConst->getSamplerRegister(), mTerrain->mLayerTex.getPointer() );
  677. if ( pass.lightMapTexConst->isValid() )
  678. GFX->setTexture( pass.lightMapTexConst->getSamplerRegister(), mTerrain->getLightMapTex() );
  679. if ( sceneData.wireframe )
  680. GFX->setStateBlock( pass.wireframeStateBlock );
  681. else if ( state->isReflectPass( ))
  682. GFX->setStateBlock( pass.reflectionStateBlock );
  683. else
  684. GFX->setStateBlock( pass.stateBlock );
  685. GFX->setShader( pass.shader );
  686. GFX->setShaderConstBuffer( pass.consts );
  687. // Let the light manager prepare any light stuff it needs.
  688. LIGHTMGR->setLightInfo( NULL,
  689. NULL,
  690. sceneData,
  691. state,
  692. mCurrPass,
  693. pass.consts );
  694. for ( U32 i=0; i < pass.materials.size(); i++ )
  695. {
  696. MaterialInfo *matInfo = pass.materials[i];
  697. if ( matInfo->detailTexConst->isValid() )
  698. GFX->setTexture( matInfo->detailTexConst->getSamplerRegister(), matInfo->detailTex );
  699. if ( matInfo->macroTexConst->isValid() )
  700. GFX->setTexture( matInfo->macroTexConst->getSamplerRegister(), matInfo->macroTex );
  701. if ( matInfo->normalTexConst->isValid() )
  702. GFX->setTexture( matInfo->normalTexConst->getSamplerRegister(), matInfo->normalTex );
  703. if ( matInfo->compositeTexConst->isValid() )
  704. GFX->setTexture( matInfo->compositeTexConst->getSamplerRegister(), matInfo->compositeTex );
  705. }
  706. pass.consts->setSafe( pass.layerSizeConst, (F32)mTerrain->mLayerTex.getWidth() );
  707. if ( pass.oneOverTerrainSize->isValid() )
  708. {
  709. F32 oneOverTerrainSize = 1.0f / mTerrain->getWorldBlockSize();
  710. pass.consts->set( pass.oneOverTerrainSize, oneOverTerrainSize );
  711. }
  712. pass.consts->setSafe( pass.squareSize, mTerrain->getSquareSize() );
  713. if ( pass.fogDataConst->isValid() )
  714. {
  715. Point3F fogData;
  716. fogData.x = sceneData.fogDensity;
  717. fogData.y = sceneData.fogDensityOffset;
  718. fogData.z = sceneData.fogHeightFalloff;
  719. pass.consts->set( pass.fogDataConst, fogData );
  720. }
  721. pass.consts->setSafe( pass.fogColorConst, sceneData.fogColor );
  722. if ( pass.lightInfoBufferConst->isValid() &&
  723. pass.lightParamsConst->isValid() )
  724. {
  725. if ( !mLightInfoTarget )
  726. mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" );
  727. GFXTextureObject *texObject = mLightInfoTarget->getTexture();
  728. // TODO: Sometimes during reset of the light manager we get a
  729. // NULL texture here. This is corrected on the next frame, but
  730. // we should still investigate why that happens.
  731. if ( texObject )
  732. {
  733. GFX->setTexture( pass.lightInfoBufferConst->getSamplerRegister(), texObject );
  734. const Point3I &targetSz = texObject->getSize();
  735. const RectI &targetVp = mLightInfoTarget->getViewport();
  736. Point4F rtParams;
  737. ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
  738. pass.consts->setSafe( pass.lightParamsConst, rtParams );
  739. }
  740. }
  741. ++mCurrPass;
  742. return true;
  743. }
  744. BaseMatInstance* TerrainCellMaterial::getShadowMat()
  745. {
  746. // Find our material which has some settings
  747. // defined on it in script.
  748. Material *mat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );
  749. // Create the material instance adding the feature which
  750. // handles rendering terrain cut outs.
  751. FeatureSet features = MATMGR->getDefaultFeatures();
  752. BaseMatInstance *matInst = mat->createMatInstance();
  753. if ( !matInst->init( features, getGFXVertexFormat<TerrVertex>() ) )
  754. {
  755. delete matInst;
  756. matInst = NULL;
  757. }
  758. return matInst;
  759. }