From 190f68b998415bf57fb0008821d3cbfce83d67d6 Mon Sep 17 00:00:00 2001 From: LuisAntonRebollo Date: Mon, 8 Dec 2014 23:31:22 +0100 Subject: [PATCH] Fix SkatterSky flare occlusion. --- Engine/source/T3D/lightFlareData.cpp | 64 ++++++++---------- Engine/source/T3D/lightFlareData.h | 8 ++- Engine/source/environment/scatterSky.cpp | 5 ++ .../source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp | 1 + Engine/source/gfx/gfxOcclusionQuery.h | 67 +++++++++++++++++++ 5 files changed, 105 insertions(+), 40 deletions(-) diff --git a/Engine/source/T3D/lightFlareData.cpp b/Engine/source/T3D/lightFlareData.cpp index 8cbad24fc..50c2b069b 100644 --- a/Engine/source/T3D/lightFlareData.cpp +++ b/Engine/source/T3D/lightFlareData.cpp @@ -26,16 +26,18 @@ #include "core/stream/bitStream.h" #include "console/engineAPI.h" #include "lighting/lightInfo.h" +#include "lighting/lightQuery.h" #include "math/mathUtils.h" #include "math/mathIO.h" #include "scene/sceneRenderState.h" #include "gfx/gfxOcclusionQuery.h" #include "gfx/gfxDrawUtil.h" +#include "gfx/gfxTextureManager.h" #include "renderInstance/renderPassManager.h" #include "T3D/gameBase/gameConnection.h" #include "T3D/gameBase/processList.h" #include "collision/collision.h" - +#include "lighting/lightManager.h" const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK | ShapeBaseObjectType | @@ -45,8 +47,6 @@ const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK | LightFlareState::~LightFlareState() { - delete occlusionQuery; - delete fullPixelQuery; } void LightFlareState::clear() @@ -59,8 +59,6 @@ void LightFlareState::clear() lightInfo = NULL; worldRadius = -1.0f; occlusion = -1.0f; - occlusionQuery = NULL; - fullPixelQuery = NULL; } Point3F LightFlareData::sBasePoints[] = @@ -296,47 +294,39 @@ bool LightFlareData::_testVisibility(const SceneRenderState *state, LightFlareSt // for one-shot initialization of LightFlareState if ( useOcclusionQuery ) { - if ( flareState->occlusionQuery == NULL ) - flareState->occlusionQuery = GFX->createOcclusionQuery(); - if ( flareState->fullPixelQuery == NULL ) - flareState->fullPixelQuery = GFX->createOcclusionQuery(); - // Always treat light as onscreen if using HOQ // it will be faded out if offscreen anyway. onScreen = true; - - // NOTE: These queries frame lock us as we block to get the - // results. This is ok as long as long as we're not too GPU - // bound... else we waste CPU time here waiting for it when - // we could have been doing other CPU work instead. + needsRaycast = false; // Test the hardware queries for rendered pixels. U32 pixels = 0, fullPixels = 0; - GFXOcclusionQuery::OcclusionQueryStatus status = flareState->occlusionQuery->getStatus( true, &pixels ); - flareState->fullPixelQuery->getStatus( true, &fullPixels ); - if ( status != GFXOcclusionQuery::Occluded && fullPixels != 0 ) + GFXOcclusionQuery::OcclusionQueryStatus status; + flareState->occlusionQuery.getLastStatus( false, &status, &pixels ); + flareState->fullPixelQuery.getLastStatus( false, NULL, &fullPixels ); + + if ( status == GFXOcclusionQuery::NotOccluded && fullPixels != 0 ) *outOcclusionFade = mClampF( (F32)pixels / (F32)fullPixels, 0.0f, 1.0f ); - // If we got a result then we don't need to fallback to the raycast. - if ( status != GFXOcclusionQuery::Unset ) - needsRaycast = false; - - // Setup the new queries. - RenderPassManager *rpm = state->getRenderPass(); - OccluderRenderInst *ri = rpm->allocInst(); - ri->type = RenderPassManager::RIT_Occluder; - ri->query = flareState->occlusionQuery; - ri->query2 = flareState->fullPixelQuery; - ri->isSphere = true; - ri->position = lightPos; - if ( isVectorLight && flareState->worldRadius > 0.0f ) - ri->scale.set( flareState->worldRadius ); - else - ri->scale.set( mOcclusionRadius ); - ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() ); + if( !flareState->occlusionQuery.isWaiting() ) + { + // Setup the new queries. + RenderPassManager *rpm = state->getRenderPass(); + OccluderRenderInst *ri = rpm->allocInst(); + ri->type = RenderPassManager::RIT_Occluder; + ri->query = flareState->occlusionQuery.getQuery(); + ri->query2 = flareState->fullPixelQuery.getQuery(); + ri->isSphere = true; + ri->position = lightPos; + if ( isVectorLight && flareState->worldRadius > 0.0f ) + ri->scale.set( flareState->worldRadius ); + else + ri->scale.set( mOcclusionRadius ); + ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() ); - // Submit the queries. - state->getRenderPass()->addInst( ri ); + // Submit the queries. + state->getRenderPass()->addInst( ri ); + } } const Point3F &camPos = state->getCameraPosition(); diff --git a/Engine/source/T3D/lightFlareData.h b/Engine/source/T3D/lightFlareData.h index a450d4e56..333bf1bf5 100644 --- a/Engine/source/T3D/lightFlareData.h +++ b/Engine/source/T3D/lightFlareData.h @@ -41,12 +41,14 @@ #ifndef _GFXSTATEBLOCK_H_ #include "gfx/gfxStateBlock.h" #endif +#ifndef _GFXOCCLUSIONQUERY_H_ +#include "gfx/gfxOcclusionQuery.h" +#endif class LightInfo; struct ObjectRenderInst; class SceneRenderState; class BaseMatInstance; -class GFXOcclusionQuery; struct LightFlareState { @@ -65,8 +67,8 @@ struct LightFlareState bool visible; F32 occlusion; GFXVertexBufferHandle vertBuffer; - GFXOcclusionQuery *occlusionQuery; - GFXOcclusionQuery *fullPixelQuery; + GFXOcclusionQueryHandle occlusionQuery; + GFXOcclusionQueryHandle fullPixelQuery; }; class LightFlareData : public SimDataBlock diff --git a/Engine/source/environment/scatterSky.cpp b/Engine/source/environment/scatterSky.cpp index ed5f8d3ad..a9d187c89 100644 --- a/Engine/source/environment/scatterSky.cpp +++ b/Engine/source/environment/scatterSky.cpp @@ -658,6 +658,11 @@ void ScatterSky::prepRenderImage( SceneRenderState *state ) mFlareState.lightMat.identity(); mFlareState.lightMat.setPosition( lightPos ); + F32 dist = ( lightPos - state->getCameraPosition( ) ).len( ); + F32 coronaScale = 0.5f; + F32 screenRadius = GFX->getViewport( ).extent.y * coronaScale * 0.5f; + mFlareState.worldRadius = screenRadius * dist / state->getWorldToScreenScale( ).y; + mFlareData->prepRender( state, &mFlareState ); } diff --git a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp index 99e664652..8d36776ca 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp @@ -130,6 +130,7 @@ GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bo //If we're stalled out, proceed with worst-case scenario -BJR if(GFX->mFrameTime->getElapsedMs()>4) { + this->begin(); this->end(); return NotOccluded; } diff --git a/Engine/source/gfx/gfxOcclusionQuery.h b/Engine/source/gfx/gfxOcclusionQuery.h index 9bf87c46d..ac6b0bf07 100644 --- a/Engine/source/gfx/gfxOcclusionQuery.h +++ b/Engine/source/gfx/gfxOcclusionQuery.h @@ -82,4 +82,71 @@ public: virtual const String describeSelf() const = 0; }; +/// Handle for GFXOcclusionQuery than store last valid state +class GFXOcclusionQueryHandle +{ +public: + + GFXOcclusionQueryHandle() + : mLastStatus(GFXOcclusionQuery::Unset), mLastData(0), mQuery(NULL), mWaiting(false) + {} + + ~GFXOcclusionQueryHandle() + { + SAFE_DELETE(mQuery); + } + + bool getLastStatus( bool block, GFXOcclusionQuery::OcclusionQueryStatus *statusPtr = NULL, U32 *data = NULL ); + GFXOcclusionQuery* getQuery() const { return mQuery; } + + void clearLastStatus() + { + mLastStatus = GFXOcclusionQuery::Unset; + mLastData = 0; + mWaiting = false; + + if( !mQuery ) + return; + + mQuery->begin(); + mQuery->end(); + } + + bool isWaiting() const { return mWaiting; } +protected: + GFXOcclusionQuery::OcclusionQueryStatus mLastStatus; + U32 mLastData; + bool mWaiting; + GFXOcclusionQuery *mQuery; +}; + +inline bool GFXOcclusionQueryHandle::getLastStatus( bool block, GFXOcclusionQuery::OcclusionQueryStatus *statusPtr, U32 *data ) +{ + if( !mQuery ) + mQuery = GFX->createOcclusionQuery(); + + GFXOcclusionQuery::OcclusionQueryStatus status = mQuery->getStatus( block, data ); + + if( status == GFXOcclusionQuery::Waiting ) + { + mWaiting = true; + if( statusPtr ) + *statusPtr = mLastStatus; + if( data ) + *data = mLastData; + + return true; + } + + if( statusPtr ) + *statusPtr = status; + + mWaiting = false; + mLastStatus = status; + mLastData = *data; + + return true; +} + + #endif // _GFXOCCLUSIONQUERY_H_ \ No newline at end of file