瀏覽代碼

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

Fix ScatterSky flare occlusion
LuisAntonRebollo 10 年之前
父節點
當前提交
e5cd80ac87

+ 27 - 37
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<OccluderRenderInst>();   
-      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<OccluderRenderInst>();   
+            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();

+ 5 - 3
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<GFXVertexPCT> vertBuffer;   
-   GFXOcclusionQuery *occlusionQuery;
-   GFXOcclusionQuery *fullPixelQuery;   
+   GFXOcclusionQueryHandle occlusionQuery;
+   GFXOcclusionQueryHandle fullPixelQuery;
 };
 
 class LightFlareData : public SimDataBlock

+ 5 - 0
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 );
    }
 

+ 1 - 0
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;
           }

+ 67 - 0
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_