terrFeatureHLSL.cpp 35 KB

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