terrFeatureGLSL.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "terrain/glsl/terrFeatureGLSL.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_glsl_shader_features_for_terrain(GFXAdapterType type)
  36. {
  37. if(type != OpenGL)
  38. return;
  39. FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL );
  40. FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureGLSL( "Terrain Parallax Texture" ) );
  41. FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL );
  42. FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL );
  43. FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatGLSL );
  44. FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL );
  45. FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) );
  46. FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL );
  47. }
  48. };
  49. MODULE_BEGIN( TerrainFeatGLSL )
  50. MODULE_INIT_AFTER( ShaderGen )
  51. MODULE_INIT
  52. {
  53. SHADERGEN->getFeatureInitSignal().notify(&register_glsl_shader_features_for_terrain);
  54. }
  55. MODULE_END;
  56. Var* TerrainFeatGLSL::_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* TerrainFeatGLSL::_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( "vec4" );
  80. inDet->mapsToSampler = true;
  81. }
  82. return inDet;
  83. }
  84. Var* TerrainFeatGLSL::_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( "vec4" );
  95. inDet->mapsToSampler = true;
  96. }
  97. return inDet;
  98. }
  99. Var* TerrainFeatGLSL::_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* TerrainFeatGLSL::_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( "vec3" );
  122. detailInfo->setName( name );
  123. detailInfo->uniform = true;
  124. detailInfo->constSortPos = cspPotentialPrimitive;
  125. }
  126. return detailInfo;
  127. }
  128. Var* TerrainFeatGLSL::_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( "vec3" );
  136. detailInfo->setName( name );
  137. detailInfo->uniform = true;
  138. detailInfo->constSortPos = cspPotentialPrimitive;
  139. }
  140. return detailInfo;
  141. }
  142. void TerrainBaseMapFeatGLSL::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", "vec3" );
  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( "vec3" );
  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", "vec3" );
  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 TerrainBaseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  202. const MaterialFeatureData &fd )
  203. {
  204. // grab connector texcoord register
  205. Var *texCoord = getInTexCoord( "texCoord", "vec3", 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( "vec4" );
  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 TerrainBaseMapFeatGLSL::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. TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL()
  234. : mTorqueDep( "shaders/common/gl/torque.glsl" ),
  235. mTerrainDep( "shaders/common/terrain/terrain.glsl" )
  236. {
  237. addDependency( &mTorqueDep );
  238. addDependency( &mTerrainDep );
  239. }
  240. void TerrainDetailMapFeatGLSL::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", "vec3", 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( "vec3" );
  270. meta->addStatement( new GenOp( " @ = tMul( @, 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( "vec4" );
  289. outTex->mapsToSampler = true;
  290. // Get the detail scale and fade info.
  291. Var *detScaleAndFade = new Var;
  292. detScaleAndFade->setType( "vec4" );
  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 TerrainBaseMapFeatGLSL::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 TerrainDetailMapFeatGLSL::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( "vec3" );
  331. }
  332. negViewTS = new Var( "negViewTS", "vec3" );
  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( "vec4" );
  341. layerSample->setName( "layerSample" );
  342. // Get the layer texture var
  343. Var *layerTex = new Var;
  344. layerTex->setType( "sampler2D" );
  345. layerTex->setName( "layerTex" );
  346. layerTex->uniform = true;
  347. layerTex->sampler = true;
  348. layerTex->constNum = Var::getTexUnitNum();
  349. // Read the layer texture to get the samples.
  350. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  351. new DecOp( layerSample ), layerTex, inTex ) );
  352. }
  353. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  354. if ( !layerSize )
  355. {
  356. layerSize = new Var;
  357. layerSize->setType( "float" );
  358. layerSize->setName( "layerSize" );
  359. layerSize->uniform = true;
  360. layerSize->constSortPos = cspPass;
  361. }
  362. // Grab the incoming detail coord.
  363. Var *inDet = _getInDetailCoord( componentList );
  364. // Get the detail id.
  365. Var *detailInfo = _getDetailIdStrengthParallax();
  366. // Create the detail blend var.
  367. Var *detailBlend = new Var;
  368. detailBlend->setType( "float" );
  369. detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) );
  370. // Calculate the blend for this detail texture.
  371. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  372. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  373. // Get a var and accumulate the blend amount.
  374. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  375. if ( !blendTotal )
  376. {
  377. blendTotal = new Var;
  378. blendTotal->setName( "blendTotal" );
  379. blendTotal->setType( "float" );
  380. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  381. }
  382. // Add to the blend total.
  383. meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) );
  384. // If we had a parallax feature... then factor in the parallax
  385. // amount so that it fades out with the layer blending.
  386. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
  387. {
  388. // Get the rest of our inputs.
  389. Var *normalMap = _getNormalMapTex();
  390. // Call the library function to do the rest.
  391. if (fd.features.hasFeature(MFT_IsDXTnm, detailIndex))
  392. {
  393. meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n",
  394. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
  395. }
  396. else
  397. {
  398. meta->addStatement(new GenOp(" @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
  399. inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
  400. }
  401. }
  402. // If this is a prepass then we skip color.
  403. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  404. {
  405. // Check to see if we have a gbuffer normal.
  406. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  407. // If we have a gbuffer normal and we don't have a
  408. // normal map feature then we need to lerp in a
  409. // default normal else the normals below this layer
  410. // will show thru.
  411. if ( gbNormal &&
  412. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  413. {
  414. Var *viewToTangent = getInViewToTangent( componentList );
  415. meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n",
  416. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  417. }
  418. output = meta;
  419. return;
  420. }
  421. Var *detailColor = (Var*)LangElement::find( "detailColor" );
  422. if ( !detailColor )
  423. {
  424. detailColor = new Var;
  425. detailColor->setType( "vec4" );
  426. detailColor->setName( "detailColor" );
  427. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  428. }
  429. // Get the detail texture.
  430. Var *detailMap = new Var;
  431. detailMap->setType( "sampler2D" );
  432. detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
  433. detailMap->uniform = true;
  434. detailMap->sampler = true;
  435. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  436. // If we're using SM 3.0 then take advantage of
  437. // dynamic branching to skip layers per-pixel.
  438. if ( GFX->getPixelShaderVersion() >= 3.0f )
  439. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  440. meta->addStatement( new GenOp( " {\r\n" ) );
  441. // Note that we're doing the standard greyscale detail
  442. // map technique here which can darken and lighten the
  443. // diffuse texture.
  444. //
  445. // We take two color samples and lerp between them for
  446. // side projection layers... else a single sample.
  447. //
  448. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  449. {
  450. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  451. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  452. }
  453. else
  454. {
  455. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  456. detailColor, detailMap, inDet ) );
  457. }
  458. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  459. detailColor, detailInfo, inDet ) );
  460. Var *baseColor = (Var*)LangElement::find( "baseColor" );
  461. Var *outColor = (Var*)LangElement::find( "col" );
  462. meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n",
  463. outColor, outColor, baseColor, detailColor, detailBlend ) );
  464. meta->addStatement( new GenOp( " }\r\n" ) );
  465. output = meta;
  466. }
  467. ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  468. {
  469. Resources res;
  470. if ( getProcessIndex() == 0 )
  471. {
  472. // If this is the first detail pass then we
  473. // samples from the layer tex.
  474. res.numTex += 1;
  475. // If this material also does parallax then it
  476. // will generate the negative view vector and the
  477. // worldToTanget transform.
  478. if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  479. res.numTexReg += 4;
  480. }
  481. // If this isn't the prepass then we sample
  482. // from the detail texture for diffuse coloring.
  483. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  484. res.numTex += 1;
  485. // If we have parallax for this layer then we'll also
  486. // be sampling the normal map for the parallax heightmap.
  487. if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
  488. res.numTex += 1;
  489. // Finally we always send the detail texture
  490. // coord to the pixel shader.
  491. res.numTexReg += 1;
  492. return res;
  493. }
  494. TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL()
  495. : mTorqueDep( "shaders/common/gl/torque.glsl" ),
  496. mTerrainDep( "shaders/common/terrain/terrain.glsl" )
  497. {
  498. addDependency( &mTorqueDep );
  499. addDependency( &mTerrainDep );
  500. }
  501. void TerrainMacroMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
  502. const MaterialFeatureData &fd )
  503. {
  504. const U32 detailIndex = getProcessIndex();
  505. // Grab incoming texture coords... the base map feature
  506. // made sure this was created.
  507. Var *inTex = (Var*)LangElement::find( "texCoord" );
  508. AssertFatal( inTex, "The texture coord is missing!" );
  509. // Grab the input position.
  510. Var *inPos = (Var*)LangElement::find( "inPosition" );
  511. if ( !inPos )
  512. inPos = (Var*)LangElement::find( "position" );
  513. // Get the object space eye position.
  514. Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive );
  515. MultiLine *meta = new MultiLine;
  516. // Get the distance from the eye to this vertex.
  517. Var *dist = (Var*)LangElement::find( "macroDist" );
  518. if ( !dist )
  519. {
  520. dist = new Var;
  521. dist->setType( "float" );
  522. dist->setName( "macroDist" );
  523. meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
  524. new DecOp( dist ), inPos, eyePos ) );
  525. }
  526. // grab connector texcoord register
  527. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  528. Var *outTex = connectComp->getElement( RT_TEXCOORD );
  529. outTex->setName( String::ToString( "macroCoord%d", detailIndex ) );
  530. outTex->setStructName( "OUT" );
  531. outTex->setType( "vec4" );
  532. outTex->mapsToSampler = true;
  533. // Get the detail scale and fade info.
  534. Var *detScaleAndFade = new Var;
  535. detScaleAndFade->setType( "vec4" );
  536. detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) );
  537. detScaleAndFade->uniform = true;
  538. detScaleAndFade->constSortPos = cspPotentialPrimitive;
  539. // Setup the detail coord.
  540. meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
  541. // And sneak the detail fade thru the w detailCoord.
  542. meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
  543. outTex, detScaleAndFade, dist, detScaleAndFade ) );
  544. output = meta;
  545. }
  546. void TerrainMacroMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  547. const MaterialFeatureData &fd )
  548. {
  549. const U32 detailIndex = getProcessIndex();
  550. Var *inTex = getVertTexCoord( "texCoord" );
  551. MultiLine *meta = new MultiLine;
  552. // We need the negative tangent space view vector
  553. // as in parallax mapping we step towards the camera.
  554. Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
  555. if ( !negViewTS &&
  556. fd.features.hasFeature( MFT_TerrainParallaxMap ) )
  557. {
  558. Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
  559. if ( !inNegViewTS )
  560. {
  561. ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
  562. inNegViewTS = connectComp->getElement( RT_TEXCOORD );
  563. inNegViewTS->setName( "outNegViewTS" );
  564. inNegViewTS->setStructName( "IN" );
  565. inNegViewTS->setType( "vec3" );
  566. }
  567. negViewTS = new Var( "negViewTS", "vec3" );
  568. meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
  569. }
  570. // Get the layer samples.
  571. Var *layerSample = (Var*)LangElement::find( "layerSample" );
  572. if ( !layerSample )
  573. {
  574. layerSample = new Var;
  575. layerSample->setType( "vec4" );
  576. layerSample->setName( "layerSample" );
  577. // Get the layer texture var
  578. Var *layerTex = new Var;
  579. layerTex->setType( "sampler2D" );
  580. layerTex->setName( "macrolayerTex" );
  581. layerTex->uniform = true;
  582. layerTex->sampler = true;
  583. layerTex->constNum = Var::getTexUnitNum();
  584. // Read the layer texture to get the samples.
  585. meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
  586. new DecOp( layerSample ), layerTex, inTex ) );
  587. }
  588. Var *layerSize = (Var*)LangElement::find( "layerSize" );
  589. if ( !layerSize )
  590. {
  591. layerSize = new Var;
  592. layerSize->setType( "float" );
  593. layerSize->setName( "layerSize" );
  594. layerSize->uniform = true;
  595. layerSize->constSortPos = cspPass;
  596. }
  597. // Grab the incoming detail coord.
  598. Var *inDet = _getInMacroCoord( componentList );
  599. // Get the detail id.
  600. Var *detailInfo = _getMacroIdStrengthParallax();
  601. // Create the detail blend var.
  602. Var *detailBlend = new Var;
  603. detailBlend->setType( "float" );
  604. detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) );
  605. // Calculate the blend for this detail texture.
  606. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
  607. new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
  608. // Get a var and accumulate the blend amount.
  609. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  610. if ( !blendTotal )
  611. {
  612. blendTotal = new Var;
  613. //blendTotal->setName( "blendTotal" );
  614. blendTotal->setName( "blendTotal" );
  615. blendTotal->setType( "float" );
  616. meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
  617. }
  618. // Add to the blend total.
  619. meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) );
  620. // If this is a prepass then we skip color.
  621. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  622. {
  623. // Check to see if we have a gbuffer normal.
  624. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  625. // If we have a gbuffer normal and we don't have a
  626. // normal map feature then we need to lerp in a
  627. // default normal else the normals below this layer
  628. // will show thru.
  629. if ( gbNormal &&
  630. !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) )
  631. {
  632. Var *viewToTangent = getInViewToTangent( componentList );
  633. meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n",
  634. gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) );
  635. }
  636. output = meta;
  637. return;
  638. }
  639. Var *detailColor = (Var*)LangElement::find( "macroColor" );
  640. if ( !detailColor )
  641. {
  642. detailColor = new Var;
  643. detailColor->setType( "vec4" );
  644. detailColor->setName( "macroColor" );
  645. meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
  646. }
  647. // Get the detail texture.
  648. Var *detailMap = new Var;
  649. detailMap->setType( "sampler2D" );
  650. detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
  651. detailMap->uniform = true;
  652. detailMap->sampler = true;
  653. detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
  654. // If we're using SM 3.0 then take advantage of
  655. // dynamic branching to skip layers per-pixel.
  656. if ( GFX->getPixelShaderVersion() >= 3.0f )
  657. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  658. meta->addStatement( new GenOp( " {\r\n" ) );
  659. // Note that we're doing the standard greyscale detail
  660. // map technique here which can darken and lighten the
  661. // diffuse texture.
  662. //
  663. // We take two color samples and lerp between them for
  664. // side projection layers... else a single sample.
  665. //
  666. if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
  667. {
  668. meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
  669. detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
  670. }
  671. else
  672. {
  673. meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
  674. detailColor, detailMap, inDet ) );
  675. }
  676. meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
  677. detailColor, detailInfo, inDet ) );
  678. Var *outColor = (Var*)LangElement::find( "col" );
  679. meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n",
  680. outColor, outColor, outColor, detailColor, detailBlend ) );
  681. meta->addStatement( new GenOp( " }\r\n" ) );
  682. output = meta;
  683. }
  684. ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  685. {
  686. Resources res;
  687. if ( getProcessIndex() == 0 )
  688. {
  689. // If this is the first detail pass then we
  690. // samples from the layer tex.
  691. res.numTex += 1;
  692. }
  693. // If this isn't the prepass then we sample
  694. // from the detail texture for diffuse coloring.
  695. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  696. res.numTex += 1;
  697. // Finally we always send the detail texture
  698. // coord to the pixel shader.
  699. res.numTexReg += 1;
  700. return res;
  701. }
  702. void TerrainNormalMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
  703. const MaterialFeatureData &fd )
  704. {
  705. // We only need to process normals during the prepass.
  706. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  707. return;
  708. MultiLine *meta = new MultiLine;
  709. // Make sure the world to tangent transform
  710. // is created and available for the pixel shader.
  711. getOutViewToTangent( componentList, meta, fd );
  712. output = meta;
  713. }
  714. void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  715. const MaterialFeatureData &fd )
  716. {
  717. // We only need to process normals during the prepass.
  718. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  719. return;
  720. MultiLine *meta = new MultiLine;
  721. Var *viewToTangent = getInViewToTangent( componentList );
  722. // This var is read from GBufferConditionerGLSL and
  723. // used in the prepass output.
  724. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  725. if ( !gbNormal )
  726. {
  727. gbNormal = new Var;
  728. gbNormal->setName( "gbNormal" );
  729. gbNormal->setType( "vec3" );
  730. meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) );
  731. }
  732. const U32 normalIndex = getProcessIndex();
  733. Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
  734. AssertFatal( detailBlend, "The detail blend is missing!" );
  735. // If we're using SM 3.0 then take advantage of
  736. // dynamic branching to skip layers per-pixel.
  737. if ( GFX->getPixelShaderVersion() >= 3.0f )
  738. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  739. meta->addStatement( new GenOp( " {\r\n" ) );
  740. // Get the normal map texture.
  741. Var *normalMap = _getNormalMapTex();
  742. /// Get the texture coord.
  743. Var *inDet = _getInDetailCoord( componentList );
  744. Var *inTex = getVertTexCoord( "texCoord" );
  745. // Sample the normal map.
  746. //
  747. // We take two normal samples and lerp between them for
  748. // side projection layers... else a single sample.
  749. LangElement *texOp;
  750. if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
  751. {
  752. texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
  753. normalMap, inDet, normalMap, inDet, inTex );
  754. }
  755. else
  756. texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
  757. // create bump normal
  758. Var *bumpNorm = new Var;
  759. bumpNorm->setName( "bumpNormal" );
  760. bumpNorm->setType( "vec4" );
  761. LangElement *bumpNormDecl = new DecOp( bumpNorm );
  762. meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
  763. // Normalize is done later...
  764. // Note: The reverse mul order is intentional. Affine matrix.
  765. meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
  766. gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
  767. // End the conditional block.
  768. meta->addStatement( new GenOp( " }\r\n" ) );
  769. // If this is the last normal map then we
  770. // can test to see the total blend value
  771. // to see if we should clip the result.
  772. //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
  773. //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
  774. output = meta;
  775. }
  776. ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  777. {
  778. Resources res;
  779. // We only need to process normals during the prepass.
  780. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  781. {
  782. // If this is the first normal map and there
  783. // are no parallax features then we will
  784. // generate the worldToTanget transform.
  785. if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  786. ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
  787. res.numTexReg = 3;
  788. res.numTex = 1;
  789. }
  790. return res;
  791. }
  792. void TerrainLightMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  793. const MaterialFeatureData &fd )
  794. {
  795. // grab connector texcoord register
  796. Var *inTex = (Var*)LangElement::find( "texCoord" );
  797. if ( !inTex )
  798. return;
  799. // Get the lightmap texture.
  800. Var *lightMap = new Var;
  801. lightMap->setType( "sampler2D" );
  802. lightMap->setName( "lightMapTex" );
  803. lightMap->uniform = true;
  804. lightMap->sampler = true;
  805. lightMap->constNum = Var::getTexUnitNum();
  806. MultiLine *meta = new MultiLine;
  807. // Find or create the lightMask value which is read by
  808. // RTLighting to mask out the lights.
  809. //
  810. // The first light is always the sunlight so we apply
  811. // the shadow mask to only the first channel.
  812. //
  813. Var *lightMask = (Var*)LangElement::find( "lightMask" );
  814. if ( !lightMask )
  815. {
  816. lightMask = new Var( "lightMask", "vec4" );
  817. meta->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask ) ) );
  818. }
  819. meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
  820. output = meta;
  821. }
  822. ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  823. {
  824. Resources res;
  825. res.numTex = 1;
  826. return res;
  827. }
  828. void TerrainAdditiveFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  829. const MaterialFeatureData &fd )
  830. {
  831. Var *color = (Var*) LangElement::find( "col" );
  832. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  833. if ( !color || !blendTotal )
  834. return;
  835. MultiLine *meta = new MultiLine;
  836. meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
  837. meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
  838. output = meta;
  839. }