Torque3D Documentation / _generateds / shaderFeatureHLSL.cpp

shaderFeatureHLSL.cpp

Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

More...

Detailed Description

   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 "shaderGen/HLSL/shaderFeatureHLSL.h"
  26
  27#include "shaderGen/langElement.h"
  28#include "shaderGen/shaderOp.h"
  29#include "shaderGen/shaderGenVars.h"
  30#include "gfx/gfxDevice.h"
  31#include "materials/matInstance.h"
  32#include "materials/processedMaterial.h"
  33#include "materials/materialFeatureTypes.h"
  34#include "core/util/autoPtr.h"
  35
  36#include "lighting/advanced/advancedLightBinManager.h"
  37#include "ts/tsShape.h"
  38
  39#include "shaderGen/shaderGen.h"
  40
  41LangElement * ShaderFeatureHLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList
  42                                                   Var **texSpaceMat )
  43{
  44   Var *N = (Var*) LangElement::find( "normal" );
  45   Var *B = (Var*) LangElement::find( "B" );
  46   Var *T = (Var*) LangElement::find( "T" );
  47
  48   Var *tangentW = (Var*) LangElement::find( "tangentW" );
  49   
  50   // setup matrix var
  51   *texSpaceMat = new Var;
  52   (*texSpaceMat)->setType( "float3x3" );
  53   (*texSpaceMat)->setName( "objToTangentSpace" );
  54
  55   MultiLine *meta = new MultiLine;
  56   meta->addStatement( new GenOp( "   @;\r\n", new DecOp( *texSpaceMat ) ) );
  57
  58   // Protect against missing normal and tangent.
  59   if ( !N || !T )
  60   {
  61      meta->addStatement( new GenOp( "   @[0] = float3( 1, 0, 0 ); @[1] = float3( 0, 1, 0 ); @[2] = float3( 0, 0, 1 );\r\n", 
  62         *texSpaceMat, *texSpaceMat, *texSpaceMat ) );
  63      return meta;
  64   }
  65
  66   meta->addStatement( new GenOp( "   @[0] = @;\r\n", *texSpaceMat, T ) );
  67   if ( B )
  68      meta->addStatement( new GenOp( "   @[1] = @;\r\n", *texSpaceMat, B ) );
  69   else
  70   {
  71      if(dStricmp((char*)T->type, "float4") == 0)
  72         meta->addStatement( new GenOp( "   @[1] = cross( @, normalize(@) ) * @.w;\r\n", *texSpaceMat, T, N, T ) );
  73      else if (tangentW)
  74         meta->addStatement(new GenOp("   @[1] = cross( @, normalize(@) ) * @;\r\n", *texSpaceMat, <a href="/coding/group/group__engineapi__types/#group__engineapi__types_1ga16a0f7e7053a679c9bf4289b441a2be7">T</a>, N, tangentW));
  75      else
  76         meta->addStatement( new GenOp( "   @[1] = cross( @, normalize(@) );\r\n", *texSpaceMat, T, N ) );
  77   }
  78   meta->addStatement( new GenOp( "   @[2] = normalize(@);\r\n", *texSpaceMat, N ) );
  79
  80   return meta;
  81}
  82
  83LangElement* ShaderFeatureHLSL::assignColor( LangElement *elem, 
  84                                             Material::BlendOp blend, 
  85                                             LangElement *lerpElem, 
  86                                             ShaderFeature::OutputTarget outputTarget )
  87{
  88
  89   // search for color var
  90   Var *color = (Var*) LangElement::find( getOutputTargetVarName(outputTarget) );
  91
  92   if ( !color )
  93   {
  94      // create color var
  95      color = new Var;
  96      color->setType( "fragout" );
  97      color->setName( getOutputTargetVarName(outputTarget) );
  98      color->setStructName( "OUT" );
  99
 100      return new GenOp( "@ = @", color, elem );
 101   }
 102
 103   LangElement *assign;
 104
 105   switch ( blend )
 106   {
 107      case Material::Add:
 108         assign = new GenOp( "@ += @", color, elem );
 109         break;
 110
 111      case Material::Sub:
 112         assign = new GenOp( "@ -= @", color, elem );
 113         break;
 114
 115      case Material::Mul:
 116         assign = new GenOp( "@ *= @", color, elem );
 117         break;
 118
 119      case Material::PreMul:
 120         assign = new GenOp("@.rgb = @.rgb + (@.rgb*(1.0-@.a))", color, elem, color, elem);
 121         break;
 122
 123      case Material::AddAlpha:
 124         assign = new GenOp( "@ += @ * @.a", color, elem, elem );
 125         break;
 126
 127      case Material::LerpAlpha:
 128         if ( !lerpElem )
 129            lerpElem = elem;
 130         assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem );
 131         break;
 132      
 133      case Material::ToneMap:
 134         assign = new GenOp( "@ = 1.0 - exp(-1.0 * @ * @)", color, color, elem );
 135         break;
 136         
 137      default:
 138         AssertFatal(false, "Unrecognized color blendOp");
 139         // Fallthru
 140
 141      case Material::None:
 142         assign = new GenOp( "@ = @", color, elem );
 143         break;    
 144   }
 145  
 146   return assign;
 147}
 148
 149
 150LangElement *ShaderFeatureHLSL::expandNormalMap(   LangElement *sampleNormalOp, 
 151                                                   LangElement *normalDecl, 
 152                                                   LangElement *normalVar, 
 153                                                   const MaterialFeatureData &fd )
 154{
 155   MultiLine *meta = new MultiLine;
 156   const bool hasBc3 = fd.features.hasFeature(MFT_IsBC3nm, getProcessIndex() );
 157   const bool hasBc5 = fd.features.hasFeature(MFT_IsBC5nm, getProcessIndex() );
 158   if ( hasBc3 || hasBc5 )
 159   {
 160      if ( fd.features[MFT_ImposterVert] )
 161      {
 162         // The imposter system uses object space normals and
 163         // encodes them with the z axis in the alpha component.
 164         meta->addStatement( new GenOp( "   @ = float4( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, sampleNormalOp ) );
 165      }
 166      else if( hasBc3 )
 167      {
 168         // BC3 Swizzle trick
 169         meta->addStatement( new GenOp( "   @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) );
 170         meta->addStatement( new GenOp( "   @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) );
 171      }
 172      else if (hasBc5)
 173      {
 174         // BC5
 175         meta->addStatement(new GenOp("   @ = float4( @.gr * 2.0 - 1.0, 0.0, 0.0 ); // bc5nm\r\n", normalDecl, sampleNormalOp ) );
 176         meta->addStatement(new GenOp("   @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // bc5nm\r\n", normalVar, normalVar, normalVar )) ;
 177      }
 178   }
 179   else
 180   {
 181      meta->addStatement( new GenOp( "   @ = @;\r\n", normalDecl, sampleNormalOp ) );
 182      meta->addStatement( new GenOp( "   @.xyz = @.xyz * 2.0 - 1.0;\r\n", normalVar, normalVar ) );
 183   }
 184
 185   return meta;
 186}
 187
 188ShaderFeatureHLSL::ShaderFeatureHLSL()
 189{
 190   output = NULL;
 191}
 192
 193Var * ShaderFeatureHLSL::getVertTexCoord( const String &name )
 194{
 195   Var *inTex = NULL;
 196
 197   for( U32 i=0; i<LangElement::elementList.size(); i++ )
 198   {
 199      if( !String::compare( (char*)LangElement::elementList[i]->name, name.c_str() ) )
 200      {
 201         inTex = dynamic_cast<Var*>( LangElement::elementList[i] );
 202         if ( inTex )
 203         {
 204            // NOTE: This used to do this check...
 205            //
 206            // String::compare( (char*)inTex->structName, "IN" )
 207            //
 208            // ... to ensure that the var was from the input
 209            // vertex structure, but this kept some features
 210            // ( ie. imposter vert ) from decoding their own
 211            // coords for other features to use.
 212            //
 213            // If we run into issues with collisions between
 214            // IN vars and local vars we may need to revise.
 215            
 216            break;
 217         }
 218      }
 219   }
 220
 221   return inTex;
 222}
 223
 224Var* ShaderFeatureHLSL::getOutObjToTangentSpace(   Vector<ShaderComponent*> &componentList,
 225                                                   MultiLine *meta,
 226                                                   const MaterialFeatureData &fd )
 227{
 228   Var *outObjToTangentSpace = (Var*)LangElement::find( "objToTangentSpace" );
 229   if ( !outObjToTangentSpace )
 230      meta->addStatement( setupTexSpaceMat( componentList, &outObjToTangentSpace ) );
 231
 232   return outObjToTangentSpace;
 233}
 234
 235Var* ShaderFeatureHLSL::getOutWorldToTangent(   Vector<ShaderComponent*> &componentList,
 236                                                MultiLine *meta,
 237                                                const MaterialFeatureData &fd )
 238{
 239   Var *outWorldToTangent = (Var*)LangElement::find( "outWorldToTangent" );
 240   if ( outWorldToTangent )
 241      return outWorldToTangent;
 242      
 243   Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" );
 244   if ( !worldToTangent )
 245   {
 246      Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd );
 247
 248      if (!fd.features[MFT_ParticleNormal] )
 249      {
 250         // turn obj->tangent into world->tangent
 251         worldToTangent = new Var;
 252         worldToTangent->setType( "float3x3" );
 253         worldToTangent->setName( "worldToTangent" );
 254         LangElement *worldToTangentDecl = new DecOp( worldToTangent );
 255
 256         // Get the world->obj transform
 257         Var *worldToObj = (Var*)LangElement::find( "worldToObj" );
 258         if ( !worldToObj )
 259         {
 260            worldToObj = new Var;
 261            worldToObj->setName( "worldToObj" );
 262
 263            if ( fd.features[MFT_UseInstancing] ) 
 264            {
 265               // We just use transpose to convert the 3x3 portion of
 266               // the object transform to its inverse.
 267               worldToObj->setType( "float3x3" );
 268               Var *objTrans = getObjTrans( componentList, true, meta );
 269               meta->addStatement( new GenOp( "   @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( worldToObj ), objTrans ) );
 270            }
 271            else
 272            {
 273               worldToObj->setType( "float4x4" );
 274               worldToObj->uniform = true;
 275               worldToObj->constSortPos = cspPrimitive;
 276            }
 277         }
 278
 279         // assign world->tangent transform
 280         meta->addStatement( new GenOp( "   @ = mul( @, (float3x3)@ );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) );
 281      }
 282      else
 283      {
 284         // Assume particle normal generation has set this up in the proper space
 285         worldToTangent = texSpaceMat;
 286      }
 287   }
 288
 289   // send transform to pixel shader
 290   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 291
 292   outWorldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
 293   outWorldToTangent->setName( "outWorldToTangent" );
 294   outWorldToTangent->setStructName( "OUT" );
 295   outWorldToTangent->setType( "float3x3" );
 296   meta->addStatement( new GenOp( "   @ = @;\r\n", outWorldToTangent, worldToTangent ) );
 297
 298   return outWorldToTangent;
 299}
 300
 301Var* ShaderFeatureHLSL::getOutViewToTangent( Vector<ShaderComponent*> &componentList,
 302                                             MultiLine *meta,
 303                                             const MaterialFeatureData &fd )
 304{
 305   Var *outViewToTangent = (Var*)LangElement::find( "outViewToTangent" );
 306   if ( outViewToTangent )
 307      return outViewToTangent;
 308
 309   Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
 310   if ( !viewToTangent )
 311   {
 312
 313      Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd );
 314
 315      if ( !fd.features[MFT_ParticleNormal] )
 316      {
 317         // turn obj->tangent into world->tangent
 318         viewToTangent = new Var;
 319         viewToTangent->setType( "float3x3" );
 320         viewToTangent->setName( "viewToTangent" );
 321         LangElement *viewToTangentDecl = new DecOp( viewToTangent );
 322
 323         // Get the view->obj transform
 324         Var *viewToObj = getInvWorldView( componentList, fd.features[MFT_UseInstancing], meta );
 325
 326         // assign world->tangent transform
 327         meta->addStatement( new GenOp( "   @ = mul( @, (float3x3)@ );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) );
 328      }
 329      else
 330      {
 331         // Assume particle normal generation has set this up in the proper space
 332         viewToTangent = texSpaceMat;
 333      }
 334   }
 335
 336   // send transform to pixel shader
 337   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 338
 339   outViewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
 340   outViewToTangent->setName( "outViewToTangent" );
 341   outViewToTangent->setStructName( "OUT" );
 342   outViewToTangent->setType( "float3x3" );
 343   meta->addStatement( new GenOp( "   @ = @;\r\n", outViewToTangent, viewToTangent ) );
 344
 345   return outViewToTangent;
 346}
 347
 348Var* ShaderFeatureHLSL::getOutTexCoord(   const char *name,
 349                                          const char *type,
 350                                          bool useTexAnim,
 351                                          MultiLine *meta,
 352                                          Vector<ShaderComponent*> &componentList )
 353{
 354   String outTexName = String::ToString( "out_%s", name );
 355   Var *texCoord = (Var*)LangElement::find( outTexName );
 356   if ( !texCoord )
 357   {
 358      Var *inTex = getVertTexCoord( name );
 359      AssertFatal( inTex, "ShaderFeatureHLSL::getOutTexCoord - Unknown vertex input coord!" );
 360
 361      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 362
 363      texCoord = connectComp->getElement( RT_TEXCOORD );
 364      texCoord->setName( outTexName );
 365      texCoord->setStructName( "OUT" );
 366      texCoord->setType( type );
 367
 368      if ( useTexAnim )
 369      {
 370         inTex->setType( "float2" );
 371         
 372         // create texture mat var
 373         Var *texMat = new Var;
 374         texMat->setType( "float4x4" );
 375         texMat->setName( "texMat" );
 376         texMat->uniform = true;
 377         texMat->constSortPos = cspPass;      
 378         
 379         // Statement allows for casting of different types which
 380         // eliminates vector truncation problems.
 381         String statement = String::ToString("   @ = (%s)mul(@, float4(@,1,1));\r\n", type);
 382         meta->addStatement( new GenOp( statement, texCoord, texMat, inTex ) );
 383      }
 384      else
 385      {
 386         // Statement allows for casting of different types which
 387         // eliminates vector truncation problems.
 388         String statement = String::ToString( "   @ = (%s)@;\r\n", type );
 389         meta->addStatement( new GenOp( statement, texCoord, inTex ) );
 390      }
 391   }
 392
 393   AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0, 
 394      "ShaderFeatureHLSL::getOutTexCoord - Type mismatch!" );
 395
 396   return texCoord;
 397}
 398
 399Var* ShaderFeatureHLSL::getInTexCoord( const char *name,
 400                                       const char *type,
 401                                       Vector<ShaderComponent*> &componentList )
 402{
 403   Var* texCoord = (Var*)LangElement::find( name );
 404   if ( !texCoord )
 405   {
 406      ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] );
 407      texCoord = connectComp->getElement( RT_TEXCOORD );
 408      texCoord->setName( name );
 409      texCoord->setStructName( "IN" );
 410      texCoord->setType( type );
 411   }
 412
 413   AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0, 
 414      "ShaderFeatureHLSL::getInTexCoord - Type mismatch!" );
 415
 416   return texCoord;
 417}
 418
 419Var* ShaderFeatureHLSL::getInColor( const char *name,
 420                                    const char *type,
 421                                    Vector<ShaderComponent*> &componentList )
 422{
 423   Var *inColor = (Var*)LangElement::find( name );
 424   if ( !inColor )
 425   {
 426      ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] );
 427      inColor = connectComp->getElement( RT_COLOR );
 428      inColor->setName( name );
 429      inColor->setStructName( "IN" );
 430      inColor->setType( type );
 431   }
 432
 433   AssertFatal( String::compare( type, (const char*)inColor->type ) == 0, 
 434      "ShaderFeatureHLSL::getInColor - Type mismatch!" );
 435
 436   return inColor;
 437}
 438
 439Var* ShaderFeatureHLSL::addOutVpos( MultiLine *meta,
 440                                    Vector<ShaderComponent*> &componentList )
 441{
 442   // Nothing to do if we're on SM 3.0... we use the real vpos.
 443   if ( GFX->getPixelShaderVersion() >= 3.0f )
 444      return NULL;
 445
 446   // For SM 2.x we need to generate the vpos in the vertex shader
 447   // and pass it as a texture coord to the pixel shader.
 448
 449   Var *outVpos = (Var*)LangElement::find( "outVpos" );
 450   if ( !outVpos )
 451   {
 452      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 453
 454      outVpos = connectComp->getElement( RT_TEXCOORD );
 455      outVpos->setName( "outVpos" );
 456      outVpos->setStructName( "OUT" );
 457      outVpos->setType( "float4" );
 458
 459      Var *outPosition = (Var*) LangElement::find( "hpos" );
 460      AssertFatal( outPosition, "ShaderFeatureHLSL::addOutVpos - Didn't find the output position." );
 461
 462      meta->addStatement( new GenOp( "   @ = @;\r\n", outVpos, outPosition ) );
 463   }
 464
 465   return outVpos;
 466}
 467
 468Var* ShaderFeatureHLSL::getInVpos(  MultiLine *meta,
 469                                    Vector<ShaderComponent*> &componentList )
 470{
 471   Var *inVpos = (Var*)LangElement::find( "vpos" );
 472   if ( inVpos )
 473      return inVpos;
 474
 475   ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
 476
 477   inVpos = connectComp->getElement( RT_SVPOSITION );
 478   inVpos->setName( "vpos" );
 479   inVpos->setStructName( "IN" );
 480   inVpos->setType( "float4" );
 481   return inVpos;
 482}
 483
 484Var* ShaderFeatureHLSL::getInWorldToTangent( Vector<ShaderComponent*> &componentList )
 485{
 486   Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" );
 487   if ( !worldToTangent )
 488   {
 489      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 490      worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
 491      worldToTangent->setName( "worldToTangent" );
 492      worldToTangent->setStructName( "IN" );
 493      worldToTangent->setType( "float3x3" );
 494   }
 495
 496   return worldToTangent;
 497}
 498
 499Var* ShaderFeatureHLSL::getInViewToTangent( Vector<ShaderComponent*> &componentList )
 500{
 501   Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
 502   if ( !viewToTangent )
 503   {
 504      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 505      viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
 506      viewToTangent->setName( "viewToTangent" );
 507      viewToTangent->setStructName( "IN" );
 508      viewToTangent->setType( "float3x3" );
 509   }
 510
 511   return viewToTangent;
 512}
 513
 514Var* ShaderFeatureHLSL::getNormalMapTex()
 515{
 516   Var *normalMap = (Var*)LangElement::find("bumpMap");
 517   if (!normalMap)
 518   {
 519      normalMap = new Var;
 520      normalMap->setType("SamplerState");
 521      normalMap->setName("bumpMap");
 522      normalMap->uniform = true;
 523      normalMap->sampler = true;
 524      normalMap->constNum = Var::getTexUnitNum();
 525
 526      Var* normalMapTex = new Var;
 527      normalMapTex->setName("bumpMapTex");
 528      normalMapTex->setType("Texture2D");
 529      normalMapTex->uniform = true;
 530      normalMapTex->texture = true;
 531      normalMapTex->constNum = normalMap->constNum;
 532   }
 533
 534   return normalMap;
 535}
 536
 537Var* ShaderFeatureHLSL::getObjTrans(   Vector<ShaderComponent*> &componentList,                                       
 538                                       bool useInstancing,
 539                                       MultiLine *meta )
 540{
 541   Var *objTrans = (Var*)LangElement::find( "objTrans" );
 542   if ( objTrans )
 543      return objTrans;
 544
 545   if ( useInstancing )
 546   {
 547      ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] );
 548      Var *instObjTrans = vertStruct->getElement( RT_TEXCOORD, 4, 4 );
 549      instObjTrans->setStructName( "IN" );
 550      instObjTrans->setName( "inst_objectTrans" );
 551
 552      mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+0 );
 553      mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+1 );
 554      mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+2 );
 555      mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+3 );
 556
 557      objTrans = new Var;
 558      objTrans->setType( "float4x4" );
 559      objTrans->setName( "objTrans" );
 560      meta->addStatement( new GenOp( "   @ = { // Instancing!\r\n", new DecOp( objTrans ), instObjTrans ) );
 561      meta->addStatement( new GenOp( "      @[0],\r\n", instObjTrans ) );
 562      meta->addStatement( new GenOp( "      @[1],\r\n", instObjTrans ) );
 563      meta->addStatement( new GenOp( "      @[2],\r\n",instObjTrans ) );
 564      meta->addStatement( new GenOp( "      @[3] };\r\n", instObjTrans ) );
 565   }
 566   else
 567   {
 568      objTrans = new Var;
 569      objTrans->setType( "float4x4" );
 570      objTrans->setName( "objTrans" );
 571      objTrans->uniform = true;
 572      objTrans->constSortPos = cspPrimitive;
 573   }
 574
 575   return objTrans;
 576}
 577
 578Var* ShaderFeatureHLSL::getModelView(  Vector<ShaderComponent*> &componentList,                                       
 579                                       bool useInstancing,
 580                                       MultiLine *meta )
 581{
 582   Var *modelview = (Var*)LangElement::find( "modelview" );
 583   if ( modelview )
 584      return modelview;
 585
 586   if ( useInstancing )
 587   {
 588      Var *objTrans = getObjTrans( componentList, useInstancing, meta );
 589
 590      Var *viewProj = (Var*)LangElement::find( "viewProj" );
 591      if ( !viewProj )
 592      {
 593         viewProj = new Var;
 594         viewProj->setType( "float4x4" );
 595         viewProj->setName( "viewProj" );
 596         viewProj->uniform = true;
 597         viewProj->constSortPos = cspPass;        
 598      }
 599
 600      modelview = new Var;
 601      modelview->setType( "float4x4" );
 602      modelview->setName( "modelview" );
 603      meta->addStatement( new GenOp( "   @ = mul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) );
 604   }
 605   else
 606   {
 607      modelview = new Var;
 608      modelview->setType( "float4x4" );
 609      modelview->setName( "modelview" );
 610      modelview->uniform = true;
 611      modelview->constSortPos = cspPrimitive;   
 612   }
 613
 614   return modelview;
 615}
 616
 617Var* ShaderFeatureHLSL::getWorldView(  Vector<ShaderComponent*> &componentList,                                       
 618                                       bool useInstancing,
 619                                       MultiLine *meta )
 620{
 621   Var *worldView = (Var*)LangElement::find( "worldViewOnly" );
 622   if ( worldView )
 623      return worldView;
 624
 625   if ( useInstancing )
 626   {
 627      Var *objTrans = getObjTrans( componentList, useInstancing, meta );
 628
 629      Var *worldToCamera = (Var*)LangElement::find( "worldToCamera" );
 630      if ( !worldToCamera )
 631      {
 632         worldToCamera = new Var;
 633         worldToCamera->setType( "float4x4" );
 634         worldToCamera->setName( "worldToCamera" );
 635         worldToCamera->uniform = true;
 636         worldToCamera->constSortPos = cspPass;        
 637      }
 638
 639      worldView = new Var;
 640      worldView->setType( "float4x4" );
 641      worldView->setName( "worldViewOnly" );
 642
 643      meta->addStatement( new GenOp( "   @ = mul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) );
 644   }
 645   else
 646   {
 647      worldView = new Var;
 648      worldView->setType( "float4x4" );
 649      worldView->setName( "worldViewOnly" );
 650      worldView->uniform = true;
 651      worldView->constSortPos = cspPrimitive;  
 652   }
 653
 654   return worldView;
 655}
 656
 657
 658Var* ShaderFeatureHLSL::getInvWorldView(  Vector<ShaderComponent*> &componentList,                                       
 659                                          bool useInstancing,
 660                                          MultiLine *meta )
 661{
 662   Var *viewToObj = (Var*)LangElement::find( "viewToObj" );
 663   if ( viewToObj )
 664      return viewToObj;
 665
 666   if ( useInstancing )
 667   {
 668      Var *worldView = getWorldView( componentList, useInstancing, meta );
 669
 670      viewToObj = new Var;
 671      viewToObj->setType( "float3x3" );
 672      viewToObj->setName( "viewToObj" );
 673
 674      // We just use transpose to convert the 3x3 portion 
 675      // of the world view transform into its inverse.
 676
 677      meta->addStatement( new GenOp( "   @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( viewToObj ), worldView ) );
 678   }
 679   else
 680   {
 681      viewToObj = new Var;
 682      viewToObj->setType( "float4x4" );
 683      viewToObj->setName( "viewToObj" );
 684      viewToObj->uniform = true;
 685      viewToObj->constSortPos = cspPrimitive;
 686   }
 687
 688   return viewToObj;
 689}
 690
 691void ShaderFeatureHLSL::getWsPosition( Vector<ShaderComponent*> &componentList,                                       
 692                                       bool useInstancing,
 693                                       MultiLine *meta,
 694                                       LangElement *wsPosition )
 695{
 696   Var *inPosition = (Var*)LangElement::find( "wsPosition" );
 697   if ( inPosition )
 698   {
 699      meta->addStatement( new GenOp( "   @ = @.xyz;\r\n", 
 700         wsPosition, inPosition ) );
 701      return;
 702   }
 703
 704   // Get the input position.
 705   inPosition = (Var*)LangElement::find( "inPosition" );
 706   if ( !inPosition )
 707      inPosition = (Var*)LangElement::find( "position" );
 708
 709   AssertFatal( inPosition, "ShaderFeatureHLSL::getWsPosition - The vertex position was not found!" );
 710
 711   Var *objTrans = getObjTrans( componentList, useInstancing, meta );
 712
 713   meta->addStatement( new GenOp( "   @ = mul( @, float4( @.xyz, 1 ) ).xyz;\r\n", 
 714      wsPosition, objTrans, inPosition ) );
 715}
 716
 717Var* ShaderFeatureHLSL::addOutWsPosition( Vector<ShaderComponent*> &componentList,                                       
 718                                          bool useInstancing,
 719                                          MultiLine *meta )
 720{
 721   Var *outWsPosition = (Var*)LangElement::find( "outWsPosition" );
 722   if ( !outWsPosition )
 723   {
 724      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 725      outWsPosition = connectComp->getElement( RT_TEXCOORD );
 726      outWsPosition->setName( "outWsPosition" );
 727      outWsPosition->setStructName( "OUT" );
 728      outWsPosition->setType( "float3" );
 729
 730      getWsPosition( componentList, useInstancing, meta, outWsPosition );
 731   }
 732
 733   return outWsPosition;
 734}
 735
 736Var* ShaderFeatureHLSL::getInWsPosition( Vector<ShaderComponent*> &componentList )
 737{
 738   Var *wsPosition = (Var*)LangElement::find( "wsPosition" );
 739   if ( !wsPosition )
 740   {
 741      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 742      wsPosition = connectComp->getElement( RT_TEXCOORD );
 743      wsPosition->setName( "wsPosition" );
 744      wsPosition->setStructName( "IN" );
 745      wsPosition->setType( "float3" );
 746   }
 747
 748   return wsPosition;
 749}
 750
 751Var* ShaderFeatureHLSL::getWsView( Var *wsPosition, MultiLine *meta )
 752{
 753   Var *wsView = (Var*)LangElement::find( "wsView" );
 754   if ( !wsView )
 755   {
 756      wsView = new Var( "wsView", "float3" );
 757
 758      Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
 759      if ( !eyePos )
 760      {
 761         eyePos = new Var;
 762         eyePos->setType( "float3" );
 763         eyePos->setName( "eyePosWorld" );
 764         eyePos->uniform = true;
 765         eyePos->constSortPos = cspPass;
 766      }
 767
 768      meta->addStatement( new GenOp( "   @ = normalize( @ - @ );\r\n", 
 769         new DecOp( wsView ), eyePos, wsPosition ) );
 770   }
 771
 772   return wsView;
 773}
 774
 775Var* ShaderFeatureHLSL::getInWorldNormal(Vector<ShaderComponent*>& componentList)
 776{
 777   Var* wsNormal = (Var*)LangElement::find("wsNormal");
 778   if (!wsNormal)
 779   {
 780      ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
 781      wsNormal = connectComp->getElement(RT_TEXCOORD);
 782      wsNormal->setName("wsNormal");
 783      wsNormal->setStructName("IN");
 784      wsNormal->setType("float3");
 785   }
 786
 787   return wsNormal;
 788}
 789
 790Var* ShaderFeatureHLSL::addOutDetailTexCoord(   Vector<ShaderComponent*> &componentList, 
 791                                                MultiLine *meta,
 792                                                bool useTexAnim,
 793                                                bool useFoliageTexCoord)
 794{
 795   // Check if its already added.
 796   Var *outTex = (Var*)LangElement::find( "detCoord" );
 797   if ( outTex )
 798      return outTex;
 799
 800   // Grab incoming texture coords.
 801   Var *inTex = getVertTexCoord( "texCoord" );
 802
 803   if (useFoliageTexCoord)
 804      inTex->setType("float4");
 805   else
 806      inTex->setType("float2");
 807
 808   // create detail variable
 809   Var *detScale = new Var;
 810   detScale->setType( "float2" );
 811   detScale->setName( "detailScale" );
 812   detScale->uniform = true;
 813   detScale->constSortPos = cspPotentialPrimitive;
 814   
 815   // grab connector texcoord register
 816   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
 817   outTex = connectComp->getElement( RT_TEXCOORD );
 818   outTex->setName( "detCoord" );
 819   outTex->setStructName( "OUT" );
 820   outTex->setType( "float2" );
 821
 822   if ( useTexAnim )
 823   {
 824      // Find or create the texture matrix.
 825      Var *texMat = (Var*)LangElement::find( "texMat" );
 826      if ( !texMat )
 827      {
 828         texMat = new Var;
 829         texMat->setType( "float4x4" );
 830         texMat->setName( "texMat" );
 831         texMat->uniform = true;
 832         texMat->constSortPos = cspPass;   
 833      }
 834
 835      meta->addStatement(new GenOp("   @ = mul(@, float4(@.xy,1,1)).xy * @;\r\n", outTex, texMat, inTex, detScale));
 836   }
 837   else
 838   {
 839      // setup output to mul texCoord by detail scale
 840      meta->addStatement( new GenOp( "   @ = @.xy * @;\r\n", outTex, inTex, detScale ) );
 841   }
 842
 843   return outTex;
 844}
 845
 846Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd)
 847{
 848   ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
 849
 850   Var* diffuseColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
 851
 852   Var* ormConfig = (Var*)LangElement::find("ORMConfig");
 853   if (!ormConfig)
 854   {
 855      Var* metalness = (Var*)LangElement::find("metalness");
 856      if (!metalness)
 857      {
 858         metalness = new Var("metalness", "float");
 859         metalness->uniform = true;
 860         metalness->constSortPos = cspPotentialPrimitive;
 861      }
 862
 863      Var* roughness = (Var*)LangElement::find("roughness");
 864      if (!roughness)
 865      {
 866         roughness = new Var("roughness", "float");
 867         roughness->uniform = true;
 868         roughness->constSortPos = cspPotentialPrimitive;
 869      }
 870
 871      ormConfig = new Var("ORMConfig", "float4");
 872      LangElement* colorDecl = new DecOp(ormConfig);
 873      meta->addStatement(new GenOp("   @ = float4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct matinfo, no ao darkening
 874   }
 875
 876   Var* normal = (Var*)LangElement::find("normal");
 877   if (!normal)
 878   {
 879      normal = new Var("normal", "float3");
 880      meta->addStatement(new GenOp("  @;\r\n\n", new DecOp(normal)));
 881
 882      Var* wsNormal = (Var*)LangElement::find("wsNormal");
 883
 884      if (!fd.features[MFT_NormalMap])
 885      {
 886         if (!wsNormal)
 887            wsNormal = getInWorldNormal(componentList);
 888
 889         meta->addStatement(new GenOp("  @ = normalize( @ );\r\n\n", normal, wsNormal));
 890      }
 891      else
 892      {
 893         meta->addStatement(new GenOp("   @ = normalize(  @ );\r\n", normal, wsNormal));
 894      }      
 895   }
 896
 897   Var* wsEyePos = (Var*)LangElement::find("eyePosWorld");
 898   Var* wsPosition = getInWsPosition(componentList);
 899   Var* wsView = getWsView(wsPosition, meta);
 900
 901   Var* surface = (Var*)LangElement::find("surface");
 902
 903   if (!surface)
 904   {
 905      surface = new Var("surface", "Surface");
 906      meta->addStatement(new GenOp("  @ = createForwardSurface(@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig,
 907         wsPosition, wsEyePos, wsView));
 908   }
 909
 910   return surface;
 911}
 912//****************************************************************************
 913// Base Texture
 914//****************************************************************************
 915
 916DiffuseMapFeatHLSL::DiffuseMapFeatHLSL()
 917: mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl"))
 918{
 919   addDependency(&mTorqueDep);
 920}
 921
 922void DiffuseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
 923                                       const MaterialFeatureData &fd )
 924{
 925   MultiLine *meta = new MultiLine;
 926   getOutTexCoord(   "texCoord", 
 927                     "float2", 
 928                     fd.features[MFT_TexAnim], 
 929                     meta, 
 930                     componentList );
 931   output = meta;
 932}
 933
 934U32 DiffuseMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const
 935{
 936   return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
 937}
 938
 939void DiffuseMapFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
 940                                       const MaterialFeatureData &fd )
 941{
 942   // grab connector texcoord register
 943   Var *inTex = getInTexCoord( "texCoord", "float2", componentList );
 944
 945   //determine output target
 946   ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget;
 947   if (fd.features[MFT_isDeferred])
 948      targ = ShaderFeature::RenderTarget1;
 949
 950   // create texture var
 951   Var *diffuseMap = new Var;
 952   diffuseMap->setType( "SamplerState" );
 953   diffuseMap->setName( "diffuseMap" );
 954   diffuseMap->uniform = true;
 955   diffuseMap->sampler = true;
 956   diffuseMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
 957
 958   Var* diffuseMapTex = new Var;
 959   diffuseMapTex->setName("diffuseMapTex");
 960   diffuseMapTex->setType("Texture2D");
 961   diffuseMapTex->uniform = true;
 962   diffuseMapTex->texture = true;
 963   diffuseMapTex->constNum = diffuseMap->constNum;
 964   
 965   // create sample color
 966   Var *diffColor = new Var;
 967   diffColor->setType("float4");
 968   diffColor->setName("diffuseColor");
 969   LangElement *colorDecl = new DecOp(diffColor);
 970
 971   MultiLine * meta = new MultiLine;
 972   output = meta;
 973
 974   if (  fd.features[MFT_CubeMap] )
 975   {
 976      meta->addStatement(new GenOp("   @ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex));
 977      meta->addStatement(new GenOp("   @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ)));
 978   }
 979   else if(fd.features[MFT_DiffuseMapAtlas])
 980   {   
 981      // Handle atlased textures
 982      // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47
 983
 984      Var *atlasedTex = new Var;
 985      atlasedTex->setName("atlasedTexCoord");
 986      atlasedTex->setType("float2");
 987      LangElement *atDecl = new DecOp(atlasedTex);
 988
 989      // Parameters of the texture atlas
 990      Var *atParams = new Var;
 991      atParams->setType("float4");
 992      atParams->setName("diffuseAtlasParams");
 993      atParams->uniform = true;
 994      atParams->constSortPos = cspPotentialPrimitive;
 995
 996      // Parameters of the texture (tile) this object is using in the atlas
 997      Var *tileParams = new Var;
 998      tileParams->setType("float4");
 999      tileParams->setName("diffuseAtlasTileParams");
1000      tileParams->uniform = true;
1001      tileParams->constSortPos = cspPotentialPrimitive;
1002
1003      const bool is_sm3 = (GFX->getPixelShaderVersion() > 2.0f);
1004      if(is_sm3)
1005      {
1006         // Figure out the mip level
1007         meta->addStatement(new GenOp("   float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams));
1008         meta->addStatement(new GenOp("   float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams));
1009         meta->addStatement(new GenOp("   float mipLod = 0.5 * log2(max(dot(_dx, _dx), dot(_dy, _dy)));\r\n"));
1010         meta->addStatement(new GenOp("   mipLod = clamp(mipLod, 0.0, @.w);\r\n", atParams));
1011
1012         // And the size of the mip level
1013         meta->addStatement(new GenOp("   float mipPixSz = pow(2.0, @.w - mipLod);\r\n", atParams));
1014         meta->addStatement(new GenOp("   float2 mipSz = mipPixSz / @.xy;\r\n", atParams));
1015      }
1016      else
1017      {
1018         meta->addStatement(new GenOp("   float2 mipSz = float2(1.0, 1.0);\r\n"));
1019      }
1020
1021      // Tiling mode
1022      // TODO: Select wrap or clamp somehow
1023      if( true ) // Wrap
1024         meta->addStatement(new GenOp("   @ = frac(@);\r\n", atDecl, inTex));
1025      else       // Clamp
1026         meta->addStatement(new GenOp("   @ = saturate(@);\r\n", atDecl, inTex));
1027
1028      // Finally scale/offset, and correct for filtering
1029      meta->addStatement(new GenOp("   @ = @ * ((mipSz * @.xy - 1.0) / mipSz) + 0.5 / mipSz + @.xy * @.xy;\r\n", 
1030         atlasedTex, atlasedTex, atParams, atParams, tileParams));
1031
1032      // Add a newline
1033      meta->addStatement(new GenOp( "\r\n"));
1034
1035      // For the rest of the feature...
1036      inTex = atlasedTex;
1037
1038      // To dump out UV coords...
1039//#define DEBUG_ATLASED_UV_COORDS
1040#ifdef DEBUG_ATLASED_UV_COORDS
1041      if(!fd.features[MFT_DeferredConditioner])
1042      {
1043         meta->addStatement(new GenOp("   @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams));
1044         meta->addStatement(new GenOp("   @; return OUT;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) );
1045         return;
1046      }
1047#endif
1048      meta->addStatement(new GenOp("   @ = @.SampleLevel(@,@,mipLod);\r\n",
1049         new DecOp(diffColor), diffuseMapTex, diffuseMap, inTex));
1050
1051      meta->addStatement(new GenOp("   @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) );
1052   }
1053   else
1054   {
1055       meta->addStatement(new GenOp("@ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex));
1056
1057      meta->addStatement(new GenOp("   @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ)));
1058   }   
1059}
1060
1061ShaderFeature::Resources DiffuseMapFeatHLSL::getResources( const MaterialFeatureData &fd )
1062{
1063   Resources res; 
1064   res.numTex = 1;
1065   res.numTexReg = 1;
1066
1067   return res;
1068}
1069
1070void DiffuseMapFeatHLSL::setTexData(   Material::StageData &stageDat,
1071                                       const MaterialFeatureData &fd,
1072                                       RenderPassData &passData,
1073                                       U32 &texIndex )
1074{
1075   GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap );
1076   if ( tex )
1077   {
1078      passData.mSamplerNames[ texIndex ] = "diffuseMap";
1079      passData.mTexSlot[ texIndex++ ].texObject = tex;
1080   }
1081}
1082
1083
1084//****************************************************************************
1085// Overlay Texture
1086//****************************************************************************
1087
1088void OverlayTexFeatHLSL::processVert(  Vector<ShaderComponent*> &componentList, 
1089                                       const MaterialFeatureData &fd )
1090{
1091   Var *inTex = getVertTexCoord( "texCoord2" );
1092   AssertFatal( inTex, "OverlayTexFeatHLSL::processVert() - The second UV set was not found!" );
1093
1094   // grab connector texcoord register
1095   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1096   Var *outTex = connectComp->getElement( RT_TEXCOORD );
1097   outTex->setName( "outTexCoord2" );
1098   outTex->setStructName( "OUT" );
1099   outTex->setType( "float2" );
1100
1101   if( fd.features[MFT_TexAnim] )
1102   {
1103      inTex->setType( "float4" );
1104
1105      // Find or create the texture matrix.
1106      Var *texMat = (Var*)LangElement::find( "texMat" );
1107      if ( !texMat )
1108      {
1109         texMat = new Var;
1110         texMat->setType( "float4x4" );
1111         texMat->setName( "texMat" );
1112         texMat->uniform = true;
1113         texMat->constSortPos = cspPass;   
1114      }
1115     
1116      output = new GenOp( "   @ = mul(@, @);\r\n", outTex, texMat, inTex );
1117      return;
1118   }
1119   
1120   // setup language elements to output incoming tex coords to output
1121   output = new GenOp( "   @ = @;\r\n", outTex, inTex );
1122}
1123
1124void OverlayTexFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
1125                                       const MaterialFeatureData &fd )
1126{
1127
1128   // grab connector texcoord register
1129   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1130   Var *inTex = connectComp->getElement( RT_TEXCOORD );
1131   inTex->setName( "texCoord2" );
1132   inTex->setStructName( "IN" );
1133   inTex->setType( "float2" );
1134
1135   // create texture var
1136   Var *diffuseMap = new Var;
1137   diffuseMap->setType( "SamplerState" );
1138   diffuseMap->setName( "overlayMap" );
1139   diffuseMap->uniform = true;
1140   diffuseMap->sampler = true;
1141   diffuseMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1142
1143   Var* diffuseMapTex = new Var;
1144   diffuseMapTex->setName("overlayMapTex");
1145   diffuseMapTex->setType("Texture2D");
1146   diffuseMapTex->uniform = true;
1147   diffuseMapTex->texture = true;
1148   diffuseMapTex->constNum = diffuseMap->constNum;
1149
1150   LangElement *statement = new GenOp("@.Sample(@, @)", diffuseMapTex, diffuseMap, inTex);
1151
1152   output = new GenOp( "   @;\r\n", assignColor( statement, Material::LerpAlpha ) );
1153}
1154
1155ShaderFeature::Resources OverlayTexFeatHLSL::getResources( const MaterialFeatureData &fd )
1156{
1157   Resources res; 
1158   res.numTex = 1;
1159   res.numTexReg = 1;
1160   return res;
1161}
1162
1163void OverlayTexFeatHLSL::setTexData(   Material::StageData &stageDat,
1164                                       const MaterialFeatureData &fd,
1165                                       RenderPassData &passData,
1166                                       U32 &texIndex )
1167{
1168   GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
1169   if ( tex )
1170   {
1171      passData.mSamplerNames[texIndex] = "overlayMap";
1172      passData.mTexSlot[ texIndex++ ].texObject = tex;
1173   }
1174}
1175
1176
1177//****************************************************************************
1178// Diffuse color
1179//****************************************************************************
1180
1181U32 DiffuseFeatureHLSL::getOutputTargets(const MaterialFeatureData &fd) const
1182{
1183   return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
1184}
1185
1186void DiffuseFeatureHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
1187                                       const MaterialFeatureData &fd )
1188{
1189   Var *diffuseMaterialColor  = new Var;
1190   diffuseMaterialColor->setType( "float4" );
1191   diffuseMaterialColor->setName( "diffuseMaterialColor" );
1192   diffuseMaterialColor->uniform = true;
1193   diffuseMaterialColor->constSortPos = cspPotentialPrimitive;
1194
1195   MultiLine* meta = new MultiLine;
1196   Var *col = (Var*)LangElement::find("col");
1197   ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget;
1198   if (fd.features[MFT_isDeferred])
1199   {
1200      targ = ShaderFeature::RenderTarget1;
1201
1202      col = (Var*)LangElement::find("col1");
1203      if (!col)
1204      {
1205         // create color var
1206         col = new Var;
1207         col->setType("fragout");
1208         col->setName(getOutputTargetVarName(targ));
1209         col->setStructName("OUT");
1210         meta->addStatement(new GenOp("   @ = float4(1.0,1.0,1.0,1.0);\r\n", col));
1211      }
1212   }
1213
1214   Material::BlendOp op;
1215   
1216   if (fd.features[MFT_DiffuseMap])
1217      op = Material::Mul;
1218   else
1219      op = Material::None;
1220
1221   meta->addStatement( new GenOp( "   @;\r\n", assignColor( diffuseMaterialColor, op, NULL, targ ) ) );
1222   output = meta;
1223}
1224
1225
1226//****************************************************************************
1227// Diffuse vertex color
1228//****************************************************************************
1229
1230void DiffuseVertColorFeatureHLSL::processVert(  Vector< ShaderComponent*>& componentList, 
1231                                                const MaterialFeatureData& fd )
1232{
1233   // Create vertex color connector if it doesn't exist.
1234   
1235   Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
1236   if( !outColor )
1237   {
1238      // Search for vert color.
1239      
1240      Var* inColor = dynamic_cast< Var* >( LangElement::find( "diffuse" ) );
1241      if( !inColor )
1242      {
1243         output = NULL;
1244         return;
1245      }
1246      
1247      // Create connector.
1248
1249      ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
1250      AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
1251      outColor = connectComp->getElement( RT_COLOR );
1252      outColor->setName( "vertColor" );
1253      outColor->setStructName( "OUT" );
1254      outColor->setType( "float4" );
1255
1256      output = new GenOp( "   @ = @.bgra;\r\n", outColor, inColor );
1257   }
1258   else
1259      output = NULL; // Nothing we need to do.
1260}
1261
1262void DiffuseVertColorFeatureHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
1263                                                const MaterialFeatureData &fd )
1264{
1265   Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
1266   if( !vertColor )
1267   {
1268      ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
1269      AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
1270      vertColor = connectComp->getElement( RT_COLOR );
1271      vertColor->setName( "vertColor" );
1272      vertColor->setStructName( "IN" );
1273      vertColor->setType( "float4" );
1274   }
1275   
1276   MultiLine* meta = new MultiLine;
1277   if (fd.features[MFT_isDeferred])
1278      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
1279   else
1280      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul)));
1281   output = meta;
1282}
1283
1284
1285//****************************************************************************
1286// Lightmap
1287//****************************************************************************
1288
1289void LightmapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
1290                                    const MaterialFeatureData &fd )
1291{
1292   // grab tex register from incoming vert
1293   Var *inTex = getVertTexCoord( "texCoord2" );
1294
1295   // grab connector texcoord register
1296   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1297   Var *outTex = connectComp->getElement( RT_TEXCOORD );
1298   outTex->setName( "texCoord2" );
1299   outTex->setStructName( "OUT" );
1300   outTex->setType( "float2" );
1301
1302   // setup language elements to output incoming tex coords to output
1303   output = new GenOp( "   @ = @;\r\n", outTex, inTex );
1304}
1305
1306void LightmapFeatHLSL::processPix(  Vector<ShaderComponent*> &componentList, 
1307                                    const MaterialFeatureData &fd )
1308{
1309   // grab connector texcoord register
1310   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1311   Var *inTex = connectComp->getElement( RT_TEXCOORD );
1312   inTex->setName( "texCoord2" );
1313   inTex->setStructName( "IN" );
1314   inTex->setType( "float2" );
1315
1316   // create texture var
1317   Var *lightMap = new Var;
1318   lightMap->setType( "SamplerState" );
1319   lightMap->setName( "lightMap" );
1320   lightMap->uniform = true;
1321   lightMap->sampler = true;
1322   lightMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1323
1324   Var *lightMapTex = new Var;
1325   lightMapTex->setName("lightMapTex");
1326   lightMapTex->setType("Texture2D");
1327   lightMapTex->uniform = true;
1328   lightMapTex->texture = true;
1329   lightMapTex->constNum = lightMap->constNum;
1330   
1331   // argh, ORMConfigMap should prob use this too
1332   if( fd.features[MFT_NormalMap] )
1333   {
1334      Var *lmColor = new Var;
1335      lmColor->setName( "lmColor" );
1336      lmColor->setType( "float4" );
1337      LangElement *lmColorDecl = new DecOp( lmColor );
1338      
1339      output = new GenOp("   @ = @.Sample(@, @);\r\n", lmColorDecl, lightMapTex, lightMap, inTex);
1340
1341      return;
1342   }
1343
1344   // Add realtime lighting, if it is available
1345   LangElement *statement = NULL;
1346   if( fd.features[MFT_RTLighting] )
1347   {
1348      // Advanced lighting is the only dynamic lighting supported right now
1349      Var *inColor = (Var*) LangElement::find( "d_lightcolor" );
1350      if(inColor != NULL)
1351      {
1352         // Find out if RTLighting should be added or substituted
1353         bool bPreProcessedLighting = false;
1354         AdvancedLightBinManager *lightBin;
1355         if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
1356            bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
1357
1358         // Lightmap has already been included in the advanced light bin, so
1359         // no need to do any sampling or anything
1360         if (bPreProcessedLighting)
1361            statement = new GenOp("float4(@, 1.0)", inColor);
1362         else
1363         {
1364            statement = new GenOp("@.Sample(@, @) + float4(@.rgb, 0.0)", lightMapTex, lightMap, inTex, inColor);
1365         }
1366      }
1367   }
1368   
1369   // If we still don't have it... then just sample the lightmap.   
1370   if (!statement)
1371   {
1372      statement = new GenOp("@.Sample(@, @)", lightMapTex, lightMap, inTex);
1373   }
1374
1375   // Assign to proper render target
1376   MultiLine *meta = new MultiLine;
1377   if( fd.features[MFT_LightbufferMRT] )
1378   {
1379      meta->addStatement( new GenOp( "   @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
1380      meta->addStatement( new GenOp( "   @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
1381   }
1382   else
1383      meta->addStatement( new GenOp( "   @;\r\n", assignColor( statement, Material::Mul ) ) );
1384
1385   output = meta;
1386}
1387
1388ShaderFeature::Resources LightmapFeatHLSL::getResources( const MaterialFeatureData &fd )
1389{
1390   Resources res; 
1391   res.numTex = 1;
1392   res.numTexReg = 1;
1393
1394   return res;
1395}
1396
1397void LightmapFeatHLSL::setTexData(  Material::StageData &stageDat,
1398                                    const MaterialFeatureData &fd,
1399                                    RenderPassData &passData,
1400                                    U32 &texIndex )
1401{
1402   GFXTextureObject *tex = stageDat.getTex( MFT_LightMap );
1403   passData.mSamplerNames[ texIndex ] = "lightMap";
1404   if ( tex )
1405      passData.mTexSlot[ texIndex++ ].texObject = tex;
1406   else
1407      passData.mTexType[ texIndex++ ] = Material::Lightmap;
1408}
1409
1410U32 LightmapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
1411{
1412   return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
1413}
1414
1415//****************************************************************************
1416// Tonemap
1417//****************************************************************************
1418
1419void TonemapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
1420                                    const MaterialFeatureData &fd )
1421{
1422   // Grab the connector
1423   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1424
1425   // Set up the second set of texCoords
1426   Var *inTex2 = getVertTexCoord( "texCoord2" );
1427
1428   if ( inTex2 )
1429   {
1430      Var *outTex2 = connectComp->getElement( RT_TEXCOORD );
1431      outTex2->setName( "texCoord2" );
1432      outTex2->setStructName( "OUT" );
1433      outTex2->setType( "float2" );
1434
1435      output = new GenOp( "   @ = @;\r\n", outTex2, inTex2 );
1436   }
1437}
1438
1439void TonemapFeatHLSL::processPix(  Vector<ShaderComponent*> &componentList, 
1440                                    const MaterialFeatureData &fd )
1441{
1442   // Grab connector
1443   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1444
1445   Var *inTex2 = connectComp->getElement( RT_TEXCOORD );
1446   inTex2->setName( "texCoord2" );
1447   inTex2->setStructName( "IN" );
1448   inTex2->setType( "float2" );
1449
1450   // create texture var
1451   Var *toneMap = new Var;
1452   toneMap->setType( "SamplerState" );
1453   toneMap->setName( "toneMap" );
1454   toneMap->uniform = true;
1455   toneMap->sampler = true;
1456   toneMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1457
1458   Var *toneMapTex = new Var;
1459   toneMapTex->setName("toneMapTex");
1460   toneMapTex->setType("Texture2D");
1461   toneMapTex->uniform = true;
1462   toneMapTex->texture = true;
1463   toneMapTex->constNum = toneMap->constNum;
1464
1465   MultiLine * meta = new MultiLine;
1466
1467   // First get the toneMap color
1468   Var *toneMapColor = new Var;
1469   toneMapColor->setType( "float4" );
1470   toneMapColor->setName( "toneMapColor" );
1471   LangElement *toneMapColorDecl = new DecOp( toneMapColor );
1472
1473   meta->addStatement(new GenOp("   @ = @.Sample(@, @);\r\n", toneMapColorDecl, toneMapTex, toneMap, inTex2));
1474
1475   // We do a different calculation if there is a diffuse map or not
1476   Material::BlendOp blendOp = Material::Mul;
1477   if ( fd.features[MFT_DiffuseMap] )
1478   {
1479      // Reverse the tonemap
1480      meta->addStatement( new GenOp( "   @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) );
1481
1482      // Re-tonemap with the current color factored in
1483      blendOp = Material::ToneMap;
1484   }
1485
1486   // Find out if RTLighting should be added
1487   bool bPreProcessedLighting = false;
1488   AdvancedLightBinManager *lightBin;
1489   if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
1490      bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
1491
1492   // Add in the realtime lighting contribution
1493   if ( fd.features[MFT_RTLighting] )
1494   {
1495      // Right now, only Advanced Lighting is supported
1496      Var *inColor = (Var*) LangElement::find( "d_lightcolor" );
1497      if(inColor != NULL)
1498      {
1499         // Assign value in d_lightcolor to toneMapColor if it exists. This is
1500         // the dynamic light buffer, and it already has the tonemap included
1501         if(bPreProcessedLighting)
1502            meta->addStatement( new GenOp( "   @.rgb = @;\r\n", toneMapColor, inColor ) );
1503         else
1504            meta->addStatement( new GenOp( "   @.rgb += @.rgb;\r\n", toneMapColor, inColor ) );
1505      }
1506   }
1507
1508   // Assign to proper render target
1509   if( fd.features[MFT_LightbufferMRT] )
1510   {
1511      meta->addStatement( new GenOp( "   @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
1512      meta->addStatement( new GenOp( "   @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
1513   }
1514   else
1515      meta->addStatement( new GenOp( "   @;\r\n", assignColor( toneMapColor, blendOp ) ) );
1516  
1517   output = meta;
1518}
1519
1520ShaderFeature::Resources TonemapFeatHLSL::getResources( const MaterialFeatureData &fd )
1521{
1522   Resources res; 
1523   res.numTex = 1;
1524   res.numTexReg = 1;
1525
1526   return res;
1527}
1528
1529void TonemapFeatHLSL::setTexData(  Material::StageData &stageDat,
1530                                    const MaterialFeatureData &fd,
1531                                    RenderPassData &passData,
1532                                    U32 &texIndex )
1533{
1534   GFXTextureObject *tex = stageDat.getTex( MFT_ToneMap );
1535   if ( tex )
1536   {
1537      passData.mTexType[ texIndex ] = Material::ToneMapTex;
1538      passData.mSamplerNames[ texIndex ] = "toneMap";
1539      passData.mTexSlot[ texIndex++ ].texObject = tex;
1540   }
1541}
1542
1543U32 TonemapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
1544{
1545   return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
1546}
1547
1548//****************************************************************************
1549// pureLIGHT Lighting
1550//****************************************************************************
1551
1552void VertLitHLSL::processVert(   Vector<ShaderComponent*> &componentList, 
1553                                 const MaterialFeatureData &fd )
1554{
1555   // If we have a lightMap or toneMap then our lighting will be
1556   // handled by the MFT_LightMap or MFT_ToneNamp feature instead
1557   if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] )
1558   {
1559      output = NULL;
1560      return;
1561   }
1562
1563   // Create vertex color connector if it doesn't exist.
1564   
1565   Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
1566   if( !outColor )
1567   {
1568      // Search for vert color
1569      Var *inColor = (Var*) LangElement::find( "diffuse" );   
1570
1571      // If there isn't a vertex color then we can't do anything
1572      if( !inColor )
1573      {
1574         output = NULL;
1575         return;
1576      }
1577
1578      // Grab the connector color
1579      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1580      outColor = connectComp->getElement( RT_COLOR );
1581      outColor->setName( "vertColor" );
1582      outColor->setStructName( "OUT" );
1583      outColor->setType( "float4" );
1584
1585      output = new GenOp( "   @ = @;\r\n", outColor, inColor );
1586   }
1587   else
1588      output = NULL; // Nothing we need to do.
1589}
1590
1591void VertLitHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
1592                                       const MaterialFeatureData &fd )
1593{
1594   // If we have a lightMap or toneMap then our lighting will be
1595   // handled by the MFT_LightMap or MFT_ToneNamp feature instead
1596   if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] )
1597   {
1598      output = NULL;
1599      return;
1600   }
1601   
1602   // Grab the connector color register
1603   Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
1604   if( !vertColor )
1605   {
1606      ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
1607      AssertFatal( connectComp, "VertLitGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
1608      vertColor = connectComp->getElement( RT_COLOR );
1609      vertColor->setName( "vertColor" );
1610      vertColor->setStructName( "IN" );
1611      vertColor->setType( "float4" );
1612   }
1613
1614   MultiLine * meta = new MultiLine;
1615
1616   // Defaults (no diffuse map)
1617   Material::BlendOp blendOp = Material::Mul;
1618   LangElement *outColor = vertColor;
1619
1620   // We do a different calculation if there is a diffuse map or not
1621   if ( fd.features[MFT_DiffuseMap] || fd.features[MFT_VertLitTone] )
1622   {
1623      Var * finalVertColor = new Var;
1624      finalVertColor->setName( "finalVertColor" );
1625      finalVertColor->setType( "float4" );
1626      LangElement *finalVertColorDecl = new DecOp( finalVertColor );
1627      
1628      // Reverse the tonemap
1629      meta->addStatement( new GenOp( "   @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) );
1630
1631      // Set the blend op to tonemap
1632      blendOp = Material::ToneMap;
1633      outColor = finalVertColor;
1634   }
1635
1636   // Add in the realtime lighting contribution, if applicable
1637   if ( fd.features[MFT_RTLighting] )
1638   {
1639      Var *rtLightingColor = (Var*) LangElement::find( "d_lightcolor" );
1640      if(rtLightingColor != NULL)
1641      {
1642         bool bPreProcessedLighting = false;
1643         AdvancedLightBinManager *lightBin;
1644         if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
1645            bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
1646
1647         // Assign value in d_lightcolor to toneMapColor if it exists. This is
1648         // the dynamic light buffer, and it already has the baked-vertex-color 
1649         // included in it
1650         if(bPreProcessedLighting)
1651            outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor );
1652         else
1653            outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor );
1654      }
1655   }
1656
1657   // Output the color
1658   if ( fd.features[MFT_LightbufferMRT] )
1659   {
1660      meta->addStatement( new GenOp( "   @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
1661      meta->addStatement( new GenOp( "   @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
1662   }
1663   else
1664      meta->addStatement( new GenOp( "   @;\r\n", assignColor( outColor, blendOp ) ) );
1665
1666   output = meta;
1667}
1668
1669U32 VertLitHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
1670{
1671   return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
1672}
1673
1674//****************************************************************************
1675// Detail map
1676//****************************************************************************
1677
1678void DetailFeatHLSL::processVert(   Vector<ShaderComponent*> &componentList, 
1679                                    const MaterialFeatureData &fd )
1680{
1681   MultiLine *meta = new MultiLine;
1682   addOutDetailTexCoord( componentList, 
1683                         meta,
1684                         fd.features[MFT_TexAnim], fd.features[MFT_Foliage] );
1685   output = meta;
1686}
1687
1688void DetailFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 
1689                                 const MaterialFeatureData &fd )
1690{
1691   // Get the detail texture coord.
1692   Var *inTex = getInTexCoord( "detCoord", "float2", componentList );
1693
1694   // create texture var
1695   Var *detailMap = new Var;
1696   detailMap->setType( "SamplerState" );
1697   detailMap->setName( "detailMap" );
1698   detailMap->uniform = true;
1699   detailMap->sampler = true;
1700   detailMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1701
1702   Var* detailMapTex = new Var;
1703   detailMapTex->setName("detailMapTex");
1704   detailMapTex->setType("Texture2D");
1705   detailMapTex->uniform = true;
1706   detailMapTex->texture = true;
1707   detailMapTex->constNum = detailMap->constNum;
1708
1709   // We're doing the standard greyscale detail map
1710   // technique which can darken and lighten the 
1711   // diffuse texture.
1712
1713   // TODO: We could add a feature to toggle between this
1714   // and a simple multiplication with the detail map.
1715
1716   LangElement *statement = new GenOp("( @.Sample(@, @) * 2.0 ) - 1.0", detailMapTex, detailMap, inTex);
1717
1718   if (  fd.features[MFT_isDeferred])
1719      output = new GenOp( "   @;\r\n", assignColor( statement, Material::Add, NULL, ShaderFeature::RenderTarget1 ) );
1720   else
1721      output = new GenOp( "   @;\r\n", assignColor( statement, Material::Add ) );
1722}
1723
1724ShaderFeature::Resources DetailFeatHLSL::getResources( const MaterialFeatureData &fd )
1725{
1726   Resources res; 
1727   res.numTex = 1;
1728   res.numTexReg = 1;
1729
1730   return res;
1731}
1732
1733void DetailFeatHLSL::setTexData( Material::StageData &stageDat,
1734                                 const MaterialFeatureData &fd,
1735                                 RenderPassData &passData,
1736                                 U32 &texIndex )
1737{
1738   GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
1739   if ( tex )
1740   {
1741      passData.mSamplerNames[texIndex] = "detailMap";
1742      passData.mTexSlot[ texIndex++ ].texObject = tex;
1743   }
1744}
1745
1746
1747//****************************************************************************
1748// Vertex position
1749//****************************************************************************
1750
1751void VertPositionHLSL::determineFeature(  Material *material,
1752                                          const GFXVertexFormat *vertexFormat,
1753                                          U32 stageNum,
1754                                          const FeatureType &type,
1755                                          const FeatureSet &features,
1756                                          MaterialFeatureData *outFeatureData )
1757{
1758   // This feature is always on!
1759   outFeatureData->features.addFeature( type );
1760}
1761
1762void VertPositionHLSL::processVert( Vector<ShaderComponent*> &componentList, 
1763                                    const MaterialFeatureData &fd )
1764{
1765   // First check for an input position from a previous feature
1766   // then look for the default vertex position.
1767   Var *inPosition = (Var*)LangElement::find( "inPosition" );
1768   if ( !inPosition )
1769      inPosition = (Var*)LangElement::find( "position" );
1770
1771   // grab connector position
1772   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1773   Var *outPosition = connectComp->getElement(RT_SVPOSITION);
1774   
1775   outPosition->setName( "hpos" );
1776   outPosition->setStructName( "OUT" );
1777
1778   MultiLine *meta = new MultiLine;
1779
1780   Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta ); 
1781
1782   meta->addStatement( new GenOp( "   @ = mul(@, float4(@.xyz,1));\r\n", 
1783      outPosition, modelview, inPosition ) );
1784
1785   if (fd.materialFeatures[MFT_isBackground])
1786   {
1787      meta->addStatement(new GenOp("   @ = @.xyww;\r\n", outPosition, outPosition));
1788   }
1789
1790   output = meta;
1791}
1792
1793void VertPositionHLSL::processPix( Vector<ShaderComponent*> &componentList,
1794                                   const MaterialFeatureData &fd)
1795{
1796   // grab connector position
1797   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
1798   Var *outPosition = connectComp->getElement(RT_SVPOSITION);
1799   outPosition->setName("vpos");
1800   outPosition->setStructName("IN");
1801}
1802
1803
1804//****************************************************************************
1805// Reflect Cubemap
1806//****************************************************************************
1807
1808void ReflectCubeFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
1809                                       const MaterialFeatureData &fd )
1810{
1811   // search for vert normal
1812   Var *inNormal = (Var*) LangElement::find( "normal" );
1813   if ( !inNormal )
1814      return;
1815
1816   MultiLine * meta = new MultiLine;
1817
1818   // If a base or bump tex is present in the material, but not in the
1819   // current pass - we need to add one to the current pass to use
1820   // its alpha channel as a gloss map.  Here we just need the tex coords.
1821   if( !fd.features[MFT_DiffuseMap] &&
1822       !fd.features[MFT_NormalMap] )
1823   {
1824      if( fd.materialFeatures[MFT_DiffuseMap] ||
1825          fd.materialFeatures[MFT_NormalMap] )
1826      {
1827         // find incoming texture var
1828         Var *inTex = getVertTexCoord( "texCoord" );
1829
1830         // grab connector texcoord register
1831         ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1832         Var *outTex = connectComp->getElement( RT_TEXCOORD );
1833         outTex->setName( "texCoord" );
1834         outTex->setStructName( "OUT" );
1835         outTex->setType( "float2" );
1836
1837         // setup language elements to output incoming tex coords to output
1838         meta->addStatement( new GenOp( "   @ = @;\r\n", outTex, inTex ) );
1839      }
1840   }
1841       
1842    // create cubeTrans
1843    bool useInstancing = fd.features[MFT_UseInstancing];
1844    Var *cubeTrans = getObjTrans( componentList, useInstancing, meta );
1845
1846    // cube vert position
1847    Var * cubeVertPos = new Var;
1848    cubeVertPos->setName( "cubeVertPos" );
1849    cubeVertPos->setType( "float3" );
1850    LangElement *cubeVertPosDecl = new DecOp( cubeVertPos );
1851
1852    meta->addStatement( new GenOp( "   @ = mul(@, float4(@,1)).xyz;\r\n", 
1853                        cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) );
1854
1855    // cube normal
1856    Var * cubeNormal = new Var;
1857    cubeNormal->setName( "cubeNormal" );
1858    cubeNormal->setType( "float3" );
1859    LangElement *cubeNormDecl = new DecOp( cubeNormal );
1860
1861    meta->addStatement(new GenOp("   @ = ( mul( (@),  float4(@, 0) ) ).xyz;\r\n",
1862       cubeNormDecl, cubeTrans, inNormal));
1863       
1864    meta->addStatement(new GenOp("   @ = bool(length(@)) ? normalize(@) : @;\r\n",
1865         cubeNormal, cubeNormal, cubeNormal, cubeNormal));
1866
1867    // grab the eye position
1868    Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
1869    if ( !eyePos )
1870    {
1871        eyePos = new Var( "eyePosWorld", "float3" );
1872        eyePos->uniform = true;
1873        eyePos->constSortPos = cspPass;
1874    }
1875
1876    // eye to vert
1877    Var * eyeToVert = new Var;
1878    eyeToVert->setName( "eyeToVert" );
1879    eyeToVert->setType( "float3" );
1880    LangElement *e2vDecl = new DecOp( eyeToVert );
1881
1882    meta->addStatement( new GenOp( "   @ = @ - @;\r\n", 
1883                        e2vDecl, cubeVertPos, eyePos ) );
1884
1885    // grab connector texcoord register
1886    ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1887    Var *reflectVec = connectComp->getElement( RT_TEXCOORD );
1888    reflectVec->setName( "reflectVec" );
1889    reflectVec->setStructName( "OUT" );
1890    reflectVec->setType( "float3" );
1891
1892    meta->addStatement( new GenOp( "   @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) );
1893
1894    output = meta;
1895}
1896
1897void ReflectCubeFeatHLSL::processPix(  Vector<ShaderComponent*> &componentList, 
1898                                       const MaterialFeatureData &fd )
1899{
1900   MultiLine * meta = new MultiLine;
1901   Var *glossColor = NULL;
1902   
1903   // If a base or bump tex is present in the material, but not in the
1904   // current pass - we need to add one to the current pass to use
1905   // its alpha channel as a gloss map.
1906   if( !fd.features[MFT_DiffuseMap] &&
1907       !fd.features[MFT_NormalMap])
1908   {
1909      if( fd.materialFeatures[MFT_DiffuseMap] ||
1910          fd.materialFeatures[MFT_NormalMap])
1911      {
1912         // grab connector texcoord register
1913         Var *inTex = getInTexCoord("texCoord", "float2", componentList);
1914
1915         // create texture var
1916         Var *newMap = new Var;
1917         newMap->setType( "SamplerState" );
1918         newMap->setName( "glossMap" );
1919         newMap->uniform = true;
1920         newMap->sampler = true;
1921         newMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1922
1923         Var* glowMapTex = new Var;
1924         glowMapTex->setName("glowMapTex");
1925         glowMapTex->setType("Texture2D");
1926         glowMapTex->uniform = true;
1927         glowMapTex->texture = true;
1928         glowMapTex->constNum = newMap->constNum;
1929      
1930         // create sample color
1931         Var *color = new Var;
1932         color->setType( "float4" );
1933         color->setName( "diffuseColor" );
1934         LangElement *colorDecl = new DecOp( color );
1935
1936         glossColor = color;
1937         
1938          meta->addStatement(new GenOp("   @ = @.Sample( @, @ );\r\n", colorDecl, glowMapTex, newMap, inTex));
1939      }
1940   }
1941   if (!glossColor)
1942   {
1943      if (fd.features[MFT_isDeferred])
1944         glossColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1));
1945      if (!glossColor)
1946         glossColor = (Var*)LangElement::find("diffuseColor");
1947      if (!glossColor)
1948         glossColor = (Var*)LangElement::find("bumpNormal");
1949   }
1950
1951   // grab connector texcoord register
1952   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
1953   Var *reflectVec = connectComp->getElement( RT_TEXCOORD );
1954   reflectVec->setName( "reflectVec" );
1955   reflectVec->setStructName( "IN" );
1956   reflectVec->setType( "float3" );
1957
1958   // create cubemap var
1959   Var *cubeMap = new Var;
1960   cubeMap->setType( "SamplerState" );
1961   cubeMap->setName( "cubeMap" );
1962   cubeMap->uniform = true;
1963   cubeMap->sampler = true;
1964   cubeMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
1965
1966   Var* cubeMapTex = new Var;
1967   cubeMapTex->setName("cubeMapTex");
1968   cubeMapTex->setType("TextureCube");  // cubeMapTex->setType("TextureCube");
1969   cubeMapTex->uniform = true;
1970   cubeMapTex->texture = true;
1971   cubeMapTex->constNum = cubeMap->constNum;
1972
1973   Var *cubeMips = new Var;
1974   cubeMips->setType("float");
1975   cubeMips->setName("cubeMips");
1976   cubeMips->uniform = true;
1977   cubeMips->constSortPos = cspPotentialPrimitive;
1978
1979   // TODO: Restore the lighting attenuation here!
1980   Var *attn = NULL;
1981   //if ( fd.materialFeatures[MFT_DynamicLight] )
1982      //attn = (Var*)LangElement::find("attn");
1983   //else 
1984      if ( fd.materialFeatures[MFT_RTLighting] )
1985      attn =(Var*)LangElement::find("d_NL_Att");
1986      
1987   LangElement *texCube = NULL;
1988   Var* matinfo = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
1989   Var *roughness = (Var*)LangElement::find("roughness");
1990
1991   if (roughness) //try to grab roughness directly
1992   {
1993      texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, roughness, cubeMips, cubeMips);
1994   }
1995   else if (glossColor)//failing that, try and find color data
1996   {
1997      texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @.b)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, glossColor, cubeMips, cubeMips);
1998   }
1999   else //failing *that*, just draw the cubemap
2000   {
2001      texCube = new GenOp("@.Sample( @, @ )", cubeMapTex, cubeMap, reflectVec);
2002   }
2003
2004   LangElement *lerpVal = NULL;
2005   Material::BlendOp blendOp = Material::LerpAlpha;
2006
2007   // Note that the lerpVal needs to be a float4 so that
2008   // it will work with the LerpAlpha blend.
2009
2010   if (matinfo)
2011   {
2012      if (attn)
2013         lerpVal = new GenOp("@ * saturate( @ )", matinfo, attn);
2014      else
2015         lerpVal = new GenOp("@", matinfo);
2016   }
2017   else if ( glossColor )
2018   {
2019      if ( attn )
2020         lerpVal = new GenOp( "@ * saturate( @ )", glossColor, attn );
2021      else
2022         lerpVal = glossColor;
2023   }
2024   else
2025   {
2026      if ( attn )
2027         lerpVal = new GenOp( "saturate( @ ).xxxx", attn );
2028      else
2029         blendOp = Material::Mul;
2030   }
2031   
2032   Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3));
2033   if (fd.features[MFT_isDeferred])
2034   {
2035       //metalness: black(0) = color, white(1) = reflection
2036       if (fd.features[MFT_ToneMap])
2037          meta->addStatement(new GenOp("   @ *= @;\r\n", targ, texCube));
2038       else
2039          meta->addStatement(new GenOp("   @ = @;\r\n", targ, texCube));
2040   }
2041   else
2042   {
2043      meta->addStatement(new GenOp("   //forward lit cubemapping\r\n"));
2044      targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2045      
2046      Var *metalness = (Var*)LangElement::find("metalness");
2047      if (metalness)
2048      {
2049         Var *dColor = new Var("dColor", "float3");
2050         Var *reflectColor = new Var("reflectColor", "float3");
2051         meta->addStatement(new GenOp("   @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), targ, targ, metalness));
2052         meta->addStatement(new GenOp("   @ = @.rgb*(@).rgb*@;\r\n", new DecOp(reflectColor), targ, texCube, metalness));
2053         meta->addStatement(new GenOp("   @.rgb = @+@;\r\n", targ, dColor, reflectColor));
2054      }
2055      else if (lerpVal)
2056         meta->addStatement(new GenOp("   @ *= float4(@.rgb*@.a, @.a);\r\n", targ, texCube, lerpVal, targ));
2057      else
2058         meta->addStatement(new GenOp("   @.rgb *= @.rgb;\r\n", targ, texCube));
2059   }
2060   output = meta;
2061}
2062
2063ShaderFeature::Resources ReflectCubeFeatHLSL::getResources( const MaterialFeatureData &fd )
2064{
2065   Resources res; 
2066
2067   if( fd.features[MFT_DiffuseMap] ||
2068       fd.features[MFT_NormalMap] )
2069   {
2070      res.numTex = 1;
2071      res.numTexReg = 1;
2072   }
2073   else
2074   {
2075      res.numTex = 2;
2076      res.numTexReg = 2;
2077   }
2078
2079   return res;
2080}
2081
2082void ReflectCubeFeatHLSL::setTexData(  Material::StageData &stageDat,
2083                                       const MaterialFeatureData &stageFeatures,
2084                                       RenderPassData &passData,
2085                                       U32 &texIndex )
2086{
2087   // set up a gloss map if one is not present in the current pass
2088   // but is present in the current material stage
2089   if( !passData.mFeatureData.features[MFT_DiffuseMap] &&
2090       !passData.mFeatureData.features[MFT_NormalMap] )
2091   {
2092      GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
2093      if (  tex && stageFeatures.features[MFT_DiffuseMap] )
2094      {
2095         passData.mSamplerNames[ texIndex ] = "diffuseMap";
2096         passData.mTexSlot[ texIndex++ ].texObject = tex;
2097      }
2098      else
2099      {
2100         tex = stageDat.getTex( MFT_NormalMap );
2101
2102         if (  tex && stageFeatures.features[ MFT_NormalMap ] )
2103         {
2104            passData.mSamplerNames[ texIndex ] = "bumpMap";
2105            passData.mTexSlot[ texIndex++ ].texObject = tex;
2106         }
2107      }
2108   }
2109
2110   if( stageDat.getCubemap() )
2111   {
2112      passData.mCubeMap = stageDat.getCubemap();
2113      passData.mSamplerNames[texIndex] = "cubeMap";
2114      passData.mTexType[texIndex++] = Material::Cube;
2115   }
2116   else
2117   {
2118      if( stageFeatures.features[MFT_CubeMap] )
2119      {
2120         // assuming here that it is a scenegraph cubemap
2121         passData.mSamplerNames[texIndex] = "cubeMap";
2122         passData.mTexType[texIndex++] = Material::SGCube;
2123      }
2124   }
2125
2126}
2127
2128
2129//****************************************************************************
2130// RTLighting
2131//****************************************************************************
2132
2133RTLightingFeatHLSL::RTLightingFeatHLSL()
2134   : mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl" ))
2135{
2136   addDependency( &mDep );
2137}
2138
2139void RTLightingFeatHLSL::processVert(  Vector<ShaderComponent*> &componentList, 
2140                                       const MaterialFeatureData &fd )
2141{
2142   MultiLine *meta = new MultiLine;   
2143
2144   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2145   getOutWorldToTangent(componentList, meta, fd);
2146
2147   // Special case for lighting imposters. We dont have a vert normal and may not
2148   // have a normal map. Generate and pass the normal data the pixel shader needs.
2149   if ( fd.features[MFT_ImposterVert] )
2150   {
2151      
2152      if ( !fd.features[MFT_NormalMap] )
2153      {
2154         Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
2155         if ( !eyePos )
2156         {
2157            eyePos = new Var( "eyePosWorld", "float3" );
2158            eyePos->uniform = true;
2159            eyePos->constSortPos = cspPass;
2160         }
2161
2162         //Temporarily disabled while we figure out how to better handle normals without a normal map
2163         /*Var *inPosition = (Var*)LangElement::find( "position" );
2164
2165         Var *outNormal = connectComp->getElement( RT_TEXCOORD );
2166         outNormal->setName( "wsNormal" );
2167         outNormal->setStructName( "OUT" );
2168         outNormal->setType( "float3" );
2169
2170         // Transform the normal to world space.
2171         meta->addStatement( new GenOp( "   @ = normalize( @ - @.xyz );\r\n", outNormal, eyePos, inPosition ) );*/
2172      }
2173
2174      addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
2175
2176      output = meta;
2177
2178      return;
2179   }
2180
2181   // Find the incoming vertex normal.
2182   Var *inNormal = (Var*)LangElement::find( "normal" );   
2183
2184   // Skip out on realtime lighting if we don't have a normal
2185   // or we're doing some sort of baked lighting.
2186   if (  !inNormal || 
2187         fd.features[MFT_LightMap] || 
2188         fd.features[MFT_ToneMap] || 
2189         fd.features[MFT_VertLit] )
2190      return;   
2191
2192   // If there isn't a normal map then we need to pass
2193   // the world space normal to the pixel shader ourselves.
2194   //Temporarily disabled while we figure out how to better handle normals without a normal map
2195   if ( !fd.features[MFT_NormalMap] )
2196   {
2197      Var *outNormal = connectComp->getElement( RT_TEXCOORD );
2198      outNormal->setName( "wsNormal" );
2199      outNormal->setStructName( "OUT" );
2200      outNormal->setType( "float3" );
2201
2202      // Get the transform to world space.
2203      Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta );
2204
2205      // Transform the normal to world space.
2206      meta->addStatement( new GenOp( "   @ = mul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) );
2207   }
2208
2209   addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
2210
2211   output = meta;
2212}
2213
2214void RTLightingFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
2215                                       const MaterialFeatureData &fd )
2216{
2217   // Skip out on realtime lighting if we don't have a normal
2218   // or we're doing some sort of baked lighting.
2219   //
2220   // TODO: We can totally detect for this in the material
2221   // feature setup... we should move it out of here!
2222   //
2223   if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit] )
2224      return;
2225  
2226   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2227
2228   MultiLine *meta = new MultiLine;
2229
2230   // Now the wsPosition and wsView.
2231   Var* worldToTangent = getInWorldToTangent(componentList);
2232   Var* wsNormal = getInWorldNormal(componentList);
2233   Var *wsPosition = getInWsPosition( componentList );
2234   
2235   Var *wsView = getWsView( wsPosition, meta );
2236   
2237   // Look for a light mask generated from a previous
2238   // feature (this is done for BL terrain lightmaps).
2239   LangElement *lightMask = LangElement::find( "lightMask" );
2240   if ( !lightMask )
2241      lightMask = new GenOp( "float4( 1, 1, 1, 1 )" );
2242
2243   // Get all the light constants.
2244   Var *inLightPos  = new Var( "inLightPos", "float4" );
2245   inLightPos->uniform = true;
2246   inLightPos->arraySize = 4;
2247   inLightPos->constSortPos = cspPotentialPrimitive;
2248
2249   Var * inLightConfigData = new Var( "inLightConfigData", "float4" );
2250   inLightConfigData->uniform = true;
2251   inLightConfigData->arraySize = 4;
2252   inLightConfigData->constSortPos = cspPotentialPrimitive;
2253
2254   Var *inLightColor  = new Var( "inLightColor", "float4" );
2255   inLightColor->uniform = true;
2256   inLightColor->arraySize = 4;
2257   inLightColor->constSortPos = cspPotentialPrimitive;
2258
2259   Var *inLightSpotDir  = new Var( "inLightSpotDir", "float4" );
2260   inLightSpotDir->uniform = true;
2261   inLightSpotDir->arraySize = 4;
2262   inLightSpotDir->constSortPos = cspPotentialPrimitive;
2263
2264   Var * lightSpotParams = new Var( "lightSpotParams", "float2" );
2265   lightSpotParams->uniform = true;
2266   lightSpotParams->arraySize = 4;
2267   lightSpotParams->constSortPos = cspPotentialPrimitive;
2268
2269   Var* hasVectorLight = new Var("hasVectorLight", "int");
2270   hasVectorLight->uniform = true;
2271   hasVectorLight->constSortPos = cspPotentialPrimitive;
2272
2273   Var* vectorLightDirection = new Var("vectorLightDirection", "float4");
2274   vectorLightDirection->uniform = true;
2275   vectorLightDirection->constSortPos = cspPotentialPrimitive;
2276
2277   Var* vectorLightColor = new Var("vectorLightColor", "float4");
2278   vectorLightColor->uniform = true;
2279   vectorLightColor->constSortPos = cspPotentialPrimitive;
2280
2281   Var* vectorLightBrightness = new Var("vectorLightBrightness", "float");
2282   vectorLightBrightness->uniform = true;
2283   vectorLightBrightness->constSortPos = cspPotentialPrimitive;
2284
2285   Var* surface = getSurface(componentList, meta, fd);
2286   if (!surface)
2287   {
2288      Con::errorf("ShaderGen::RTLightingFeatHLSL()  - failed to generate surface!");
2289      return;
2290   }   
2291   Var *roughness = (Var*)LangElement::find("roughness");
2292
2293   Var *metalness = (Var*)LangElement::find("metalness");
2294
2295   Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2296
2297   Var *ambient  = new Var( "ambient", "float4" );
2298   ambient->uniform = true;
2299   ambient->constSortPos = cspPass;
2300   
2301   Var* lighting = new Var("lighting", "float4");
2302   meta->addStatement(new GenOp("   @ = compute4Lights( @, @, @, @,\r\n"
2303      "      @, @, @, @, @, @, @);\r\n",
2304      new DecOp(lighting), surface, lightMask, inLightPos, inLightConfigData, inLightColor, inLightSpotDir, lightSpotParams,
2305         hasVectorLight, vectorLightDirection, vectorLightColor, vectorLightBrightness));
2306
2307   meta->addStatement(new GenOp("   @.rgb += @.rgb;\r\n", curColor, lighting));
2308
2309   output = meta;  
2310}
2311
2312ShaderFeature::Resources RTLightingFeatHLSL::getResources( const MaterialFeatureData &fd )
2313{
2314   Resources res;
2315
2316   // These features disable realtime lighting.
2317   if (  !fd.features[MFT_LightMap] && 
2318         !fd.features[MFT_ToneMap] &&
2319         !fd.features[MFT_VertLit] )
2320   {
2321      // If enabled we pass the position.
2322      res.numTexReg = 1;
2323
2324      // If there isn't a bump map then we pass the
2325      // world space normal as well.
2326      if ( !fd.features[MFT_NormalMap] )
2327         res.numTexReg++;
2328   }
2329
2330   return res;
2331}
2332
2333
2334//****************************************************************************
2335// Fog
2336//****************************************************************************
2337
2338FogFeatHLSL::FogFeatHLSL()
2339   : mFogDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2340{
2341   addDependency( &mFogDep );
2342}
2343
2344void FogFeatHLSL::processVert(   Vector<ShaderComponent*> &componentList, 
2345                                 const MaterialFeatureData &fd )
2346{
2347   MultiLine *meta = new MultiLine;
2348
2349   const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false );
2350   if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 )
2351   {
2352      // Grab the eye position.
2353      Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
2354      if ( !eyePos )
2355      {
2356         eyePos = new Var( "eyePosWorld", "float3" );
2357         eyePos->uniform = true;
2358         eyePos->constSortPos = cspPass;
2359      }
2360
2361      Var *fogData = new Var( "fogData", "float3" );
2362      fogData->uniform = true;
2363      fogData->constSortPos = cspPass;   
2364
2365      Var *wsPosition = new Var( "fogPos", "float3" );
2366      getWsPosition( componentList, 
2367                     fd.features[MFT_UseInstancing], 
2368                     meta,
2369                     new DecOp( wsPosition ) );
2370
2371      // We pass the fog amount to the pixel shader.
2372      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2373      Var *fogAmount = connectComp->getElement( RT_TEXCOORD );
2374      fogAmount->setName( "fogAmount" );
2375      fogAmount->setStructName( "OUT" );
2376      fogAmount->setType( "float" );
2377
2378      meta->addStatement( new GenOp( "   @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n", 
2379         fogAmount, eyePos, wsPosition, fogData, fogData, fogData ) );
2380   }
2381   else
2382   {
2383      // We fog in world space... make sure the world space
2384      // position is passed to the pixel shader.  This is
2385      // often already passed for lighting, so it takes up
2386      // no extra output registers.
2387      addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
2388   }
2389
2390   output = meta;
2391}
2392
2393void FogFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 
2394                              const MaterialFeatureData &fd )
2395{
2396   MultiLine *meta = new MultiLine;
2397
2398   Var *fogColor = new Var;
2399   fogColor->setType( "float4" );
2400   fogColor->setName( "fogColor" );
2401   fogColor->uniform = true;
2402   fogColor->constSortPos = cspPass;
2403
2404   // Get the out color.
2405   Var *color = (Var*) LangElement::find( "col" );
2406   if ( !color )
2407   {
2408      color = new Var;
2409      color->setType( "fragout" );
2410      color->setName( "col" );
2411      color->setStructName( "OUT" );
2412   }
2413
2414   Var *fogAmount;
2415
2416   const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false );
2417   if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 )
2418   {
2419      // Per-vertex.... just get the fog amount.
2420      ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2421      fogAmount = connectComp->getElement( RT_TEXCOORD );
2422      fogAmount->setName( "fogAmount" );
2423      fogAmount->setStructName( "IN" );
2424      fogAmount->setType( "float" );
2425   }
2426   else
2427   {
2428      Var *wsPosition = getInWsPosition( componentList );
2429
2430      // grab the eye position
2431      Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
2432      if ( !eyePos )
2433      {
2434         eyePos = new Var( "eyePosWorld", "float3" );
2435         eyePos->uniform = true;
2436         eyePos->constSortPos = cspPass;
2437      }
2438
2439      Var *fogData = new Var( "fogData", "float3" );
2440      fogData->uniform = true;
2441      fogData->constSortPos = cspPass;   
2442
2443      /// Get the fog amount.
2444      fogAmount = new Var( "fogAmount", "float" );
2445      meta->addStatement( new GenOp( "   @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n", 
2446         new DecOp( fogAmount ), eyePos, wsPosition, fogData, fogData, fogData ) );
2447   }
2448
2449   // Lerp between the fog color and diffuse color.
2450   LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount );
2451   meta->addStatement( new GenOp( "   @.rgb = @;\r\n", color, fogLerp ) );
2452
2453   output = meta;
2454}
2455
2456ShaderFeature::Resources FogFeatHLSL::getResources( const MaterialFeatureData &fd )
2457{
2458   Resources res;
2459   res.numTexReg = 1;
2460   return res;
2461}
2462
2463
2464//****************************************************************************
2465// Visibility
2466//****************************************************************************
2467
2468VisibilityFeatHLSL::VisibilityFeatHLSL()
2469   : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2470{
2471   addDependency( &mTorqueDep );
2472}
2473
2474void VisibilityFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 
2475                                      const MaterialFeatureData &fd )
2476{
2477   MultiLine *meta = new MultiLine;
2478   output = meta;
2479
2480   if ( fd.features[ MFT_UseInstancing ] )
2481   {
2482      // We pass the visibility to the pixel shader via
2483      // another output register.
2484      //
2485      // TODO: We should see if we can share this register
2486      // with some other common instanced data.
2487      //
2488      ShaderConnector *conn = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2489      Var *outVisibility = conn->getElement( RT_TEXCOORD );
2490      outVisibility->setStructName( "OUT" );
2491      outVisibility->setName( "visibility" );
2492      outVisibility->setType( "float" );
2493
2494      ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] );
2495      Var *instVisibility = vertStruct->getElement( RT_TEXCOORD, 1 );
2496      instVisibility->setStructName( "IN" );
2497      instVisibility->setName( "inst_visibility" );
2498      instVisibility->setType( "float" );
2499      mInstancingFormat->addElement( "visibility", GFXDeclType_Float, instVisibility->constNum );
2500
2501      meta->addStatement( new GenOp( "   @ = @; // Instancing!\r\n", outVisibility, instVisibility ) );
2502   }
2503
2504   if ( fd.features[ MFT_IsTranslucent ] )
2505      return;
2506
2507   addOutVpos( meta, componentList );
2508}
2509
2510void VisibilityFeatHLSL::processPix(   Vector<ShaderComponent*> &componentList, 
2511                                       const MaterialFeatureData &fd )
2512{
2513   // Get the visibility constant.
2514   Var *visibility = NULL;
2515   if ( fd.features[ MFT_UseInstancing ] )
2516      visibility = getInTexCoord( "visibility", "float", componentList );
2517   else
2518   {
2519      visibility = (Var*)LangElement::find( "visibility" );
2520
2521      if ( !visibility )
2522      {
2523         visibility = new Var();
2524         visibility->setType( "float" );
2525         visibility->setName( "visibility" );
2526         visibility->uniform = true;
2527         visibility->constSortPos = cspPotentialPrimitive;  
2528      }
2529   }
2530
2531   MultiLine *meta = new MultiLine;
2532   output = meta;
2533
2534   // Translucent objects do a simple alpha fade.
2535   if ( fd.features[ MFT_IsTranslucent ] )
2536   {
2537      Var *color = (Var*)LangElement::find( "col" );      
2538      meta->addStatement( new GenOp( "   @.a *= @;\r\n", color, visibility ) );
2539      return;
2540   }
2541
2542   // Everything else does a fizzle.
2543   Var *vPos = getInVpos( meta, componentList );
2544   // vpos is a float4 in d3d11
2545   meta->addStatement( new GenOp( "   fizzle( @.xy, @ );\r\n", vPos, visibility ) );
2546}
2547
2548ShaderFeature::Resources VisibilityFeatHLSL::getResources( const MaterialFeatureData &fd )
2549{
2550   Resources res; 
2551
2552   // TODO: Fix for instancing.
2553   
2554   if ( !fd.features[ MFT_IsTranslucent ] )
2555      res.numTexReg = 1;
2556
2557   return res;
2558}
2559
2560//****************************************************************************
2561// AlphaTest
2562//****************************************************************************
2563
2564void AlphaTestHLSL::processPix(  Vector<ShaderComponent*> &componentList,
2565                                 const MaterialFeatureData &fd )
2566{
2567   // If we're below SM3 and don't have a depth output
2568   // feature then don't waste an instruction here.
2569   if (( GFX->getPixelShaderVersion() < 3.0 &&
2570        !fd.features[ MFT_EyeSpaceDepthOut ]  &&
2571        !fd.features[ MFT_DepthOut ] ) ||
2572         fd.features[MFT_IsTranslucent])
2573   {
2574      output = NULL;
2575      return;
2576   }
2577
2578   // If we don't have a color var then we cannot do an alpha test.
2579   Var *color = (Var*)LangElement::find( "col1" );
2580   if (!color)
2581      color = (Var*)LangElement::find("col");
2582   if ( !color )
2583   {
2584      output = NULL;
2585      return;
2586   }
2587
2588   // Now grab the alpha test value.
2589   Var *alphaTestVal  = new Var;
2590   alphaTestVal->setType( "float" );
2591   alphaTestVal->setName( "alphaTestValue" );
2592   alphaTestVal->uniform = true;
2593   alphaTestVal->constSortPos = cspPotentialPrimitive;
2594
2595   // Do the clip.
2596   output = new GenOp( "   clip( @.a - @ );\r\n", color, alphaTestVal );
2597}
2598
2599
2600//****************************************************************************
2601// GlowMask
2602//****************************************************************************
2603
2604void GlowMaskHLSL::processPix(   Vector<ShaderComponent*> &componentList,
2605                                 const MaterialFeatureData &fd )
2606{
2607   output = NULL;
2608
2609   // Get the output color... and make it black to mask out 
2610   // glow passes rendered before us.
2611   //
2612   // The shader compiler will optimize out all the other
2613   // code above that doesn't contribute to the alpha mask.
2614   Var *color = (Var*)LangElement::find( "col" );
2615   if ( color )
2616      output = new GenOp( "   @.rgb = 0;\r\n", color );
2617}
2618
2619
2620//****************************************************************************
2621// RenderTargetZero
2622//****************************************************************************
2623
2624void RenderTargetZeroHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
2625{
2626   // Do not actually assign zero, but instead a number so close to zero it may as well be zero.
2627   // This will prevent a divide by zero causing an FP special on float render targets
2628   output = new GenOp( "   @;\r\n", assignColor( new GenOp( "0.00001" ), Material::None, NULL, mOutputTargetMask ) );
2629}
2630
2631
2632//****************************************************************************
2633// HDR Output
2634//****************************************************************************
2635
2636HDROutHLSL::HDROutHLSL()
2637   : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2638{
2639   addDependency( &mTorqueDep );
2640}
2641
2642void HDROutHLSL::processPix(  Vector<ShaderComponent*> &componentList,
2643                              const MaterialFeatureData &fd )
2644{
2645   // Let the helper function do the work.
2646   Var *color = (Var*)LangElement::find( "col" );
2647   if ( color )
2648      output = new GenOp( "   @ = hdrEncode( @ );\r\n", color, color );
2649}
2650
2651//****************************************************************************
2652// FoliageFeatureHLSL
2653//****************************************************************************
2654
2655#include "T3D/fx/groundCover.h"
2656
2657FoliageFeatureHLSL::FoliageFeatureHLSL()
2658: mDep(ShaderGen::smCommonShaderPath + String("/foliage.hlsl" ))
2659{
2660   addDependency( &mDep );
2661}
2662
2663void FoliageFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList, 
2664                                      const MaterialFeatureData &fd )
2665{      
2666   // Get the input variables we need.
2667
2668   Var *inPosition = (Var*)LangElement::find( "inPosition" );
2669   if ( !inPosition )
2670      inPosition = (Var*)LangElement::find( "position" );
2671      
2672   Var *inColor = (Var*)LangElement::find( "diffuse" );   
2673   
2674   Var *inParams = (Var*)LangElement::find( "texCoord" );   
2675
2676   MultiLine *meta = new MultiLine;
2677
2678   // Declare the normal and tangent variables since they do not exist
2679   // in this vert type, but we do need to set them up for others.
2680
2681   Var *normal = (Var*)LangElement::find( "normal" );   
2682   AssertFatal( normal, "FoliageFeatureHLSL requires vert normal!" );   
2683
2684   Var *tangent = new Var;
2685   tangent->setType( "float3" );
2686   tangent->setName( "T" );
2687   LangElement *tangentDec = new DecOp( tangent );
2688   meta->addStatement( new GenOp( "   @;\n", tangentDec ) );         
2689
2690   // We add a float foliageFade to the OUT structure.
2691   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2692   Var *fade = connectComp->getElement( RT_TEXCOORD );
2693   fade->setName( "foliageFade" );
2694   fade->setStructName( "OUT" );
2695   fade->setType( "float" );
2696
2697   // grab the eye position
2698   Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
2699   if ( !eyePos )
2700   {
2701      eyePos = new Var( "eyePosWorld", "float3" );
2702      eyePos->uniform = true;
2703      eyePos->constSortPos = cspPass;
2704   }
2705
2706   // All actual work is offloaded to this method.
2707   meta->addStatement( new GenOp( "   foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) );   
2708
2709   // Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert.
2710   meta->addStatement( new GenOp( "   @ = @.a;\r\n", fade, inColor ) );
2711
2712   output = meta;
2713}
2714
2715void FoliageFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList, 
2716                                     const MaterialFeatureData &fd )
2717{
2718   // Find / create IN.foliageFade
2719   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2720   Var *fade = connectComp->getElement( RT_TEXCOORD );
2721   fade->setName( "foliageFade" );
2722   fade->setStructName( "IN" );
2723   fade->setType( "float" );
2724      
2725   // Find / create visibility
2726   Var *visibility = (Var*) LangElement::find( "visibility" );
2727   if ( !visibility )
2728   {
2729      visibility = new Var();
2730      visibility->setType( "float" );
2731      visibility->setName( "visibility" );
2732      visibility->uniform = true;
2733      visibility->constSortPos = cspPotentialPrimitive;  
2734   }      
2735
2736   MultiLine *meta = new MultiLine;
2737
2738   // Multiply foliageFade into visibility.
2739   meta->addStatement( new GenOp( "   @ *= @;\r\n", visibility, fade ) );
2740
2741   output = meta;
2742}
2743
2744void FoliageFeatureHLSL::determineFeature( Material *material, const GFXVertexFormat *vertexFormat, U32 stageNum, const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData )
2745{      
2746   // This isn't really necessary since the outFeatureData will be filtered after
2747   // this call.
2748   if ( features.hasFeature( MFT_Foliage  ) )
2749      outFeatureData->features.addFeature( type );
2750}
2751
2752
2753ShaderFeatureConstHandles* FoliageFeatureHLSL::createConstHandles( GFXShader *shader, SimObject *userObject )
2754{
2755   GroundCover *gcover = dynamic_cast< GroundCover* >( userObject );
2756   AssertFatal( gcover != NULL, "FoliageFeatureHLSL::createConstHandles - userObject was not valid!" );
2757
2758   GroundCoverShaderConstHandles *handles = new GroundCoverShaderConstHandles();
2759   handles->mGroundCover = gcover;
2760
2761   handles->init( shader );
2762   
2763   return handles;
2764}
2765
2766
2767void ParticleNormalFeatureHLSL::processVert(Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd)
2768{
2769   MultiLine *meta = new MultiLine;
2770   output = meta;
2771
2772   // Calculate normal and tangent values since we want to keep particle verts
2773   // as light-weight as possible
2774
2775   Var *normal = (Var*) LangElement::find("normal");
2776   if(normal == NULL)
2777   {
2778      normal = new Var;
2779      normal->setType( "float3" );
2780      normal->setName( "normal" );
2781
2782      // These values are not accidental. It is slightly adjusted from facing straight into the
2783      // screen because there is a discontinuity at (0, 1, 0) for gbuffer encoding. Do not
2784      // cause this value to be (0, -1, 0) or interlaced normals will be discontinuous.
2785      // [11/23/2009 Pat]
2786      meta->addStatement(new GenOp("   @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal)));
2787   }
2788
2789   Var *T = (Var*) LangElement::find( "T" );
2790   if(T == NULL)
2791   {
2792      T = new Var;
2793      T->setType( "float3" );
2794      T->setName( "T" );
2795      meta->addStatement(new GenOp("   @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T)));
2796   }
2797}
2798
2799//****************************************************************************
2800// ImposterVertFeatureHLSL
2801//****************************************************************************
2802
2803ImposterVertFeatureHLSL::ImposterVertFeatureHLSL()
2804   :  mDep(ShaderGen::smCommonShaderPath + String("/imposter.hlsl" ))
2805{
2806   addDependency( &mDep );
2807}
2808
2809void ImposterVertFeatureHLSL::processVert(   Vector<ShaderComponent*> &componentList, 
2810                                             const MaterialFeatureData &fd )
2811{      
2812   MultiLine *meta = new MultiLine;
2813   output = meta;
2814
2815   // Get the input vertex variables.   
2816   Var *inPosition = (Var*)LangElement::find( "position" );
2817   Var *inMiscParams = (Var*)LangElement::find( "tcImposterParams" );   
2818   Var *inUpVec = (Var*)LangElement::find( "tcImposterUpVec" );   
2819   Var *inRightVec = (Var*)LangElement::find( "tcImposterRightVec" );
2820
2821   // Get the input shader constants.
2822   Var *imposterLimits  = new Var;
2823   imposterLimits->setType( "float4" );
2824   imposterLimits->setName( "imposterLimits" );
2825   imposterLimits->uniform = true;
2826   imposterLimits->constSortPos = cspPotentialPrimitive;
2827
2828   Var *imposterUVs  = new Var;
2829   imposterUVs->setType( "float4" );
2830   imposterUVs->setName( "imposterUVs" );
2831   imposterUVs->arraySize = 64; // See imposter.hlsl
2832   imposterUVs->uniform = true;
2833   imposterUVs->constSortPos = cspPotentialPrimitive;
2834
2835   Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
2836   if ( !eyePos )
2837   {
2838      eyePos = new Var( "eyePosWorld", "float3" );
2839      eyePos->uniform = true;
2840      eyePos->constSortPos = cspPass;
2841   }
2842
2843   // Declare the outputs from this feature.
2844   Var *outInPosition = new Var;
2845   outInPosition->setType( "float3" );
2846   outInPosition->setName( "inPosition" );
2847   meta->addStatement( new GenOp( "   @;\r\n", new DecOp( outInPosition ) ) );         
2848
2849   Var *outTexCoord = new Var;
2850   outTexCoord->setType( "float2" );
2851   outTexCoord->setName( "texCoord" );
2852   meta->addStatement( new GenOp( "   @;\r\n", new DecOp( outTexCoord ) ) );         
2853
2854   Var *outWorldToTangent = new Var;
2855   outWorldToTangent->setType( "float3x3" );
2856   outWorldToTangent->setName( "worldToTangent" );
2857   meta->addStatement( new GenOp( "   @;\r\n", new DecOp( outWorldToTangent ) ) );         
2858
2859   // Add imposterFade to the OUT structure.
2860   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2861   Var *outFade = connectComp->getElement( RT_TEXCOORD );
2862   outFade->setName( "imposterFade" );
2863   outFade->setStructName( "OUT" );
2864   outFade->setType( "float" ); 
2865
2866   // Assign OUT.imposterFade
2867   meta->addStatement( new GenOp( "   @ = @.y;\r\n", outFade, inMiscParams ) );
2868
2869   // All actual work is done in this method.
2870   meta->addStatement( new GenOp( "   imposter_v( @.xyz, @.w, @.x * length(@), normalize(@), normalize(@), @.y, @.x, @.z, @.w, @, @, @, @, @ );\r\n",
2871
2872                        inPosition,
2873                        inPosition,
2874
2875                        inMiscParams,
2876                        inRightVec,
2877
2878                        inUpVec,
2879                        inRightVec,
2880
2881                        imposterLimits,
2882                        imposterLimits,
2883                        imposterLimits,
2884                        imposterLimits,
2885
2886                        eyePos,
2887                        imposterUVs,
2888
2889                        outInPosition, 
2890                        outTexCoord,
2891                        outWorldToTangent ) );
2892
2893   // Copy the position to wsPosition for use in shaders 
2894   // down stream instead of looking for objTrans.
2895   Var *wsPosition = new Var;
2896   wsPosition->setType( "float3" );
2897   wsPosition->setName( "wsPosition" );
2898   meta->addStatement( new GenOp( "   @ = @.xyz;\r\n", new DecOp( wsPosition ), outInPosition ) ); 
2899
2900   // If we new viewToTangent... its the same as the
2901   // world to tangent for an imposter.
2902   Var *viewToTangent = new Var;
2903   viewToTangent->setType( "float3x3" );
2904   viewToTangent->setName( "viewToTangent" );
2905   meta->addStatement( new GenOp( "   @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) );       
2906}
2907
2908void ImposterVertFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList,
2909                                          const MaterialFeatureData &fd )
2910{
2911   // Find / create IN.imposterFade
2912   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2913   Var *fade = connectComp->getElement( RT_TEXCOORD );
2914   fade->setName( "imposterFade" );
2915   fade->setStructName( "IN" );
2916   fade->setType( "float" );
2917      
2918   // Find / create visibility
2919   Var *visibility = (Var*) LangElement::find( "visibility" );
2920   if ( !visibility )
2921   {
2922      visibility = new Var();
2923      visibility->setType( "float" );
2924      visibility->setName( "visibility" );
2925      visibility->uniform = true;
2926      visibility->constSortPos = cspPotentialPrimitive;  
2927   }      
2928
2929   MultiLine *meta = new MultiLine;
2930
2931   // Multiply foliageFade into visibility.
2932   meta->addStatement( new GenOp( "   @ *= @;\r\n", visibility, fade ) );
2933
2934   output = meta;
2935}
2936
2937void ImposterVertFeatureHLSL::determineFeature( Material *material, 
2938                                                const GFXVertexFormat *vertexFormat, 
2939                                                U32 stageNum, 
2940                                                const FeatureType &type, 
2941                                                const FeatureSet &features, 
2942                                                MaterialFeatureData *outFeatureData )
2943{      
2944   if ( features.hasFeature( MFT_ImposterVert ) )
2945      outFeatureData->features.addFeature( MFT_ImposterVert );
2946}
2947
2948//****************************************************************************
2949// HardwareSkinningFeatureHLSL
2950//****************************************************************************
2951
2952void HardwareSkinningFeatureHLSL::processVert(   Vector<ShaderComponent*> &componentList, 
2953                                             const MaterialFeatureData &fd )
2954{      
2955   MultiLine *meta = new MultiLine;
2956
2957   Var *inPosition = (Var*)LangElement::find( "inPosition" );
2958   Var *inNormal = (Var*)LangElement::find( "inNormal" );
2959
2960   if ( !inPosition )
2961      inPosition = (Var*)LangElement::find( "position" );
2962
2963   if ( !inNormal )
2964      inNormal = (Var*)LangElement::find( "normal" );
2965
2966   Var* posePos = new Var("posePos", "float3");
2967   Var* poseNormal = new Var("poseNormal", "float3");
2968   Var* poseMat = new Var("poseMat", "float4x3");
2969   Var* poseRotMat = new Var("poseRotMat", "float3x3");
2970   Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms");
2971
2972   if (!nodeTransforms)
2973   {
2974      nodeTransforms = new Var("nodeTransforms", "float4x3");
2975      nodeTransforms->uniform = true;
2976      nodeTransforms->arraySize = TSShape::smMaxSkinBones;
2977      nodeTransforms->constSortPos = cspPotentialPrimitive;
2978   }
2979   
2980   U32 numIndices = mVertexFormat->getNumBlendIndices();
2981   meta->addStatement( new GenOp( "   @ = 0.0;\r\n", new DecOp( posePos ) ) );  
2982   meta->addStatement( new GenOp( "   @ = 0.0;\r\n", new DecOp( poseNormal ) ) );
2983   meta->addStatement( new GenOp( "   @;\r\n", new DecOp( poseMat ) ) );
2984   meta->addStatement(new GenOp("   @;\r\n   int i;\r\n", new DecOp(poseRotMat)));
2985
2986   for (U32 i=0; i<numIndices; i++)
2987   {
2988      // NOTE: To keep things simple, we assume all 4 bone indices are used in each element chunk.
2989      LangElement* inIndices = (Var*)LangElement::find(String::ToString( "blendIndices%d", i ));
2990      LangElement* inWeights = (Var*)LangElement::find(String::ToString( "blendWeight%d", i ));
2991       
2992      AssertFatal(inIndices && inWeights, "Something went wrong here");
2993      AssertFatal(poseMat && nodeTransforms && posePos && inPosition && inWeights && poseNormal && inNormal && poseRotMat, "Something went REALLY wrong here");
2994      
2995      meta->addStatement( new GenOp( "   for (i=0; i<4; i++) {\r\n" ) );
2996         meta->addStatement( new GenOp( "      int poseIdx = int(@[i]);\r\n", inIndices ) );
2997         meta->addStatement( new GenOp( "      float poseWeight = @[i];\r\n", inWeights) );
2998         meta->addStatement( new GenOp( "      @ = @[poseIdx];\r\n", poseMat, nodeTransforms) );
2999         meta->addStatement( new GenOp( "      @ = (float3x3)@;\r\n", poseRotMat, poseMat) );
3000         meta->addStatement( new GenOp( "      @ += (mul(float4(@, 1), @)).xyz * poseWeight;\r\n", posePos, inPosition, poseMat) );
3001         meta->addStatement( new GenOp( "      @ += (mul(@,@) * poseWeight);\r\n", poseNormal, inNormal, poseRotMat) );
3002      meta->addStatement( new GenOp( "   }\r\n" ) );
3003   }
3004   
3005   // Assign new position and normal
3006   meta->addStatement( new GenOp( "   @ = @;\r\n", inPosition, posePos ) );
3007   meta->addStatement( new GenOp( "   @ = normalize(@);\r\n", inNormal, poseNormal ) );
3008
3009   output = meta;
3010}
3011
3012//****************************************************************************
3013// ReflectionProbeFeatHLSL
3014//****************************************************************************
3015
3016ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL()
3017   : mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl"))
3018{
3019   addDependency(&mDep);
3020}
3021
3022void ReflectionProbeFeatHLSL::processVert(Vector<ShaderComponent*>& componentList,
3023   const MaterialFeatureData& fd)
3024{
3025   MultiLine* meta = new MultiLine;
3026   output = meta;
3027   // Also output the worldToTanget transform which
3028   // we use to create the world space normal.
3029   getOutWorldToTangent(componentList, meta, fd);
3030}
3031
3032void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
3033   const MaterialFeatureData &fd)
3034{
3035   // Skip out on realtime lighting if we don't have a normal
3036   // or we're doing some sort of baked lighting.
3037   //
3038   // TODO: We can totally detect for this in the material
3039   // feature setup... we should move it out of here!
3040   //
3041   if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit])
3042      return;
3043
3044   ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
3045
3046   MultiLine *meta = new MultiLine;
3047   
3048   // Now the wsPosition and wsView.
3049   Var* worldToTangent = getInWorldToTangent(componentList);
3050   Var *wsNormal = getInWorldNormal(componentList);
3051   Var* wsPosition = getInWsPosition(componentList);
3052   Var *wsView = getWsView(wsPosition, meta);
3053   
3054   //Reflection Probe WIP
3055   U32 MAX_FORWARD_PROBES = 4;
3056
3057   Var *numProbes = new Var("numProbes", "int");
3058   numProbes->uniform = true;
3059   numProbes->constSortPos = cspPotentialPrimitive;
3060
3061   Var *cubeMips = new Var("cubeMips", "float");
3062   cubeMips->uniform = true;
3063   cubeMips->constSortPos = cspPotentialPrimitive;
3064
3065   Var * skylightCubemapIdx = new Var("skylightCubemapIdx", "float");
3066   skylightCubemapIdx->uniform = true;
3067   skylightCubemapIdx->constSortPos = cspPotentialPrimitive;
3068
3069   Var *inProbePosArray = new Var("inProbePosArray", "float4");
3070   inProbePosArray->arraySize = MAX_FORWARD_PROBES;
3071   inProbePosArray->uniform = true;
3072   inProbePosArray->constSortPos = cspPotentialPrimitive;
3073
3074   Var *inRefPosArray = new Var("inRefPosArray", "float4");
3075   inRefPosArray->arraySize = MAX_FORWARD_PROBES;
3076   inRefPosArray->uniform = true;
3077   inRefPosArray->constSortPos = cspPotentialPrimitive;
3078
3079   Var * refScaleArray = new Var("inRefScale", "float4");
3080   refScaleArray->arraySize = MAX_FORWARD_PROBES;
3081   refScaleArray->uniform = true;
3082   refScaleArray->constSortPos = cspPotentialPrimitive;
3083
3084   Var *probeConfigData = new Var("probeConfigData", "float4");
3085   probeConfigData->arraySize = MAX_FORWARD_PROBES;
3086   probeConfigData->uniform = true;
3087   probeConfigData->constSortPos = cspPotentialPrimitive;
3088
3089   Var *worldToObjArray = new Var("worldToObjArray", "float4x4");
3090   worldToObjArray->arraySize = MAX_FORWARD_PROBES;
3091   worldToObjArray->uniform = true;
3092   worldToObjArray->constSortPos = cspPotentialPrimitive;
3093
3094   Var *BRDFTexture = new Var("BRDFTexture", "SamplerState");
3095   BRDFTexture->uniform = true;
3096   BRDFTexture->sampler = true;
3097   BRDFTexture->constNum = Var::getTexUnitNum();     // used as texture unit num here
3098
3099   Var *BRDFTextureTex = new Var("texture_BRDFTexture", "Texture2D");
3100   BRDFTextureTex->uniform = true;
3101   BRDFTextureTex->texture = true;
3102   BRDFTextureTex->constNum = BRDFTexture->constNum;
3103
3104   Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState");
3105   specularCubemapAR->uniform = true;
3106   specularCubemapAR->sampler = true;
3107   specularCubemapAR->constNum = Var::getTexUnitNum();     // used as texture unit num here
3108
3109   Var *specularCubemapARTex = new Var("texture_specularCubemapAR", "TextureCubeArray");
3110   specularCubemapARTex->uniform = true;
3111   specularCubemapARTex->texture = true;
3112   specularCubemapARTex->constNum = specularCubemapAR->constNum;
3113
3114   Var *irradianceCubemapAR = new Var("irradianceCubemapAR", "SamplerState");
3115   irradianceCubemapAR->uniform = true;
3116   irradianceCubemapAR->sampler = true;
3117   irradianceCubemapAR->constNum = Var::getTexUnitNum();     // used as texture unit num here
3118
3119   Var *irradianceCubemapARTex = new Var("texture_irradianceCubemapAR", "TextureCubeArray");
3120   irradianceCubemapARTex->uniform = true;
3121   irradianceCubemapARTex->texture = true;
3122   irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum;
3123
3124   Var* surface = getSurface(componentList, meta, fd);
3125
3126   if (!surface)
3127   {
3128      Con::errorf("ShaderGen::ReflectionProbeFeatHLSL()  - failed to generate surface!");
3129      return;
3130   }
3131
3132   Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
3133
3134   //Reflection vec
3135   Var* ibl = (Var*)LangElement::find("ibl");
3136   if (!ibl)
3137   {
3138      ibl = new Var("ibl", "float3");
3139   }
3140
3141   String computeForwardProbes = String::String("   @ = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t");
3142   computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); 
3143   computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
3144      
3145   meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray,
3146      skylightCubemapIdx, BRDFTexture,
3147      irradianceCubemapAR, specularCubemapAR));
3148
3149   meta->addStatement(new GenOp("   @.rgb = @.rgb;\r\n", curColor, ibl));
3150
3151   output = meta;
3152}
3153
3154ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFeatureData &fd)
3155{
3156   Resources res;
3157
3158   res.numTex = 3;
3159   res.numTexReg = 3;
3160
3161   return res;
3162}
3163
3164void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
3165   const MaterialFeatureData &stageFeatures,
3166   RenderPassData &passData,
3167   U32 &texIndex)
3168{
3169   if (stageFeatures.features[MFT_ReflectionProbes])
3170   {
3171      passData.mSamplerNames[texIndex] = "BRDFTexture";
3172      passData.mTexType[texIndex++] = Material::Standard;
3173      // assuming here that it is a scenegraph cubemap
3174      passData.mSamplerNames[texIndex] = "specularCubemapAR";
3175      passData.mTexType[texIndex++] = Material::SGCube;
3176      passData.mSamplerNames[texIndex] = "irradianceCubemapAR";
3177      passData.mTexType[texIndex++] = Material::SGCube;
3178   }
3179}
3180