terrCellMaterial.cpp 30 KB

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