terrCellMaterial.cpp 31 KB

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