Browse Source

Includes a fix to get lights to render more correctly in the reflection pass. Also includes a helper function to force a render from a passed in transform and frustum.

Areloch 8 years ago
parent
commit
212fc80dfc

+ 192 - 0
Engine/source/T3D/gameFunctions.cpp

@@ -33,6 +33,8 @@
 #include "core/module.h"
 #include "core/module.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
 #include "platform/output/IDisplayDevice.h"
 #include "platform/output/IDisplayDevice.h"
+#include "postFx/postEffectManager.h"
+#include "gfx/gfxTransformSaver.h"
 
 
 static void RegisterGameFunctions();
 static void RegisterGameFunctions();
 static void Process3D();
 static void Process3D();
@@ -432,7 +434,197 @@ void GameRenderWorld()
    PROFILE_END();
    PROFILE_END();
 }
 }
 
 
+//================================================================================================
+//Render a full frame from a given transform and frustum, and render out to a target
+//================================================================================================
+void renderFrame(GFXTextureTargetRef* target, MatrixF transform, Frustum frustum, U32 typeMask, ColorI canvasClearColor)
+{
+   if (!GFX->allowRender() || GFX->canCurrentlyRender())
+      return;
+
+   PROFILE_START(GameFunctions_RenderFrame);
+
+   GFX->setActiveRenderTarget(*target);
+   if (!GFX->getActiveRenderTarget())
+      return;
+
+   GFXTarget* renderTarget = GFX->getActiveRenderTarget();
+   if (renderTarget == NULL)
+      return;
+
+   // Make sure the root control is the size of the canvas.
+   Point2I size = renderTarget->getSize();
+   if (size.x == 0 || size.y == 0)
+      return;
+
+   //Now, getting to the meat of it!
+#ifdef TORQUE_GFX_STATE_DEBUG
+   GFX->getDebugStateManager()->startFrame();
+#endif
+   RectI targetRect(0, 0, size.x, size.y);
+
+   // Signal the interested parties.
+   GuiCanvas::getGuiCanvasFrameSignal().trigger(true);
+
+   GFXTransformSaver saver;
+
+   // Gross hack to make sure we don't end up with advanced lighting and msaa 
+   // at the same time, which causes artifacts. At the same time we don't 
+   // want to just throw the settings the user has chosen if the light manager 
+   // changes at a later time.
+   /*GFXVideoMode mode = mPlatformWindow->getVideoMode();
+   if (dStricmp(LIGHTMGR->getId(), "ADVLM") == 0 && mode.antialiasLevel > 0)
+   {
+      const char *pref = Con::getVariable("$pref::Video::mode");
+      mode.parseFromString(pref);
+      mode.antialiasLevel = 0;
+      mPlatformWindow->setVideoMode(mode);
+
+      Con::printf("AntiAliasing has been disabled; it is not compatible with AdvancedLighting.");
+   }
+   else if (dStricmp(LIGHTMGR->getId(), "BLM") == 0)
+   {
+      const char *pref = Con::getVariable("$pref::Video::mode");
+
+      U32 prefAA = dAtoi(StringUnit::getUnit(pref, 5, " "));
+      if (prefAA != mode.antialiasLevel)
+      {
+         mode.parseFromString(pref);
+         mPlatformWindow->setVideoMode(mode);
+
+         Con::printf("AntiAliasing has been enabled while running BasicLighting.");
+      }
+   }*/
+
+   // Begin GFX
+   PROFILE_START(GameFunctions_RenderFrame_GFXBeginScene);
+   bool beginSceneRes = GFX->beginScene();
+   PROFILE_END();
+
+   PROFILE_START(GameFunctions_RenderFrame_OffscreenCanvases);
+
+   // Render all offscreen canvas objects here since we may need them in the render loop
+   if (GuiOffscreenCanvas::sList.size() != 0)
+   {
+      // Reset the entire state since oculus shit will have barfed it.
+      GFX->updateStates(true);
+
+      for (Vector<GuiOffscreenCanvas*>::iterator itr = GuiOffscreenCanvas::sList.begin(); itr != GuiOffscreenCanvas::sList.end(); itr++)
+      {
+         (*itr)->renderFrame(false, false);
+      }
+
+      GFX->setActiveRenderTarget(renderTarget);
+   }
+
+   PROFILE_END();
+
+   // Can't render if waiting for device to reset.   
+   if (!beginSceneRes)
+   {
+      // Since we already triggered the signal once for begin-of-frame,
+      // we should be consistent and trigger it again for end-of-frame.
+      GuiCanvas::getGuiCanvasFrameSignal().trigger(false);
+
+      return;
+   }
+
+   // Clear the current viewport area
+   GFX->setViewport(targetRect);
+   GFX->clear(GFXClearZBuffer | GFXClearStencil | GFXClearTarget, canvasClearColor, 1.0f, 0);
+
+   // Make sure we have a clean matrix state 
+   // before we start rendering anything!   
+   GFX->setWorldMatrix(MatrixF::Identity);
+   GFX->setViewMatrix(MatrixF::Identity);
+   GFX->setProjectionMatrix(MatrixF::Identity);
+
+   {
+      GFXStateBlockDesc d;
+
+      d.cullDefined = true;
+      d.cullMode = GFXCullNone;
+      d.zDefined = true;
+      d.zEnable = false;
+
+      GFXStateBlockRef mDefaultGuiSB = GFX->createStateBlock(d);
+
+      GFX->setClipRect(targetRect);
+      GFX->setStateBlock(mDefaultGuiSB);
+
+      GFXTargetRef origTarget = GFX->getActiveRenderTarget();
+      U32 origStyle = GFX->getCurrentRenderStyle();
+
+      // Clear the zBuffer so GUI doesn't hose object rendering accidentally
+      GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
+
+      GFX->setFrustum(frustum);
+      MatrixF mSaveProjection = GFX->getProjectionMatrix();
+      
+      // We're going to be displaying this render at size of this control in
+      // pixels - let the scene know so that it can calculate e.g. reflections
+      // correctly for that final display result.
+      gClientSceneGraph->setDisplayTargetResolution(size);
+
+      // Set the GFX world matrix to the world-to-camera transform, but don't 
+      // change the cameraMatrix in mLastCameraQuery. This is because 
+      // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
+      // transform. In-place invert would save a copy but mess up any GUIs that
+      // depend on that value.
+      CameraQuery camera;
+      GameProcessCameraQuery(&camera);
+
+      MatrixF worldToCamera = transform;
+
+      RotationF tranRot = RotationF(transform);
+      EulerF trf = tranRot.asEulerF(RotationF::Degrees);
+      Point3F pos = transform.getPosition();
+
+      GFX->setWorldMatrix(worldToCamera);
+
+      mSaveProjection = GFX->getProjectionMatrix();
+      MatrixF mSaveModelview = GFX->getWorldMatrix();
+
+      Point2F mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
+      Frustum mSaveFrustum = GFX->getFrustum();
+      mSaveFrustum.setTransform(transform);
+
+      // Set the default non-clip projection as some 
+      // objects depend on this even in non-reflect cases.
+      gClientSceneGraph->setNonClipProjection(mSaveProjection);
+
+      // Give the post effect manager the worldToCamera, and cameraToScreen matrices
+      PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
+
+      //renderWorld(guiViewport);
+      PROFILE_START(GameFunctions_RenderFrame_RenderWorld);
+      FrameAllocator::setWaterMark(0);
+
+      gClientSceneGraph->renderScene(SPT_Reflect, typeMask);
+
+      // renderScene leaves some states dirty, which causes problems if GameTSCtrl is the last Gui object rendered
+      GFX->updateStates();
+
+      AssertFatal(FrameAllocator::getWaterMark() == 0,
+         "Error, someone didn't reset the water mark on the frame allocator!");
+      FrameAllocator::setWaterMark(0);
+      PROFILE_END();
+   }
+
+   PROFILE_START(GameFunctions_RenderFrame_GFXEndScene);
+   GFX->endScene();
+   PROFILE_END();
+
+#ifdef TORQUE_GFX_STATE_DEBUG
+   GFX->getDebugStateManager()->endFrame();
+#endif
+
+   saver.restore();
+
+   PROFILE_END();
+}
 
 
+//================================================================================================
 static void Process3D()
 static void Process3D()
 {
 {
    MATMGR->updateTime();
    MATMGR->updateTime();

+ 13 - 0
Engine/source/T3D/gameFunctions.h

@@ -29,6 +29,15 @@
 #ifndef _MMATRIX_H_
 #ifndef _MMATRIX_H_
 #include "math/mMatrix.h"
 #include "math/mMatrix.h"
 #endif
 #endif
+#ifndef _GFXTARGET_H_
+#include "gfx/gfxTarget.h"
+#endif
+#ifndef _MATHUTIL_FRUSTUM_H_
+#include "math/util/frustum.h"
+#endif
+#ifndef _COLOR_H_
+#include "core/color.h"
+#endif
 
 
 struct CameraQuery;
 struct CameraQuery;
 
 
@@ -37,6 +46,10 @@ struct CameraQuery;
 /// scene ONLY - new guis, no damage flashes.
 /// scene ONLY - new guis, no damage flashes.
 void GameRenderWorld();
 void GameRenderWorld();
 
 
+/// Does a full, top-to-bottom call to render a frame. This does all the setup to make a render happen
+/// Allowing setting of a intended render target, a view transform, the view frustum, resolution, objects-to-render typemask, and the clear color
+void renderFrame(GFXTextureTargetRef* target, MatrixF transform, Frustum frustum, U32 typeMask, ColorI canvasClearColor);
+
 /// Renders overlays such as damage flashes, white outs, and water masks.  
 /// Renders overlays such as damage flashes, white outs, and water masks.  
 /// These are usually a color applied over the entire screen.
 /// These are usually a color applied over the entire screen.
 void GameRenderFilters(const CameraQuery& camq);
 void GameRenderFilters(const CameraQuery& camq);

+ 53 - 9
Engine/source/lighting/advanced/advancedLightBinManager.cpp

@@ -267,7 +267,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
    sgData.init( state );
    sgData.init( state );
 
 
    // There are cases where shadow rendering is disabled.
    // There are cases where shadow rendering is disabled.
-   const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;
+   const bool disableShadows = /*state->isReflectPass() || */ShadowMapPass::smDisableShadows;
 
 
    // Pick the right material for rendering the sunlight... we only
    // Pick the right material for rendering the sunlight... we only
    // cast shadows when its enabled and we're not in a reflection.
    // cast shadows when its enabled and we're not in a reflection.
@@ -300,6 +300,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
       GFX->setVertexBuffer( mFarFrustumQuadVerts );
       GFX->setVertexBuffer( mFarFrustumQuadVerts );
       GFX->setPrimitiveBuffer( NULL );
       GFX->setPrimitiveBuffer( NULL );
 
 
+      vectorMatInfo->matInstance->mSpecialLight = true;
+
       // Render the material passes
       // Render the material passes
       while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
       while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
       {
       {
@@ -337,6 +339,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
 
 
       lsp->getOcclusionQuery()->begin();
       lsp->getOcclusionQuery()->begin();
 
 
+      curLightMat->matInstance->mSpecialLight = false;
+
       // Render the material passes
       // Render the material passes
       while( curLightMat->matInstance->setupPass( state, sgData ) )
       while( curLightMat->matInstance->setupPass( state, sgData ) )
       {
       {
@@ -497,6 +501,17 @@ void AdvancedLightBinManager::_setupPerFrameParameters( const SceneRenderState *
                                           farPlane, 
                                           farPlane, 
                                           vsFarPlane);
                                           vsFarPlane);
    }
    }
+
+   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
+   //matrixSet.restoreSceneViewProjection();
+
+   const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
+
+   MatrixF inverseViewMatrix = worldToCameraXfm;
+   //inverseViewMatrix.fullInverse();
+   //inverseViewMatrix.transpose();
+
+   //MatrixF inverseViewMatrix = MatrixF::Identity;
 }
 }
 
 
 void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light )
 void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light )
@@ -747,6 +762,10 @@ bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgDa
          mProcessedMaterial->getNumPasses() == 0 )
          mProcessedMaterial->getNumPasses() == 0 )
       return false;
       return false;
 
 
+   U32 reflectStatus = Base;
+   if (state->isReflectPass())
+      reflectStatus = Reflecting;
+
    // Fetch the lightmap params
    // Fetch the lightmap params
    const LightMapParams *lmParams = sgData.lights[0]->getExtended<LightMapParams>();
    const LightMapParams *lmParams = sgData.lights[0]->getExtended<LightMapParams>();
    
    
@@ -795,14 +814,21 @@ bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgDa
    {
    {
       // If this is not an internal pass, and this light is represented in lightmaps
       // If this is not an internal pass, and this light is represented in lightmaps
       // than only effect non-lightmapped geometry for this pass
       // than only effect non-lightmapped geometry for this pass
-      if(lmParams->representedInLightmap)
-         GFX->setStateBlock(mLitState[StaticLightNonLMGeometry]);
+      if (lmParams->representedInLightmap)
+      {
+         GFX->setStateBlock(mLitState[StaticLightNonLMGeometry][reflectStatus]);
+      }
       else // This is a normal, dynamic light.
       else // This is a normal, dynamic light.
-         GFX->setStateBlock(mLitState[DynamicLight]);
-      
+      {
+         if (mSpecialLight)
+            GFX->setStateBlock(mLitState[SunLight][reflectStatus]);
+         else
+            GFX->setStateBlock(mLitState[DynamicLight][reflectStatus]);
+      }
+
    }
    }
    else // Internal pass, this is the add-specular/multiply-darken-color pass
    else // Internal pass, this is the add-specular/multiply-darken-color pass
-      GFX->setStateBlock(mLitState[StaticLightLMGeometry]);
+      GFX->setStateBlock(mLitState[StaticLightLMGeometry][reflectStatus]);
 
 
    return bRetVal;
    return bRetVal;
 }
 }
@@ -832,17 +858,32 @@ bool LightMatInstance::init( const FeatureSet &features, const GFXVertexFormat *
 
 
    //DynamicLight State: This will effect lightmapped and non-lightmapped geometry
    //DynamicLight State: This will effect lightmapped and non-lightmapped geometry
    // in the same way.
    // in the same way.
+
+   litState.separateAlphaBlendDefined = true;
+   litState.separateAlphaBlendEnable = false;
+   litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask | RenderDeferredMgr::OpaqueStaticLitMask;
+   litState.setCullMode(GFXCullCW);
+   mLitState[DynamicLight][Base] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCCW);
+   mLitState[DynamicLight][Reflecting] = GFX->createStateBlock(litState);
+
    litState.separateAlphaBlendDefined = true;
    litState.separateAlphaBlendDefined = true;
    litState.separateAlphaBlendEnable = false;
    litState.separateAlphaBlendEnable = false;
    litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask | RenderDeferredMgr::OpaqueStaticLitMask;
    litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask | RenderDeferredMgr::OpaqueStaticLitMask;
-   mLitState[DynamicLight] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCCW);
+   mLitState[SunLight][Base] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCCW);
+   mLitState[SunLight][Reflecting] = GFX->createStateBlock(litState);
 
 
    // StaticLightNonLMGeometry State: This will treat non-lightmapped geometry
    // StaticLightNonLMGeometry State: This will treat non-lightmapped geometry
    // in the usual way, but will not effect lightmapped geometry.
    // in the usual way, but will not effect lightmapped geometry.
    litState.separateAlphaBlendDefined = true;
    litState.separateAlphaBlendDefined = true;
    litState.separateAlphaBlendEnable = false;
    litState.separateAlphaBlendEnable = false;
    litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask;
    litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask;
-   mLitState[StaticLightNonLMGeometry] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCW);
+   mLitState[StaticLightNonLMGeometry][Base] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCCW);
+   mLitState[StaticLightNonLMGeometry][Reflecting] = GFX->createStateBlock(litState);
 
 
    // StaticLightLMGeometry State: This will add specular information (alpha) but
    // StaticLightLMGeometry State: This will add specular information (alpha) but
    // multiply-darken color information. 
    // multiply-darken color information. 
@@ -854,7 +895,10 @@ bool LightMatInstance::init( const FeatureSet &features, const GFXVertexFormat *
    litState.separateAlphaBlendSrc = GFXBlendOne;
    litState.separateAlphaBlendSrc = GFXBlendOne;
    litState.separateAlphaBlendDest = GFXBlendOne;
    litState.separateAlphaBlendDest = GFXBlendOne;
    litState.separateAlphaBlendOp = GFXBlendOpAdd;
    litState.separateAlphaBlendOp = GFXBlendOpAdd;
-   mLitState[StaticLightLMGeometry] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCW);
+   mLitState[StaticLightLMGeometry][Base] = GFX->createStateBlock(litState);
+   litState.setCullMode(GFXCullCCW);
+   mLitState[StaticLightLMGeometry][Reflecting] = GFX->createStateBlock(litState);
 
 
    return true;
    return true;
 }
 }

+ 7 - 3
Engine/source/lighting/advanced/advancedLightBinManager.h

@@ -60,19 +60,23 @@ protected:
    enum
    enum
    {
    {
       DynamicLight = 0,
       DynamicLight = 0,
+      SunLight,
       StaticLightNonLMGeometry,
       StaticLightNonLMGeometry,
       StaticLightLMGeometry,
       StaticLightLMGeometry,
-      NUM_LIT_STATES
+      NUM_LIT_STATES,
+      Base = 0,
+      Reflecting = 1
    };
    };
-   GFXStateBlockRef mLitState[NUM_LIT_STATES];
+   GFXStateBlockRef mLitState[NUM_LIT_STATES][2];
 
 
 public:
 public:
    LightMatInstance(Material &mat) : Parent(mat), mLightMapParamsSC(NULL), mInternalPass(false) {}
    LightMatInstance(Material &mat) : Parent(mat), mLightMapParamsSC(NULL), mInternalPass(false) {}
 
 
    virtual bool init( const FeatureSet &features, const GFXVertexFormat *vertexFormat );
    virtual bool init( const FeatureSet &features, const GFXVertexFormat *vertexFormat );
    virtual bool setupPass( SceneRenderState *state, const SceneData &sgData );
    virtual bool setupPass( SceneRenderState *state, const SceneData &sgData );
-};
 
 
+   bool mSpecialLight;
+};
 
 
 class AdvancedLightBinManager : public RenderTexTargetBinManager
 class AdvancedLightBinManager : public RenderTexTargetBinManager
 {
 {