Torque3D Documentation / _generateds / renderDeferredMgr.cpp

renderDeferredMgr.cpp

Engine/source/renderInstance/renderDeferredMgr.cpp

More...

Public Functions

ConsoleDocClass(RenderDeferredMgr , "@brief The <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin which performs <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> z+normals deferred used in Advanced <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting.\n\n</a>" "This <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin is used in Advanced Lighting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> gather all opaque mesh <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> instances " "and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the g-buffer <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> use in lighting the scene and doing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n\n</a>" "<a href="/coding/class/classposteffect/">PostEffect</a> and other shaders can access the output of this bin by using the #deferred " "texture target name. See the edge anti-aliasing post effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n\n</a>" "@see game/core/scripts/client/postFx/edgeAA." TORQUE_SCRIPT_EXTENSION "\n" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )

Detailed Description

Public Functions

ConsoleDocClass(RenderDeferredMgr , "@brief The <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin which performs <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> z+normals deferred used in Advanced <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting.\n\n</a>" "This <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin is used in Advanced Lighting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> gather all opaque mesh <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> instances " "and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the g-buffer <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> use in lighting the scene and doing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n\n</a>" "<a href="/coding/class/classposteffect/">PostEffect</a> and other shaders can access the output of this bin by using the #deferred " "texture target name. See the edge anti-aliasing post effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n\n</a>" "@see game/core/scripts/client/postFx/edgeAA." TORQUE_SCRIPT_EXTENSION "\n" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )

IMPLEMENT_CONOBJECT(RenderDeferredMgr )

   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 "renderInstance/renderDeferredMgr.h"
  26
  27#include "gfx/gfxTransformSaver.h"
  28#include "materials/sceneData.h"
  29#include "materials/materialManager.h"
  30#include "materials/materialFeatureTypes.h"
  31#include "core/util/safeDelete.h"
  32#include "shaderGen/featureMgr.h"
  33#include "shaderGen/HLSL/depthHLSL.h"
  34#include "shaderGen/GLSL/depthGLSL.h"
  35#include "shaderGen/conditionerFeature.h"
  36#include "shaderGen/shaderGenVars.h"
  37#include "scene/sceneRenderState.h"
  38#include "gfx/gfxStringEnumTranslate.h"
  39#include "gfx/gfxDebugEvent.h"
  40#include "gfx/gfxCardProfile.h"
  41#include "materials/customMaterialDefinition.h"
  42#include "lighting/advanced/advancedLightManager.h"
  43#include "lighting/advanced/advancedLightBinManager.h"
  44#include "terrain/terrCell.h"
  45#include "renderInstance/renderTerrainMgr.h"
  46#include "terrain/terrCellMaterial.h"
  47#include "math/mathUtils.h"
  48#include "math/util/matrixSet.h"
  49#include "gfx/gfxTextureManager.h"
  50#include "gfx/primBuilder.h"
  51#include "gfx/gfxDrawUtil.h"
  52#include "materials/shaderData.h"
  53#include "gfx/sim/cubemapData.h"
  54
  55#include "materials/customShaderBindingData.h"
  56
  57const MatInstanceHookType DeferredMatInstanceHook::Type( "Deferred" );
  58const String RenderDeferredMgr::BufferName("deferred");
  59const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred");
  60const String RenderDeferredMgr::ColorBufferName("color");
  61const String RenderDeferredMgr::MatInfoBufferName("matinfo");
  62
  63IMPLEMENT_CONOBJECT(RenderDeferredMgr);
  64
  65ConsoleDocClass( RenderDeferredMgr, 
  66   "@brief The render bin which performs a z+normals deferred used in Advanced Lighting.\n\n"
  67   "This render bin is used in Advanced Lighting to gather all opaque mesh render instances "
  68   "and render them to the g-buffer for use in lighting the scene and doing effects.\n\n"
  69   "PostEffect and other shaders can access the output of this bin by using the #deferred "
  70   "texture target name.  See the edge anti-aliasing post effect for an example.\n\n"
  71   "@see game/core/scripts/client/postFx/edgeAA." TORQUE_SCRIPT_EXTENSION "\n"
  72   "@ingroup RenderBin\n" );
  73
  74
  75RenderDeferredMgr::RenderSignal& RenderDeferredMgr::getRenderSignal()
  76{
  77   static RenderSignal theSignal;
  78   return theSignal;
  79}
  80
  81
  82RenderDeferredMgr::RenderDeferredMgr( bool gatherDepth,
  83                                    GFXFormat format )
  84   :  Parent(  RIT_Deferred,
  85               0.01f,
  86               0.01f,
  87               format,
  88               Point2I( Parent::DefaultTargetSize, Parent::DefaultTargetSize),
  89               gatherDepth ? Parent::DefaultTargetChainLength : 0 ),
  90      mDeferredMatInstance( NULL )
  91{
  92   notifyType( RenderPassManager::RIT_Decal );
  93   notifyType( RenderPassManager::RIT_DecalRoad );
  94   notifyType( RenderPassManager::RIT_Mesh );
  95   notifyType( RenderPassManager::RIT_Terrain );
  96   notifyType( RenderPassManager::RIT_Object );
  97   notifyType( RenderPassManager::RIT_Probes );
  98
  99   // We want a full-resolution buffer
 100   mTargetSizeType = RenderTexTargetBinManager::WindowSize;
 101
 102   if(getTargetChainLength() > 0)
 103      GFXShader::addGlobalMacro( "TORQUE_LINEAR_DEPTH" );
 104
 105   mNamedTarget.registerWithName( BufferName );
 106   mColorTarget.registerWithName( ColorBufferName );
 107   mMatInfoTarget.registerWithName( MatInfoBufferName );
 108
 109   _registerFeatures();
 110}
 111
 112RenderDeferredMgr::~RenderDeferredMgr()
 113{
 114   GFXShader::removeGlobalMacro( "TORQUE_LINEAR_DEPTH" );
 115
 116   mColorTarget.release();
 117   mMatInfoTarget.release();
 118   _unregisterFeatures();
 119   SAFE_DELETE( mDeferredMatInstance );
 120}
 121
 122void RenderDeferredMgr::_registerFeatures()
 123{
 124   ConditionerFeature *cond = new LinearEyeDepthConditioner( getTargetFormat() );
 125   FEATUREMGR->registerFeature( MFT_DeferredConditioner, cond );
 126   mNamedTarget.setConditioner( cond );
 127}
 128
 129void RenderDeferredMgr::_unregisterFeatures()
 130{
 131   mNamedTarget.setConditioner( NULL );
 132   FEATUREMGR->unregisterFeature(MFT_DeferredConditioner);
 133}
 134
 135bool RenderDeferredMgr::setTargetSize(const Point2I &newTargetSize)
 136{
 137   bool ret = Parent::setTargetSize( newTargetSize );
 138   mNamedTarget.setViewport( GFX->getViewport() );
 139   mColorTarget.setViewport( GFX->getViewport() );
 140   mMatInfoTarget.setViewport( GFX->getViewport() );
 141   return ret;
 142}
 143
 144bool RenderDeferredMgr::_updateTargets()
 145{
 146   PROFILE_SCOPE(RenderDeferredMgr_updateTargets);
 147
 148   bool ret = Parent::_updateTargets();
 149
 150   // check for an output conditioner, and update it's format
 151   ConditionerFeature *outputConditioner = dynamic_cast<ConditionerFeature *>(FEATUREMGR->getByType(MFT_DeferredConditioner));
 152   if( outputConditioner && outputConditioner->setBufferFormat(mTargetFormat) )
 153   {
 154      // reload materials, the conditioner needs to alter the generated shaders
 155   }
 156
 157   // TODO: these formats should be passed in and not hard-coded
 158   const GFXFormat colorFormat = GFXFormatR8G8B8A8_SRGB;
 159   const GFXFormat matInfoFormat = GFXFormatR8G8B8A8;
 160
 161   // andrewmac: Deferred Shading Color Buffer
 162   if (mColorTex.getFormat() != colorFormat || mColorTex.getWidthHeight() != mTargetSize || GFX->recentlyReset())
 163   {
 164      mColorTarget.release();
 165      mColorTex.set(mTargetSize.x, mTargetSize.y, colorFormat,
 166         &GFXRenderTargetSRGBProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
 167         1, GFXTextureManager::AA_MATCH_BACKBUFFER);
 168      mColorTarget.setTexture(mColorTex);
 169 
 170      for (U32 i = 0; i < mTargetChainLength; i++)
 171         mTargetChain[i]->attachTexture(GFXTextureTarget::Color1, mColorTarget.getTexture());
 172   }
 173 
 174   // andrewmac: Deferred Shading Material Info Buffer
 175   if (mMatInfoTex.getFormat() != matInfoFormat || mMatInfoTex.getWidthHeight() != mTargetSize || GFX->recentlyReset())
 176   {
 177      mMatInfoTarget.release();
 178      mMatInfoTex.set(mTargetSize.x, mTargetSize.y, matInfoFormat,
 179         &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
 180         1, GFXTextureManager::AA_MATCH_BACKBUFFER);
 181      mMatInfoTarget.setTexture(mMatInfoTex);
 182 
 183      for (U32 i = 0; i < mTargetChainLength; i++)
 184         mTargetChain[i]->attachTexture(GFXTextureTarget::Color2, mMatInfoTarget.getTexture());
 185   }
 186
 187   //scene color target
 188   NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken");
 189   if (sceneColorTargetRef.isValid())
 190   {
 191      for (U32 i = 0; i < mTargetChainLength; i++)
 192         mTargetChain[i]->attachTexture(GFXTextureTarget::Color3, sceneColorTargetRef->getTexture(0));
 193   }
 194   else
 195   {
 196      Con::errorf("RenderDeferredMgr: Could not find AL_FormatToken");
 197      return false;
 198   }
 199
 200   GFX->finalizeReset();
 201
 202   return ret;
 203}
 204
 205void RenderDeferredMgr::_createDeferredMaterial()
 206{
 207   SAFE_DELETE(mDeferredMatInstance);
 208
 209   const GFXVertexFormat *vertexFormat = getGFXVertexFormat<GFXVertexPNTTB>();
 210
 211   MatInstance* deferredMat = static_cast<MatInstance*>(MATMGR->createMatInstance("AL_DefaultDeferredMaterial", vertexFormat));
 212   AssertFatal( deferredMat, "TODO: Handle this better." );
 213   mDeferredMatInstance = new DeferredMatInstance(deferredMat, this);
 214   mDeferredMatInstance->init( MATMGR->getDefaultFeatures(), vertexFormat);
 215   delete deferredMat;
 216}
 217
 218void RenderDeferredMgr::setDeferredMaterial( DeferredMatInstance *mat )
 219{
 220   SAFE_DELETE(mDeferredMatInstance);
 221   mDeferredMatInstance = mat;
 222}
 223
 224void RenderDeferredMgr::addElement( RenderInst *inst )
 225{
 226   PROFILE_SCOPE( RenderDeferredMgr_addElement )
 227
 228   // Skip out if this bin is disabled.
 229   if (  gClientSceneGraph->getCurrentRenderState() &&
 230         gClientSceneGraph->getCurrentRenderState()->disableAdvancedLightingBins() )
 231      return;
 232
 233   // First what type of render instance is it?
 234   const bool isDecalMeshInst = ((inst->type == RenderPassManager::RIT_Decal)||(inst->type == RenderPassManager::RIT_DecalRoad));
 235
 236   const bool isMeshInst = inst->type == RenderPassManager::RIT_Mesh;
 237
 238   const bool isTerrainInst = inst->type == RenderPassManager::RIT_Terrain;
 239
 240   const bool isProbeInst = inst->type == RenderPassManager::RIT_Probes;
 241
 242   // Get the material if its a mesh.
 243   BaseMatInstance* matInst = NULL;
 244   if ( isMeshInst || isDecalMeshInst )
 245      matInst = static_cast<MeshRenderInst*>(inst)->matInst;
 246
 247   if (matInst)
 248   {
 249      // If its a custom material and it refracts... skip it.
 250      if (matInst->isCustomMaterial() &&
 251         static_cast<CustomMaterial*>(matInst->getMaterial())->mRefract)
 252         return;
 253
 254      // Make sure we got a deferred material.
 255      matInst = getDeferredMaterial(matInst);
 256      if (!matInst || !matInst->isValid())
 257         return;
 258   }
 259
 260   // We're gonna add it to the bin... get the right element list.
 261   Vector< MainSortElem> *elementList;
 262   if ( isMeshInst || isDecalMeshInst )
 263      elementList = &mElementList;
 264   else if ( isTerrainInst )
 265      elementList = &mTerrainElementList;
 266   else if (isProbeInst)
 267      elementList = &mProbeElementList;
 268   else
 269      elementList = &mObjectElementList;
 270
 271   elementList->increment();
 272   MainSortElem &elem = elementList->last();
 273   elem.inst = inst;
 274
 275   // Store the original key... we might need it.
 276   U32 originalKey = elem.key;
 277
 278   // Sort front-to-back first to get the most fillrate savings.
 279   const F32 invSortDistSq = F32_MAX - inst->sortDistSq;
 280   elem.key = *((U32*)&invSortDistSq);
 281
 282   // Next sort by pre-pass material if its a mesh... use the original sort key.
 283   if (isMeshInst && matInst)
 284      elem.key2 = matInst->getStateHint();
 285   else
 286      elem.key2 = originalKey;
 287}
 288
 289void RenderDeferredMgr::sort()
 290{
 291   PROFILE_SCOPE( RenderDeferredMgr_sort );
 292   Parent::sort();
 293   dQsort( mTerrainElementList.address(), mTerrainElementList.size(), sizeof(MainSortElem), cmpKeyFunc);
 294   dQsort( mObjectElementList.address(), mObjectElementList.size(), sizeof(MainSortElem), cmpKeyFunc);
 295}
 296
 297void RenderDeferredMgr::clear()
 298{
 299   Parent::clear();
 300   mProbeElementList.clear();
 301   mTerrainElementList.clear();
 302   mObjectElementList.clear();
 303}
 304
 305void RenderDeferredMgr::render( SceneRenderState *state )
 306{
 307   PROFILE_SCOPE(RenderDeferredMgr_render);
 308
 309   // Take a look at the SceneRenderState and see if we should skip drawing the pre-pass
 310   if ( state->disableAdvancedLightingBins() )
 311      return;
 312
 313   // NOTE: We don't early out here when the element list is
 314   // zero because we need the deferred to be cleared.
 315
 316   // Automagically save & restore our viewport and transforms.
 317   GFXTransformSaver saver;
 318
 319   GFXDEBUGEVENT_SCOPE( RenderDeferredMgr_Render, ColorI::RED );
 320
 321   // Tell the superclass we're about to render
 322   const bool isRenderingToTarget = _onPreRender(state);
 323
 324   // Clear z-buffer and g-buffer.
 325   GFX->clear(GFXClearZBuffer | GFXClearStencil, LinearColorF::ZERO, 1.0f, 0);
 326   GFX->clearColorAttachment(0, LinearColorF::ONE);//normdepth
 327   GFX->clearColorAttachment(1, LinearColorF::ZERO);//albedo
 328   GFX->clearColorAttachment(2, LinearColorF::ZERO);//matinfo
 329   //AL_FormatToken is cleared by it's own class
 330
 331   // Restore transforms
 332   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
 333   matrixSet.restoreSceneViewProjection();
 334   const MatrixF worldViewXfm = GFX->getWorldMatrix();
 335
 336   // Setup the default deferred material for object instances.
 337   if ( !mDeferredMatInstance )
 338      _createDeferredMaterial();
 339   if ( mDeferredMatInstance )
 340   {
 341      matrixSet.setWorld(MatrixF::Identity);
 342      mDeferredMatInstance->setTransforms(matrixSet, state);
 343   }
 344
 345   // Signal start of deferred
 346   getRenderSignal().trigger( state, this, true );
 347   
 348   // First do a loop and render all the terrain... these are 
 349   // usually the big blockers in a scene and will save us fillrate
 350   // on the smaller meshes and objects.
 351
 352   // The terrain doesn't need any scene graph data
 353   // in the the deferred... so just clear it.
 354   SceneData sgData;
 355   sgData.init( state, SceneData::DeferredBin );
 356
 357   Vector< MainSortElem >::const_iterator itr = mTerrainElementList.begin();
 358   for ( ; itr != mTerrainElementList.end(); itr++ )
 359   {
 360      TerrainRenderInst *ri = static_cast<TerrainRenderInst*>( itr->inst );
 361
 362      TerrainCellMaterial *mat = ri->cellMat->getDeferredMat();
 363
 364      GFX->setPrimitiveBuffer( ri->primBuff );
 365      GFX->setVertexBuffer( ri->vertBuff );
 366
 367      mat->setTransformAndEye(   *ri->objectToWorldXfm,
 368                                 worldViewXfm,
 369                                 GFX->getProjectionMatrix(),
 370                                 state->getFarPlane() );
 371
 372      while ( mat->setupPass( state, sgData ) )
 373         GFX->drawPrimitive( ri->prim );
 374   }
 375
 376   // init loop data
 377   GFXTextureObject *lastLM = NULL;
 378   GFXCubemap *lastCubemap = NULL;
 379   GFXTextureObject *lastReflectTex = NULL;
 380   GFXTextureObject *lastAccuTex = NULL;
 381   
 382   // Next render all the meshes.
 383   itr = mElementList.begin();
 384   for ( ; itr != mElementList.end(); )
 385   {
 386      MeshRenderInst *ri = static_cast<MeshRenderInst*>( itr->inst );
 387
 388      // Get the deferred material.
 389      BaseMatInstance *mat = getDeferredMaterial( ri->matInst );
 390
 391      // Set up SG data proper like and flag it 
 392      // as a pre-pass render
 393      setupSGData( ri, sgData );
 394
 395      Vector< MainSortElem >::const_iterator meshItr, endOfBatchItr = itr;
 396
 397      while ( mat->setupPass( state, sgData ) )
 398      {
 399         meshItr = itr;
 400         for ( ; meshItr != mElementList.end(); meshItr++ )
 401         {
 402            MeshRenderInst *passRI = static_cast<MeshRenderInst*>( meshItr->inst );
 403
 404            // Check to see if we need to break this batch.
 405            //
 406            // NOTE: We're comparing the non-deferred materials 
 407            // here so we don't incur the cost of looking up the 
 408            // deferred hook on each inst.
 409            //
 410            if ( newPassNeeded( ri, passRI ) )
 411               break;
 412
 413            // Set up SG data for this instance.
 414            setupSGData( passRI, sgData );
 415            mat->setSceneInfo(state, sgData);
 416
 417            matrixSet.setWorld(*passRI->objectToWorld);
 418            matrixSet.setView(*passRI->worldToCamera);
 419            matrixSet.setProjection(*passRI->projection);
 420            mat->setTransforms(matrixSet, state);
 421
 422            // Setup HW skinning transforms if applicable
 423            if (mat->usesHardwareSkinning())
 424            {
 425               mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
 426            }
 427
 428            //push along any overriden fields that are instance-specific as well
 429            if (passRI->mCustomShaderData.size() > 0)
 430            {
 431               mat->setCustomShaderData(passRI->mCustomShaderData);
 432            }
 433
 434            // If we're instanced then don't render yet.
 435            if ( mat->isInstanced() )
 436            {
 437               // Let the material increment the instance buffer, but
 438               // break the batch if it runs out of room for more.
 439               if ( !mat->stepInstance() )
 440               {
 441                  meshItr++;
 442                  break;
 443               }
 444
 445               continue;
 446            }
 447
 448            bool dirty = false;
 449
 450            // set the lightmaps if different
 451            if( passRI->lightmap && passRI->lightmap != lastLM )
 452            {
 453               sgData.lightmap = passRI->lightmap;
 454               lastLM = passRI->lightmap;
 455               dirty = true;
 456            }
 457
 458            // set the cubemap if different.
 459            if ( passRI->cubemap != lastCubemap )
 460            {
 461               sgData.cubemap = passRI->cubemap;
 462               lastCubemap = passRI->cubemap;
 463               dirty = true;
 464            }
 465
 466            if ( passRI->reflectTex != lastReflectTex )
 467            {
 468               sgData.reflectTex = passRI->reflectTex;
 469               lastReflectTex = passRI->reflectTex;
 470               dirty = true;
 471            }
 472            
 473            // Update accumulation texture if it changed.
 474            // Note: accumulation texture can be NULL, and must be updated.
 475            if (passRI->accuTex != lastAccuTex)
 476            {
 477               sgData.accuTex = passRI->accuTex;
 478               lastAccuTex = passRI->accuTex;
 479               dirty = true;
 480            }
 481
 482            if ( dirty )
 483               mat->setTextureStages( state, sgData );
 484
 485            // Setup the vertex and index buffers.
 486            mat->setBuffers( passRI->vertBuff, passRI->primBuff );
 487
 488            // Render this sucker.
 489            if ( passRI->prim )
 490               GFX->drawPrimitive( *passRI->prim );
 491            else
 492               GFX->drawPrimitive( passRI->primBuffIndex );
 493         }
 494
 495         // Draw the instanced batch.
 496         if ( mat->isInstanced() )
 497         {
 498            // Sets the buffers including the instancing stream.
 499            mat->setBuffers( ri->vertBuff, ri->primBuff );
 500
 501            if ( ri->prim )
 502               GFX->drawPrimitive( *ri->prim );
 503            else
 504               GFX->drawPrimitive( ri->primBuffIndex );
 505         }
 506
 507         endOfBatchItr = meshItr;
 508
 509      } // while( mat->setupPass(state, sgData) )
 510
 511      // Force the increment if none happened, otherwise go to end of batch.
 512      itr = ( itr == endOfBatchItr ) ? itr + 1 : endOfBatchItr;
 513   }
 514
 515   // The final loop is for object render instances.
 516   itr = mObjectElementList.begin();
 517   for ( ; itr != mObjectElementList.end(); itr++ )
 518   {
 519      ObjectRenderInst *ri = static_cast<ObjectRenderInst*>( itr->inst );
 520      if ( ri->renderDelegate )
 521         ri->renderDelegate( ri, state, mDeferredMatInstance );
 522   }
 523
 524   // Signal end of pre-pass
 525   getRenderSignal().trigger( state, this, false );
 526
 527   if(isRenderingToTarget)
 528      _onPostRender();
 529}
 530
 531const GFXStateBlockDesc & RenderDeferredMgr::getOpaqueStenciWriteDesc( bool lightmappedGeometry /*= true*/ )
 532{
 533   static bool sbInit = false;
 534   static GFXStateBlockDesc sOpaqueStaticLitStencilWriteDesc;
 535   static GFXStateBlockDesc sOpaqueDynamicLitStencilWriteDesc;
 536
 537   if(!sbInit)
 538   {
 539      sbInit = true;
 540
 541      // Build the static opaque stencil write/test state block descriptions
 542      sOpaqueStaticLitStencilWriteDesc.stencilDefined = true;
 543      sOpaqueStaticLitStencilWriteDesc.stencilEnable = true;
 544      sOpaqueStaticLitStencilWriteDesc.stencilWriteMask = 0x03;
 545      sOpaqueStaticLitStencilWriteDesc.stencilMask = 0x03;
 546      sOpaqueStaticLitStencilWriteDesc.stencilRef = RenderDeferredMgr::OpaqueStaticLitMask;
 547      sOpaqueStaticLitStencilWriteDesc.stencilPassOp = GFXStencilOpReplace;
 548      sOpaqueStaticLitStencilWriteDesc.stencilFailOp = GFXStencilOpKeep;
 549      sOpaqueStaticLitStencilWriteDesc.stencilZFailOp = GFXStencilOpKeep;
 550      sOpaqueStaticLitStencilWriteDesc.stencilFunc = GFXCmpAlways;
 551
 552      // Same only dynamic
 553      sOpaqueDynamicLitStencilWriteDesc = sOpaqueStaticLitStencilWriteDesc;
 554      sOpaqueDynamicLitStencilWriteDesc.stencilRef = RenderDeferredMgr::OpaqueDynamicLitMask;
 555   }
 556
 557   return (lightmappedGeometry ? sOpaqueStaticLitStencilWriteDesc : sOpaqueDynamicLitStencilWriteDesc);
 558}
 559
 560const GFXStateBlockDesc & RenderDeferredMgr::getOpaqueStencilTestDesc()
 561{
 562   static bool sbInit = false;
 563   static GFXStateBlockDesc sOpaqueStencilTestDesc;
 564
 565   if(!sbInit)
 566   {
 567      // Build opaque test
 568      sbInit = true;
 569      sOpaqueStencilTestDesc.stencilDefined = true;
 570      sOpaqueStencilTestDesc.stencilEnable = true;
 571      sOpaqueStencilTestDesc.stencilWriteMask = 0xFE;
 572      sOpaqueStencilTestDesc.stencilMask = 0x03;
 573      sOpaqueStencilTestDesc.stencilRef = 0;
 574      sOpaqueStencilTestDesc.stencilPassOp = GFXStencilOpKeep;
 575      sOpaqueStencilTestDesc.stencilFailOp = GFXStencilOpKeep;
 576      sOpaqueStencilTestDesc.stencilZFailOp = GFXStencilOpKeep;
 577      sOpaqueStencilTestDesc.stencilFunc = GFXCmpLess;
 578   }
 579
 580   return sOpaqueStencilTestDesc;
 581}
 582
 583//------------------------------------------------------------------------------
 584//------------------------------------------------------------------------------
 585
 586
 587ProcessedDeferredMaterial::ProcessedDeferredMaterial( Material& mat, const RenderDeferredMgr *deferredMgr )
 588: Parent(mat), mDeferredMgr(deferredMgr), mIsLightmappedGeometry(false)
 589{
 590
 591}
 592
 593void ProcessedDeferredMaterial::_determineFeatures( U32 stageNum,
 594                                                   MaterialFeatureData &fd,
 595                                                   const FeatureSet &features )
 596{
 597   Parent::_determineFeatures( stageNum, fd, features );
 598   if (fd.features.hasFeature(MFT_ForwardShading))
 599      return;
 600
 601   // Find this for use down below...
 602   bool bEnableMRTLightmap = false;
 603   AdvancedLightBinManager *lightBin;
 604   if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
 605      bEnableMRTLightmap = lightBin->MRTLightmapsDuringDeferred();
 606
 607   // If this material has a lightmap or tonemap (texture or baked vertex color),
 608   // it must be static. Otherwise it is dynamic.
 609   mIsLightmappedGeometry = ( fd.features.hasFeature( MFT_ToneMap ) ||
 610                              fd.features.hasFeature( MFT_LightMap ) ||
 611                              fd.features.hasFeature( MFT_VertLit ) ||
 612                              ( bEnableMRTLightmap && (fd.features.hasFeature( MFT_IsTranslucent ) ||
 613                                                      fd.features.hasFeature( MFT_ForwardShading ) ||
 614                                                      fd.features.hasFeature( MFT_IsTranslucentZWrite) ) ) );
 615
 616   // Integrate proper opaque stencil write state
 617   mUserDefined.addDesc( mDeferredMgr->getOpaqueStenciWriteDesc( mIsLightmappedGeometry ) );
 618
 619   FeatureSet newFeatures;
 620
 621   // These are always on for deferred.
 622   newFeatures.addFeature( MFT_EyeSpaceDepthOut );
 623   newFeatures.addFeature( MFT_DeferredConditioner );
 624
 625#ifndef TORQUE_DEDICATED
 626
 627   //tag all materials running through deferred as deferred
 628   newFeatures.addFeature(MFT_isDeferred);
 629
 630   // Deferred Shading : Diffuse
 631   if (mStages[stageNum].getTex( MFT_DiffuseMap ))
 632   {
 633      newFeatures.addFeature(MFT_DiffuseMap);
 634   }
 635   newFeatures.addFeature( MFT_DiffuseColor );
 636   
 637   if (mMaterial->mInvertRoughness[stageNum])
 638      newFeatures.addFeature(MFT_InvertRoughness);
 639
 640   // Deferred Shading : PBR Config
 641   if( mStages[stageNum].getTex( MFT_OrmMap ) )
 642   {
 643       newFeatures.addFeature( MFT_OrmMap );
 644   }
 645   else
 646       newFeatures.addFeature( MFT_ORMConfigVars );
 647
 648   if (mStages[stageNum].getTex(MFT_GlowMap))
 649   {
 650      newFeatures.addFeature(MFT_GlowMap);
 651   }
 652
 653   // Deferred Shading : Material Info Flags
 654   newFeatures.addFeature( MFT_MatInfoFlags );
 655
 656   for ( U32 i=0; i < fd.features.getCount(); i++ )
 657   {
 658      const FeatureType &type = fd.features.getAt( i );
 659
 660      // Turn on the diffuse texture only if we
 661      // have alpha test.
 662      if ( type == MFT_AlphaTest )
 663      {
 664         newFeatures.addFeature( MFT_AlphaTest );
 665         newFeatures.addFeature( MFT_DiffuseMap );
 666      }
 667
 668      else if ( type == MFT_IsTranslucentZWrite )
 669      {
 670         newFeatures.addFeature( MFT_IsTranslucentZWrite );
 671         newFeatures.addFeature( MFT_DiffuseMap );
 672      }
 673
 674      // Always allow these.
 675      else if (   type == MFT_IsBC3nm ||
 676                  type == MFT_IsBC5nm ||
 677                  type == MFT_TexAnim ||
 678                  type == MFT_NormalMap ||
 679                  type == MFT_DetailNormalMap ||
 680                  type == MFT_AlphaTest ||
 681                  type == MFT_Parallax ||
 682                  type == MFT_Visibility ||
 683                  type == MFT_UseInstancing ||
 684                  type == MFT_DiffuseVertColor ||
 685                  type == MFT_DetailMap ||
 686                  type == MFT_DiffuseMapAtlas)
 687         newFeatures.addFeature( type );
 688
 689      // Add any transform features.
 690      else if (   type.getGroup() == MFG_PreTransform ||
 691                  type.getGroup() == MFG_Transform ||
 692                  type.getGroup() == MFG_PostTransform )
 693         newFeatures.addFeature( type );
 694   }
 695
 696   if (mMaterial->mAccuEnabled[stageNum])
 697   {
 698      newFeatures.addFeature(MFT_AccuMap);
 699      mHasAccumulation = true;
 700   }
 701
 702   // we need both diffuse and normal maps + sm3 to have an accu map
 703   if (newFeatures[MFT_AccuMap] &&
 704      (!newFeatures[MFT_DiffuseMap] ||
 705      !newFeatures[MFT_NormalMap] ||
 706      GFX->getPixelShaderVersion() < 3.0f)) {
 707      AssertWarn(false, "SAHARA: Using an Accu Map requires SM 3.0 and a normal map.");
 708      newFeatures.removeFeature(MFT_AccuMap);
 709      mHasAccumulation = false;
 710   }
 711
 712   // if we still have the AccuMap feature, we add all accu constant features
 713   if (newFeatures[MFT_AccuMap]) {
 714      // add the dependencies of the accu map
 715      newFeatures.addFeature(MFT_AccuScale);
 716      newFeatures.addFeature(MFT_AccuDirection);
 717      newFeatures.addFeature(MFT_AccuStrength);
 718      newFeatures.addFeature(MFT_AccuCoverage);
 719      newFeatures.addFeature(MFT_AccuSpecular);
 720      // now remove some features that are not compatible with this
 721      newFeatures.removeFeature(MFT_UseInstancing);
 722   }
 723
 724   // If there is lightmapped geometry support, add the MRT light buffer features
 725   if(bEnableMRTLightmap)
 726   {
 727      // If this material has a lightmap, pass it through, and flag it to
 728      // send it's output to RenderTarget3
 729      if( fd.features.hasFeature( MFT_ToneMap ) )
 730      {
 731         newFeatures.addFeature( MFT_ToneMap );
 732         newFeatures.addFeature( MFT_LightbufferMRT );
 733      }
 734      else if( fd.features.hasFeature( MFT_LightMap ) )
 735      {
 736         newFeatures.addFeature( MFT_LightMap );
 737         newFeatures.addFeature( MFT_LightbufferMRT );
 738      }
 739      else if( fd.features.hasFeature( MFT_VertLit ) )
 740      {
 741         // Flag un-tone-map if necesasary
 742         if( fd.features.hasFeature( MFT_DiffuseMap ) )
 743            newFeatures.addFeature( MFT_VertLitTone );
 744
 745         newFeatures.addFeature( MFT_VertLit );
 746         newFeatures.addFeature( MFT_LightbufferMRT );
 747      }
 748      else if (!fd.features.hasFeature(MFT_GlowMap))
 749      {
 750            newFeatures.addFeature( MFT_RenderTarget3_Zero );
 751      }
 752   }
 753
 754   // cubemaps only available on stage 0 for now - bramage   
 755   if ( stageNum < 1 && 
 756         (  (  mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) ||
 757               mMaterial->mDynamicCubemap ) )
 758   {
 759      if (!mMaterial->mDynamicCubemap)
 760         fd.features.addFeature(MFT_StaticCubemap);
 761      newFeatures.addFeature( MFT_CubeMap );
 762   }
 763   if (mMaterial->mVertLit[stageNum])
 764      newFeatures.addFeature(MFT_VertLit);
 765
 766   if (mMaterial->mMinnaertConstant[stageNum] > 0.0f)
 767      newFeatures.addFeature(MFT_MinnaertShading);
 768
 769   if (mMaterial->mSubSurface[stageNum])
 770      newFeatures.addFeature(MFT_SubSurface);
 771   
 772#endif
 773
 774   // Set the new features.
 775   fd.features = newFeatures;
 776}
 777
 778U32 ProcessedDeferredMaterial::getNumStages()
 779{
 780   // Loops through all stages to determine how many 
 781   // stages we actually use.  
 782   // 
 783   // The first stage is always active else we shouldn't be
 784   // creating the material to begin with.
 785   U32 numStages = 1;
 786
 787   U32 i;
 788   for( i=1; i<Material::MAX_STAGES; i++ )
 789   {
 790      // Assume stage is inactive
 791      bool stageActive = false;
 792
 793      // Cubemaps only on first stage
 794      if( i == 0 )
 795      {
 796         // If we have a cubemap the stage is active
 797         if( mMaterial->mCubemapData || mMaterial->mDynamicCubemap )
 798         {
 799            numStages++;
 800            continue;
 801         }
 802      }
 803
 804      // If we have a texture for the a feature the 
 805      // stage is active.
 806      if ( mStages[i].hasValidTex() )
 807         stageActive = true;
 808      
 809      // If this stage has diffuse color, it's active
 810      if (  mMaterial->mDiffuse[i].alpha > 0 &&
 811            mMaterial->mDiffuse[i] != LinearColorF::WHITE )
 812         stageActive = true;
 813
 814      // If we have a Material that is vertex lit
 815      // then it may not have a texture
 816      if( mMaterial->mVertLit[i] )
 817         stageActive = true;
 818
 819      // Increment the number of active stages
 820      numStages += stageActive;
 821   }
 822
 823   return numStages;
 824}
 825
 826void ProcessedDeferredMaterial::addStateBlockDesc(const GFXStateBlockDesc& desc)
 827{
 828   GFXStateBlockDesc deferredStateBlock = desc;
 829
 830   // Adjust color writes if this is a pure z-fill pass
 831   const bool pixelOutEnabled = mDeferredMgr->getTargetChainLength() > 0;
 832   if ( !pixelOutEnabled )
 833   {
 834      deferredStateBlock.colorWriteDefined = true;
 835      deferredStateBlock.colorWriteRed = pixelOutEnabled;
 836      deferredStateBlock.colorWriteGreen = pixelOutEnabled;
 837      deferredStateBlock.colorWriteBlue = pixelOutEnabled;
 838      deferredStateBlock.colorWriteAlpha = pixelOutEnabled;
 839   }
 840
 841   // Never allow the alpha test state when rendering
 842   // the deferred as we use the alpha channel for the
 843   // depth information... MFT_AlphaTest will handle it.
 844   deferredStateBlock.alphaDefined = true;
 845   deferredStateBlock.alphaTestEnable = false;
 846
 847   // If we're translucent then we're doing deferred blending
 848   // which never writes to the depth channels.
 849   const bool isTranslucent = getMaterial()->isTranslucent();
 850   if ( isTranslucent )
 851   {
 852      deferredStateBlock.setBlend( true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha );
 853      deferredStateBlock.setColorWrites(false, false, false, true);
 854   }
 855
 856   // Enable z reads, but only enable zwrites if we're not translucent.
 857   deferredStateBlock.setZReadWrite( true, isTranslucent ? false : true );
 858
 859   // Pass to parent
 860   Parent::addStateBlockDesc(deferredStateBlock);
 861}
 862
 863DeferredMatInstance::DeferredMatInstance(MatInstance* root, const RenderDeferredMgr *deferredMgr)
 864: Parent(*root->getMaterial()), mDeferredMgr(deferredMgr)
 865{
 866   mFeatureList = root->getRequestedFeatures();
 867   mVertexFormat = root->getVertexFormat();
 868   mUserObject = root->getUserObject();
 869}
 870
 871DeferredMatInstance::~DeferredMatInstance()
 872{
 873}
 874
 875ProcessedMaterial* DeferredMatInstance::getShaderMaterial()
 876{
 877   return new ProcessedDeferredMaterial(*mMaterial, mDeferredMgr);
 878}
 879
 880bool DeferredMatInstance::init( const FeatureSet &features,
 881                               const GFXVertexFormat *vertexFormat )
 882{
 883   bool vaild = Parent::init(features, vertexFormat);
 884
 885   if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr(0, 1).equal("#"))
 886   {
 887      String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1);
 888      NamedTexTarget *texTarget = NamedTexTarget::find(texTargetBufferName);
 889      RenderPassData* rpd = getPass(0);
 890
 891      if (rpd)
 892      {
 893         rpd->mTexSlot[0].texTarget = texTarget;
 894         rpd->mTexType[0] = Material::TexTarget;
 895         rpd->mSamplerNames[0] = "diffuseMap";
 896      }
 897   }
 898   return vaild;
 899}
 900
 901DeferredMatInstanceHook::DeferredMatInstanceHook( MatInstance *baseMatInst,
 902                                                const RenderDeferredMgr *deferredMgr )
 903   : mHookedDeferredMatInst(NULL), mDeferredManager(deferredMgr)
 904{
 905   // If the material is a custom material then
 906   // hope that using DefaultDeferredMaterial gives
 907   // them a good deferred.
 908   if ( baseMatInst->isCustomMaterial() )
 909   {
 910      MatInstance* dummyInst = static_cast<MatInstance*>( MATMGR->createMatInstance( "AL_DefaultDeferredMaterial", baseMatInst->getVertexFormat() ) );
 911
 912      mHookedDeferredMatInst = new DeferredMatInstance( dummyInst, deferredMgr );
 913      mHookedDeferredMatInst->init( dummyInst->getRequestedFeatures(), baseMatInst->getVertexFormat());
 914
 915      delete dummyInst;
 916      return;
 917   }
 918
 919   // Create the deferred material instance.
 920   mHookedDeferredMatInst = new DeferredMatInstance(baseMatInst, deferredMgr);
 921   mHookedDeferredMatInst->getFeaturesDelegate() = baseMatInst->getFeaturesDelegate();
 922
 923   // Get the features, but remove the instancing feature if the
 924   // original material didn't end up using it.
 925   FeatureSet features = baseMatInst->getRequestedFeatures();
 926   if ( !baseMatInst->isInstanced() )
 927      features.removeFeature( MFT_UseInstancing );
 928
 929   // Initialize the material.
 930   mHookedDeferredMatInst->init(features, baseMatInst->getVertexFormat());
 931}
 932
 933DeferredMatInstanceHook::~DeferredMatInstanceHook()
 934{
 935   SAFE_DELETE(mHookedDeferredMatInst);
 936}
 937
 938//------------------------------------------------------------------------------
 939//------------------------------------------------------------------------------
 940
 941void LinearEyeDepthConditioner::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
 942{
 943   // find depth
 944   ShaderFeature *depthFeat = FEATUREMGR->getByType( MFT_EyeSpaceDepthOut );
 945   AssertFatal( depthFeat != NULL, "No eye space depth feature found!" );
 946
 947   Var *depth = (Var*) LangElement::find(depthFeat->getOutputVarName());
 948   AssertFatal( depth, "Something went bad with ShaderGen. The depth should be already generated by the EyeSpaceDepthOut feature." );
 949
 950   MultiLine *meta = new MultiLine;
 951
 952   meta->addStatement( assignOutput( depth ) );
 953
 954   output = meta;
 955}
 956
 957Var *LinearEyeDepthConditioner::_conditionOutput( Var *unconditionedOutput, MultiLine *meta )
 958{
 959   Var *retVar = NULL;
 960
 961   String fracMethodName = (GFX->getAdapterType() == OpenGL) ? "fract" : "frac";
 962
 963   switch(getBufferFormat())
 964   {
 965   case GFXFormatR8G8B8A8:
 966      retVar = new Var;
 967      retVar->setType("float4");
 968      retVar->setName("_ppDepth");
 969      meta->addStatement( new GenOp( "   // depth conditioner: packing to rgba\r\n" ) );
 970      meta->addStatement( new GenOp(
 971         avar( "   @ = %s(@ * (255.0/256) * float4(1, 255, 255 * 255, 255 * 255 * 255));\r\n", fracMethodName.c_str() ),
 972         new DecOp(retVar), unconditionedOutput ) );
 973      break;
 974   default:
 975      retVar = unconditionedOutput;
 976      meta->addStatement( new GenOp( "   // depth conditioner: no conditioning\r\n" ) );
 977      break;
 978   }
 979
 980   AssertFatal( retVar != NULL, avar( "Cannot condition output to buffer format: %s", GFXStringTextureFormat[getBufferFormat()] ) );
 981   return retVar;
 982}
 983
 984Var *LinearEyeDepthConditioner::_unconditionInput( Var *conditionedInput, MultiLine *meta )
 985{
 986   String float4Typename = (GFX->getAdapterType() == OpenGL) ? "vec4" : "float4";
 987
 988   Var *retVar = conditionedInput;
 989   if(getBufferFormat() != GFXFormat_COUNT)
 990   {
 991      retVar = new Var;
 992      retVar->setType(float4Typename.c_str());
 993      retVar->setName("_ppDepth");
 994      meta->addStatement( new GenOp( avar( "   @ = %s(0, 0, 1, 1);\r\n", float4Typename.c_str() ), new DecOp(retVar) ) );
 995
 996      switch(getBufferFormat())
 997      {
 998      case GFXFormatR32F:
 999      case GFXFormatR16F:
1000         meta->addStatement( new GenOp( "   // depth conditioner: float texture\r\n" ) );
1001         meta->addStatement( new GenOp( "   @.w = @.r;\r\n", retVar, conditionedInput ) );
1002         break;
1003
1004      case GFXFormatR8G8B8A8:
1005         meta->addStatement( new GenOp( "   // depth conditioner: unpacking from rgba\r\n" ) );
1006         meta->addStatement( new GenOp(
1007            avar( "   @.w = dot(@ * (256.0/255), %s(1, 1 / 255, 1 / (255 * 255), 1 / (255 * 255 * 255)));\r\n", float4Typename.c_str() )
1008            , retVar, conditionedInput ) );
1009         break;
1010      default:
1011         AssertFatal(false, "LinearEyeDepthConditioner::_unconditionInput - Unrecognized buffer format");
1012      }
1013   }
1014
1015   return retVar;
1016}
1017
1018Var* LinearEyeDepthConditioner::printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta )
1019{
1020   const bool isCondition = ( methodType == ConditionerFeature::ConditionMethod );
1021
1022   Var *retVal = NULL;
1023
1024   // The uncondition method inputs are changed
1025   if( isCondition )
1026      retVal = Parent::printMethodHeader( methodType, methodName, stream, meta );
1027   else
1028   {
1029      Var *methodVar = new Var;
1030      methodVar->setName(methodName);
1031      if (GFX->getAdapterType() == OpenGL)
1032         methodVar->setType("vec4");
1033      else
1034         methodVar->setType("inline float4");
1035      DecOp *methodDecl = new DecOp(methodVar);
1036
1037      Var *deferredSampler = new Var;
1038      deferredSampler->setName("deferredSamplerVar");
1039      deferredSampler->setType("sampler2D");
1040      DecOp *deferredSamplerDecl = NULL;
1041
1042      Var *deferredTex = NULL;
1043      DecOp *deferredTexDecl = NULL;
1044      if (GFX->getAdapterType() == Direct3D11)
1045      {
1046         deferredSampler->setType("SamplerState");
1047
1048         deferredTex = new Var;
1049         deferredTex->setName("deferredTexVar");
1050         deferredTex->setType("Texture2D");
1051         deferredTexDecl = new DecOp(deferredTex);
1052      }
1053
1054      deferredSamplerDecl = new DecOp(deferredSampler);
1055
1056      Var *screenUV = new Var;
1057      screenUV->setName("screenUVVar");
1058      if (GFX->getAdapterType() == OpenGL)
1059         screenUV->setType("vec2");
1060      else
1061         screenUV->setType("float2");
1062      DecOp *screenUVDecl = new DecOp(screenUV);
1063
1064      Var *bufferSample = new Var;
1065      bufferSample->setName("bufferSample");
1066      if (GFX->getAdapterType() == OpenGL)
1067         bufferSample->setType("vec4");
1068      else
1069         bufferSample->setType("float4");
1070      DecOp *bufferSampleDecl = new DecOp(bufferSample);
1071
1072      if (deferredTex)
1073         meta->addStatement(new GenOp("@(@, @, @)\r\n", methodDecl, deferredSamplerDecl, deferredTexDecl, screenUVDecl));
1074      else
1075         meta->addStatement(new GenOp("@(@, @)\r\n", methodDecl, deferredSamplerDecl, screenUVDecl));
1076
1077      meta->addStatement(new GenOp("{\r\n"));
1078
1079      meta->addStatement(new GenOp("   // Sampler g-buffer\r\n"));
1080
1081      // The linear depth target has no mipmaps, so use tex2dlod when
1082      // possible so that the shader compiler can optimize.
1083      if (GFX->getAdapterType() == OpenGL)
1084         meta->addStatement(new GenOp("@ = texture2DLod(@, @, 0); \r\n", bufferSampleDecl, deferredSampler, screenUV));
1085      else
1086      {
1087         if (deferredTex)
1088            meta->addStatement(new GenOp("@ = @.SampleLevel(@, @, 0);\r\n", bufferSampleDecl, deferredTex, deferredSampler, screenUV));
1089         else
1090            meta->addStatement(new GenOp("@ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, deferredSampler, screenUV));
1091      }
1092
1093      // We don't use this way of passing var's around, so this should cause a crash
1094      // if something uses this improperly
1095      retVal = bufferSample;
1096   }
1097
1098   return retVal;
1099}
1100