terrFeatureHLSL.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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_TerrainLightMap, new TerrainLightMapFeatHLSL );
  41. FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
  42. FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
  43. }
  44. MODULE_END;
  45. Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp )
  46. {
  47. Var *theVar = (Var*)LangElement::find( name );
  48. if ( !theVar )
  49. {
  50. theVar = new Var;
  51. theVar->setType( type );
  52. theVar->setName( name );
  53. theVar->uniform = true;
  54. theVar->constSortPos = csp;
  55. }
  56. return theVar;
  57. }
  58. Var* TerrainFeatHLSL::_getInDetailCoord( Vector<ShaderComponent*> &componentList )
  59. {
  60. String name( String::ToString( "detCoord%d", getProcessIndex() ) );
  61. Var *inDet = (Var*)LangElement::find( name );
  62. if ( !inDet )
  63. {
  64. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  65. inDet = connectComp->getElement( RT_TEXCOORD );
  66. inDet->setName( name );
  67. inDet->setStructName( "IN" );
  68. inDet->setType( "float4" );
  69. inDet->mapsToSampler = true;
  70. }
  71. return inDet;
  72. }
  73. Var* TerrainFeatHLSL::_getNormalMapTex()
  74. {
  75. String name( String::ToString( "normalMap%d", getProcessIndex() ) );
  76. Var *normalMap = (Var*)LangElement::find( name );
  77. if ( !normalMap )
  78. {
  79. normalMap = new Var;
  80. normalMap->setType( "sampler2D" );
  81. normalMap->setName( name );
  82. normalMap->uniform = true;
  83. normalMap->sampler = true;
  84. normalMap->constNum = Var::getTexUnitNum();
  85. }
  86. return normalMap;
  87. }
  88. Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
  89. {
  90. String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
  91. Var *detailInfo = (Var*)LangElement::find( name );
  92. if ( !detailInfo )
  93. {
  94. detailInfo = new Var;
  95. detailInfo->setType( "float3" );
  96. detailInfo->setName( name );
  97. detailInfo->uniform = true;
  98. detailInfo->constSortPos = cspPotentialPrimitive;
  99. }
  100. return detailInfo;
  101. }
  102. void TerrainBaseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  103. const MaterialFeatureData &fd )
  104. {
  105. MultiLine *meta = new MultiLine;
  106. output = meta;
  107. // Generate the incoming texture var.
  108. Var *inTex;
  109. {
  110. Var *inPos = (Var*)LangElement::find( "inPosition" );
  111. if ( !inPos )
  112. inPos = (Var*)LangElement::find( "position" );
  113. inTex = new Var( "texCoord", "float3" );
  114. Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass );
  115. // NOTE: The y coord here should be negative to have
  116. // the texture maps not end up flipped which also caused
  117. // normal and parallax mapping to be incorrect.
  118. //
  119. // This mistake early in development means that the layer
  120. // id bilinear blend depends on it being that way.
  121. //
  122. // So instead i fixed this by flipping the base and detail
  123. // coord y scale to compensate when rendering.
  124. //
  125. meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
  126. new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
  127. }
  128. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  129. // Pass the texture coord to the pixel shader.
  130. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  131. outTex->setName( "outTexCoord" );
  132. outTex->setStructName( "OUT" );
  133. outTex->setType( "float3" );
  134. outTex->mapsToSampler = true;
  135. meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) );
  136. // If this shader has a side projected layer then we
  137. // pass the dot product between the +Y and the normal
  138. // thru outTexCoord.z for use in blending the textures.
  139. if ( fd.features.hasFeature( MFT_TerrainSideProject ) )
  140. {
  141. Var *inNormal = (Var*)LangElement::find( "normal" );
  142. meta->addStatement(
  143. new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n",
  144. outTex, inNormal, inNormal ) );
  145. }
  146. else
  147. meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) );
  148. // HACK: This is sort of lazy... we generate the tanget
  149. // vector here so that we're sure it exists in the parallax
  150. // and normal features which will expect "T" to exist.
  151. //
  152. // If this shader doesn't use it the shader compiler will
  153. // optimize away this code.
  154. //
  155. Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
  156. Var *inTanget = new Var( "T", "float3" );
  157. Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
  158. meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n",
  159. new DecOp( inTanget ), squareSize, inTangentZ ) );
  160. }
  161. void TerrainBaseMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  162. const MaterialFeatureData &fd )
  163. {
  164. // grab connector texcoord register
  165. Var *texCoord = getInTexCoord( "texCoord", "float3", true, componentList );
  166. // We do nothing more if this is a prepass.
  167. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  168. return;
  169. // create texture var
  170. Var *diffuseMap = new Var;
  171. diffuseMap->setType( "sampler2D" );
  172. diffuseMap->setName( "baseTexMap" );
  173. diffuseMap->uniform = true;
  174. diffuseMap->sampler = true;
  175. diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  176. MultiLine *meta = new MultiLine;
  177. Var *baseColor = new Var;
  178. baseColor->setType( "float4" );
  179. baseColor->setName( "baseColor" );
  180. meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) );
  181. meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) );
  182. output = meta;
  183. }
  184. ShaderFeature::Resources TerrainBaseMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  185. {
  186. Resources res;
  187. res.numTexReg = 1;
  188. // We only sample from the base map during a diffuse pass.
  189. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  190. res.numTex = 1;
  191. return res;
  192. }
  193. TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL()
  194. : mTorqueDep( "shaders/common/torque.hlsl" ),
  195. mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
  196. {
  197. addDependency( &mTorqueDep );
  198. addDependency( &mTerrainDep );
  199. }
  200. void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  201. const MaterialFeatureData &fd )
  202. {
  203. const U32 detailIndex = getProcessIndex();
  204. // Grab incoming texture coords... the base map feature
  205. // made sure this was created.
  206. Var *inTex = (Var*)LangElement::find( "texCoord" );
  207. AssertFatal( inTex, "The texture coord is missing!" );
  208. // Grab the input position.
  209. Var *inPos = (Var*)LangElement::find( "inPosition" );
  210. if ( !inPos )
  211. inPos = (Var*)LangElement::find( "position" );
  212. // Get the object space eye position.
  213. Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
  214. MultiLine *meta = new MultiLine;
  215. // If we have parallax mapping then make sure we've sent
  216. // the negative view vector to the pixel shader.
  217. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  218. !LangElement::find( "outNegViewTS" ) )
  219. {
  220. // Get the object to tangent transform which
  221. // will consume 3 output registers.
  222. Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd );
  223. // Now use a single output register to send the negative
  224. // view vector in tangent space to the pixel shader.
  225. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  226. Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD );
  227. outNegViewTS->setName( "outNegViewTS" );
  228. outNegViewTS->setStructName( "OUT" );
  229. outNegViewTS->setType( "float3" );
  230. meta->addStatement( new GenOp( " @ = mul( @, float3( @ - @.xyz ) );\r\n",
  231. outNegViewTS, objToTangentSpace, eyePos, inPos ) );
  232. }
  233. // Get the distance from the eye to this vertex.
  234. Var *dist = (Var*)LangElement::find( "dist" );
  235. if ( !dist )
  236. {
  237. dist = new Var;
  238. dist->setType( "float" );
  239. dist->setName( "dist" );
  240. meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
  241. new DecOp( dist ), inPos, eyePos ) );
  242. }
  243. // grab connector texcoord register
  244. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  245. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  246. outTex->setName( String::ToString( "detCoord%d", detailIndex ) );
  247. outTex->setStructName( "OUT" );
  248. outTex->setType( "float4" );
  249. outTex->mapsToSampler = true;
  250. // Get the detail scale and fade info.
  251. Var *detScaleAndFade = new Var;
  252. detScaleAndFade->setType( "float4" );
  253. detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) );
  254. detScaleAndFade->uniform = true;
  255. detScaleAndFade->constSortPos = cspPotentialPrimitive;
  256. // Setup the detail coord.
  257. //
  258. // NOTE: You see here we scale the texture coord by 'xyx'
  259. // to generate the detail coord. This y is here because
  260. // its scale is flipped to correct for the non negative y
  261. // in texCoord.
  262. //
  263. // See TerrainBaseMapFeatHLSL::processVert().
  264. //
  265. meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
  266. // And sneak the detail fade thru the w detailCoord.
  267. meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
  268. outTex, detScaleAndFade, dist, detScaleAndFade ) );
  269. output = meta;
  270. }
  271. void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  272. const MaterialFeatureData &fd )
  273. {
  274. const U32 detailIndex = getProcessIndex();
  275. Var *inTex = getVertTexCoord( "texCoord" );
  276. MultiLine *meta = new MultiLine;
  277. // We need the negative tangent space view vector
  278. // as in parallax mapping we step towards the camera.
  279. Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
  280. if ( !negViewTS &&
  281. fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  282. {
  283. Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
  284. if ( !inNegViewTS )
  285. {
  286. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  287. inNegViewTS = connectComp->getElement( RT_TEXCOORD );
  288. inNegViewTS->setName( "outNegViewTS" );
  289. inNegViewTS->setStructName( "IN" );
  290. inNegViewTS->setType( "float3" );
  291. }
  292. negViewTS = new Var( "negViewTS", "float3" );
  293. meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
  294. }
  295. // Get the layer samples.
  296. Var *layerSample = (Var*)LangElement::find( "layerSample" );
  297. if ( !layerSample )
  298. {
  299. layerSample = new Var;
  300. layerSample->setType( "float4" );
  301. layerSample->setName( "layerSample" );
  302. // Get the layer texture var
  303. Var *layerTex = new Var;
  304. layerTex->setType( "sampler2D" );
  305. layerTex->setName( "layerTex" );
  306. layerTex->uniform = true;
  307. layerTex->sampler = true;
  308. layerTex->constNum = Var::getTexUnitNum();
  309. // Read the layer texture to get the samples.
  310. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  311. new DecOp( layerSample ), layerTex, inTex ) );
  312. }
  313. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  314. if ( !layerSize )
  315. {
  316. layerSize = new Var;
  317. layerSize->setType( "float" );
  318. layerSize->setName( "layerSize" );
  319. layerSize->uniform = true;
  320. layerSize->constSortPos = cspPass;
  321. }
  322. // Grab the incoming detail coord.
  323. Var *inDet = _getInDetailCoord( componentList );
  324. // Get the detail id.
  325. Var *detailInfo = _getDetailIdStrengthParallax();
  326. // Create the detail blend var.
  327. Var *detailBlend = new Var;
  328. detailBlend->setType( "float" );
  329. detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) );
  330. // Calculate the blend for this detail texture.
  331. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  332. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  333. // Get a var and accumulate the blend amount.
  334. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  335. if ( !blendTotal )
  336. {
  337. blendTotal = new Var;
  338. blendTotal->setName( "blendTotal" );
  339. blendTotal->setType( "float" );
  340. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  341. }
  342. // Add to the blend total.
  343. meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) );
  344. // If we had a parallax feature... then factor in the parallax
  345. // amount so that it fades out with the layer blending.
  346. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
  347. {
  348. // Get the rest of our inputs.
  349. Var *normalMap = _getNormalMapTex();
  350. // Call the library function to do the rest.
  351. meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
  352. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) );
  353. }
  354. // If this is a prepass then we skip color.
  355. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  356. {
  357. // Check to see if we have a gbuffer normal.
  358. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  359. // If we have a gbuffer normal and we don't have a
  360. // normal map feature then we need to lerp in a
  361. // default normal else the normals below this layer
  362. // will show thru.
  363. if ( gbNormal &&
  364. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  365. {
  366. Var *viewToTangent = getInViewToTangent( componentList );
  367. meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n",
  368. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  369. }
  370. output = meta;
  371. return;
  372. }
  373. Var *detailColor = (Var*)LangElement::find( "detailColor" );
  374. if ( !detailColor )
  375. {
  376. detailColor = new Var;
  377. detailColor->setType( "float4" );
  378. detailColor->setName( "detailColor" );
  379. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  380. }
  381. // Get the detail texture.
  382. Var *detailMap = new Var;
  383. detailMap->setType( "sampler2D" );
  384. detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
  385. detailMap->uniform = true;
  386. detailMap->sampler = true;
  387. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  388. // If we're using SM 3.0 then take advantage of
  389. // dynamic branching to skip layers per-pixel.
  390. if ( GFX->getPixelShaderVersion() >= 3.0f )
  391. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  392. meta->addStatement( new GenOp( " {\r\n" ) );
  393. // Note that we're doing the standard greyscale detail
  394. // map technique here which can darken and lighten the
  395. // diffuse texture.
  396. //
  397. // We take two color samples and lerp between them for
  398. // side projection layers... else a single sample.
  399. //
  400. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  401. {
  402. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  403. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  404. }
  405. else
  406. {
  407. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  408. detailColor, detailMap, inDet ) );
  409. }
  410. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  411. detailColor, detailInfo, inDet ) );
  412. Var *baseColor = (Var*)LangElement::find( "baseColor" );
  413. Var *outColor = (Var*)LangElement::find( "col" );
  414. meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n",
  415. outColor, outColor, baseColor, detailColor, detailBlend ) );
  416. meta->addStatement( new GenOp( " }\r\n" ) );
  417. output = meta;
  418. }
  419. ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  420. {
  421. Resources res;
  422. if ( getProcessIndex() == 0 )
  423. {
  424. // If this is the first detail pass then we
  425. // samples from the layer tex.
  426. res.numTex += 1;
  427. // If this material also does parallax then it
  428. // will generate the negative view vector and the
  429. // worldToTanget transform.
  430. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  431. res.numTexReg += 4;
  432. }
  433. // If this isn't the prepass then we sample
  434. // from the detail texture for diffuse coloring.
  435. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  436. res.numTex += 1;
  437. // If we have parallax for this layer then we'll also
  438. // be sampling the normal map for the parallax heightmap.
  439. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
  440. res.numTex += 1;
  441. // Finally we always send the detail texture
  442. // coord to the pixel shader.
  443. res.numTexReg += 1;
  444. return res;
  445. }
  446. void TerrainNormalMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
  447. const MaterialFeatureData &fd )
  448. {
  449. // We only need to process normals during the prepass.
  450. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  451. return;
  452. MultiLine *meta = new MultiLine;
  453. // Make sure the world to tangent transform
  454. // is created and available for the pixel shader.
  455. getOutViewToTangent( componentList, meta, fd );
  456. output = meta;
  457. }
  458. void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  459. const MaterialFeatureData &fd )
  460. {
  461. // We only need to process normals during the prepass.
  462. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  463. return;
  464. MultiLine *meta = new MultiLine;
  465. Var *viewToTangent = getInViewToTangent( componentList );
  466. // This var is read from GBufferConditionerHLSL and
  467. // used in the prepass output.
  468. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  469. if ( !gbNormal )
  470. {
  471. gbNormal = new Var;
  472. gbNormal->setName( "gbNormal" );
  473. gbNormal->setType( "float3" );
  474. meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) );
  475. }
  476. const U32 normalIndex = getProcessIndex();
  477. Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
  478. AssertFatal( detailBlend, "The detail blend is missing!" );
  479. // If we're using SM 3.0 then take advantage of
  480. // dynamic branching to skip layers per-pixel.
  481. if ( GFX->getPixelShaderVersion() >= 3.0f )
  482. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  483. meta->addStatement( new GenOp( " {\r\n" ) );
  484. // Get the normal map texture.
  485. Var *normalMap = _getNormalMapTex();
  486. /// Get the texture coord.
  487. Var *inDet = _getInDetailCoord( componentList );
  488. Var *inTex = getVertTexCoord( "texCoord" );
  489. // Sample the normal map.
  490. //
  491. // We take two normal samples and lerp between them for
  492. // side projection layers... else a single sample.
  493. LangElement *texOp;
  494. if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
  495. {
  496. texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
  497. normalMap, inDet, normalMap, inDet, inTex );
  498. }
  499. else
  500. texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
  501. // create bump normal
  502. Var *bumpNorm = new Var;
  503. bumpNorm->setName( "bumpNormal" );
  504. bumpNorm->setType( "float4" );
  505. LangElement *bumpNormDecl = new DecOp( bumpNorm );
  506. meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
  507. // Normalize is done later...
  508. // Note: The reverse mul order is intentional. Affine matrix.
  509. meta->addStatement( new GenOp( " @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n",
  510. gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
  511. // End the conditional block.
  512. meta->addStatement( new GenOp( " }\r\n" ) );
  513. // If this is the last normal map then we
  514. // can test to see the total blend value
  515. // to see if we should clip the result.
  516. //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
  517. //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
  518. output = meta;
  519. }
  520. ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  521. {
  522. Resources res;
  523. // We only need to process normals during the prepass.
  524. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  525. {
  526. // If this is the first normal map and there
  527. // are no parallax features then we will
  528. // generate the worldToTanget transform.
  529. if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  530. ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
  531. res.numTexReg = 3;
  532. res.numTex = 1;
  533. }
  534. return res;
  535. }
  536. void TerrainLightMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  537. const MaterialFeatureData &fd )
  538. {
  539. // grab connector texcoord register
  540. Var *inTex = (Var*)LangElement::find( "texCoord" );
  541. if ( !inTex )
  542. return;
  543. // Get the lightmap texture.
  544. Var *lightMap = new Var;
  545. lightMap->setType( "sampler2D" );
  546. lightMap->setName( "lightMapTex" );
  547. lightMap->uniform = true;
  548. lightMap->sampler = true;
  549. lightMap->constNum = Var::getTexUnitNum();
  550. MultiLine *meta = new MultiLine;
  551. // Find or create the lightMask value which is read by
  552. // RTLighting to mask out the lights.
  553. //
  554. // The first light is always the sunlight so we apply
  555. // the shadow mask to only the first channel.
  556. //
  557. Var *lightMask = (Var*)LangElement::find( "lightMask" );
  558. if ( !lightMask )
  559. {
  560. lightMask = new Var( "lightMask", "float4" );
  561. meta->addStatement( new GenOp( " @ = 1;\r\n", new DecOp( lightMask ) ) );
  562. }
  563. meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
  564. output = meta;
  565. }
  566. ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFeatureData &fd )
  567. {
  568. Resources res;
  569. res.numTex = 1;
  570. return res;
  571. }
  572. void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
  573. const MaterialFeatureData &fd )
  574. {
  575. Var *color = (Var*) LangElement::find( "col" );
  576. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  577. if ( !color || !blendTotal )
  578. return;
  579. MultiLine *meta = new MultiLine;
  580. meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
  581. meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
  582. output = meta;
  583. }