terrCellMaterial.cpp 27 KB

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