diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index 153209933..a39e4bf8d 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/Engine/source/T3D/decal/decalManager.cpp @@ -1004,7 +1004,7 @@ void DecalManager::prepRenderImage( SceneRenderState* state ) PROFILE_START( DecalManager_RenderDecals_SphereTreeCull ); - const Frustum& rootFrustum = state->getFrustum(); + const Frustum& rootFrustum = state->getCameraFrustum(); // Populate vector of decal instances to be rendered with all // decals from visible decal spheres. @@ -1448,7 +1448,7 @@ void DecalManager::_renderDecalSpheres( ObjectRenderInst* ri, SceneRenderState* DecalSphere *decalSphere = grid[i]; const SphereF &worldSphere = decalSphere->mWorldSphere; - if( state->getFrustum().isCulled( worldSphere ) ) + if( state->getCullingFrustum().isCulled( worldSphere ) ) continue; drawUtil->drawSphere( desc, worldSphere.radius, worldSphere.center, sphereColor ); diff --git a/Engine/source/T3D/fx/fxFoliageReplicator.cpp b/Engine/source/T3D/fx/fxFoliageReplicator.cpp index 04b6c8976..7e88b174f 100644 --- a/Engine/source/T3D/fx/fxFoliageReplicator.cpp +++ b/Engine/source/T3D/fx/fxFoliageReplicator.cpp @@ -146,7 +146,7 @@ void fxFoliageRenderList::SetupClipPlanes( SceneRenderState* state, const F32 fa const F32 nearPlane = state->getNearPlane(); const F32 farPlane = farClipPlane; - const Frustum& frustum = state->getFrustum(); + const Frustum& frustum = state->getCullingFrustum(); // [rene, 23-Feb-11] Why isn't this preserving the ortho state of the original frustum? diff --git a/Engine/source/T3D/fx/groundCover.cpp b/Engine/source/T3D/fx/groundCover.cpp index 1d0c2f9fd..5317f139e 100644 --- a/Engine/source/T3D/fx/groundCover.cpp +++ b/Engine/source/T3D/fx/groundCover.cpp @@ -1539,7 +1539,7 @@ void GroundCover::prepRenderImage( SceneRenderState *state ) // Setup the frustum culler. if ( ( mCuller.getPosition().isZero() || !mDebugLockFrustum ) && !state->isShadowPass() ) - mCuller = state->getFrustum(); + mCuller = state->getCullingFrustum(); // Update the cells, but only during the diffuse pass. // We don't want cell generation to thrash when the reflection camera diff --git a/Engine/source/T3D/groundPlane.cpp b/Engine/source/T3D/groundPlane.cpp index d3d27d5cb..b188a7d39 100644 --- a/Engine/source/T3D/groundPlane.cpp +++ b/Engine/source/T3D/groundPlane.cpp @@ -352,7 +352,7 @@ void GroundPlane::prepRenderImage( SceneRenderState* state ) PROFILE_SCOPE( GroundPlane_prepRender ); // Update the geometry. - createGeometry( state->getFrustum() ); + createGeometry( state->getCullingFrustum() ); if( mVertexBuffer.isNull() ) return; diff --git a/Engine/source/T3D/lightFlareData.cpp b/Engine/source/T3D/lightFlareData.cpp index 5a3e0e322..8cbad24fc 100644 --- a/Engine/source/T3D/lightFlareData.cpp +++ b/Engine/source/T3D/lightFlareData.cpp @@ -279,7 +279,7 @@ bool LightFlareData::_testVisibility(const SceneRenderState *state, LightFlareSt const Point3F &lightPos = flareState->lightMat.getPosition(); const RectI &viewport = GFX->getViewport(); MatrixF projMatrix; - state->getFrustum().getProjectionMatrix(&projMatrix); + state->getCameraFrustum().getProjectionMatrix(&projMatrix); if( state->isReflectPass() ) projMatrix = state->getSceneManager()->getNonClipProjection(); bool onScreen = MathUtils::mProjectWorldToScreen( lightPos, outLightPosSS, viewport, GFX->getWorldMatrix(), projMatrix ); @@ -465,7 +465,7 @@ void LightFlareData::prepRender( SceneRenderState *state, LightFlareState *flare // Take any projection offset into account so that the point where the flare's // elements converge is at the 'eye' point rather than the center of the viewport. - const Point2F& projOffset = state->getFrustum().getProjectionOffset(); + const Point2F& projOffset = state->getCameraFrustum().getProjectionOffset(); Point3F flareVec( -lightPosSS + Point3F(projOffset.x, projOffset.y, 0.0f) ); const F32 flareLength = flareVec.len(); if ( flareLength > 0.0f ) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index b1315cd2a..f2e666c4f 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -525,7 +525,7 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) Frustum culler; if ( mMeshCulling ) { - culler = state->getFrustum(); + culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); diff --git a/Engine/source/environment/decalRoad.cpp b/Engine/source/environment/decalRoad.cpp index 71d29be96..7bd240095 100644 --- a/Engine/source/environment/decalRoad.cpp +++ b/Engine/source/environment/decalRoad.cpp @@ -721,7 +721,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state ) if ( !smShowRoad && smEditorOpen ) return; - const Frustum &frustum = state->getFrustum(); + const Frustum &frustum = state->getCameraFrustum(); MeshRenderInst coreRI; coreRI.clear(); diff --git a/Engine/source/environment/scatterSky.cpp b/Engine/source/environment/scatterSky.cpp index cebc8b9b2..7fdf25296 100644 --- a/Engine/source/environment/scatterSky.cpp +++ b/Engine/source/environment/scatterSky.cpp @@ -930,7 +930,7 @@ void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMat Point3F camPos( 0, 0, smViewerHeight ); Point4F miscParams( camPos.z, camPos.z * camPos.z, mScale, mScale / mRayleighScaleDepth ); - Frustum frust = state->getFrustum(); + Frustum frust = state->getCameraFrustum(); frust.setFarDist( smEarthRadius + smAtmosphereRadius ); MatrixF proj( true ); frust.getProjectionMatrix( &proj ); diff --git a/Engine/source/environment/waterPlane.cpp b/Engine/source/environment/waterPlane.cpp index c0158a61f..eab66a466 100644 --- a/Engine/source/environment/waterPlane.cpp +++ b/Engine/source/environment/waterPlane.cpp @@ -173,7 +173,7 @@ void WaterPlane::unpackUpdate(NetConnection* con, BitStream* stream) void WaterPlane::setupVBIB( SceneRenderState *state ) { - const Frustum &frustum = state->getFrustum(); + const Frustum &frustum = state->getCullingFrustum(); // Water base-color, assigned as color for all verts. const GFXVertexColor vertCol(mWaterFogData.color); @@ -708,7 +708,7 @@ void WaterPlane::prepRenderImage( SceneRenderState *state ) mMatrixSet->setSceneView(GFX->getWorldMatrix()); - const Frustum &frustum = state->getFrustum(); + const Frustum &frustum = state->getCameraFrustum(); if ( mPrimBuff.isNull() || mGenerateVB || diff --git a/Engine/source/forest/forestRender.cpp b/Engine/source/forest/forestRender.cpp index 0c7a3fb91..3fa2b3047 100644 --- a/Engine/source/forest/forestRender.cpp +++ b/Engine/source/forest/forestRender.cpp @@ -110,7 +110,7 @@ void Forest::prepRenderImage( SceneRenderState *state ) // the forest, so pass down a LightQuery for it. LightQuery lightQuery; rdata.setLightQuery( &lightQuery ); - Frustum culler = state->getFrustum(); + Frustum culler = state->getCullingFrustum(); // Adjust the far distance if the cull scale has changed. if ( !mIsEqual( cullScale, 1.0f ) ) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index 069f0e762..d8620e856 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -444,7 +444,7 @@ void AdvancedLightBinManager::_deleteLightMaterials() void AdvancedLightBinManager::_setupPerFrameParameters( const SceneRenderState *state ) { PROFILE_SCOPE( AdvancedLightBinManager_SetupPerFrameParameters ); - const Frustum &frustum = state->getFrustum(); + const Frustum &frustum = state->getCameraFrustum(); MatrixF invCam( frustum.getTransform() ); invCam.inverse(); diff --git a/Engine/source/lighting/common/projectedShadow.cpp b/Engine/source/lighting/common/projectedShadow.cpp index de3a31f8f..ed4a7b903 100644 --- a/Engine/source/lighting/common/projectedShadow.cpp +++ b/Engine/source/lighting/common/projectedShadow.cpp @@ -324,7 +324,7 @@ bool ProjectedShadow::_updateDecal( const SceneRenderState *state ) bool shouldClip = lightDirChanged || hasMoved || hasScaled; // Now, check and see if the object is visible. - const Frustum &frust = state->getFrustum(); + const Frustum &frust = state->getCullingFrustum(); if ( frust.isCulled( SphereF( mDecalInstance->mPosition, mDecalInstance->mSize * mDecalInstance->mSize ) ) && !shouldClip ) return false; diff --git a/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp b/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp index e8bf8df31..71a4fe585 100644 --- a/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp @@ -207,7 +207,7 @@ void PSSMLightShadowMap::_render( RenderPassManager* renderPass, _setNumSplits( params->numSplits, texSize ); mLogWeight = params->logWeight; - Frustum fullFrustum( diffuseState->getFrustum() ); + Frustum fullFrustum( diffuseState->getCameraFrustum() ); fullFrustum.cropNearFar(fullFrustum.getNearDist(), params->shadowDistance); GFXFrustumSaver frustSaver; @@ -223,7 +223,7 @@ void PSSMLightShadowMap::_render( RenderPassManager* renderPass, // Calculate our standard light matrices MatrixF lightMatrix; - calcLightMatrices( lightMatrix, diffuseState->getFrustum() ); + calcLightMatrices( lightMatrix, diffuseState->getCameraFrustum() ); lightMatrix.inverse(); MatrixF lightViewProj = GFX->getProjectionMatrix() * lightMatrix; diff --git a/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp b/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp index 3d13f245c..e8dc240a2 100644 --- a/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp @@ -67,7 +67,7 @@ void SingleLightShadowMap::_render( RenderPassManager* renderPass, GFXTransformSaver saver; MatrixF lightMatrix; - calcLightMatrices( lightMatrix, diffuseState->getFrustum() ); + calcLightMatrices( lightMatrix, diffuseState->getCameraFrustum() ); lightMatrix.inverse(); GFX->setWorldMatrix(lightMatrix); diff --git a/Engine/source/math/util/frustum.cpp b/Engine/source/math/util/frustum.cpp index 7cff16e4c..f95814b3f 100644 --- a/Engine/source/math/util/frustum.cpp +++ b/Engine/source/math/util/frustum.cpp @@ -228,6 +228,100 @@ void Frustum::cropNearFar(F32 newNearDist, F32 newFarDist) //----------------------------------------------------------------------------- +bool Frustum::bakeProjectionOffset() +{ + // Nothing to bake if ortho + if( mIsOrtho ) + return false; + + // Nothing to bake if no offset + if( mProjectionOffset.isZero() ) + return false; + + // Near plane points in camera space + Point3F np[4]; + np[0].set( mNearLeft, mNearDist, mNearTop ); // NearTopLeft + np[1].set( mNearRight, mNearDist, mNearTop ); // NearTopRight + np[2].set( mNearLeft, mNearDist, mNearBottom ); // NearBottomLeft + np[3].set( mNearRight, mNearDist, mNearBottom ); // NearBottomRight + + // Generate the near plane + PlaneF nearPlane( np[0], np[1], np[3] ); + + // Far plane points in camera space + const F32 farOverNear = mFarDist / mNearDist; + Point3F fp0( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopLeft + Point3F fp1( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopRight + Point3F fp2( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomLeft + Point3F fp3( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomRight + + // Generate the far plane + PlaneF farPlane( fp0, fp1, fp3 ); + + // The offset camera point + Point3F offsetCamera( mProjectionOffset.x, 0.0f, mProjectionOffset.y ); + + // The near plane point we'll be using for our calculations below + U32 nIndex = 0; + if( mProjectionOffset.x < 0.0 ) + { + // Offset to the left so we'll need to use the near plane point on the right + nIndex = 1; + } + if( mProjectionOffset.y > 0.0 ) + { + // Offset to the top so we'll need to use the near plane point at the bottom + nIndex += 2; + } + + // Begin by calculating the offset point on the far plane as it goes + // from the offset camera to the edge of the near plane. + Point3F farPoint; + Point3F fdir = np[nIndex] - offsetCamera; + fdir.normalize(); + if( farPlane.intersect(offsetCamera, fdir, &farPoint) ) + { + // Calculate the new near plane edge from the non-offset camera position + // to the far plane point from above. + Point3F nearPoint; + Point3F ndir = farPoint; + ndir.normalize(); + if( nearPlane.intersect( Point3F::Zero, ndir, &nearPoint) ) + { + // Handle a x offset + if( mProjectionOffset.x < 0.0 ) + { + // The new near plane right side + mNearRight = nearPoint.x; + } + else if( mProjectionOffset.x > 0.0 ) + { + // The new near plane left side + mNearLeft = nearPoint.x; + } + + // Handle a y offset + if( mProjectionOffset.y < 0.0 ) + { + // The new near plane top side + mNearTop = nearPoint.y; + } + else if( mProjectionOffset.y > 0.0 ) + { + // The new near plane bottom side + mNearBottom = nearPoint.y; + } + } + } + + mDirty = true; + + // Indicate that we've modified the frustum + return true; +} + +//----------------------------------------------------------------------------- + void FrustumData::_update() const { if( !mDirty ) diff --git a/Engine/source/math/util/frustum.h b/Engine/source/math/util/frustum.h index 50b935985..0f71063d9 100644 --- a/Engine/source/math/util/frustum.h +++ b/Engine/source/math/util/frustum.h @@ -412,6 +412,9 @@ class Frustum : public PolyhedronImpl< FrustumData > /// points typically used for early rejection. const Box3F& getBounds() const { _update(); return mBounds; } + // Does the frustum have a projection offset? + bool hasProjectionOffset() const { return !mProjectionOffset.isZero(); } + /// Get the offset used when calculating the projection matrix const Point2F& getProjectionOffset() const { return mProjectionOffset; } @@ -424,6 +427,10 @@ class Frustum : public PolyhedronImpl< FrustumData > /// Clear any offset used when calculating the projection matrix void clearProjectionOffset() { mProjectionOffset.zero(); mProjectionOffsetMatrix.identity(); } + /// Enlarges the frustum to contain the planes generated by a project offset, if any. + /// Used by scene culling to ensure that all object are contained within the asymetrical frustum. + bool bakeProjectionOffset(); + /// Generates a projection matrix from the frustum. void getProjectionMatrix( MatrixF *proj, bool gfxRotate=true ) const; diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index 9a0e9e4e4..aff1e6f2c 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -719,7 +719,7 @@ void PostEffect::_setupConstants( const SceneRenderState *state ) mShaderConsts->setSafe( mNearFarSC, Point2F( state->getNearPlane(), state->getFarPlane() ) ); mShaderConsts->setSafe( mInvNearFarSC, Point2F( 1.0f / state->getNearPlane(), 1.0f / state->getFarPlane() ) ); mShaderConsts->setSafe( mWorldToScreenScaleSC, state->getWorldToScreenScale() ); - mShaderConsts->setSafe( mProjectionOffsetSC, state->getFrustum().getProjectionOffset() ); + mShaderConsts->setSafe( mProjectionOffsetSC, state->getCameraFrustum().getProjectionOffset() ); mShaderConsts->setSafe( mFogColorSC, state->getSceneManager()->getFogData().color ); if ( mWaterColorSC->isValid() ) @@ -750,7 +750,7 @@ void PostEffect::_setupConstants( const SceneRenderState *state ) { // Grab our projection matrix // from the frustum. - Frustum frust = state->getFrustum(); + Frustum frust = state->getCameraFrustum(); MatrixF proj( true ); frust.getProjectionMatrix( &proj ); @@ -1219,7 +1219,7 @@ void PostEffect::process( const SceneRenderState *state, Frustum frustum; if ( state ) - frustum = state->getFrustum(); + frustum = state->getCameraFrustum(); else { // If we don't have a scene state then setup diff --git a/Engine/source/scene/culling/sceneCullingState.cpp b/Engine/source/scene/culling/sceneCullingState.cpp index b8608160d..f3b4022fa 100644 --- a/Engine/source/scene/culling/sceneCullingState.cpp +++ b/Engine/source/scene/culling/sceneCullingState.cpp @@ -68,17 +68,21 @@ SceneCullingState::SceneCullingState( SceneManager* sceneManager, const SceneCam mZoneVisibilityFlags.setSize( numZones ); mZoneVisibilityFlags.clear(); + // Culling frustum + + mCullingFrustum = mCameraState.getFrustum(); + mCullingFrustum.bakeProjectionOffset(); + // Construct the root culling volume from - // the camera's view frustum. Omit the frustum's + // the culling frustum. Omit the frustum's // near and far plane so we don't test it repeatedly. - const Frustum& frustum = mCameraState.getFrustum(); PlaneF* planes = allocateData< PlaneF >( 4 ); - planes[ 0 ] = frustum.getPlanes()[ Frustum::PlaneLeft ]; - planes[ 1 ] = frustum.getPlanes()[ Frustum::PlaneRight ]; - planes[ 2 ] = frustum.getPlanes()[ Frustum::PlaneTop]; - planes[ 3 ] = frustum.getPlanes()[ Frustum::PlaneBottom ]; + planes[ 0 ] = mCullingFrustum.getPlanes()[ Frustum::PlaneLeft ]; + planes[ 1 ] = mCullingFrustum.getPlanes()[ Frustum::PlaneRight ]; + planes[ 2 ] = mCullingFrustum.getPlanes()[ Frustum::PlaneTop]; + planes[ 3 ] = mCullingFrustum.getPlanes()[ Frustum::PlaneBottom ]; mRootVolume = SceneCullingVolume( SceneCullingVolume::Includer, @@ -219,7 +223,7 @@ bool SceneCullingState::createCullingVolume( const Point3F* vertices, U32 numVer { const Point3F& viewPos = getCameraState().getViewPosition(); const Point3F& viewDir = getCameraState().getViewDirection(); - const bool isOrtho = getFrustum().isOrtho(); + const bool isOrtho = getCullingFrustum().isOrtho(); //TODO: check if we need to handle penetration of the near plane for occluders specially @@ -440,8 +444,8 @@ bool SceneCullingState::createCullingVolume( const Point3F* vertices, U32 numVer if( type == SceneCullingVolume::Occluder ) { - const F32 widthEstimatePercentage = widthEstimate / getFrustum().getWidth(); - const F32 heightEstimatePercentage = heightEstimate / getFrustum().getHeight(); + const F32 widthEstimatePercentage = widthEstimate / getCullingFrustum().getWidth(); + const F32 heightEstimatePercentage = heightEstimate / getCullingFrustum().getHeight(); if( widthEstimatePercentage < smOccluderMinWidthPercentage || heightEstimatePercentage < smOccluderMinHeightPercentage ) @@ -614,7 +618,7 @@ inline SceneZoneCullingState::CullingTestResult SceneCullingState::_test( const if( disableZoneCulling() ) { - if( !OCCLUDERS_ONLY && !getFrustum().isCulled( bounds ) ) + if( !OCCLUDERS_ONLY && !getCullingFrustum().isCulled( bounds ) ) return SceneZoneCullingState::CullingTestPositiveByInclusion; return SceneZoneCullingState::CullingTestNegative; @@ -631,7 +635,7 @@ inline SceneZoneCullingState::CullingTestResult SceneCullingState::_test( const } else { - const PlaneF* frustumPlanes = getFrustum().getPlanes(); + const PlaneF* frustumPlanes = getCullingFrustum().getPlanes(); return _test( bounds, @@ -715,8 +719,8 @@ U32 SceneCullingState::cullObjects( SceneObject** objects, U32 numObjects, U32 c // We test near and far planes separately in order to not do the tests // repeatedly, so fetch the planes now. - const PlaneF& nearPlane = getFrustum().getPlanes()[ Frustum::PlaneNear ]; - const PlaneF& farPlane = getFrustum().getPlanes()[ Frustum::PlaneFar ]; + const PlaneF& nearPlane = getCullingFrustum().getPlanes()[ Frustum::PlaneNear ]; + const PlaneF& farPlane = getCullingFrustum().getPlanes()[ Frustum::PlaneFar ]; for( U32 i = 0; i < numObjects; ++ i ) { @@ -766,7 +770,7 @@ U32 SceneCullingState::cullObjects( SceneObject** objects, U32 numObjects, U32 c ( object->getTypeMask() & CULLING_EXCLUDE_TYPEMASK ) || disableZoneCulling() ) { - isCulled = getFrustum().isCulled( object->getWorldBox() ); + isCulled = getCullingFrustum().isCulled( object->getWorldBox() ); } // Go through the zones that the object is assigned to and @@ -881,8 +885,8 @@ void SceneCullingState::debugRenderCullingVolumes() const const ColorI occluderColor( 255, 0, 0, 255 ); const ColorI includerColor( 0, 255, 0, 255 ); - const PlaneF& nearPlane = getFrustum().getPlanes()[ Frustum::PlaneNear ]; - const PlaneF& farPlane = getFrustum().getPlanes()[ Frustum::PlaneFar ]; + const PlaneF& nearPlane = getCullingFrustum().getPlanes()[ Frustum::PlaneNear ]; + const PlaneF& farPlane = getCullingFrustum().getPlanes()[ Frustum::PlaneFar ]; DebugDrawer* drawer = DebugDrawer::get(); const SceneZoneSpaceManager* zoneManager = mSceneManager->getZoneManager(); diff --git a/Engine/source/scene/culling/sceneCullingState.h b/Engine/source/scene/culling/sceneCullingState.h index b7a231da8..b63b219c2 100644 --- a/Engine/source/scene/culling/sceneCullingState.h +++ b/Engine/source/scene/culling/sceneCullingState.h @@ -100,9 +100,12 @@ class SceneCullingState /// The viewing state that defines how the scene is being viewed. SceneCameraState mCameraState; - /// The root culling volume corresponding to the camera frustum. + /// The root culling volume corresponding to the culling frustum. SceneCullingVolume mRootVolume; + /// The root culling frustum, which may be different from the camera frustum + Frustum mCullingFrustum; + /// Occluders that have been added to this render state. Adding an occluder does not /// necessarily result in an occluder volume being added. To not repeatedly try to /// process the same occluder object, all objects that are added are recorded here. @@ -136,7 +139,10 @@ class SceneCullingState SceneManager* getSceneManager() const { return mSceneManager; } /// Return the root frustum which is used to set up scene visibility. - const Frustum& getFrustum() const { return getCameraState().getFrustum(); } + const Frustum& getCullingFrustum() const { return mCullingFrustum; } + + /// Return the root frustum which is used to set up scene visibility. + const Frustum& getCameraFrustum() const { return getCameraState().getFrustum(); } /// Return the viewing state that defines how the scene is being viewed. const SceneCameraState& getCameraState() const { return mCameraState; } diff --git a/Engine/source/scene/reflector.cpp b/Engine/source/scene/reflector.cpp index 91a29f99b..2b96737e6 100644 --- a/Engine/source/scene/reflector.cpp +++ b/Engine/source/scene/reflector.cpp @@ -420,7 +420,7 @@ void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx ) reflectRenderState.disableAdvancedLightingBins(true); // render scene - LIGHTMGR->registerGlobalLights( &reflectRenderState.getFrustum(), false ); + LIGHTMGR->registerGlobalLights( &reflectRenderState.getCullingFrustum(), false ); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, mDesc->objectTypeMask ); LIGHTMGR->unregisterAllLights(); diff --git a/Engine/source/scene/sceneManager.cpp b/Engine/source/scene/sceneManager.cpp index 6db76d590..3fcd37422 100644 --- a/Engine/source/scene/sceneManager.cpp +++ b/Engine/source/scene/sceneManager.cpp @@ -191,7 +191,7 @@ void SceneManager::renderScene( SceneRenderState* renderState, U32 objectMask, S // Get the lights for rendering the scene. PROFILE_START( SceneGraph_registerLights ); - LIGHTMGR->registerGlobalLights( &renderState->getFrustum(), false ); + LIGHTMGR->registerGlobalLights( &renderState->getCullingFrustum(), false ); PROFILE_END(); // If its a diffuse pass, update the current ambient light level. @@ -404,7 +404,7 @@ void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZ // the opportunity to render editor visualizations even if // they are otherwise not in view. - if( !state->getFrustum().getBounds().isOverlapped( state->getRenderArea() ) ) + if( !state->getCullingFrustum().getBounds().isOverlapped( state->getRenderArea() ) ) { // This handles fringe cases like flying backwards into a zone where you // end up pretty much standing on a zone border and looking directly into @@ -415,7 +415,7 @@ void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZ return; } - Box3F queryBox = state->getFrustum().getBounds(); + Box3F queryBox = state->getCullingFrustum().getBounds(); if( !gEditingMission ) { queryBox.minExtents.setMax( state->getRenderArea().minExtents ); diff --git a/Engine/source/scene/sceneRenderState.h b/Engine/source/scene/sceneRenderState.h index 7a66e40aa..4b8fd200d 100644 --- a/Engine/source/scene/sceneRenderState.h +++ b/Engine/source/scene/sceneRenderState.h @@ -145,8 +145,11 @@ class SceneRenderState const SceneCullingState& getCullingState() const { return mCullingState; } SceneCullingState& getCullingState() { return mCullingState; } - /// Returns the root frustum. - const Frustum& getFrustum() const { return getCullingState().getFrustum(); } + /// Returns the root culling frustum. + const Frustum& getCullingFrustum() const { return getCullingState().getCullingFrustum(); } + + /// Returns the root camera frustum. + const Frustum& getCameraFrustum() const { return getCullingState().getCameraFrustum(); } /// @} @@ -262,10 +265,10 @@ class SceneRenderState const MatrixF& getCameraTransform() const { return getCullingState().getCameraState().getViewWorldMatrix(); } /// Returns the minimum distance something must be from the camera to not be culled. - F32 getNearPlane() const { return getFrustum().getNearDist(); } + F32 getNearPlane() const { return getCullingFrustum().getNearDist(); } /// Returns the maximum distance something can be from the camera to not be culled. - F32 getFarPlane() const { return getFrustum().getFarDist(); } + F32 getFarPlane() const { return getCullingFrustum().getFarDist(); } /// Returns the camera vector normalized to 1 / far distance. const Point3F& getVectorEye() const { return mVectorEye; }