projectedShadow.cpp
Engine/source/lighting/common/projectedShadow.cpp
Public Functions
GFX_ImplementTextureProfile(BLProjectedShadowProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(BLProjectedShadowZProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa3a2027753aec009ced4f0818a231296">GFXTextureProfile::ZTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
Detailed Description
Public Functions
GFX_ImplementTextureProfile(BLProjectedShadowProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(BLProjectedShadowZProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa3a2027753aec009ced4f0818a231296">GFXTextureProfile::ZTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
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 "lighting/common/projectedShadow.h" 26 27#include "gfx/primBuilder.h" 28#include "gfx/gfxTextureManager.h" 29#include "gfx/bitmap/gBitmap.h" 30#include "gfx/gfxDebugEvent.h" 31#include "math/mathUtils.h" 32#include "lighting/lightInfo.h" 33#include "lighting/lightingInterfaces.h" 34#include "T3D/shapeBase.h" 35#include "scene/sceneManager.h" 36#include "lighting/lightManager.h" 37#include "ts/tsMesh.h" 38#include "T3D/decal/decalManager.h" 39#include "T3D/decal/decalInstance.h" 40#include "renderInstance/renderPassManager.h" 41#include "renderInstance/renderMeshMgr.h" 42#include "gfx/gfxTransformSaver.h" 43#include "materials/customMaterialDefinition.h" 44#include "materials/materialFeatureTypes.h" 45#include "console/console.h" 46#include "postFx/postEffect.h" 47#ifdef TORQUE_BASIC_LIGHTING 48#include "lighting/basic/basicLightManager.h" 49#else 50#include "lighting/advanced/advancedLightManager.h" 51#endif 52#include "lighting/shadowMap/shadowMatHook.h" 53#include "materials/materialManager.h" 54#include "lighting/shadowMap/lightShadowMap.h" 55 56 57SimObjectPtr<RenderPassManager> ProjectedShadow::smRenderPass = NULL; 58SimObjectPtr<PostEffect> ProjectedShadow::smShadowFilter = NULL; 59F32 ProjectedShadow::smDepthAdjust = 10.0f; 60 61F32 ProjectedShadow::smFadeStartPixelSize = 200.0f; 62F32 ProjectedShadow::smFadeEndPixelSize = 35.0f; 63 64 65GFX_ImplementTextureProfile( BLProjectedShadowProfile, 66 GFXTextureProfile::DiffuseMap, 67 GFXTextureProfile::PreserveSize | 68 GFXTextureProfile::RenderTarget | 69 GFXTextureProfile::Pooled, 70 GFXTextureProfile::NONE ); 71 72GFX_ImplementTextureProfile( BLProjectedShadowZProfile, 73 GFXTextureProfile::DiffuseMap, 74 GFXTextureProfile::PreserveSize | 75 GFXTextureProfile::ZTarget | 76 GFXTextureProfile::Pooled, 77 GFXTextureProfile::NONE ); 78 79 80ProjectedShadow::ProjectedShadow( SceneObject *object ) 81{ 82 mParentObject = object; 83 mShapeBase = dynamic_cast<ShapeBase*>( object ); 84 85 mRadius = 0; 86 mLastRenderTime = 0; 87 mUpdateTexture = false; 88 89 mShadowLength = 10.0f; 90 91 mDecalData = new DecalData; 92 mDecalData->skipVertexNormals = true; 93 94 mDecalInstance = NULL; 95 96 mLastLightDir.set( 0, 0, 0 ); 97 mLastObjectPosition.set( object->getRenderPosition() ); 98 mLastObjectScale.set( object->getScale() ); 99 100 CustomMaterial *customMat = NULL; 101 Sim::findObject( "BL_ProjectedShadowMaterial", customMat ); 102 if ( customMat ) 103 { 104 mDecalData->material = customMat; 105 mDecalData->matInst = customMat->createMatInstance(); 106 } 107 else 108 mDecalData->matInst = MATMGR->createMatInstance( "WarningMaterial" ); 109 110 mDecalData->matInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<GFXVertexPNTT>() ); 111 112 mCasterPositionSC = NULL; 113 mShadowLengthSC = NULL; 114} 115 116ProjectedShadow::~ProjectedShadow() 117{ 118 if ( mDecalInstance ) 119 gDecalManager->removeDecal( mDecalInstance ); 120 121 delete mDecalData; 122 123 mShadowTexture = NULL; 124 mRenderTarget = NULL; 125} 126 127bool ProjectedShadow::shouldRender( const SceneRenderState *state ) 128{ 129 // Don't render if our object has been removed from the 130 // scene graph. 131 132 if( !mParentObject->getSceneManager() ) 133 return false; 134 135 // Don't render if the ShapeBase 136 // object's fade value is greater 137 // than the visibility epsilon. 138 bool shapeFade = mShapeBase && mShapeBase->getFadeVal() < TSMesh::VISIBILITY_EPSILON; 139 140 // Get the shapebase datablock if we have one. 141 ShapeBaseData *data = NULL; 142 if ( mShapeBase ) 143 data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); 144 145 // Also don't render if 146 // the camera distance is greater 147 // than the shadow length. 148 if ( shapeFade || !mDecalData || 149 ( mDecalInstance && 150 mDecalInstance->calcPixelSize( state->getViewport().extent.y, state->getCameraPosition(), state->getWorldToScreenScale().y ) < mDecalInstance->mDataBlock->fadeEndPixelSize ) ) 151 { 152 // Release our shadow texture 153 // so that others can grab it out 154 // of the pool. 155 mShadowTexture = NULL; 156 157 return false; 158 } 159 160 return true; 161} 162 163bool ProjectedShadow::_updateDecal( const SceneRenderState *state ) 164{ 165 PROFILE_SCOPE( ProjectedShadow_UpdateDecal ); 166 167 if ( !LIGHTMGR ) 168 return false; 169 170 // Get the position of the decal first. 171 const Box3F &objBox = mParentObject->getObjBox(); 172 const Point3F boxCenter = objBox.getCenter(); 173 Point3F decalPos = boxCenter; 174 const MatrixF &renderTransform = mParentObject->getRenderTransform(); 175 { 176 // Set up the decal position. 177 // We use the object space box center 178 // multiplied by the render transform 179 // of the object to ensure we benefit 180 // from interpolation. 181 MatrixF t( renderTransform ); 182 t.setColumn(2,Point3F::UnitZ); 183 t.mulP( decalPos ); 184 } 185 186 if ( mDecalInstance ) 187 { 188 mDecalInstance->mPosition = decalPos; 189 if ( !shouldRender( state ) ) 190 return false; 191 } 192 193 // Get the sunlight for the shadow projection. 194 // We want the LightManager to return NULL if it can't 195 // get the "real" sun, so we specify false for the useDefault parameter. 196 LightInfo *lights[4] = {0}; 197 LightQuery query; 198 query.init( mParentObject->getWorldSphere() ); 199 query.getLights( lights, 4 ); 200 201 Point3F pos = renderTransform.getPosition(); 202 203 Point3F lightDir( 0, 0, 0 ); 204 Point3F tmp( 0, 0, 0 ); 205 F32 weight = 0; 206 F32 range = 0; 207 U32 lightCount = 0; 208 F32 dist = 0; 209 F32 fade = 0; 210 for ( U32 i = 0; i < 4; i++ ) 211 { 212 // If we got a NULL light, 213 // we're at the end of the list. 214 if ( !lights[i] ) 215 break; 216 217 if ( !lights[i]->getCastShadows() ) 218 continue; 219 220 if ( lights[i]->getType() != LightInfo::Point ) 221 tmp = lights[i]->getDirection(); 222 else 223 tmp = pos - lights[i]->getPosition(); 224 225 range = lights[i]->getRange().x; 226 dist = ( (tmp.lenSquared()) / ((range * range) * 0.5f)); 227 weight = mClampF( 1.0f - ( tmp.lenSquared() / (range * range)), 0.00001f, 1.0f ); 228 229 if ( lights[i]->getType() == LightInfo::Vector ) 230 fade = getMax( fade, 1.0f ); 231 else 232 fade = getMax( fade, mClampF( 1.0f - dist, 0.00001f, 1.0f ) ); 233 234 lightDir += tmp * weight; 235 lightCount++; 236 } 237 238 if (mShapeBase) 239 fade *= mShapeBase->getFadeVal(); 240 241 lightDir.normalize(); 242 243 // No light... no shadow. 244 if ( !lights[0] ) 245 return false; 246 247 // Has the light direction 248 // changed since last update? 249 bool lightDirChanged = !mLastLightDir.equal( lightDir ); 250 251 // Has the parent object moved 252 // or scaled since the last update? 253 bool hasMoved = !mLastObjectPosition.equal( mParentObject->getRenderPosition() ); 254 bool hasScaled = !mLastObjectScale.equal( mParentObject->getScale() ); 255 256 // Set the last light direction 257 // to the current light direction. 258 mLastLightDir = lightDir; 259 mLastObjectPosition = mParentObject->getRenderPosition(); 260 mLastObjectScale = mParentObject->getScale(); 261 262 263 // Temps used to generate 264 // tangent vector for DecalInstance below. 265 VectorF right( 0, 0, 0 ); 266 VectorF fwd( 0, 0, 0 ); 267 VectorF tmpFwd( 0, 0, 0 ); 268 269 U32 idx = lightDir.getLeastComponentIndex(); 270 271 tmpFwd[idx] = 1.0f; 272 273 right = mCross( tmpFwd, lightDir ); 274 fwd = mCross( lightDir, right ); 275 right = mCross( fwd, lightDir ); 276 277 right.normalize(); 278 279 // Set up the world to light space 280 // matrix, along with proper position 281 // and rotation to be used as the world 282 // matrix for the render to texture later on. 283 static MatrixF sRotMat(EulerF( 0.0f, -(M_PI_F/2.0f), 0.0f)); 284 mWorldToLight.identity(); 285 MathUtils::getMatrixFromForwardVector( lightDir, &mWorldToLight ); 286 mWorldToLight.setPosition( ( pos + boxCenter ) - ( ( (mRadius * smDepthAdjust) + 0.001f ) * lightDir ) ); 287 mWorldToLight.mul( sRotMat ); 288 mWorldToLight.inverse(); 289 290 // Get the shapebase datablock if we have one. 291 ShapeBaseData *data = NULL; 292 if ( mShapeBase ) 293 data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); 294 295 // We use the object box's extents multiplied 296 // by the object's scale divided by 2 for the radius 297 // because the object's worldsphere radius is not 298 // rotationally invariant. 299 mRadius = (objBox.getExtents() * mParentObject->getScale()).len() * 0.5f; 300 301 if ( data ) 302 mRadius *= data->shadowSphereAdjust; 303 304 // Create the decal if we don't have one yet. 305 if ( !mDecalInstance ) 306 mDecalInstance = gDecalManager->addDecal( decalPos, 307 lightDir, 308 right, 309 mDecalData, 310 1.0f, 311 0, 312 PermanentDecal | ClipDecal | CustomDecal ); 313 314 if ( !mDecalInstance ) 315 return false; 316 317 mDecalInstance->mVisibility = fade; 318 319 // Setup decal parameters. 320 mDecalInstance->mSize = mRadius * 2.0f; 321 mDecalInstance->mNormal = -lightDir; 322 mDecalInstance->mTangent = -right; 323 mDecalInstance->mRotAroundNormal = 0; 324 mDecalInstance->mPosition = decalPos; 325 mDecalInstance->mDataBlock = mDecalData; 326 327 // If the position of the world 328 // space box center is the same 329 // as the decal's position, and 330 // the light direction has not 331 // changed, we don't need to clip. 332 bool shouldClip = lightDirChanged || hasMoved || hasScaled; 333 334 // Now, check and see if the object is visible. 335 const Frustum &frust = state->getCullingFrustum(); 336 if ( frust.isCulled( SphereF( mDecalInstance->mPosition, mDecalInstance->mSize * mDecalInstance->mSize ) ) && !shouldClip ) 337 return false; 338 339 F32 shadowLen = 10.0f; 340 if ( data ) 341 shadowLen = data->shadowProjectionDistance; 342 343 const Point3F &boxExtents = objBox.getExtents(); 344 345 346 mShadowLength = shadowLen * mParentObject->getScale().z; 347 348 // Set up clip depth, and box half 349 // offset for decal clipping. 350 Point2F clipParams( mShadowLength, (boxExtents.x + boxExtents.y) * 0.25f ); 351 352 bool render = false; 353 bool clipSucceeded = true; 354 355 // Clip! 356 if ( shouldClip ) 357 { 358 clipSucceeded = gDecalManager->clipDecal( mDecalInstance, 359 NULL, 360 &clipParams ); 361 } 362 363 // If the clip failed, 364 // we'll return false in 365 // order to keep from 366 // unnecessarily rendering 367 // into the texture. If 368 // there was no reason to clip 369 // on this update, we'll assume we 370 // should update the texture. 371 render = clipSucceeded; 372 373 // Tell the DecalManager we've changed this decal. 374 gDecalManager->notifyDecalModified( mDecalInstance ); 375 376 return render; 377} 378 379void ProjectedShadow::_calcScore( const SceneRenderState *state ) 380{ 381 if ( !mDecalInstance ) 382 return; 383 384 F32 pixRadius = mDecalInstance->calcPixelSize( state->getViewport().extent.y, state->getCameraPosition(), state->getWorldToScreenScale().y ); 385 386 F32 pct = pixRadius / mDecalInstance->mDataBlock->fadeStartPixelSize; 387 388 U32 msSinceLastRender = Platform::getVirtualMilliseconds() - getLastRenderTime(); 389 390 ShapeBaseData *data = NULL; 391 if ( mShapeBase ) 392 data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); 393 394 // For every 1s this shadow hasn't been 395 // updated we'll add 10 to the score. 396 F32 secs = mFloor( (F32)msSinceLastRender / 1000.0f ); 397 398 mScore = pct + secs; 399 mClampF( mScore, 0.0f, 2000.0f ); 400} 401 402void ProjectedShadow::update( const SceneRenderState *state ) 403{ 404 mUpdateTexture = true; 405 406 // Set the decal lod settings. 407 mDecalData->fadeStartPixelSize = smFadeStartPixelSize; 408 mDecalData->fadeEndPixelSize = smFadeEndPixelSize; 409 410 // Update our decal before 411 // we render to texture. 412 // If it fails, something bad happened 413 // (no light to grab/failed clip) and we should return. 414 if ( !_updateDecal( state ) ) 415 { 416 // Release our shadow texture 417 // so that others can grab it out 418 // of the pool. 419 mShadowTexture = NULL; 420 mUpdateTexture = false; 421 return; 422 } 423 424 _calcScore( state ); 425 426 if ( !mCasterPositionSC || !mCasterPositionSC->isValid() ) 427 mCasterPositionSC = mDecalData->matInst->getMaterialParameterHandle( "$shadowCasterPosition" ); 428 429 if ( !mShadowLengthSC || !mShadowLengthSC->isValid() ) 430 mShadowLengthSC = mDecalData->matInst->getMaterialParameterHandle( "$shadowLength" ); 431 432 MaterialParameters *matParams = mDecalData->matInst->getMaterialParameters(); 433 434 matParams->setSafe( mCasterPositionSC, mParentObject->getRenderPosition() ); 435 matParams->setSafe( mShadowLengthSC, mShadowLength / 4.0f ); 436} 437 438void ProjectedShadow::render( F32 camDist, const TSRenderState &rdata ) 439{ 440 if ( !mUpdateTexture ) 441 return; 442 443 // Do the render to texture, 444 // DecalManager handles rendering 445 // the shadow onto the world. 446 _renderToTexture( camDist, rdata ); 447} 448 449BaseMatInstance* ProjectedShadow::_getShadowMaterial( BaseMatInstance *inMat ) 450{ 451 // See if we have an existing material hook. 452 ShadowMaterialHook *hook = static_cast<ShadowMaterialHook*>( inMat->getHook( ShadowMaterialHook::Type ) ); 453 if ( !hook ) 454 { 455 // Create a hook and initialize it using the incoming material. 456 hook = new ShadowMaterialHook; 457 hook->init( inMat ); 458 inMat->addHook( hook ); 459 } 460 461 return hook->getShadowMat( ShadowType_Spot ); 462} 463 464void ProjectedShadow::_renderToTexture( F32 camDist, const TSRenderState &rdata ) 465{ 466 PROFILE_SCOPE( ProjectedShadow_RenderToTexture ); 467 468 GFXDEBUGEVENT_SCOPE( ProjectedShadow_RenderToTexture, ColorI( 255, 0, 0 ) ); 469 470 RenderPassManager *renderPass = _getRenderPass(); 471 if ( !renderPass ) 472 return; 473 474 GFXTransformSaver saver; 475 476 // NOTE: GFXTransformSaver does not save/restore the frustum 477 // so we must save it here before we modify it. 478 F32 l, r, b, t, n, f; 479 bool ortho; 480 GFX->getFrustum( &l, &r, &b, &t, &n, &f, &ortho ); 481 482 // Set the orthographic projection 483 // matrix up, to be based on the radius 484 // generated based on our shape. 485 GFX->setOrtho( -mRadius, mRadius, -mRadius, mRadius, 0.001f, (mRadius * 2) * smDepthAdjust, true ); 486 487 // Set the world to light space 488 // matrix set up in shouldRender(). 489 GFX->setWorldMatrix( mWorldToLight ); 490 491 // Get the shapebase datablock if we have one. 492 ShapeBaseData *data = NULL; 493 if ( mShapeBase ) 494 data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); 495 496 // Init or update the shadow texture size. 497 if ( mShadowTexture.isNull() || ( data && data->shadowSize != mShadowTexture.getWidth() ) ) 498 { 499 U32 texSize = getNextPow2( data ? data->shadowSize : 256 * LightShadowMap::smShadowTexScalar ); 500 mShadowTexture.set( texSize, texSize, GFXFormatR8G8B8A8, &PostFxTargetProfile, "BLShadow" ); 501 } 502 503 GFX->pushActiveRenderTarget(); 504 505 if ( !mRenderTarget ) 506 mRenderTarget = GFX->allocRenderToTextureTarget(); 507 508 mRenderTarget->attachTexture( GFXTextureTarget::DepthStencil, _getDepthTarget( mShadowTexture->getWidth(), mShadowTexture->getHeight() ) ); 509 mRenderTarget->attachTexture( GFXTextureTarget::Color0, mShadowTexture ); 510 GFX->setActiveRenderTarget( mRenderTarget ); 511 512 GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 0, 0, 0, 0 ), 1.0f, 0 ); 513 514 const SceneRenderState *diffuseState = rdata.getSceneState(); 515 SceneManager *sceneManager = diffuseState->getSceneManager(); 516 517 SceneRenderState baseState 518 ( 519 sceneManager, 520 SPT_Shadow, 521 SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), 522 renderPass 523 ); 524 525 baseState.getMaterialDelegate().bind( &ProjectedShadow::_getShadowMaterial ); 526 baseState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); 527 baseState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); 528 baseState.getCullingState().disableZoneCulling( true ); 529 530 mParentObject->prepRenderImage( &baseState ); 531 renderPass->renderPass( &baseState ); 532 533 // Delete the SceneRenderState we allocated. 534 mRenderTarget->resolve(); 535 GFX->popActiveRenderTarget(); 536 537 // If we're close enough then filter the shadow. 538#ifdef TORQUE_BASIC_LIGHTING 539 if (camDist < BasicLightManager::getShadowFilterDistance()) 540#else 541 if (camDist < AdvancedLightManager::getShadowFilterDistance()) 542#endif 543 { 544 if ( !smShadowFilter ) 545 { 546 PostEffect *filter = NULL; 547 548 if ( !Sim::findObject( "BL_ShadowFilterPostFx", filter ) ) 549 Con::errorf( "ProjectedShadow::_renderToTexture() - 'BL_ShadowFilterPostFx' not found!" ); 550 551 smShadowFilter = filter; 552 } 553 554 if ( smShadowFilter ) 555 smShadowFilter->process( NULL, mShadowTexture ); 556 } 557 558 // Restore frustum 559 if (!ortho) 560 GFX->setFrustum(l, r, b, t, n, f); 561 else 562 GFX->setOrtho(l, r, b, t, n, f); 563 564 // Set the last render time. 565 mLastRenderTime = Platform::getVirtualMilliseconds(); 566 567 // HACK: Will remove in future release! 568 mDecalInstance->mCustomTex = &mShadowTexture; 569} 570 571RenderPassManager* ProjectedShadow::_getRenderPass() 572{ 573 if ( smRenderPass.isNull() ) 574 { 575 SimObject* renderPass = NULL; 576 577 if ( !Sim::findObject( "BL_ProjectedShadowRPM", renderPass ) ) 578 Con::errorf( "ProjectedShadow::init() - 'BL_ProjectedShadowRPM' not initialized" ); 579 else 580 smRenderPass = dynamic_cast<RenderPassManager*>(renderPass); 581 } 582 583 return smRenderPass; 584} 585 586GFXTextureObject* ProjectedShadow::_getDepthTarget( U32 width, U32 height ) 587{ 588 // Get a depth texture target from the pooled profile 589 // which is returned as a temporary. 590 GFXTexHandle depthTex( width, height, GFXFormatD24S8, &BLProjectedShadowZProfile, 591 "ProjectedShadow::_getDepthTarget()" ); 592 593 return depthTex; 594} 595