Browse Source

Basic fix for reflections in both stereo rendering modes

James Urquhart 9 years ago
parent
commit
1198932e87

+ 20 - 103
Engine/source/gui/3d/guiTSControl.cpp

@@ -353,10 +353,12 @@ static FovPort CalculateFovPortForCanvas(const RectI viewport, const CameraQuery
    return fovPort;
 }
 
-void GuiTSCtrl::_internalRender(RectI viewport, Frustum &frustum)
+void GuiTSCtrl::_internalRender(RectI guiViewport, RectI renderViewport, Frustum &frustum)
 {
    GFXTransformSaver saver;
-   Point2I renderSize = viewport.extent;
+   Point2I renderSize = renderViewport.extent;
+   GFXTarget *origTarget = GFX->getActiveRenderTarget();
+   S32 origStereoTarget = GFX->getCurrentStereoTarget();
 
    if (mForceFOV != 0)
       mLastCameraQuery.fov = mDegToRad(mForceFOV);
@@ -380,7 +382,9 @@ void GuiTSCtrl::_internalRender(RectI viewport, Frustum &frustum)
 		   mLastCameraQuery);
    }
 
-   GFX->setViewport(viewport);
+   GFX->setActiveRenderTarget(origTarget);
+   GFX->setCurrentStereoTarget(origStereoTarget);
+   GFX->setViewport(renderViewport);
 
    // Clear the zBuffer so GUI doesn't hose object rendering accidentally
    GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
@@ -410,7 +414,7 @@ void GuiTSCtrl::_internalRender(RectI viewport, Frustum &frustum)
 
    mSaveProjection = GFX->getProjectionMatrix();
    mSaveModelview = GFX->getWorldMatrix();
-   mSaveViewport = viewport;
+   mSaveViewport = guiViewport;
    mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
    mSaveFrustum = GFX->getFrustum();
    mSaveFrustum.setTransform(mLastCameraQuery.cameraMatrix);
@@ -422,7 +426,7 @@ void GuiTSCtrl::_internalRender(RectI viewport, Frustum &frustum)
    // Give the post effect manager the worldToCamera, and cameraToScreen matrices
    PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
 
-   renderWorld(viewport);
+   renderWorld(guiViewport);
 
    DebugDrawer* debugDraw = DebugDrawer::get();
    if (mRenderStyle == RenderStyleStereoSideBySide && debugDraw->willDraw())
@@ -445,97 +449,6 @@ void GuiTSCtrl::_internalRender(RectI viewport, Frustum &frustum)
 	   debugDraw->render();
    }
 
-   // Render the canvas overlay if its available
-   if (mStereoCanvas.getPointer() && mStereoGuiTarget.getPointer() && mStereoCanvas->size() != 0)
-   {
-	   GFXDEBUGEVENT_SCOPE(StereoGui_Render, ColorI(255, 0, 0));
-	   MatrixF proj(1);
-
-	   Frustum originalFrustum = frustum;
-	   GFXTextureObject *texObject = mStereoGuiTarget->getTexture(0);
-	   const FovPort *currentFovPort = GFX->getStereoFovPort();
-	   const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms();
-	   const Point3F *eyeOffset = GFX->getStereoEyeOffsets();
-	   Frustum gfxFrustum = originalFrustum;
-
-	   GFX->setClipRect(viewport);
-	   GFX->setViewport(viewport);
-	   GFX->setFrustum(frustum);
-
-	   MatrixF eyeWorldTrans(1);
-	   if (mLastCameraQuery.currentEye != -1)
-	   {
-		   eyeWorldTrans.setPosition(Point3F(eyeOffset[mLastCameraQuery.currentEye].x, eyeOffset[mLastCameraQuery.currentEye].y, eyeOffset[mLastCameraQuery.currentEye].z));
-	   }
-	   MatrixF eyeWorld(1);
-	   eyeWorld.mul(eyeWorldTrans);
-	   eyeWorld.inverse();
-
-	   GFX->setWorldMatrix(eyeWorld);
-	   GFX->setViewMatrix(MatrixF::Identity);
-
-	   if (!mStereoOverlayVB.getPointer())
-	   {
-		   mStereoOverlayVB.set(GFX, 4, GFXBufferTypeStatic);
-		   GFXVertexPCT *verts = mStereoOverlayVB.lock(0, 4);
-
-		   F32 texLeft = 0.0f;
-		   F32 texRight = 1.0f;
-		   F32 texTop = 1.0f;
-		   F32 texBottom = 0.0f;
-
-		   F32 rectRatio = gfxFrustum.getWidth() / gfxFrustum.getHeight();
-		   F32 rectWidth = gfxFrustum.getWidth() * TS_OVERLAY_SCREEN_WIDTH;
-		   F32 rectHeight = rectWidth * rectRatio;
-
-		   F32 screenLeft = -rectWidth * 0.5;
-		   F32 screenRight = rectWidth * 0.5;
-		   F32 screenTop = -rectHeight * 0.5;
-		   F32 screenBottom = rectHeight * 0.5;
-
-		   const F32 fillConv = 0.0f;
-		   const F32 frustumDepthAdjusted = gfxFrustum.getNearDist() + 0.012;
-		   verts[0].point.set(screenLeft - fillConv, frustumDepthAdjusted, screenTop - fillConv);
-		   verts[1].point.set(screenRight - fillConv, frustumDepthAdjusted, screenTop - fillConv);
-		   verts[2].point.set(screenLeft - fillConv, frustumDepthAdjusted, screenBottom - fillConv);
-		   verts[3].point.set(screenRight - fillConv, frustumDepthAdjusted, screenBottom - fillConv);
-
-		   verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255, 255, 255, 255);
-
-		   verts[0].texCoord.set(texLeft, texTop);
-		   verts[1].texCoord.set(texRight, texTop);
-		   verts[2].texCoord.set(texLeft, texBottom);
-		   verts[3].texCoord.set(texRight, texBottom);
-
-		   mStereoOverlayVB.unlock();
-	   }
-
-	   if (!mStereoGuiSB.getPointer())
-	   {
-		   // DrawBitmapStretchSR
-		   GFXStateBlockDesc bitmapStretchSR;
-		   bitmapStretchSR.setCullMode(GFXCullNone);
-		   bitmapStretchSR.setZReadWrite(false, false);
-		   bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
-		   bitmapStretchSR.samplersDefined = true;
-
-		   bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear();
-		   bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint;
-		   bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint;
-		   bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint;
-
-		   mStereoGuiSB = GFX->createStateBlock(bitmapStretchSR);
-	   }
-
-	   GFX->setPrimitiveBuffer(NULL);
-	   GFX->setVertexBuffer(mStereoOverlayVB);
-	   GFX->setStateBlock(mStereoGuiSB);
-	   GFX->setTexture(0, texObject);
-	   GFX->setupGenericShaders(GFXDevice::GSModColorTexture);
-	   GFX->drawPrimitive(GFXTriangleStrip, 0, 2);
-   }
-
-
    saver.restore();
 }
 
@@ -659,7 +572,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
       // Allow render size to originate from the render target
       if (mLastCameraQuery.stereoTargets[0])
       {
-         renderSize = mLastCameraQuery.stereoViewports[0].extent;
+         renderSize = mLastCameraQuery.stereoTargets[0]->getSize();
          renderingToTarget = true;
       }
 
@@ -667,7 +580,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
       MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]);
 
       GFX->activateStereoTarget(-1);
-      _internalRender(RectI(updateRect.point, updateRect.extent), frustum);
+      _internalRender(RectI(updateRect.point, updateRect.extent), RectI(Point2I(0,0), renderSize), frustum);
      
       // Notify device we've rendered the right, thus the last stereo frame.
       GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
@@ -726,17 +639,21 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
       frustum.update();
 	  GFX->activateStereoTarget(0);
 	  mLastCameraQuery.currentEye = 0;
-      _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
+	  GFX->beginField();
+	  _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
       GFX->getDeviceEventSignal().trigger(GFXDevice::deLeftStereoFrameRendered);
+	  GFX->endField();
 
       // Right
 	  GFX->activateStereoTarget(1);
 	  mLastCameraQuery.currentEye = 1;
       MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[1]);
       mLastCameraQuery.cameraMatrix = myTransforms[1];
-      frustum.update();
-      _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[1]->getSize()), frustum);
-      GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
+	  frustum.update();
+	  GFX->beginField();
+	  _internalRender(RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[1]->getSize()), RectI(Point2I(0, 0), mLastCameraQuery.stereoTargets[0]->getSize()), frustum);
+	  GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered);
+	  GFX->endField();
 
       mLastCameraQuery.cameraMatrix = origMatrix;
 
@@ -805,7 +722,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
       tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y);
 #endif
 
-      _internalRender(tempRect, frustum);
+      _internalRender(tempRect, tempRect, frustum);
    }
 
    // TODO: Some render to sort of overlay system?

+ 1 - 1
Engine/source/gui/3d/guiTSControl.h

@@ -123,7 +123,7 @@ public:
    GuiTSCtrl();
 
    void onPreRender();
-   void _internalRender(RectI viewport, Frustum &frustum);
+   void _internalRender(RectI guiViewport, RectI renderViewport, Frustum &frustum);
    void onRender(Point2I offset, const RectI &updateRect);
    virtual bool processCameraQuery(CameraQuery *query);
 

+ 45 - 11
Engine/source/scene/reflectionManager.cpp

@@ -95,9 +95,9 @@ ReflectionManager::ReflectionManager()
 void ReflectionManager::initConsole()
 {
    Con::addVariable( "$pref::Reflect::refractTexScale", TypeF32, &ReflectionManager::smRefractTexScale, "RefractTex has dimensions equal to the active render target scaled in both x and y by this float.\n"
-	   "@ingroup Rendering");
+      "@ingroup Rendering");
    Con::addVariable( "$pref::Reflect::frameLimitMS", TypeS32, &ReflectionManager::smFrameReflectionMS, "ReflectionManager tries not to spend more than this amount of time updating reflections per frame.\n"
-	   "@ingroup Rendering");
+      "@ingroup Rendering");
 }
 
 ReflectionManager::~ReflectionManager()
@@ -136,22 +136,49 @@ void ReflectionManager::update(  F32 timeSlice,
    // visibility of reflectors.
    Frustum culler;
 
+   // jamesu - normally we just need a frustum which covers the current ports, however for SBS mode 
+   // we need something which covers both viewports.
    S32 stereoTarget = GFX->getCurrentStereoTarget();
    if (stereoTarget != -1)
    {
-	   MathUtils::makeFovPortFrustum(&culler, false, query.nearPlane, query.farPlane, query.fovPort[stereoTarget]);
+      // In this case we're rendering in stereo using a specific eye
+      MathUtils::makeFovPortFrustum(&culler, false, query.nearPlane, query.farPlane, query.fovPort[stereoTarget], query.headMatrix);
+   }
+   else if (GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide)
+   {
+      // Calculate an ideal culling size here, we'll just assume double fov based on the first fovport based on 
+      // the head position.
+      FovPort port = query.fovPort[0];
+      F32 leftSize = query.nearPlane * port.leftTan;
+      F32 rightSize = query.nearPlane * port.rightTan;
+      F32 upSize = query.nearPlane * port.upTan;
+      F32 downSize = query.nearPlane * port.downTan;
+
+      F32 left = -leftSize;
+      F32 right = rightSize;
+      F32 top = upSize;
+      F32 bottom = -downSize;
+
+      F32 fovInRadians = mAtan2((top - bottom) / 2.0f, query.nearPlane) * 3.0f;
+
+      culler.set(false,
+         fovInRadians,
+         (F32)(query.stereoViewports[0].extent.x + query.stereoViewports[1].extent.x) / (F32)query.stereoViewports[0].extent.y,
+         query.nearPlane,
+         query.farPlane,
+         query.headMatrix);
    }
    else
    {
-	   culler.set(false,
-		   query.fov,
-		   (F32)resolution.x / (F32)resolution.y,
-		   query.nearPlane,
-		   query.farPlane,
-		   query.cameraMatrix);
+      // Normal culling
+      culler.set(false,
+         query.fov,
+         (F32)resolution.x / (F32)resolution.y,
+         query.nearPlane,
+         query.farPlane,
+         query.cameraMatrix);
    }
 
-
    // Manipulate the frustum for tiled screenshots
    const bool screenShotMode = gScreenShot && gScreenShot->isPending();
    if ( screenShotMode )
@@ -170,6 +197,7 @@ void ReflectionManager::update(  F32 timeSlice,
    refparams.viewportExtent = resolution;
    refparams.culler = culler;
    refparams.startOfUpdateMs = startOfUpdateMs;
+   refparams.eyeId = stereoTarget;
 
    // Update the reflection score.
    ReflectorList::iterator reflectorIter = mReflectors.begin();
@@ -184,6 +212,7 @@ void ReflectionManager::update(  F32 timeSlice,
    mTimer->getElapsedMs();
    mTimer->reset();
    U32 numUpdated = 0;
+   U32 currentTarget = stereoTarget >= 0 ? stereoTarget : 0;
    reflectorIter = mReflectors.begin();
    for ( ; reflectorIter != mReflectors.end(); reflectorIter++ )
    {      
@@ -193,7 +222,12 @@ void ReflectionManager::update(  F32 timeSlice,
          break;
 
       (*reflectorIter)->updateReflection( refparams );
-      (*reflectorIter)->lastUpdateMs = startOfUpdateMs;
+
+     if (stereoTarget != 0) // only update MS if we're not rendering the left eye in separate mode
+     {
+        (*reflectorIter)->lastUpdateMs = startOfUpdateMs;
+     }
+
       numUpdated++;
 
       // If we run out of update time then stop.

+ 76 - 35
Engine/source/scene/reflector.cpp

@@ -533,19 +533,28 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
    texDim = getMin( texDim, params.viewportExtent.x );
    texDim = getMin( texDim, params.viewportExtent.y );
 
-   bool texResize = ( texDim != mLastTexSize );  
-   mLastTexSize = texDim;
+   S32 currentTarget = params.eyeId >= 0 ? params.eyeId : 0;
+
+   const Point2I texSize = Point2I(texDim, texDim);
 
-   const Point2I texSize( texDim, texDim );
+   bool texResize = (texSize != mLastTexSize);
+   mLastTexSize = texSize;
 
    if (  texResize || 
-         reflectTex.isNull() ||
+         innerReflectTex[currentTarget].isNull() || 
+       innerReflectTex[currentTarget]->getSize() != texSize || 
          reflectTex->getFormat() != REFLECTMGR->getReflectFormat() )
    {
-      reflectTex = REFLECTMGR->allocRenderTarget( texSize );
-      depthBuff = LightShadowMap::_getDepthTarget( texSize.x, texSize.y );
+      innerReflectTex[currentTarget] = REFLECTMGR->allocRenderTarget( texSize );
    }
 
+   if ( texResize || depthBuff.isNull() )
+   {
+     depthBuff = LightShadowMap::_getDepthTarget(texSize.x, texSize.y);
+   }
+
+   reflectTex = innerReflectTex[currentTarget];
+
    // store current matrices
    GFXTransformSaver saver;
 
@@ -554,17 +563,17 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
    S32 stereoTarget = GFX->getCurrentStereoTarget();
    if (stereoTarget != -1)
    {
-	   MathUtils::makeFovPortFrustum(&frustum, false, params.query->nearPlane, params.query->farPlane, params.query->fovPort[stereoTarget]);
+      MathUtils::makeFovPortFrustum(&frustum, false, params.query->nearPlane, params.query->farPlane, params.query->fovPort[stereoTarget]);
    }
    else
    {
-	   Point2I viewport(params.viewportExtent);
-	   if (GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide)
-	   {
-		   viewport.x *= 0.5f;
-	   }
-	   F32 aspectRatio = F32(viewport.x) / F32(viewport.y);
-	   frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane);
+      Point2I viewport(params.viewportExtent);
+      if (GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide)
+      {
+         viewport.x *= 0.5f;
+      }
+      F32 aspectRatio = F32(viewport.x) / F32(viewport.y);
+      frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane);
    }
 
    // Manipulate the frustum for tiled screenshots
@@ -587,7 +596,7 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
 
    if(reflectTarget.isNull())
       reflectTarget = GFX->allocRenderToTextureTarget();
-   reflectTarget->attachTexture( GFXTextureTarget::Color0, reflectTex );
+   reflectTarget->attachTexture( GFXTextureTarget::Color0, innerReflectTex[currentTarget] );
    reflectTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff );
    GFX->pushActiveRenderTarget();
    GFX->setActiveRenderTarget( reflectTarget );
@@ -615,8 +624,18 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
       MatrixF origNonClipProjection = gClientSceneGraph->getNonClipProjection();
       PFXFrameState origPFXState = PFXMGR->getFrameState();
 
-      const FovPort *currentFovPort = GFX->getStereoFovPort();
-      MatrixF inverseEyeTransforms[2];
+     const FovPort *currentFovPort = params.query->fovPort;
+     MatrixF inverseEyeTransforms[2];
+     Frustum gfxFrustum;
+
+     // Calculate viewport based on texture size
+     RectI stereoViewports[2];
+     stereoViewports[0] = params.query->stereoViewports[0];
+     stereoViewports[1] = params.query->stereoViewports[1];
+     stereoViewports[0].extent.x = stereoViewports[1].extent.x = texSize.x / 2;
+     stereoViewports[0].extent.y = stereoViewports[1].extent.y = texSize.y;
+     stereoViewports[0].point.x = 0;
+     stereoViewports[1].point.x = stereoViewports[0].extent.x;
 
       // Calculate world transforms for eyes
       inverseEyeTransforms[0] = params.query->eyeTransforms[0];
@@ -624,50 +643,64 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
       inverseEyeTransforms[0].inverse();
       inverseEyeTransforms[1].inverse();
 
-      Frustum originalFrustum = GFX->getFrustum();
-
+     //
       // Render left half of display
-      GFX->activateStereoTarget(0);
-      GFX->setWorldMatrix(params.query->eyeTransforms[0]);
+      //
 
-      Frustum gfxFrustum = originalFrustum;
-      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[0], inverseEyeTransforms[0]);
+     GFX->setViewport(stereoViewports[0]);
+     GFX->setCurrentStereoTarget(0);
+      MathUtils::makeFovPortFrustum(&gfxFrustum, params.query->ortho, params.query->nearPlane, params.query->farPlane, params.query->fovPort[0]);
+     gfxFrustum.update();
       GFX->setFrustum(gfxFrustum);
 
       setGFXMatrices( params.query->eyeTransforms[0] );
 
-      SceneCameraState cameraStateLeft = SceneCameraState::fromGFX();
-      SceneRenderState renderStateLeft( gClientSceneGraph, SPT_Reflect, cameraStateLeft );
+     SceneRenderState renderStateLeft
+      (
+        gClientSceneGraph,
+        SPT_Reflect,
+        SceneCameraState::fromGFX()
+      );
+
       renderStateLeft.setSceneRenderStyle(SRS_SideBySide);
       renderStateLeft.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
-      renderStateLeft.setDiffuseCameraTransform( params.query->headMatrix );
+     renderStateLeft.setDiffuseCameraTransform(params.query->headMatrix);
+     //renderStateLeft.disableAdvancedLightingBins(true);
 
       gClientSceneGraph->renderSceneNoLights( &renderStateLeft, objTypeFlag );
 
+     //
       // Render right half of display
-      GFX->activateStereoTarget(1);
-      GFX->setWorldMatrix(params.query->eyeTransforms[1]);
+     //
 
-      gfxFrustum = originalFrustum;
-      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[1], inverseEyeTransforms[1]);
+     GFX->setViewport(stereoViewports[1]);
+     GFX->setCurrentStereoTarget(1);
+     MathUtils::makeFovPortFrustum(&gfxFrustum, params.query->ortho, params.query->nearPlane, params.query->farPlane, params.query->fovPort[1]);
+     gfxFrustum.update();
       GFX->setFrustum(gfxFrustum);
 
       setGFXMatrices( params.query->eyeTransforms[1] );
 
-      SceneCameraState cameraStateRight = SceneCameraState::fromGFX();
-      SceneRenderState renderStateRight( gClientSceneGraph, SPT_Reflect, cameraStateRight );
+     SceneRenderState renderStateRight
+     (
+        gClientSceneGraph,
+        SPT_Reflect,
+        SceneCameraState::fromGFX()
+     );
+
       renderStateRight.setSceneRenderStyle(SRS_SideBySide);
       renderStateRight.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
       renderStateRight.setDiffuseCameraTransform( params.query->headMatrix );
-      renderStateRight.disableAdvancedLightingBins(true);
+      //renderStateRight.disableAdvancedLightingBins(true);
 
       gClientSceneGraph->renderSceneNoLights( &renderStateRight, objTypeFlag );
 
       // Restore previous values
-      GFX->setFrustum(gfxFrustum);
+      GFX->setFrustum(frustum);
       GFX->setViewport(originalVP);
       gClientSceneGraph->setNonClipProjection(origNonClipProjection);
       PFXMGR->setFrameState(origPFXState);
+     GFX->setCurrentStereoTarget(-1);
    }
    else
    {
@@ -690,6 +723,14 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
    reflectTarget->resolve();
    GFX->popActiveRenderTarget();
 
+#ifdef DEBUG_REFLECT_TEX
+   static U32 reflectStage = 0;
+   char buf[128]; dSprintf(buf, 128, "F:\\REFLECT-OUT%i.PNG", reflectStage);
+   //reflectTex->dumpToDisk("PNG", buf);
+   reflectStage++;
+   if (reflectStage > 1) reflectStage = 0;
+#endif
+
    // Restore detail adjust amount.
    TSShapeInstance::smDetailAdjust = detailAdjustBackup;
 
@@ -803,7 +844,7 @@ MatrixF PlaneReflector::getFrustumClipProj( MatrixF &modelview )
    // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
    // transform it into camera space by multiplying it
    // by the inverse of the projection matrix
-   Vector4F	q;
+   Vector4F   q;
    q.x = sgn(clipPlane.x) / proj(0,0);
    q.y = sgn(clipPlane.y) / proj(1,1);
    q.z = -1.0F;

+ 6 - 3
Engine/source/scene/reflector.h

@@ -53,6 +53,7 @@ struct ReflectParams
    Point2I viewportExtent;
    Frustum culler;
    U32 startOfUpdateMs;
+   S8 eyeId;
 };
 
 
@@ -191,7 +192,7 @@ public:
    {
       refplane.set( Point3F(0,0,0), Point3F(0,0,1) );
       objectSpace = false;
-      mLastTexSize = 0;
+      mLastTexSize = Point2I(0,0);
    }
 
    virtual ~PlaneReflector() {}
@@ -213,7 +214,7 @@ public:
 
 protected:
 
-   U32 mLastTexSize;
+   Point2I mLastTexSize;
 
    // The camera position at the last update.
    Point3F mLastPos;
@@ -224,7 +225,9 @@ protected:
 public:
 
    GFXTextureTargetRef reflectTarget;
-   GFXTexHandle reflectTex;
+
+   GFXTexHandle innerReflectTex[2]; /// < Textures we actually render to
+   GFXTexHandle reflectTex; ///< Last texture we rendered to
    GFXTexHandle depthBuff;
    PlaneF refplane;
    bool objectSpace;

+ 2 - 2
Engine/source/scene/sceneManager.cpp

@@ -256,7 +256,7 @@ void SceneManager::renderScene( SceneRenderState* renderState, U32 objectMask, S
       GFX->setWorldMatrix(worldEyeTransforms[0]);
 
       Frustum gfxFrustum = originalFrustum;
-      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[0], eyeTransforms[0]);
+      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[0]);
       GFX->setFrustum(gfxFrustum);
 
       SceneCameraState cameraStateLeft = SceneCameraState::fromGFX();
@@ -277,7 +277,7 @@ void SceneManager::renderScene( SceneRenderState* renderState, U32 objectMask, S
       GFX->setWorldMatrix(worldEyeTransforms[1]);
 
       gfxFrustum = originalFrustum;
-      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[1], eyeTransforms[1]);
+      MathUtils::makeFovPortFrustum(&gfxFrustum, gfxFrustum.isOrtho(), gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[1]);
       GFX->setFrustum(gfxFrustum);
 
       SceneCameraState cameraStateRight = SceneCameraState::fromGFX();