Torque3D Documentation / _generateds / shaderFeatureGLSL.cpp

shaderFeatureGLSL.cpp

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