Torque3D Documentation / _generateds / terrFeatureHLSL.cpp

terrFeatureHLSL.cpp

Engine/source/terrain/hlsl/terrFeatureHLSL.cpp

More...

Public Variables

Detailed Description

Public Variables

 MODULE_END 
 MODULE_INIT 
   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platform.h"
  25#include "terrain/hlsl/terrFeatureHLSL.h"
  26
  27#include "terrain/terrFeatureTypes.h"
  28#include "materials/materialFeatureTypes.h"
  29#include "materials/materialFeatureData.h"
  30#include "materials/processedMaterial.h"
  31#include "gfx/gfxDevice.h"
  32#include "shaderGen/langElement.h"
  33#include "shaderGen/shaderOp.h"
  34#include "shaderGen/featureMgr.h"
  35#include "shaderGen/shaderGen.h"
  36#include "core/module.h"
  37
  38namespace 
  39{
  40   void register_hlsl_shader_features_for_terrain(GFXAdapterType type)
  41   {
  42      if (type != Direct3D9 && type != Direct3D9_360 && type != Direct3D11)
  43         return;
  44
  45      FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatHLSL );
  46      FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) );   
  47      FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL );
  48      FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatHLSL );
  49      FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatHLSL );
  50      FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL );
  51      FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
  52      FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );     
  53      FEATUREMGR->registerFeature( MFT_DeferredTerrainBaseMap, new TerrainBaseMapFeatHLSL );
  54      FEATUREMGR->registerFeature( MFT_DeferredTerrainMacroMap, new TerrainMacroMapFeatHLSL );
  55      FEATUREMGR->registerFeature( MFT_DeferredTerrainDetailMap, new TerrainDetailMapFeatHLSL );
  56      FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL );
  57   }
  58};
  59
  60MODULE_BEGIN( TerrainFeatHLSL )
  61
  62   MODULE_INIT_AFTER( ShaderGen )
  63
  64   MODULE_INIT
  65   {      
  66      SHADERGEN->getFeatureInitSignal().notify(&register_hlsl_shader_features_for_terrain);
  67   }
  68
  69MODULE_END;
  70
  71
  72TerrainFeatHLSL::TerrainFeatHLSL()
  73   : mTorqueDep( "shaders/common/torque.hlsl" )
  74{      
  75   addDependency( &mTorqueDep );
  76}
  77
  78Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp )
  79{
  80   Var *theVar = (Var*)LangElement::find( name );
  81   if ( !theVar )
  82   {
  83      theVar = new Var;
  84      theVar->setType( type );
  85      theVar->setName( name );
  86      theVar->uniform = true;
  87      theVar->constSortPos = csp;
  88   }
  89
  90   return theVar;
  91}
  92
  93Var* TerrainFeatHLSL::_getInDetailCoord( Vector<ShaderComponent*> &componentList )
  94{
  95   String name( String::ToString( "detCoord%d", getProcessIndex() ) );
  96   Var *inDet = (Var*)LangElement::find( name );
  97
  98   if ( !inDet )
  99   {
 100      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 101
 102      inDet = connectComp->getElement( RT_TEXCOORD );
 103      inDet->setName( name );
 104      inDet->setStructName( "IN" );
 105      inDet->setType( "float4" );
 106      inDet->mapsToSampler = true;
 107   }
 108
 109   return inDet;
 110}
 111
 112Var* TerrainFeatHLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList )
 113{
 114   String name( String::ToString( "macroCoord%d", getProcessIndex() ) );
 115   Var *inDet = (Var*)LangElement::find( name );
 116
 117   if ( !inDet )
 118   {
 119      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 120
 121      inDet = connectComp->getElement( RT_TEXCOORD );
 122      inDet->setName( name );
 123      inDet->setStructName( "IN" );
 124      inDet->setType( "float4" );
 125      inDet->mapsToSampler = true;
 126   }
 127
 128   return inDet;
 129}
 130
 131Var* TerrainFeatHLSL::_getNormalMapTex()
 132{
 133   String name(String::ToString("normalMap%d", getProcessIndex()));
 134   Var *normalMap = (Var*)LangElement::find(name);
 135
 136   if (!normalMap)
 137   {
 138      normalMap = new Var;
 139      if (mIsDirect3D11)
 140         normalMap->setType("SamplerState");
 141      else
 142         normalMap->setType("sampler2D");
 143
 144      normalMap->setName(name);
 145      normalMap->uniform = true;
 146      normalMap->sampler = true;
 147      normalMap->constNum = Var::getTexUnitNum();
 148   }
 149
 150   return normalMap;
 151}
 152
 153Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
 154{
 155   String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
 156
 157   Var *detailInfo = (Var*)LangElement::find( name );
 158   if ( !detailInfo )
 159   {
 160      detailInfo = new Var;
 161      detailInfo->setType( "float3" );
 162      detailInfo->setName( name );
 163      detailInfo->uniform = true;
 164      detailInfo->constSortPos = cspPotentialPrimitive;
 165   }
 166
 167   return detailInfo;
 168}
 169
 170Var* TerrainFeatHLSL::_getMacroIdStrengthParallax()
 171{
 172   String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) );
 173
 174   Var *detailInfo = (Var*)LangElement::find( name );
 175   if ( !detailInfo )
 176   {
 177      detailInfo = new Var;
 178      detailInfo->setType( "float3" );
 179      detailInfo->setName( name );
 180      detailInfo->uniform = true;
 181      detailInfo->constSortPos = cspPotentialPrimitive;
 182   }
 183
 184   return detailInfo;
 185}
 186
 187
 188void TerrainBaseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
 189                                          const MaterialFeatureData &fd )
 190{
 191   MultiLine *meta = new MultiLine;
 192   output = meta;
 193
 194   // Generate the incoming texture var.
 195   Var *inTex;
 196   {
 197      Var *inPos = (Var*)LangElement::find( "inPosition" );
 198      if ( !inPos )
 199         inPos = (Var*)LangElement::find( "position" );
 200
 201      inTex = new Var( "texCoord", "float3" );
 202
 203      Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass );
 204
 205      // NOTE: The y coord here should be negative to have
 206      // the texture maps not end up flipped which also caused
 207      // normal and parallax mapping to be incorrect.
 208      //
 209      // This mistake early in development means that the layer
 210      // id bilinear blend depends on it being that way.
 211      //
 212      // So instead i fixed this by flipping the base and detail
 213      // coord y scale to compensate when rendering.
 214      //
 215      meta->addStatement( new GenOp( "   @ = @.xyz * float3( @, @, -@ );\r\n", 
 216         new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
 217   }
 218
 219   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 220
 221   // Pass the texture coord to the pixel shader.
 222   Var *outTex = connectComp->getElement( RT_TEXCOORD );
 223   outTex->setName( "outTexCoord" );
 224   outTex->setStructName( "OUT" );
 225   outTex->setType( "float3" );
 226   outTex->mapsToSampler = true;
 227   meta->addStatement( new GenOp( "   @.xy = @.xy;\r\n", outTex, inTex ) );
 228
 229   // If this shader has a side projected layer then we 
 230   // pass the dot product between the +Y and the normal
 231   // thru outTexCoord.z for use in blending the textures.
 232   if ( fd.features.hasFeature( MFT_TerrainSideProject ) )
 233   {
 234      Var *inNormal = (Var*)LangElement::find( "normal" );
 235      meta->addStatement( 
 236         new GenOp( "   @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n", 
 237            outTex, inNormal, inNormal ) );
 238   }
 239   else
 240      meta->addStatement( new GenOp( "   @.z = 0;\r\n", outTex ) );
 241
 242   // HACK: This is sort of lazy... we generate the tanget
 243   // vector here so that we're sure it exists in the parallax
 244   // and normal features which will expect "T" to exist.
 245   //
 246   // If this shader doesn't use it the shader compiler will
 247   // optimize away this code.
 248   //
 249   Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
 250   Var *inTanget = new Var( "T", "float3" );
 251   Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
 252   meta->addStatement( new GenOp( "   @ = normalize( float3( @, 0, @ ) );\r\n", 
 253      new DecOp( inTanget ), squareSize, inTangentZ ) );
 254}
 255
 256void TerrainBaseMapFeatHLSL::processPix(  Vector<ShaderComponent*> &componentList, 
 257                                          const MaterialFeatureData &fd )
 258{
 259   // grab connector texcoord register
 260   Var *texCoord = getInTexCoord( "texCoord", "float3", true, componentList );
 261
 262   // create texture var
 263   Var *diffuseMap = new Var;
 264   diffuseMap->setType( "sampler2D" );
 265   diffuseMap->setName( "baseTexMap" );
 266   diffuseMap->uniform = true;
 267   diffuseMap->sampler = true;
 268   diffuseMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
 269
 270   MultiLine *meta = new MultiLine;
 271
 272   Var *baseColor = new Var;
 273   baseColor->setType( "float4" );
 274   baseColor->setName( "baseColor" );
 275   if (mIsDirect3D11)
 276   {
 277      diffuseMap->setType("SamplerState");
 278      Var *diffuseTex = new Var;
 279      diffuseTex->setType("Texture2D");
 280      diffuseTex->setName("baseTexture");
 281      diffuseTex->uniform = true;
 282      diffuseTex->texture = true;
 283      diffuseTex->constNum = diffuseMap->constNum;
 284      meta->addStatement(new GenOp("   @ = @.Sample( @, @.xy );\r\n", new DecOp(baseColor), diffuseTex, diffuseMap, texCoord));
 285   }
 286   else
 287   {
 288      meta->addStatement(new GenOp("   @ = tex2D( @, @.xy );\r\n", new DecOp(baseColor), diffuseMap, texCoord));
 289   }
 290
 291   meta->addStatement(new GenOp("   @ = toLinear(@);\r\n", baseColor, baseColor));
 292
 293   ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
 294
 295   if (fd.features.hasFeature(MFT_isDeferred))
 296   {
 297      target= ShaderFeature::RenderTarget1;
 298   }
 299
 300   meta->addStatement( new GenOp( "   @;\r\n", assignColor( baseColor, Material::Mul,NULL,target ) ) );
 301   output = meta;
 302}
 303
 304ShaderFeature::Resources TerrainBaseMapFeatHLSL::getResources( const MaterialFeatureData &fd )
 305{
 306   Resources res; 
 307   res.numTexReg = 1;
 308      res.numTex = 1;
 309
 310   return res;
 311}
 312
 313U32 TerrainBaseMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
 314{
 315   return fd.features[MFT_DeferredTerrainBaseMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
 316}
 317
 318TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL()
 319   :  mTorqueDep( "shaders/common/torque.hlsl" ),
 320      mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
 321      
 322{
 323   addDependency( &mTorqueDep );
 324   addDependency( &mTerrainDep );
 325}
 326
 327void TerrainDetailMapFeatHLSL::processVert(  Vector<ShaderComponent*> &componentList, 
 328                                             const MaterialFeatureData &fd )
 329{
 330   const S32 detailIndex = getProcessIndex();
 331
 332   // Grab incoming texture coords... the base map feature
 333   // made sure this was created.
 334   Var *inTex = (Var*)LangElement::find( "texCoord" );
 335   AssertFatal( inTex, "The texture coord is missing!" );
 336
 337   // Grab the input position.
 338   Var *inPos = (Var*)LangElement::find( "inPosition" );
 339   if ( !inPos )
 340      inPos = (Var*)LangElement::find( "position" );
 341
 342   // Get the object space eye position.
 343   Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
 344
 345   MultiLine *meta = new MultiLine;
 346
 347   // If we have parallax mapping then make sure we've sent
 348   // the negative view vector to the pixel shader.
 349   if (  fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
 350         !LangElement::find( "outNegViewTS" ) )
 351   {
 352      // Get the object to tangent transform which
 353      // will consume 3 output registers.
 354      Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd );
 355
 356      // Now use a single output register to send the negative
 357      // view vector in tangent space to the pixel shader.
 358      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 359      Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD );
 360      outNegViewTS->setName( "outNegViewTS" );
 361      outNegViewTS->setStructName( "OUT" );
 362      outNegViewTS->setType( "float3" );
 363      meta->addStatement( new GenOp( "   @ = mul( @, float3( @ - @.xyz ) );\r\n", 
 364         outNegViewTS, objToTangentSpace, eyePos, inPos ) );
 365   }
 366
 367   // Get the distance from the eye to this vertex.
 368   Var *dist = (Var*)LangElement::find( "dist" );
 369   if ( !dist )
 370   {
 371      dist = new Var;
 372      dist->setType( "float" );
 373      dist->setName( "dist" );  
 374
 375      meta->addStatement( new GenOp( "   @ = distance( @.xyz, @ );\r\n", 
 376                                       new DecOp( dist ), inPos, eyePos ) );
 377   }
 378
 379   // grab connector texcoord register
 380   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 381   Var *outTex = connectComp->getElement( RT_TEXCOORD );
 382   outTex->setName( String::ToString( "detCoord%d", detailIndex ) );
 383   outTex->setStructName( "OUT" );
 384   outTex->setType( "float4" );
 385   outTex->mapsToSampler = true;
 386
 387   // Get the detail scale and fade info.
 388   Var *detScaleAndFade = new Var;
 389   detScaleAndFade->setType( "float4" );
 390   detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) );
 391   detScaleAndFade->uniform = true;
 392   detScaleAndFade->constSortPos = cspPotentialPrimitive;
 393
 394   // Setup the detail coord.
 395   //
 396   // NOTE: You see here we scale the texture coord by 'xyx'
 397   // to generate the detail coord.  This y is here because
 398   // its scale is flipped to correct for the non negative y
 399   // in texCoord.
 400   //
 401   // See TerrainBaseMapFeatHLSL::processVert().
 402   //
 403   meta->addStatement( new GenOp( "   @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
 404
 405   // And sneak the detail fade thru the w detailCoord.
 406   meta->addStatement( new GenOp( "   @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", 
 407                                    outTex, detScaleAndFade, dist, detScaleAndFade ) );   
 408
 409   output = meta;
 410}
 411
 412void TerrainDetailMapFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
 413                                             const MaterialFeatureData &fd )
 414{
 415   const S32 detailIndex = getProcessIndex();
 416   Var *inTex = getVertTexCoord( "texCoord" );
 417   
 418   MultiLine *meta = new MultiLine;
 419
 420   // We need the negative tangent space view vector
 421   // as in parallax mapping we step towards the camera.
 422   Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
 423   if (  !negViewTS &&
 424         fd.features.hasFeature( MFT_TerrainParallaxMap ) )
 425   {
 426      Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
 427      if ( !inNegViewTS )
 428      {
 429         ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 430         inNegViewTS = connectComp->getElement( RT_TEXCOORD );
 431         inNegViewTS->setName( "outNegViewTS" );
 432         inNegViewTS->setStructName( "IN" );
 433         inNegViewTS->setType( "float3" );
 434      }
 435
 436      negViewTS = new Var( "negViewTS", "float3" );
 437      meta->addStatement( new GenOp( "   @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
 438   }
 439
 440   // Get the layer samples.
 441   Var *layerSample = (Var*)LangElement::find( "layerSample" );
 442   if ( !layerSample )
 443   {
 444      layerSample = new Var;
 445      layerSample->setType( "float4" );
 446      layerSample->setName( "layerSample" );
 447
 448      // Get the layer texture var
 449      Var *layerTex = new Var;
 450      layerTex->setType( "sampler2D" );
 451      layerTex->setName( "layerTex" );
 452      layerTex->uniform = true;
 453      layerTex->sampler = true;
 454      layerTex->constNum = Var::getTexUnitNum();
 455
 456      if (mIsDirect3D11)
 457      {
 458         layerTex->setType("SamplerState");
 459         Var* layerTexObj = new Var;
 460         layerTexObj->setName("layerTexObj");
 461         layerTexObj->setType("Texture2D");
 462         layerTexObj->uniform = true;
 463         layerTexObj->texture = true;
 464         layerTexObj->constNum = layerTex->constNum;
 465         // Read the layer texture to get the samples.
 466         meta->addStatement(new GenOp("   @ = round( @.Sample( @, @.xy ) * 255.0f );\r\n",
 467            new DecOp(layerSample), layerTexObj, layerTex, inTex));
 468      }
 469      else
 470      {
 471         // Read the layer texture to get the samples.
 472         meta->addStatement(new GenOp("   @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
 473            new DecOp(layerSample), layerTex, inTex));
 474      }
 475   }
 476
 477   Var *layerSize = (Var*)LangElement::find( "layerSize" );
 478   if ( !layerSize )
 479   {
 480      layerSize = new Var;
 481      layerSize->setType( "float" );
 482      layerSize->setName( "layerSize" );
 483      layerSize->uniform = true;
 484      layerSize->constSortPos = cspPass;
 485   }
 486
 487   // Grab the incoming detail coord.
 488   Var *inDet = _getInDetailCoord( componentList );
 489
 490   // Get the detail id.
 491   Var *detailInfo = _getDetailIdStrengthParallax();
 492
 493   // Create the detail blend var.
 494   Var *detailBlend = new Var;
 495   detailBlend->setType( "float" );
 496   detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) );
 497
 498   // Calculate the blend for this detail texture.
 499   meta->addStatement( new GenOp( "   @ = calcBlend( @.x, @.xy, @, @ );\r\n", 
 500                                    new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
 501
 502   // Get a var and accumulate the blend amount.
 503   Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
 504   if ( !blendTotal )
 505   {
 506      blendTotal = new Var;
 507      blendTotal->setName( "blendTotal" );
 508      blendTotal->setType( "float" );
 509      meta->addStatement( new GenOp( "   @ = 0;\r\n", new DecOp( blendTotal ) ) );
 510   }
 511
 512   // Add to the blend total.
 513
 514   meta->addStatement(new GenOp("   @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
 515
 516   // If we had a parallax feature... then factor in the parallax
 517   // amount so that it fades out with the layer blending.
 518   if (fd.features.hasFeature(MFT_TerrainParallaxMap, detailIndex))
 519   {
 520      // Get the rest of our inputs.
 521      Var *normalMap = _getNormalMapTex();
 522
 523      if (mIsDirect3D11)
 524      {
 525         String name(String::ToString("normalMapTex%d", getProcessIndex()));
 526         Var *normalMapTex = (Var*)LangElement::find(name);
 527
 528         if (!normalMapTex)
 529         {
 530            normalMapTex = new Var;
 531            normalMapTex->setName(String::ToString("normalMapTex%d", getProcessIndex()));
 532            normalMapTex->setType("Texture2D");
 533            normalMapTex->uniform = true;
 534            normalMapTex->texture = true;
 535            normalMapTex->constNum = normalMap->constNum;
 536         }
 537
 538         // Call the library function to do the rest.
 539         if (fd.features.hasFeature(MFT_IsDXTnm, detailIndex))
 540         {
 541            meta->addStatement(new GenOp("   @.xy += parallaxOffsetDxtnm( @, @, @.xy, @, @.z * @ );\r\n",
 542               inDet, normalMapTex, normalMap, inDet, negViewTS, detailInfo, detailBlend));
 543         }
 544         else
 545         {
 546            meta->addStatement(new GenOp("   @.xy += parallaxOffset( @, @, @.xy, @, @.z * @ );\r\n",
 547               inDet, normalMapTex, normalMap, inDet, negViewTS, detailInfo, detailBlend));
 548         }
 549
 550      }
 551      else
 552      {
 553         // Call the library function to do the rest.
 554         if (fd.features.hasFeature(MFT_IsDXTnm, detailIndex))
 555         {
 556            meta->addStatement(new GenOp("   @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n",
 557               inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
 558         }
 559         else
 560         {
 561            meta->addStatement(new GenOp("   @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
 562               inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
 563         }
 564      }
 565   }
 566
 567   Var *detailColor = (Var*)LangElement::find( "detailColor" ); 
 568   if ( !detailColor )
 569   {
 570      detailColor = new Var;
 571      detailColor->setType( "float4" );
 572      detailColor->setName( "detailColor" );
 573      meta->addStatement( new GenOp( "   @;\r\n", new DecOp( detailColor ) ) );
 574   }
 575
 576   // Get the detail texture.
 577   Var *detailMap = new Var;
 578   detailMap->setType( "sampler2D" );
 579   detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
 580   detailMap->uniform = true;
 581   detailMap->sampler = true;
 582   detailMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
 583
 584   // If we're using SM 3.0 then take advantage of 
 585   // dynamic branching to skip layers per-pixel.
 586
 587
 588   if ( GFX->getPixelShaderVersion() >= 3.0f )
 589      meta->addStatement( new GenOp( "   if ( @ > 0.0f )\r\n", detailBlend ) );
 590
 591   meta->addStatement( new GenOp( "   {\r\n" ) );
 592
 593   // Note that we're doing the standard greyscale detail 
 594   // map technique here which can darken and lighten the 
 595   // diffuse texture.
 596   //
 597   // We take two color samples and lerp between them for
 598   // side projection layers... else a single sample.
 599   //
 600
 601   //Sampled detail texture that is not expanded
 602   if (mIsDirect3D11)
 603   {
 604      detailMap->setType("SamplerState");
 605      Var* detailTex = new Var;
 606      detailTex->setName(String::ToString("detailTex%d", detailIndex));
 607      detailTex->setType("Texture2D");
 608      detailTex->uniform = true;
 609      detailTex->texture = true;
 610      detailTex->constNum = detailMap->constNum;
 611
 612      if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
 613      {
 614
 615         meta->addStatement(new GenOp("      @ = ( lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
 616            detailColor, detailTex, detailMap, inDet, detailTex, detailMap, inDet, inTex));
 617      }
 618      else
 619      {
 620         meta->addStatement(new GenOp("      @ = ( @.Sample( @, @.xy ) * 2.0 ) - 1.0;\r\n",
 621            detailColor, detailTex, detailMap, inDet));
 622      }
 623   }
 624   else
 625   {
 626      if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
 627      {
 628
 629         meta->addStatement(new GenOp("      @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
 630            detailColor, detailMap, inDet, detailMap, inDet, inTex));
 631      }
 632      else
 633      {
 634         meta->addStatement(new GenOp("      @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
 635            detailColor, detailMap, inDet));
 636      }
 637   }
 638
 639   meta->addStatement( new GenOp( "      @ *= @.y * @.w;\r\n",
 640                                    detailColor, detailInfo, inDet ) );
 641
 642   ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
 643
 644   if(fd.features.hasFeature( MFT_DeferredTerrainDetailMap ))
 645      target= ShaderFeature::RenderTarget1;
 646
 647   Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) );
 648
 649   meta->addStatement( new GenOp( "      @ += @ * @;\r\n",
 650                                    outColor, detailColor, detailBlend));
 651
 652   meta->addStatement( new GenOp( "   }\r\n" ) );
 653
 654   output = meta;
 655}
 656
 657ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialFeatureData &fd )
 658{
 659   Resources res;
 660
 661   if ( getProcessIndex() == 0 )
 662   {
 663      // If this is the first detail pass then we 
 664      // samples from the layer tex.
 665      res.numTex += 1;
 666
 667      // If this material also does parallax then it
 668      // will generate the negative view vector and the
 669      // worldToTanget transform.
 670      if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
 671         res.numTexReg += 4;
 672   }
 673
 674   // sample from the detail texture for diffuse coloring.
 675      res.numTex += 1;
 676
 677   // If we have parallax for this layer then we'll also
 678   // be sampling the normal map for the parallax heightmap.
 679   if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
 680      res.numTex += 1;
 681
 682   // Finally we always send the detail texture 
 683   // coord to the pixel shader.
 684   res.numTexReg += 1;
 685
 686   return res;
 687}
 688
 689U32 TerrainDetailMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
 690{
 691   return fd.features[MFT_DeferredTerrainDetailMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
 692}
 693
 694
 695TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL()
 696   :  mTorqueDep( "shaders/common/torque.hlsl" ),
 697      mTerrainDep( "shaders/common/terrain/terrain.hlsl" )
 698      
 699{
 700   addDependency( &mTorqueDep );
 701   addDependency( &mTerrainDep );
 702}
 703
 704
 705void TerrainMacroMapFeatHLSL::processVert(  Vector<ShaderComponent*> &componentList, 
 706                                             const MaterialFeatureData &fd )
 707{
 708   const S32 detailIndex = getProcessIndex();
 709
 710   // Grab incoming texture coords... the base map feature
 711   // made sure this was created.
 712   Var *inTex = (Var*)LangElement::find( "texCoord" );
 713   AssertFatal( inTex, "The texture coord is missing!" );
 714
 715   // Grab the input position.
 716   Var *inPos = (Var*)LangElement::find( "inPosition" );
 717   if ( !inPos )
 718      inPos = (Var*)LangElement::find( "position" );
 719
 720   // Get the object space eye position.
 721   Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive );
 722
 723   MultiLine *meta = new MultiLine;
 724
 725   // Get the distance from the eye to this vertex.
 726   Var *dist = (Var*)LangElement::find( "macroDist" );
 727   if ( !dist )
 728   {
 729      dist = new Var;
 730      dist->setType( "float" );
 731      dist->setName( "macroDist" );  
 732
 733      meta->addStatement( new GenOp( "   @ = distance( @.xyz, @ );\r\n", 
 734                                       new DecOp( dist ), inPos, eyePos ) );
 735   }
 736
 737   // grab connector texcoord register
 738   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 739   Var *outTex = connectComp->getElement( RT_TEXCOORD );
 740   outTex->setName( String::ToString( "macroCoord%d", detailIndex ) );
 741   outTex->setStructName( "OUT" );
 742   outTex->setType( "float4" );
 743   outTex->mapsToSampler = true;
 744
 745   // Get the detail scale and fade info.
 746   Var *detScaleAndFade = new Var;
 747   detScaleAndFade->setType( "float4" );
 748   detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) );
 749   detScaleAndFade->uniform = true;
 750   detScaleAndFade->constSortPos = cspPotentialPrimitive;
 751
 752   // Setup the detail coord.
 753   meta->addStatement( new GenOp( "   @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
 754
 755   // And sneak the detail fade thru the w detailCoord.
 756   meta->addStatement( new GenOp( "   @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", 
 757                                    outTex, detScaleAndFade, dist, detScaleAndFade ) );   
 758
 759   output = meta;
 760}
 761
 762
 763void TerrainMacroMapFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
 764                                             const MaterialFeatureData &fd )
 765{
 766   const S32 detailIndex = getProcessIndex();
 767   Var *inTex = getVertTexCoord( "texCoord" );
 768   
 769   MultiLine *meta = new MultiLine;
 770
 771   // We need the negative tangent space view vector
 772   // as in parallax mapping we step towards the camera.
 773   Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
 774   if (  !negViewTS &&
 775         fd.features.hasFeature( MFT_TerrainParallaxMap ) )
 776   {
 777      Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
 778      if ( !inNegViewTS )
 779      {
 780         ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 781         inNegViewTS = connectComp->getElement( RT_TEXCOORD );
 782         inNegViewTS->setName( "outNegViewTS" );
 783         inNegViewTS->setStructName( "IN" );
 784         inNegViewTS->setType( "float3" );
 785      }
 786
 787      negViewTS = new Var( "negViewTS", "float3" );
 788      meta->addStatement( new GenOp( "   @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
 789   }
 790
 791   // Get the layer samples.
 792   Var *layerSample = (Var*)LangElement::find( "layerSample" );
 793   if ( !layerSample )
 794   {
 795      layerSample = new Var;
 796      layerSample->setType( "float4" );
 797      layerSample->setName( "layerSample" );
 798
 799      // Get the layer texture var
 800      Var *layerTex = new Var;
 801      layerTex->setType( "sampler2D" );
 802      layerTex->setName( "macrolayerTex" );
 803      layerTex->uniform = true;
 804      layerTex->sampler = true;
 805      layerTex->constNum = Var::getTexUnitNum();
 806
 807      // Read the layer texture to get the samples.
 808      if (mIsDirect3D11)
 809      {
 810         layerTex->setType("SamplerState");
 811         Var *layerTexObj = new Var;
 812         layerTexObj->setType("Texture2D");
 813         layerTexObj->setName("macroLayerTexObj");
 814         layerTexObj->uniform = true;
 815         layerTexObj->texture = true;
 816         layerTexObj->constNum = layerTex->constNum;
 817         meta->addStatement(new GenOp("   @ = round( @.Sample( @, @.xy ) * 255.0f );\r\n",
 818            new DecOp(layerSample), layerTexObj, layerTex, inTex));
 819      }
 820      else
 821         meta->addStatement(new GenOp("   @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
 822            new DecOp(layerSample), layerTex, inTex));
 823   }
 824
 825   Var *layerSize = (Var*)LangElement::find( "layerSize" );
 826   if ( !layerSize )
 827   {
 828      layerSize = new Var;
 829      layerSize->setType( "float" );
 830      layerSize->setName( "layerSize" );
 831      layerSize->uniform = true;
 832      layerSize->constSortPos = cspPass;
 833   }
 834
 835   // Grab the incoming detail coord.
 836   Var *inDet = _getInMacroCoord( componentList );
 837
 838   // Get the detail id.
 839   Var *detailInfo = _getMacroIdStrengthParallax();
 840
 841   // Create the detail blend var.
 842   Var *detailBlend = new Var;
 843   detailBlend->setType( "float" );
 844   detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) );
 845
 846   // Calculate the blend for this detail texture.
 847   meta->addStatement( new GenOp( "   @ = calcBlend( @.x, @.xy, @, @ );\r\n", 
 848                                    new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
 849
 850   // Get a var and accumulate the blend amount.
 851   Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
 852   if ( !blendTotal )
 853   {
 854      blendTotal = new Var;
 855      blendTotal->setName( "blendTotal" );
 856      blendTotal->setType( "float" );
 857      meta->addStatement( new GenOp( "   @ = 0;\r\n", new DecOp( blendTotal ) ) );
 858   }
 859
 860   // Add to the blend total.
 861   meta->addStatement(new GenOp("   @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
 862
 863   Var *detailColor = (Var*)LangElement::find( "macroColor" ); 
 864   if ( !detailColor )
 865   {
 866      detailColor = new Var;
 867      detailColor->setType( "float4" );
 868      detailColor->setName( "macroColor" );
 869      meta->addStatement( new GenOp( "   @;\r\n", new DecOp( detailColor ) ) );
 870   }
 871
 872   // Get the detail texture.
 873   Var *detailMap = new Var;
 874   detailMap->setType( "sampler2D" );
 875   detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
 876   detailMap->uniform = true;
 877   detailMap->sampler = true;
 878   detailMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
 879
 880   //Create texture object for directx 11
 881   Var *detailTex = NULL;
 882   if (mIsDirect3D11)
 883   {
 884      detailMap->setType("SamplerState");
 885      detailTex = new Var;
 886      detailTex->setName(String::ToString("macroMapTex%d", detailIndex));
 887      detailTex->setType("Texture2D");
 888      detailTex->uniform = true;
 889      detailTex->texture = true;
 890      detailTex->constNum = detailMap->constNum;
 891
 892   }
 893
 894   // If we're using SM 3.0 then take advantage of 
 895   // dynamic branching to skip layers per-pixel.
 896   if ( GFX->getPixelShaderVersion() >= 3.0f )
 897      meta->addStatement( new GenOp( "   if ( @ > 0.0f )\r\n", detailBlend ) );
 898
 899   meta->addStatement( new GenOp( "   {\r\n" ) );
 900
 901   // Note that we're doing the standard greyscale detail 
 902   // map technique here which can darken and lighten the 
 903   // diffuse texture.
 904   //
 905   // We take two color samples and lerp between them for
 906   // side projection layers... else a single sample.
 907   //
 908   if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
 909   {
 910      if (mIsDirect3D11)
 911      {
 912         meta->addStatement(new GenOp("      @ = ( lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
 913            detailColor, detailTex, detailMap, inDet, detailTex, detailMap, inDet, inTex));
 914      }
 915      else
 916         meta->addStatement(new GenOp("      @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
 917         detailColor, detailMap, inDet, detailMap, inDet, inTex));
 918   }
 919   else
 920   {
 921      if (mIsDirect3D11)
 922         meta->addStatement(new GenOp("      @ = ( @.Sample( @, @.xy ) * 2.0 ) - 1.0;\r\n",
 923         detailColor, detailTex, detailMap, inDet));
 924      else
 925         meta->addStatement(new GenOp("      @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
 926         detailColor, detailMap, inDet));
 927   }
 928
 929   meta->addStatement( new GenOp( "      @ *= @.y * @.w;\r\n",
 930                                    detailColor, detailInfo, inDet ) );
 931
 932   ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
 933
 934   if(fd.features.hasFeature(MFT_DeferredTerrainMacroMap))
 935      target= ShaderFeature::RenderTarget1;
 936
 937   Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) );
 938
 939   meta->addStatement(new GenOp("      @ += @ * @;\r\n",
 940                                    outColor, detailColor, detailBlend));
 941
 942   meta->addStatement( new GenOp( "   }\r\n" ) );
 943
 944   output = meta;
 945}
 946
 947ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFeatureData &fd )
 948{
 949   Resources res;
 950
 951   if ( getProcessIndex() == 0 )
 952   {
 953      // If this is the first detail pass then we 
 954      // samples from the layer tex.
 955      res.numTex += 1;
 956   }
 957
 958      res.numTex += 1;
 959
 960   // Finally we always send the detail texture 
 961   // coord to the pixel shader.
 962   res.numTexReg += 1;
 963
 964   return res;
 965}
 966
 967U32 TerrainMacroMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
 968{
 969   return fd.features[MFT_DeferredTerrainMacroMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
 970}
 971
 972void TerrainNormalMapFeatHLSL::processVert(  Vector<ShaderComponent*> &componentList, 
 973                                             const MaterialFeatureData &fd )
 974{
 975   // We only need to process normals during the prepass.
 976   if ( !fd.features.hasFeature( MFT_PrePassConditioner ) )
 977      return;
 978
 979   MultiLine *meta = new MultiLine;
 980
 981   // Make sure the world to tangent transform
 982   // is created and available for the pixel shader.
 983   getOutViewToTangent( componentList, meta, fd );
 984
 985   output = meta;
 986}
 987
 988void TerrainNormalMapFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
 989                                             const MaterialFeatureData &fd )
 990{
 991
 992   MultiLine *meta = new MultiLine;
 993
 994   Var *viewToTangent = getInViewToTangent( componentList );
 995
 996   // This var is read from GBufferConditionerHLSL and 
 997   // used in the prepass output.
 998   Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
 999   if ( !gbNormal )
1000   {
1001      gbNormal = new Var;
1002      gbNormal->setName( "gbNormal" );
1003      gbNormal->setType( "float3" );
1004      meta->addStatement( new GenOp( "   @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) );
1005   }
1006
1007   const S32 normalIndex = getProcessIndex();
1008
1009   Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
1010   AssertFatal( detailBlend, "The detail blend is missing!" );
1011
1012   // If we're using SM 3.0 then take advantage of 
1013   // dynamic branching to skip layers per-pixel.
1014   if ( GFX->getPixelShaderVersion() >= 3.0f )
1015      meta->addStatement( new GenOp( "   if ( @ > 0.0f )\r\n", detailBlend ) );
1016
1017   meta->addStatement( new GenOp( "   {\r\n" ) );
1018
1019   // Get the normal map texture.
1020   Var *normalMap = _getNormalMapTex();
1021
1022   /// Get the texture coord.
1023   Var *inDet = _getInDetailCoord( componentList );
1024   Var *inTex = getVertTexCoord( "texCoord" );
1025
1026   // Sample the normal map.
1027   //
1028   // We take two normal samples and lerp between them for
1029   // side projection layers... else a single sample.
1030   LangElement *texOp;
1031   if (mIsDirect3D11)
1032   {
1033      String name(String::ToString("normalMapTex%d", getProcessIndex()));
1034      Var *normalMapTex = (Var*)LangElement::find(name);
1035      if (!normalMapTex)
1036      {
1037         normalMapTex = new Var;
1038         normalMapTex->setName(String::ToString("normalMapTex%d", getProcessIndex()));
1039         normalMapTex->setType("Texture2D");
1040         normalMapTex->uniform = true;
1041         normalMapTex->texture = true;
1042         normalMapTex->constNum = normalMap->constNum;
1043      }
1044      if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex))
1045      {
1046         texOp = new GenOp("lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z )",
1047            normalMapTex, normalMap, inDet, normalMapTex, normalMap, inDet, inTex);
1048      }
1049      else
1050         texOp = new GenOp("@.Sample(@, @.xy)", normalMapTex, normalMap, inDet);
1051
1052   }
1053
1054   else
1055   {
1056      if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex))
1057      {
1058         texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
1059            normalMap, inDet, normalMap, inDet, inTex);
1060      }
1061      else
1062         texOp = new GenOp("tex2D(@, @.xy)", normalMap, inDet);
1063   }
1064
1065   // create bump normal
1066   Var *bumpNorm = new Var;
1067   bumpNorm->setName( "bumpNormal" );
1068   bumpNorm->setType( "float4" );
1069
1070   LangElement *bumpNormDecl = new DecOp( bumpNorm );
1071   meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
1072
1073   // Normalize is done later... 
1074   // Note: The reverse mul order is intentional. Affine matrix.
1075   meta->addStatement( new GenOp( "      @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n", 
1076      gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
1077
1078   // End the conditional block.
1079   meta->addStatement( new GenOp( "   }\r\n" ) );
1080
1081   // If this is the last normal map then we 
1082   // can test to see the total blend value
1083   // to see if we should clip the result.
1084   //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
1085      //meta->addStatement( new GenOp( "   clip( @ - 0.0001f );\r\n", blendTotal ) );
1086
1087   output = meta;
1088}
1089
1090ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialFeatureData &fd )
1091{
1092   Resources res;
1093
1094   // We only need to process normals during the prepass.
1095   if ( fd.features.hasFeature( MFT_PrePassConditioner ) )
1096   {
1097      // If this is the first normal map and there
1098      // are no parallax features then we will 
1099      // generate the worldToTanget transform.
1100      if (  !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
1101            ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
1102         res.numTexReg = 3;
1103
1104      res.numTex = 1;
1105   }
1106
1107   return res;
1108}
1109
1110void TerrainLightMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 
1111                                          const MaterialFeatureData &fd )
1112{
1113   // grab connector texcoord register
1114   Var *inTex = (Var*)LangElement::find( "texCoord" );
1115   if ( !inTex )
1116      return;
1117
1118   // Get the lightmap texture.
1119   Var *lightMap = new Var;
1120   lightMap->setType( "sampler2D" );
1121   lightMap->setName( "lightMapTex" );
1122   lightMap->uniform = true;
1123   lightMap->sampler = true;
1124   lightMap->constNum = Var::getTexUnitNum();
1125
1126   MultiLine *meta = new MultiLine;
1127
1128   // Find or create the lightMask value which is read by
1129   // RTLighting to mask out the lights.
1130   //
1131   // The first light is always the sunlight so we apply
1132   // the shadow mask to only the first channel.
1133   //
1134   Var *lightMask = (Var*)LangElement::find( "lightMask" );
1135   if ( !lightMask )
1136   {
1137      lightMask = new Var( "lightMask", "float4" );
1138      meta->addStatement( new GenOp( "   @ = 1;\r\n", new DecOp( lightMask ) ) );
1139   }
1140
1141   if (mIsDirect3D11)
1142   {
1143      lightMap->setType("SamplerState");
1144      Var* lightMapTex = new Var;
1145      lightMapTex->setName("lightMapTexObj");
1146      lightMapTex->setType("Texture2D");
1147      lightMapTex->uniform = true;
1148      lightMapTex->texture = true;
1149      lightMapTex->constNum = lightMap->constNum;
1150      meta->addStatement(new GenOp("   @[0] = @.Sample( @, @.xy ).r;\r\n", lightMask, lightMapTex, lightMap, inTex));
1151   }
1152   else
1153      meta->addStatement(new GenOp("   @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex));
1154
1155   output = meta;
1156}
1157
1158ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFeatureData &fd )
1159{
1160   Resources res; 
1161   res.numTex = 1;
1162   return res;
1163}
1164
1165void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 
1166                                          const MaterialFeatureData &fd )
1167{
1168   Var *color = NULL;
1169   Var *normal = NULL;
1170   if (fd.features[MFT_DeferredTerrainDetailMap])
1171   {
1172       color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) );
1173       normal = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
1174   }
1175   else
1176       color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
1177
1178   Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
1179   if ( !color || !blendTotal )
1180      return;
1181   
1182   MultiLine *meta = new MultiLine;
1183
1184   meta->addStatement( new GenOp( "   clip( @ - 0.0001 );\r\n", blendTotal ) );
1185   meta->addStatement( new GenOp( "   @.a = @;\r\n", color, blendTotal ) );
1186
1187   if (normal)
1188      meta->addStatement(new GenOp("   @.a = @;\r\n", normal, blendTotal));
1189
1190   output = meta;
1191}
1192
1193//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), 
1194//.b = specular strength, a= spec power. 
1195//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
1196//we'll most likely revisit that later. possibly several ways...
1197
1198U32 TerrainBlankInfoMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const
1199{
1200   return fd.features[MFT_DeferredTerrainBaseMap] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1;
1201}
1202
1203void TerrainBlankInfoMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
1204   const MaterialFeatureData &fd)
1205{
1206   // search for material var
1207   Var *material;
1208   OutputTarget targ = RenderTarget1;
1209   if (fd.features[MFT_isDeferred])
1210   {
1211      targ = RenderTarget2;
1212   }
1213   material = (Var*)LangElement::find(getOutputTargetVarName(targ));
1214
1215   MultiLine * meta = new MultiLine;
1216   if (!material)
1217   {
1218      // create color var
1219      material = new Var;
1220      material->setType("fragout");
1221      material->setName(getOutputTargetVarName(targ));
1222      material->setStructName("OUT");
1223   }
1224
1225   meta->addStatement(new GenOp("   @ = float4(0.0,0.0,0.0,0.0001);\r\n", material));
1226
1227   output = meta;
1228}
1229