terrFeatureHLSL.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  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/hlsl/terrFeatureHLSL.h"
  24. #include "terrain/terrFeatureTypes.h"
  25. #include "materials/materialFeatureTypes.h"
  26. #include "materials/materialFeatureData.h"
  27. #include "gfx/gfxDevice.h"
  28. #include "shaderGen/langElement.h"
  29. #include "shaderGen/shaderOp.h"
  30. #include "shaderGen/featureMgr.h"
  31. #include "shaderGen/shaderGen.h"
  32. #include "core/module.h"
  33. namespace
  34. {
  35. void register_hlsl_shader_features_for_terrain(GFXAdapterType type)
  36. {
  37. if(type != Direct3D9 && type != Direct3D9_360)
  38. return;
  39. FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatHLSL );
  40. FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) );
  41. FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL );
  42. FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatHLSL );
  43. FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatHLSL );
  44. FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL );
  45. FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
  46. FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
  47. }
  48. };
  49. MODULE_BEGIN( TerrainFeatHLSL )
  50. MODULE_INIT_AFTER( ShaderGen )
  51. MODULE_INIT
  52. {
  53. SHADERGEN->getFeatureInitSignal().notify(&register_hlsl_shader_features_for_terrain);
  54. }
  55. MODULE_END;
  56. Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp )
  57. {
  58. Var *theVar = (Var*)LangElement::find( name );
  59. if ( !theVar )
  60. {
  61. theVar = new Var;
  62. theVar->setType( type );
  63. theVar->setName( name );
  64. theVar->uniform = true;
  65. theVar->constSortPos = csp;
  66. }
  67. return theVar;
  68. }
  69. Var* TerrainFeatHLSL::_getInDetailCoord( Vector<ShaderComponent*> &componentList )
  70. {
  71. String name( String::ToString( "detCoord%d", getProcessIndex() ) );
  72. Var *inDet = (Var*)LangElement::find( name );
  73. if ( !inDet )
  74. {
  75. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  76. inDet = connectComp->getElement( RT_TEXCOORD );
  77. inDet->setName( name );
  78. inDet->setStructName( "IN" );
  79. inDet->setType( "float4" );
  80. inDet->mapsToSampler = true;
  81. }
  82. return inDet;
  83. }
  84. Var* TerrainFeatHLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList )
  85. {
  86. String name( String::ToString( "macroCoord%d", getProcessIndex() ) );
  87. Var *inDet = (Var*)LangElement::find( name );
  88. if ( !inDet )
  89. {
  90. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  91. inDet = connectComp->getElement( RT_TEXCOORD );
  92. inDet->setName( name );
  93. inDet->setStructName( "IN" );
  94. inDet->setType( "float4" );
  95. inDet->mapsToSampler = true;
  96. }
  97. return inDet;
  98. }
  99. Var* TerrainFeatHLSL::_getNormalMapTex()
  100. {
  101. String name( String::ToString( "normalMap%d", getProcessIndex() ) );
  102. Var *normalMap = (Var*)LangElement::find( name );
  103. if ( !normalMap )
  104. {
  105. normalMap = new Var;
  106. normalMap->setType( "sampler2D" );
  107. normalMap->setName( name );
  108. normalMap->uniform = true;
  109. normalMap->sampler = true;
  110. normalMap->constNum = Var::getTexUnitNum();
  111. }
  112. return normalMap;
  113. }
  114. Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
  115. {
  116. String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
  117. Var *detailInfo = (Var*)LangElement::find( name );
  118. if ( !detailInfo )
  119. {
  120. detailInfo = new Var;
  121. detailInfo->setType( "float3" );
  122. detailInfo->setName( name );
  123. detailInfo->uniform = true;
  124. detailInfo->constSortPos = cspPotentialPrimitive;
  125. }
  126. return detailInfo;
  127. }
  128. Var* TerrainFeatHLSL::_getMacroIdStrengthParallax()
  129. {
  130. String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) );
  131. Var *detailInfo = (Var*)LangElement::find( name );
  132. if ( !detailInfo )
  133. {
  134. detailInfo = new Var;
  135. detailInfo->setType( "float3" );
  136. detailInfo->setName( name );
  137. detailInfo->uniform = true;
  138. detailInfo->constSortPos = cspPotentialPrimitive;
  139. }
  140. return detailInfo;
  141. }
  142. void TerrainBaseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  143. const MaterialFeatureData &fd )
  144. {
  145. MultiLine *meta = new MultiLine;
  146. output = meta;
  147. // Generate the incoming texture var.
  148. Var *inTex;
  149. {
  150. Var *inPos = (Var*)LangElement::find( "inPosition" );
  151. if ( !inPos )
  152. inPos = (Var*)LangElement::find( "position" );
  153. inTex = new Var( "texCoord", "float3" );
  154. Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass );
  155. // NOTE: The y coord here should be negative to have
  156. // the texture maps not end up flipped which also caused
  157. // normal and parallax mapping to be incorrect.
  158. //
  159. // This mistake early in development means that the layer
  160. // id bilinear blend depends on it being that way.
  161. //
  162. // So instead i fixed this by flipping the base and detail
  163. // coord y scale to compensate when rendering.
  164. //
  165. meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
  166. new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
  167. }
  168. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  169. // Pass the texture coord to the pixel shader.
  170. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  171. outTex->setName( "outTexCoord" );
  172. outTex->setStructName( "OUT" );
  173. outTex->setType( "float3" );
  174. outTex->mapsToSampler = true;
  175. meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) );
  176. // If this shader has a side projected layer then we
  177. // pass the dot product between the +Y and the normal
  178. // thru outTexCoord.z for use in blending the textures.
  179. if ( fd.features.hasFeature( MFT_TerrainSideProject ) )
  180. {
  181. Var *inNormal = (Var*)LangElement::find( "normal" );
  182. meta->addStatement(
  183. new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n",
  184. outTex, inNormal, inNormal ) );
  185. }
  186. else
  187. meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) );
  188. // HACK: This is sort of lazy... we generate the tanget
  189. // vector here so that we're sure it exists in the parallax
  190. // and normal features which will expect "T" to exist.
  191. //
  192. // If this shader doesn't use it the shader compiler will
  193. // optimize away this code.
  194. //
  195. Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
  196. Var *inTanget = new Var( "T", "float3" );
  197. Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
  198. meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n",
  199. new DecOp( inTanget ), squareSize, inTangentZ ) );
  200. }
  201. void TerrainBaseMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  202. const MaterialFeatureData &fd )
  203. {
  204. // grab connector texcoord register
  205. Var *texCoord = getInTexCoord( "texCoord", "float3", true, componentList );
  206. // We do nothing more if this is a prepass.
  207. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  208. return;
  209. // create texture var
  210. Var *diffuseMap = new Var;
  211. diffuseMap->setType( "sampler2D" );
  212. diffuseMap->setName( "baseTexMap" );
  213. diffuseMap->uniform = true;
  214. diffuseMap->sampler = true;
  215. diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  216. MultiLine *meta = new MultiLine;
  217. Var *baseColor = new Var;
  218. baseColor->setType( "float4" );
  219. baseColor->setName( "baseColor" );
  220. meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) );
  221. meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) );
  222. output = meta;
  223. }
  224. ShaderFeature::Resources TerrainBaseMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  225. {
  226. Resources res;
  227. res.numTexReg = 1;
  228. // We only sample from the base map during a diffuse pass.
  229. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  230. res.numTex = 1;
  231. return res;
  232. }
  233. TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL()
  234. : mTorqueDep( "shaders/common/torque.hlsl" ),
  235. mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
  236. {
  237. addDependency( &mTorqueDep );
  238. addDependency( &mTerrainDep );
  239. }
  240. void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  241. const MaterialFeatureData &fd )
  242. {
  243. const U32 detailIndex = getProcessIndex();
  244. // Grab incoming texture coords... the base map feature
  245. // made sure this was created.
  246. Var *inTex = (Var*)LangElement::find( "texCoord" );
  247. AssertFatal( inTex, "The texture coord is missing!" );
  248. // Grab the input position.
  249. Var *inPos = (Var*)LangElement::find( "inPosition" );
  250. if ( !inPos )
  251. inPos = (Var*)LangElement::find( "position" );
  252. // Get the object space eye position.
  253. Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
  254. MultiLine *meta = new MultiLine;
  255. // If we have parallax mapping then make sure we've sent
  256. // the negative view vector to the pixel shader.
  257. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  258. !LangElement::find( "outNegViewTS" ) )
  259. {
  260. // Get the object to tangent transform which
  261. // will consume 3 output registers.
  262. Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd );
  263. // Now use a single output register to send the negative
  264. // view vector in tangent space to the pixel shader.
  265. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  266. Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD );
  267. outNegViewTS->setName( "outNegViewTS" );
  268. outNegViewTS->setStructName( "OUT" );
  269. outNegViewTS->setType( "float3" );
  270. meta->addStatement( new GenOp( " @ = mul( @, float3( @ - @.xyz ) );\r\n",
  271. outNegViewTS, objToTangentSpace, eyePos, inPos ) );
  272. }
  273. // Get the distance from the eye to this vertex.
  274. Var *dist = (Var*)LangElement::find( "dist" );
  275. if ( !dist )
  276. {
  277. dist = new Var;
  278. dist->setType( "float" );
  279. dist->setName( "dist" );
  280. meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
  281. new DecOp( dist ), inPos, eyePos ) );
  282. }
  283. // grab connector texcoord register
  284. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  285. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  286. outTex->setName( String::ToString( "detCoord%d", detailIndex ) );
  287. outTex->setStructName( "OUT" );
  288. outTex->setType( "float4" );
  289. outTex->mapsToSampler = true;
  290. // Get the detail scale and fade info.
  291. Var *detScaleAndFade = new Var;
  292. detScaleAndFade->setType( "float4" );
  293. detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) );
  294. detScaleAndFade->uniform = true;
  295. detScaleAndFade->constSortPos = cspPotentialPrimitive;
  296. // Setup the detail coord.
  297. //
  298. // NOTE: You see here we scale the texture coord by 'xyx'
  299. // to generate the detail coord. This y is here because
  300. // its scale is flipped to correct for the non negative y
  301. // in texCoord.
  302. //
  303. // See TerrainBaseMapFeatHLSL::processVert().
  304. //
  305. meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
  306. // And sneak the detail fade thru the w detailCoord.
  307. meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
  308. outTex, detScaleAndFade, dist, detScaleAndFade ) );
  309. output = meta;
  310. }
  311. void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  312. const MaterialFeatureData &fd )
  313. {
  314. const U32 detailIndex = getProcessIndex();
  315. Var *inTex = getVertTexCoord( "texCoord" );
  316. MultiLine *meta = new MultiLine;
  317. // We need the negative tangent space view vector
  318. // as in parallax mapping we step towards the camera.
  319. Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
  320. if ( !negViewTS &&
  321. fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  322. {
  323. Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
  324. if ( !inNegViewTS )
  325. {
  326. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  327. inNegViewTS = connectComp->getElement( RT_TEXCOORD );
  328. inNegViewTS->setName( "outNegViewTS" );
  329. inNegViewTS->setStructName( "IN" );
  330. inNegViewTS->setType( "float3" );
  331. }
  332. negViewTS = new Var( "negViewTS", "float3" );
  333. meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
  334. }
  335. // Get the layer samples.
  336. Var *layerSample = (Var*)LangElement::find( "layerSample" );
  337. if ( !layerSample )
  338. {
  339. layerSample = new Var;
  340. layerSample->setType( "float4" );
  341. layerSample->setName( "layerSample" );
  342. // Get the layer texture var
  343. Var *layerTex = new Var;
  344. layerTex->setType( "sampler2D" );
  345. layerTex->setName( "layerTex" );
  346. layerTex->uniform = true;
  347. layerTex->sampler = true;
  348. layerTex->constNum = Var::getTexUnitNum();
  349. // Read the layer texture to get the samples.
  350. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  351. new DecOp( layerSample ), layerTex, inTex ) );
  352. }
  353. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  354. if ( !layerSize )
  355. {
  356. layerSize = new Var;
  357. layerSize->setType( "float" );
  358. layerSize->setName( "layerSize" );
  359. layerSize->uniform = true;
  360. layerSize->constSortPos = cspPass;
  361. }
  362. // Grab the incoming detail coord.
  363. Var *inDet = _getInDetailCoord( componentList );
  364. // Get the detail id.
  365. Var *detailInfo = _getDetailIdStrengthParallax();
  366. // Create the detail blend var.
  367. Var *detailBlend = new Var;
  368. detailBlend->setType( "float" );
  369. detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) );
  370. // Calculate the blend for this detail texture.
  371. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  372. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  373. // Get a var and accumulate the blend amount.
  374. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  375. if ( !blendTotal )
  376. {
  377. blendTotal = new Var;
  378. blendTotal->setName( "blendTotal" );
  379. blendTotal->setType( "float" );
  380. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  381. }
  382. // Add to the blend total.
  383. meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) );
  384. // If we had a parallax feature... then factor in the parallax
  385. // amount so that it fades out with the layer blending.
  386. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
  387. {
  388. // Get the rest of our inputs.
  389. Var *normalMap = _getNormalMapTex();
  390. // Call the library function to do the rest.
  391. if(fd.features.hasFeature( MFT_IsDXTnm, detailIndex ) )
  392. {
  393. meta->addStatement( new GenOp( " @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n",
  394. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) );
  395. }
  396. else
  397. {
  398. meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
  399. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) );
  400. }
  401. }
  402. // If this is a prepass then we skip color.
  403. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  404. {
  405. // Check to see if we have a gbuffer normal.
  406. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  407. // If we have a gbuffer normal and we don't have a
  408. // normal map feature then we need to lerp in a
  409. // default normal else the normals below this layer
  410. // will show thru.
  411. if ( gbNormal &&
  412. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  413. {
  414. Var *viewToTangent = getInViewToTangent( componentList );
  415. meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n",
  416. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  417. }
  418. output = meta;
  419. return;
  420. }
  421. Var *detailColor = (Var*)LangElement::find( "detailColor" );
  422. if ( !detailColor )
  423. {
  424. detailColor = new Var;
  425. detailColor->setType( "float4" );
  426. detailColor->setName( "detailColor" );
  427. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  428. }
  429. // Get the detail texture.
  430. Var *detailMap = new Var;
  431. detailMap->setType( "sampler2D" );
  432. detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
  433. detailMap->uniform = true;
  434. detailMap->sampler = true;
  435. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  436. // If we're using SM 3.0 then take advantage of
  437. // dynamic branching to skip layers per-pixel.
  438. if ( GFX->getPixelShaderVersion() >= 3.0f )
  439. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  440. meta->addStatement( new GenOp( " {\r\n" ) );
  441. // Note that we're doing the standard greyscale detail
  442. // map technique here which can darken and lighten the
  443. // diffuse texture.
  444. //
  445. // We take two color samples and lerp between them for
  446. // side projection layers... else a single sample.
  447. //
  448. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  449. {
  450. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  451. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  452. }
  453. else
  454. {
  455. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  456. detailColor, detailMap, inDet ) );
  457. }
  458. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  459. detailColor, detailInfo, inDet ) );
  460. Var *outColor = (Var*)LangElement::find( "col" );
  461. meta->addStatement( new GenOp( " @ += @ * @;\r\n",
  462. outColor, detailColor, detailBlend));
  463. meta->addStatement( new GenOp( " }\r\n" ) );
  464. output = meta;
  465. }
  466. ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  467. {
  468. Resources res;
  469. if ( getProcessIndex() == 0 )
  470. {
  471. // If this is the first detail pass then we
  472. // samples from the layer tex.
  473. res.numTex += 1;
  474. // If this material also does parallax then it
  475. // will generate the negative view vector and the
  476. // worldToTanget transform.
  477. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  478. res.numTexReg += 4;
  479. }
  480. // If this isn't the prepass then we sample
  481. // from the detail texture for diffuse coloring.
  482. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  483. res.numTex += 1;
  484. // If we have parallax for this layer then we'll also
  485. // be sampling the normal map for the parallax heightmap.
  486. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
  487. res.numTex += 1;
  488. // Finally we always send the detail texture
  489. // coord to the pixel shader.
  490. res.numTexReg += 1;
  491. return res;
  492. }
  493. TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL()
  494. : mTorqueDep( "shaders/common/torque.hlsl" ),
  495. mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
  496. {
  497. addDependency( &mTorqueDep );
  498. addDependency( &mTerrainDep );
  499. }
  500. void TerrainMacroMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  501. const MaterialFeatureData &fd )
  502. {
  503. const U32 detailIndex = getProcessIndex();
  504. // Grab incoming texture coords... the base map feature
  505. // made sure this was created.
  506. Var *inTex = (Var*)LangElement::find( "texCoord" );
  507. AssertFatal( inTex, "The texture coord is missing!" );
  508. // Grab the input position.
  509. Var *inPos = (Var*)LangElement::find( "inPosition" );
  510. if ( !inPos )
  511. inPos = (Var*)LangElement::find( "position" );
  512. // Get the object space eye position.
  513. Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
  514. MultiLine *meta = new MultiLine;
  515. // Get the distance from the eye to this vertex.
  516. Var *dist = (Var*)LangElement::find( "macroDist" );
  517. if ( !dist )
  518. {
  519. dist = new Var;
  520. dist->setType( "float" );
  521. dist->setName( "macroDist" );
  522. meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
  523. new DecOp( dist ), inPos, eyePos ) );
  524. }
  525. // grab connector texcoord register
  526. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  527. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  528. outTex->setName( String::ToString( "macroCoord%d", detailIndex ) );
  529. outTex->setStructName( "OUT" );
  530. outTex->setType( "float4" );
  531. outTex->mapsToSampler = true;
  532. // Get the detail scale and fade info.
  533. Var *detScaleAndFade = new Var;
  534. detScaleAndFade->setType( "float4" );
  535. detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) );
  536. detScaleAndFade->uniform = true;
  537. detScaleAndFade->constSortPos = cspPotentialPrimitive;
  538. // Setup the detail coord.
  539. meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
  540. // And sneak the detail fade thru the w detailCoord.
  541. meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
  542. outTex, detScaleAndFade, dist, detScaleAndFade ) );
  543. output = meta;
  544. }
  545. void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  546. const MaterialFeatureData &fd )
  547. {
  548. const U32 detailIndex = getProcessIndex();
  549. Var *inTex = getVertTexCoord( "texCoord" );
  550. MultiLine *meta = new MultiLine;
  551. // We need the negative tangent space view vector
  552. // as in parallax mapping we step towards the camera.
  553. Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
  554. if ( !negViewTS &&
  555. fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  556. {
  557. Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
  558. if ( !inNegViewTS )
  559. {
  560. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  561. inNegViewTS = connectComp->getElement( RT_TEXCOORD );
  562. inNegViewTS->setName( "outNegViewTS" );
  563. inNegViewTS->setStructName( "IN" );
  564. inNegViewTS->setType( "float3" );
  565. }
  566. negViewTS = new Var( "negViewTS", "float3" );
  567. meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
  568. }
  569. // Get the layer samples.
  570. Var *layerSample = (Var*)LangElement::find( "layerSample" );
  571. if ( !layerSample )
  572. {
  573. layerSample = new Var;
  574. layerSample->setType( "float4" );
  575. layerSample->setName( "layerSample" );
  576. // Get the layer texture var
  577. Var *layerTex = new Var;
  578. layerTex->setType( "sampler2D" );
  579. layerTex->setName( "macrolayerTex" );
  580. layerTex->uniform = true;
  581. layerTex->sampler = true;
  582. layerTex->constNum = Var::getTexUnitNum();
  583. // Read the layer texture to get the samples.
  584. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  585. new DecOp( layerSample ), layerTex, inTex ) );
  586. }
  587. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  588. if ( !layerSize )
  589. {
  590. layerSize = new Var;
  591. layerSize->setType( "float" );
  592. layerSize->setName( "layerSize" );
  593. layerSize->uniform = true;
  594. layerSize->constSortPos = cspPass;
  595. }
  596. // Grab the incoming detail coord.
  597. Var *inDet = _getInMacroCoord( componentList );
  598. // Get the detail id.
  599. Var *detailInfo = _getMacroIdStrengthParallax();
  600. // Create the detail blend var.
  601. Var *detailBlend = new Var;
  602. detailBlend->setType( "float" );
  603. detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) );
  604. // Calculate the blend for this detail texture.
  605. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  606. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  607. // Get a var and accumulate the blend amount.
  608. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  609. if ( !blendTotal )
  610. {
  611. blendTotal = new Var;
  612. //blendTotal->setName( "blendTotal" );
  613. blendTotal->setName( "blendTotal" );
  614. blendTotal->setType( "float" );
  615. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  616. }
  617. // Add to the blend total.
  618. meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) );
  619. // If this is a prepass then we skip color.
  620. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  621. {
  622. // Check to see if we have a gbuffer normal.
  623. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  624. // If we have a gbuffer normal and we don't have a
  625. // normal map feature then we need to lerp in a
  626. // default normal else the normals below this layer
  627. // will show thru.
  628. if ( gbNormal &&
  629. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  630. {
  631. Var *viewToTangent = getInViewToTangent( componentList );
  632. meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n",
  633. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  634. }
  635. output = meta;
  636. return;
  637. }
  638. Var *detailColor = (Var*)LangElement::find( "macroColor" );
  639. if ( !detailColor )
  640. {
  641. detailColor = new Var;
  642. detailColor->setType( "float4" );
  643. detailColor->setName( "macroColor" );
  644. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  645. }
  646. // Get the detail texture.
  647. Var *detailMap = new Var;
  648. detailMap->setType( "sampler2D" );
  649. detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
  650. detailMap->uniform = true;
  651. detailMap->sampler = true;
  652. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  653. // If we're using SM 3.0 then take advantage of
  654. // dynamic branching to skip layers per-pixel.
  655. if ( GFX->getPixelShaderVersion() >= 3.0f )
  656. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  657. meta->addStatement( new GenOp( " {\r\n" ) );
  658. // Note that we're doing the standard greyscale detail
  659. // map technique here which can darken and lighten the
  660. // diffuse texture.
  661. //
  662. // We take two color samples and lerp between them for
  663. // side projection layers... else a single sample.
  664. //
  665. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  666. {
  667. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  668. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  669. }
  670. else
  671. {
  672. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  673. detailColor, detailMap, inDet ) );
  674. }
  675. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  676. detailColor, detailInfo, inDet ) );
  677. //Var *baseColor = (Var*)LangElement::find( "baseColor" );
  678. Var *outColor = (Var*)LangElement::find( "col" );
  679. meta->addStatement(new GenOp(" @ += @ * @;\r\n",
  680. outColor, detailColor, detailBlend));
  681. meta->addStatement( new GenOp( " }\r\n" ) );
  682. output = meta;
  683. }
  684. ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  685. {
  686. Resources res;
  687. if ( getProcessIndex() == 0 )
  688. {
  689. // If this is the first detail pass then we
  690. // samples from the layer tex.
  691. res.numTex += 1;
  692. }
  693. // If this isn't the prepass then we sample
  694. // from the detail texture for diffuse coloring.
  695. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  696. res.numTex += 1;
  697. // Finally we always send the detail texture
  698. // coord to the pixel shader.
  699. res.numTexReg += 1;
  700. return res;
  701. }
  702. void TerrainNormalMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  703. const MaterialFeatureData &fd )
  704. {
  705. // We only need to process normals during the prepass.
  706. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  707. return;
  708. MultiLine *meta = new MultiLine;
  709. // Make sure the world to tangent transform
  710. // is created and available for the pixel shader.
  711. getOutViewToTangent( componentList, meta, fd );
  712. output = meta;
  713. }
  714. void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  715. const MaterialFeatureData &fd )
  716. {
  717. // We only need to process normals during the prepass.
  718. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  719. return;
  720. MultiLine *meta = new MultiLine;
  721. Var *viewToTangent = getInViewToTangent( componentList );
  722. // This var is read from GBufferConditionerHLSL and
  723. // used in the prepass output.
  724. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  725. if ( !gbNormal )
  726. {
  727. gbNormal = new Var;
  728. gbNormal->setName( "gbNormal" );
  729. gbNormal->setType( "float3" );
  730. meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) );
  731. }
  732. const U32 normalIndex = getProcessIndex();
  733. Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
  734. AssertFatal( detailBlend, "The detail blend is missing!" );
  735. // If we're using SM 3.0 then take advantage of
  736. // dynamic branching to skip layers per-pixel.
  737. if ( GFX->getPixelShaderVersion() >= 3.0f )
  738. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  739. meta->addStatement( new GenOp( " {\r\n" ) );
  740. // Get the normal map texture.
  741. Var *normalMap = _getNormalMapTex();
  742. /// Get the texture coord.
  743. Var *inDet = _getInDetailCoord( componentList );
  744. Var *inTex = getVertTexCoord( "texCoord" );
  745. // Sample the normal map.
  746. //
  747. // We take two normal samples and lerp between them for
  748. // side projection layers... else a single sample.
  749. LangElement *texOp;
  750. if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
  751. {
  752. texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
  753. normalMap, inDet, normalMap, inDet, inTex );
  754. }
  755. else
  756. texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
  757. // create bump normal
  758. Var *bumpNorm = new Var;
  759. bumpNorm->setName( "bumpNormal" );
  760. bumpNorm->setType( "float4" );
  761. LangElement *bumpNormDecl = new DecOp( bumpNorm );
  762. meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
  763. // Normalize is done later...
  764. // Note: The reverse mul order is intentional. Affine matrix.
  765. meta->addStatement( new GenOp( " @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n",
  766. gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
  767. // End the conditional block.
  768. meta->addStatement( new GenOp( " }\r\n" ) );
  769. // If this is the last normal map then we
  770. // can test to see the total blend value
  771. // to see if we should clip the result.
  772. //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
  773. //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
  774. output = meta;
  775. }
  776. ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  777. {
  778. Resources res;
  779. // We only need to process normals during the prepass.
  780. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  781. {
  782. // If this is the first normal map and there
  783. // are no parallax features then we will
  784. // generate the worldToTanget transform.
  785. if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  786. ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
  787. res.numTexReg = 3;
  788. res.numTex = 1;
  789. }
  790. return res;
  791. }
  792. void TerrainLightMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  793. const MaterialFeatureData &fd )
  794. {
  795. // grab connector texcoord register
  796. Var *inTex = (Var*)LangElement::find( "texCoord" );
  797. if ( !inTex )
  798. return;
  799. // Get the lightmap texture.
  800. Var *lightMap = new Var;
  801. lightMap->setType( "sampler2D" );
  802. lightMap->setName( "lightMapTex" );
  803. lightMap->uniform = true;
  804. lightMap->sampler = true;
  805. lightMap->constNum = Var::getTexUnitNum();
  806. MultiLine *meta = new MultiLine;
  807. // Find or create the lightMask value which is read by
  808. // RTLighting to mask out the lights.
  809. //
  810. // The first light is always the sunlight so we apply
  811. // the shadow mask to only the first channel.
  812. //
  813. Var *lightMask = (Var*)LangElement::find( "lightMask" );
  814. if ( !lightMask )
  815. {
  816. lightMask = new Var( "lightMask", "float4" );
  817. meta->addStatement( new GenOp( " @ = 1;\r\n", new DecOp( lightMask ) ) );
  818. }
  819. meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
  820. output = meta;
  821. }
  822. ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  823. {
  824. Resources res;
  825. res.numTex = 1;
  826. return res;
  827. }
  828. void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  829. const MaterialFeatureData &fd )
  830. {
  831. Var *color = (Var*) LangElement::find( "col" );
  832. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  833. if ( !color || !blendTotal )
  834. return;
  835. MultiLine *meta = new MultiLine;
  836. meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
  837. meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
  838. output = meta;
  839. }