terrFeatureGLSL.cpp 38 KB

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