terrCellMaterial.cpp 30 KB

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