renderDeferredMgr.cpp
Engine/source/renderInstance/renderDeferredMgr.cpp
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