renderDeferredMgr.cpp 39 KB

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