Merge pull request #1024 from eightyeight/scattersky-flare-fix

Fix ScatterSky flare occlusion
This commit is contained in:
LuisAntonRebollo 2014-12-19 13:35:48 +01:00
commit e5cd80ac87
5 changed files with 105 additions and 40 deletions

View file

@ -26,16 +26,18 @@
#include "core/stream/bitStream.h" #include "core/stream/bitStream.h"
#include "console/engineAPI.h" #include "console/engineAPI.h"
#include "lighting/lightInfo.h" #include "lighting/lightInfo.h"
#include "lighting/lightQuery.h"
#include "math/mathUtils.h" #include "math/mathUtils.h"
#include "math/mathIO.h" #include "math/mathIO.h"
#include "scene/sceneRenderState.h" #include "scene/sceneRenderState.h"
#include "gfx/gfxOcclusionQuery.h" #include "gfx/gfxOcclusionQuery.h"
#include "gfx/gfxDrawUtil.h" #include "gfx/gfxDrawUtil.h"
#include "gfx/gfxTextureManager.h"
#include "renderInstance/renderPassManager.h" #include "renderInstance/renderPassManager.h"
#include "T3D/gameBase/gameConnection.h" #include "T3D/gameBase/gameConnection.h"
#include "T3D/gameBase/processList.h" #include "T3D/gameBase/processList.h"
#include "collision/collision.h" #include "collision/collision.h"
#include "lighting/lightManager.h"
const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK | const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK |
ShapeBaseObjectType | ShapeBaseObjectType |
@ -45,8 +47,6 @@ const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK |
LightFlareState::~LightFlareState() LightFlareState::~LightFlareState()
{ {
delete occlusionQuery;
delete fullPixelQuery;
} }
void LightFlareState::clear() void LightFlareState::clear()
@ -59,8 +59,6 @@ void LightFlareState::clear()
lightInfo = NULL; lightInfo = NULL;
worldRadius = -1.0f; worldRadius = -1.0f;
occlusion = -1.0f; occlusion = -1.0f;
occlusionQuery = NULL;
fullPixelQuery = NULL;
} }
Point3F LightFlareData::sBasePoints[] = Point3F LightFlareData::sBasePoints[] =
@ -296,47 +294,39 @@ bool LightFlareData::_testVisibility(const SceneRenderState *state, LightFlareSt
// for one-shot initialization of LightFlareState // for one-shot initialization of LightFlareState
if ( useOcclusionQuery ) 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 // Always treat light as onscreen if using HOQ
// it will be faded out if offscreen anyway. // it will be faded out if offscreen anyway.
onScreen = true; onScreen = true;
needsRaycast = false;
// 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.
// Test the hardware queries for rendered pixels. // Test the hardware queries for rendered pixels.
U32 pixels = 0, fullPixels = 0; U32 pixels = 0, fullPixels = 0;
GFXOcclusionQuery::OcclusionQueryStatus status = flareState->occlusionQuery->getStatus( true, &pixels ); GFXOcclusionQuery::OcclusionQueryStatus status;
flareState->fullPixelQuery->getStatus( true, &fullPixels ); flareState->occlusionQuery.getLastStatus( false, &status, &pixels );
if ( status != GFXOcclusionQuery::Occluded && fullPixels != 0 ) flareState->fullPixelQuery.getLastStatus( false, NULL, &fullPixels );
if ( status == GFXOcclusionQuery::NotOccluded && fullPixels != 0 )
*outOcclusionFade = mClampF( (F32)pixels / (F32)fullPixels, 0.0f, 1.0f ); *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( !flareState->occlusionQuery.isWaiting() )
if ( status != GFXOcclusionQuery::Unset ) {
needsRaycast = false; // Setup the new queries.
RenderPassManager *rpm = state->getRenderPass();
// Setup the new queries. OccluderRenderInst *ri = rpm->allocInst<OccluderRenderInst>();
RenderPassManager *rpm = state->getRenderPass(); ri->type = RenderPassManager::RIT_Occluder;
OccluderRenderInst *ri = rpm->allocInst<OccluderRenderInst>(); ri->query = flareState->occlusionQuery.getQuery();
ri->type = RenderPassManager::RIT_Occluder; ri->query2 = flareState->fullPixelQuery.getQuery();
ri->query = flareState->occlusionQuery; ri->isSphere = true;
ri->query2 = flareState->fullPixelQuery; ri->position = lightPos;
ri->isSphere = true; if ( isVectorLight && flareState->worldRadius > 0.0f )
ri->position = lightPos; ri->scale.set( flareState->worldRadius );
if ( isVectorLight && flareState->worldRadius > 0.0f ) else
ri->scale.set( flareState->worldRadius ); ri->scale.set( mOcclusionRadius );
else ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() );
ri->scale.set( mOcclusionRadius );
ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() );
// Submit the queries. // Submit the queries.
state->getRenderPass()->addInst( ri ); state->getRenderPass()->addInst( ri );
}
} }
const Point3F &camPos = state->getCameraPosition(); const Point3F &camPos = state->getCameraPosition();

View file

@ -41,12 +41,14 @@
#ifndef _GFXSTATEBLOCK_H_ #ifndef _GFXSTATEBLOCK_H_
#include "gfx/gfxStateBlock.h" #include "gfx/gfxStateBlock.h"
#endif #endif
#ifndef _GFXOCCLUSIONQUERY_H_
#include "gfx/gfxOcclusionQuery.h"
#endif
class LightInfo; class LightInfo;
struct ObjectRenderInst; struct ObjectRenderInst;
class SceneRenderState; class SceneRenderState;
class BaseMatInstance; class BaseMatInstance;
class GFXOcclusionQuery;
struct LightFlareState struct LightFlareState
{ {
@ -65,8 +67,8 @@ struct LightFlareState
bool visible; bool visible;
F32 occlusion; F32 occlusion;
GFXVertexBufferHandle<GFXVertexPCT> vertBuffer; GFXVertexBufferHandle<GFXVertexPCT> vertBuffer;
GFXOcclusionQuery *occlusionQuery; GFXOcclusionQueryHandle occlusionQuery;
GFXOcclusionQuery *fullPixelQuery; GFXOcclusionQueryHandle fullPixelQuery;
}; };
class LightFlareData : public SimDataBlock class LightFlareData : public SimDataBlock

View file

@ -658,6 +658,11 @@ void ScatterSky::prepRenderImage( SceneRenderState *state )
mFlareState.lightMat.identity(); mFlareState.lightMat.identity();
mFlareState.lightMat.setPosition( lightPos ); 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 ); mFlareData->prepRender( state, &mFlareState );
} }

View file

@ -130,6 +130,7 @@ GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bo
//If we're stalled out, proceed with worst-case scenario -BJR //If we're stalled out, proceed with worst-case scenario -BJR
if(GFX->mFrameTime->getElapsedMs()>4) if(GFX->mFrameTime->getElapsedMs()>4)
{ {
this->begin();
this->end(); this->end();
return NotOccluded; return NotOccluded;
} }

View file

@ -82,4 +82,71 @@ public:
virtual const String describeSelf() const = 0; 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_ #endif // _GFXOCCLUSIONQUERY_H_