terrFeatureHLSL.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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. meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
  392. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) );
  393. }
  394. // If this is a prepass then we skip color.
  395. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  396. {
  397. // Check to see if we have a gbuffer normal.
  398. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  399. // If we have a gbuffer normal and we don't have a
  400. // normal map feature then we need to lerp in a
  401. // default normal else the normals below this layer
  402. // will show thru.
  403. if ( gbNormal &&
  404. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  405. {
  406. Var *viewToTangent = getInViewToTangent( componentList );
  407. meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n",
  408. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  409. }
  410. output = meta;
  411. return;
  412. }
  413. Var *detailColor = (Var*)LangElement::find( "detailColor" );
  414. if ( !detailColor )
  415. {
  416. detailColor = new Var;
  417. detailColor->setType( "float4" );
  418. detailColor->setName( "detailColor" );
  419. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  420. }
  421. // Get the detail texture.
  422. Var *detailMap = new Var;
  423. detailMap->setType( "sampler2D" );
  424. detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
  425. detailMap->uniform = true;
  426. detailMap->sampler = true;
  427. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  428. // If we're using SM 3.0 then take advantage of
  429. // dynamic branching to skip layers per-pixel.
  430. if ( GFX->getPixelShaderVersion() >= 3.0f )
  431. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  432. meta->addStatement( new GenOp( " {\r\n" ) );
  433. // Note that we're doing the standard greyscale detail
  434. // map technique here which can darken and lighten the
  435. // diffuse texture.
  436. //
  437. // We take two color samples and lerp between them for
  438. // side projection layers... else a single sample.
  439. //
  440. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  441. {
  442. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  443. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  444. }
  445. else
  446. {
  447. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  448. detailColor, detailMap, inDet ) );
  449. }
  450. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  451. detailColor, detailInfo, inDet ) );
  452. Var *baseColor = (Var*)LangElement::find( "baseColor" );
  453. Var *outColor = (Var*)LangElement::find( "col" );
  454. meta->addStatement( new GenOp( " @ += @ * @;\r\n",
  455. outColor, detailColor, detailBlend));
  456. meta->addStatement( new GenOp( " }\r\n" ) );
  457. output = meta;
  458. }
  459. ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  460. {
  461. Resources res;
  462. if ( getProcessIndex() == 0 )
  463. {
  464. // If this is the first detail pass then we
  465. // samples from the layer tex.
  466. res.numTex += 1;
  467. // If this material also does parallax then it
  468. // will generate the negative view vector and the
  469. // worldToTanget transform.
  470. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  471. res.numTexReg += 4;
  472. }
  473. // If this isn't the prepass then we sample
  474. // from the detail texture for diffuse coloring.
  475. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  476. res.numTex += 1;
  477. // If we have parallax for this layer then we'll also
  478. // be sampling the normal map for the parallax heightmap.
  479. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
  480. res.numTex += 1;
  481. // Finally we always send the detail texture
  482. // coord to the pixel shader.
  483. res.numTexReg += 1;
  484. return res;
  485. }
  486. TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL()
  487. : mTorqueDep( "shaders/common/torque.hlsl" ),
  488. mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
  489. {
  490. addDependency( &mTorqueDep );
  491. addDependency( &mTerrainDep );
  492. }
  493. void TerrainMacroMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  494. const MaterialFeatureData &fd )
  495. {
  496. const U32 detailIndex = getProcessIndex();
  497. // Grab incoming texture coords... the base map feature
  498. // made sure this was created.
  499. Var *inTex = (Var*)LangElement::find( "texCoord" );
  500. AssertFatal( inTex, "The texture coord is missing!" );
  501. // Grab the input position.
  502. Var *inPos = (Var*)LangElement::find( "inPosition" );
  503. if ( !inPos )
  504. inPos = (Var*)LangElement::find( "position" );
  505. // Get the object space eye position.
  506. Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
  507. MultiLine *meta = new MultiLine;
  508. // Get the distance from the eye to this vertex.
  509. Var *dist = (Var*)LangElement::find( "macroDist" );
  510. if ( !dist )
  511. {
  512. dist = new Var;
  513. dist->setType( "float" );
  514. dist->setName( "macroDist" );
  515. meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
  516. new DecOp( dist ), inPos, eyePos ) );
  517. }
  518. // grab connector texcoord register
  519. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  520. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  521. outTex->setName( String::ToString( "macroCoord%d", detailIndex ) );
  522. outTex->setStructName( "OUT" );
  523. outTex->setType( "float4" );
  524. outTex->mapsToSampler = true;
  525. // Get the detail scale and fade info.
  526. Var *detScaleAndFade = new Var;
  527. detScaleAndFade->setType( "float4" );
  528. detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) );
  529. detScaleAndFade->uniform = true;
  530. detScaleAndFade->constSortPos = cspPotentialPrimitive;
  531. // Setup the detail coord.
  532. meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
  533. // And sneak the detail fade thru the w detailCoord.
  534. meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
  535. outTex, detScaleAndFade, dist, detScaleAndFade ) );
  536. output = meta;
  537. }
  538. void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  539. const MaterialFeatureData &fd )
  540. {
  541. const U32 detailIndex = getProcessIndex();
  542. Var *inTex = getVertTexCoord( "texCoord" );
  543. MultiLine *meta = new MultiLine;
  544. // We need the negative tangent space view vector
  545. // as in parallax mapping we step towards the camera.
  546. Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
  547. if ( !negViewTS &&
  548. fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  549. {
  550. Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
  551. if ( !inNegViewTS )
  552. {
  553. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  554. inNegViewTS = connectComp->getElement( RT_TEXCOORD );
  555. inNegViewTS->setName( "outNegViewTS" );
  556. inNegViewTS->setStructName( "IN" );
  557. inNegViewTS->setType( "float3" );
  558. }
  559. negViewTS = new Var( "negViewTS", "float3" );
  560. meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
  561. }
  562. // Get the layer samples.
  563. Var *layerSample = (Var*)LangElement::find( "layerSample" );
  564. if ( !layerSample )
  565. {
  566. layerSample = new Var;
  567. layerSample->setType( "float4" );
  568. layerSample->setName( "layerSample" );
  569. // Get the layer texture var
  570. Var *layerTex = new Var;
  571. layerTex->setType( "sampler2D" );
  572. layerTex->setName( "macrolayerTex" );
  573. layerTex->uniform = true;
  574. layerTex->sampler = true;
  575. layerTex->constNum = Var::getTexUnitNum();
  576. // Read the layer texture to get the samples.
  577. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  578. new DecOp( layerSample ), layerTex, inTex ) );
  579. }
  580. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  581. if ( !layerSize )
  582. {
  583. layerSize = new Var;
  584. layerSize->setType( "float" );
  585. layerSize->setName( "layerSize" );
  586. layerSize->uniform = true;
  587. layerSize->constSortPos = cspPass;
  588. }
  589. // Grab the incoming detail coord.
  590. Var *inDet = _getInMacroCoord( componentList );
  591. // Get the detail id.
  592. Var *detailInfo = _getMacroIdStrengthParallax();
  593. // Create the detail blend var.
  594. Var *detailBlend = new Var;
  595. detailBlend->setType( "float" );
  596. detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) );
  597. // Calculate the blend for this detail texture.
  598. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  599. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  600. // Get a var and accumulate the blend amount.
  601. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  602. if ( !blendTotal )
  603. {
  604. blendTotal = new Var;
  605. //blendTotal->setName( "blendTotal" );
  606. blendTotal->setName( "blendTotal" );
  607. blendTotal->setType( "float" );
  608. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  609. }
  610. // Add to the blend total.
  611. meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) );
  612. // If this is a prepass then we skip color.
  613. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  614. {
  615. // Check to see if we have a gbuffer normal.
  616. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  617. // If we have a gbuffer normal and we don't have a
  618. // normal map feature then we need to lerp in a
  619. // default normal else the normals below this layer
  620. // will show thru.
  621. if ( gbNormal &&
  622. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  623. {
  624. Var *viewToTangent = getInViewToTangent( componentList );
  625. meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n",
  626. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  627. }
  628. output = meta;
  629. return;
  630. }
  631. Var *detailColor = (Var*)LangElement::find( "macroColor" );
  632. if ( !detailColor )
  633. {
  634. detailColor = new Var;
  635. detailColor->setType( "float4" );
  636. detailColor->setName( "macroColor" );
  637. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  638. }
  639. // Get the detail texture.
  640. Var *detailMap = new Var;
  641. detailMap->setType( "sampler2D" );
  642. detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
  643. detailMap->uniform = true;
  644. detailMap->sampler = true;
  645. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  646. // If we're using SM 3.0 then take advantage of
  647. // dynamic branching to skip layers per-pixel.
  648. if ( GFX->getPixelShaderVersion() >= 3.0f )
  649. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  650. meta->addStatement( new GenOp( " {\r\n" ) );
  651. // Note that we're doing the standard greyscale detail
  652. // map technique here which can darken and lighten the
  653. // diffuse texture.
  654. //
  655. // We take two color samples and lerp between them for
  656. // side projection layers... else a single sample.
  657. //
  658. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  659. {
  660. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  661. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  662. }
  663. else
  664. {
  665. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  666. detailColor, detailMap, inDet ) );
  667. }
  668. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  669. detailColor, detailInfo, inDet ) );
  670. //Var *baseColor = (Var*)LangElement::find( "baseColor" );
  671. Var *outColor = (Var*)LangElement::find( "col" );
  672. meta->addStatement(new GenOp(" @ += @ * @;\r\n",
  673. outColor, detailColor, detailBlend));
  674. meta->addStatement( new GenOp( " }\r\n" ) );
  675. output = meta;
  676. }
  677. ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  678. {
  679. Resources res;
  680. if ( getProcessIndex() == 0 )
  681. {
  682. // If this is the first detail pass then we
  683. // samples from the layer tex.
  684. res.numTex += 1;
  685. }
  686. // If this isn't the prepass then we sample
  687. // from the detail texture for diffuse coloring.
  688. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  689. res.numTex += 1;
  690. // Finally we always send the detail texture
  691. // coord to the pixel shader.
  692. res.numTexReg += 1;
  693. return res;
  694. }
  695. void TerrainNormalMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  696. const MaterialFeatureData &fd )
  697. {
  698. // We only need to process normals during the prepass.
  699. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  700. return;
  701. MultiLine *meta = new MultiLine;
  702. // Make sure the world to tangent transform
  703. // is created and available for the pixel shader.
  704. getOutViewToTangent( componentList, meta, fd );
  705. output = meta;
  706. }
  707. void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  708. const MaterialFeatureData &fd )
  709. {
  710. // We only need to process normals during the prepass.
  711. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  712. return;
  713. MultiLine *meta = new MultiLine;
  714. Var *viewToTangent = getInViewToTangent( componentList );
  715. // This var is read from GBufferConditionerHLSL and
  716. // used in the prepass output.
  717. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  718. if ( !gbNormal )
  719. {
  720. gbNormal = new Var;
  721. gbNormal->setName( "gbNormal" );
  722. gbNormal->setType( "float3" );
  723. meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) );
  724. }
  725. const U32 normalIndex = getProcessIndex();
  726. Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
  727. AssertFatal( detailBlend, "The detail blend is missing!" );
  728. // If we're using SM 3.0 then take advantage of
  729. // dynamic branching to skip layers per-pixel.
  730. if ( GFX->getPixelShaderVersion() >= 3.0f )
  731. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  732. meta->addStatement( new GenOp( " {\r\n" ) );
  733. // Get the normal map texture.
  734. Var *normalMap = _getNormalMapTex();
  735. /// Get the texture coord.
  736. Var *inDet = _getInDetailCoord( componentList );
  737. Var *inTex = getVertTexCoord( "texCoord" );
  738. // Sample the normal map.
  739. //
  740. // We take two normal samples and lerp between them for
  741. // side projection layers... else a single sample.
  742. LangElement *texOp;
  743. if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
  744. {
  745. texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
  746. normalMap, inDet, normalMap, inDet, inTex );
  747. }
  748. else
  749. texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
  750. // create bump normal
  751. Var *bumpNorm = new Var;
  752. bumpNorm->setName( "bumpNormal" );
  753. bumpNorm->setType( "float4" );
  754. LangElement *bumpNormDecl = new DecOp( bumpNorm );
  755. meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
  756. // Normalize is done later...
  757. // Note: The reverse mul order is intentional. Affine matrix.
  758. meta->addStatement( new GenOp( " @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n",
  759. gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
  760. // End the conditional block.
  761. meta->addStatement( new GenOp( " }\r\n" ) );
  762. // If this is the last normal map then we
  763. // can test to see the total blend value
  764. // to see if we should clip the result.
  765. //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
  766. //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
  767. output = meta;
  768. }
  769. ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  770. {
  771. Resources res;
  772. // We only need to process normals during the prepass.
  773. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  774. {
  775. // If this is the first normal map and there
  776. // are no parallax features then we will
  777. // generate the worldToTanget transform.
  778. if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  779. ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
  780. res.numTexReg = 3;
  781. res.numTex = 1;
  782. }
  783. return res;
  784. }
  785. void TerrainLightMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  786. const MaterialFeatureData &fd )
  787. {
  788. // grab connector texcoord register
  789. Var *inTex = (Var*)LangElement::find( "texCoord" );
  790. if ( !inTex )
  791. return;
  792. // Get the lightmap texture.
  793. Var *lightMap = new Var;
  794. lightMap->setType( "sampler2D" );
  795. lightMap->setName( "lightMapTex" );
  796. lightMap->uniform = true;
  797. lightMap->sampler = true;
  798. lightMap->constNum = Var::getTexUnitNum();
  799. MultiLine *meta = new MultiLine;
  800. // Find or create the lightMask value which is read by
  801. // RTLighting to mask out the lights.
  802. //
  803. // The first light is always the sunlight so we apply
  804. // the shadow mask to only the first channel.
  805. //
  806. Var *lightMask = (Var*)LangElement::find( "lightMask" );
  807. if ( !lightMask )
  808. {
  809. lightMask = new Var( "lightMask", "float4" );
  810. meta->addStatement( new GenOp( " @ = 1;\r\n", new DecOp( lightMask ) ) );
  811. }
  812. meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
  813. output = meta;
  814. }
  815. ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  816. {
  817. Resources res;
  818. res.numTex = 1;
  819. return res;
  820. }
  821. void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  822. const MaterialFeatureData &fd )
  823. {
  824. Var *color = (Var*) LangElement::find( "col" );
  825. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  826. if ( !color || !blendTotal )
  827. return;
  828. MultiLine *meta = new MultiLine;
  829. meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
  830. meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
  831. output = meta;
  832. }