terrFeatureGLSL.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  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( " @ = max( @, @ );\r\n", blendTotal, 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( @, tGetMatrix3Row(@, 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( "vec4" );
  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( " @ = lerp( @, @ + @, @ );\r\n",
  455. outColor, outColor, baseColor, detailColor, detailBlend ) );
  456. meta->addStatement( new GenOp( " }\r\n" ) );
  457. output = meta;
  458. }
  459. ShaderFeature::Resources TerrainDetailMapFeatGLSL::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. TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL()
  487. : mTorqueDep( "shaders/common/gl/torque.glsl" ),
  488. mTerrainDep( "shaders/common/terrain/terrain.glsl" )
  489. {
  490. addDependency( &mTorqueDep );
  491. addDependency( &mTerrainDep );
  492. }
  493. void TerrainMacroMapFeatGLSL::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", "vec3", 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( "vec4" );
  524. outTex->mapsToSampler = true;
  525. // Get the detail scale and fade info.
  526. Var *detScaleAndFade = new Var;
  527. detScaleAndFade->setType( "vec4" );
  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 TerrainMacroMapFeatGLSL::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( "vec3" );
  558. }
  559. negViewTS = new Var( "negViewTS", "vec3" );
  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( "vec4" );
  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( " @ = max( @, @ );\r\n", blendTotal, 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( @, tGetMatrix3Row(@, 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( "vec4" );
  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( " @ = lerp( @, @ + @, @ );\r\n",
  673. outColor, outColor, outColor, detailColor, detailBlend ) );
  674. //outColor, outColor, baseColor, detailColor, detailBlend ) );
  675. meta->addStatement( new GenOp( " }\r\n" ) );
  676. output = meta;
  677. }
  678. ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  679. {
  680. Resources res;
  681. if ( getProcessIndex() == 0 )
  682. {
  683. // If this is the first detail pass then we
  684. // samples from the layer tex.
  685. res.numTex += 1;
  686. }
  687. // If this isn't the prepass then we sample
  688. // from the detail texture for diffuse coloring.
  689. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  690. res.numTex += 1;
  691. // Finally we always send the detail texture
  692. // coord to the pixel shader.
  693. res.numTexReg += 1;
  694. return res;
  695. }
  696. void TerrainNormalMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
  697. const MaterialFeatureData &fd )
  698. {
  699. // We only need to process normals during the prepass.
  700. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  701. return;
  702. MultiLine *meta = new MultiLine;
  703. // Make sure the world to tangent transform
  704. // is created and available for the pixel shader.
  705. getOutViewToTangent( componentList, meta, fd );
  706. output = meta;
  707. }
  708. void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  709. const MaterialFeatureData &fd )
  710. {
  711. // We only need to process normals during the prepass.
  712. if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
  713. return;
  714. MultiLine *meta = new MultiLine;
  715. Var *viewToTangent = getInViewToTangent( componentList );
  716. // This var is read from GBufferConditionerGLSL and
  717. // used in the prepass output.
  718. Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
  719. if ( !gbNormal )
  720. {
  721. gbNormal = new Var;
  722. gbNormal->setName( "gbNormal" );
  723. gbNormal->setType( "vec3" );
  724. meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) );
  725. }
  726. const U32 normalIndex = getProcessIndex();
  727. Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
  728. AssertFatal( detailBlend, "The detail blend is missing!" );
  729. // If we're using SM 3.0 then take advantage of
  730. // dynamic branching to skip layers per-pixel.
  731. if ( GFX->getPixelShaderVersion() >= 3.0f )
  732. meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
  733. meta->addStatement( new GenOp( " {\r\n" ) );
  734. // Get the normal map texture.
  735. Var *normalMap = _getNormalMapTex();
  736. /// Get the texture coord.
  737. Var *inDet = _getInDetailCoord( componentList );
  738. Var *inTex = getVertTexCoord( "texCoord" );
  739. // Sample the normal map.
  740. //
  741. // We take two normal samples and lerp between them for
  742. // side projection layers... else a single sample.
  743. LangElement *texOp;
  744. if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
  745. {
  746. texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
  747. normalMap, inDet, normalMap, inDet, inTex );
  748. }
  749. else
  750. texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
  751. // create bump normal
  752. Var *bumpNorm = new Var;
  753. bumpNorm->setName( "bumpNormal" );
  754. bumpNorm->setType( "vec4" );
  755. LangElement *bumpNormDecl = new DecOp( bumpNorm );
  756. meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
  757. // Normalize is done later...
  758. // Note: The reverse mul order is intentional. Affine matrix.
  759. meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
  760. gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
  761. // End the conditional block.
  762. meta->addStatement( new GenOp( " }\r\n" ) );
  763. // If this is the last normal map then we
  764. // can test to see the total blend value
  765. // to see if we should clip the result.
  766. //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
  767. //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
  768. output = meta;
  769. }
  770. ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  771. {
  772. Resources res;
  773. // We only need to process normals during the prepass.
  774. if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
  775. {
  776. // If this is the first normal map and there
  777. // are no parallax features then we will
  778. // generate the worldToTanget transform.
  779. if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
  780. ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
  781. res.numTexReg = 3;
  782. res.numTex = 1;
  783. }
  784. return res;
  785. }
  786. void TerrainLightMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  787. const MaterialFeatureData &fd )
  788. {
  789. // grab connector texcoord register
  790. Var *inTex = (Var*)LangElement::find( "texCoord" );
  791. if ( !inTex )
  792. return;
  793. // Get the lightmap texture.
  794. Var *lightMap = new Var;
  795. lightMap->setType( "sampler2D" );
  796. lightMap->setName( "lightMapTex" );
  797. lightMap->uniform = true;
  798. lightMap->sampler = true;
  799. lightMap->constNum = Var::getTexUnitNum();
  800. MultiLine *meta = new MultiLine;
  801. // Find or create the lightMask value which is read by
  802. // RTLighting to mask out the lights.
  803. //
  804. // The first light is always the sunlight so we apply
  805. // the shadow mask to only the first channel.
  806. //
  807. Var *lightMask = (Var*)LangElement::find( "lightMask" );
  808. if ( !lightMask )
  809. {
  810. lightMask = new Var( "lightMask", "vec4" );
  811. meta->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask ) ) );
  812. }
  813. meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
  814. output = meta;
  815. }
  816. ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData &fd )
  817. {
  818. Resources res;
  819. res.numTex = 1;
  820. return res;
  821. }
  822. void TerrainAdditiveFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
  823. const MaterialFeatureData &fd )
  824. {
  825. Var *color = (Var*) LangElement::find( "col" );
  826. Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
  827. if ( !color || !blendTotal )
  828. return;
  829. MultiLine *meta = new MultiLine;
  830. meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
  831. meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
  832. output = meta;
  833. }