Skip to content

Commit

Permalink
Merge pull request #1330 from jamesu/stereo_render_fix
Browse files Browse the repository at this point in the history
Basic fix for stereo rendering without a display device
  • Loading branch information
crabmusket committed Jul 2, 2015
2 parents f0333aa + a691278 commit 6b9e5dd
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 30 deletions.
15 changes: 14 additions & 1 deletion Engine/source/T3D/gameFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,13 @@ bool GameProcessCameraQuery(CameraQuery *query)

// Provide some default values
query->projectionOffset = Point2F::Zero;

query->stereoTargets[0] = 0;
query->stereoTargets[1] = 0;
query->eyeOffset[0] = Point3F::Zero;
query->eyeOffset[1] = Point3F::Zero;
query->hasFovPort = false;
query->hasStereoTargets = false;

F32 cameraFov = 0.0f;
bool fovSet = false;

Expand Down Expand Up @@ -383,13 +389,20 @@ bool GameProcessCameraQuery(CameraQuery *query)
{
display->getFovPorts(query->fovPort);
fovSet = true;
query->hasFovPort = true;
}

// Grab the latest overriding render view transforms
connection->getControlCameraEyeTransforms(display, query->eyeTransforms);

display->getStereoViewports(query->stereoViewports);
display->getStereoTargets(query->stereoTargets);
query->hasStereoTargets = true;
}
else
{
query->eyeTransforms[0] = query->cameraMatrix;
query->eyeTransforms[1] = query->cameraMatrix;
}

// Use the connection's FOV settings if requried
Expand Down
4 changes: 2 additions & 2 deletions Engine/source/gfx/gfxDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,10 @@ class GFXDevice
void setStereoEyeTransforms(MatrixF *transforms) { dMemcpy(mStereoEyeTransforms, transforms, sizeof(mStereoEyeTransforms)); dMemcpy(mInverseStereoEyeTransforms, transforms, sizeof(mInverseStereoEyeTransforms)); mInverseStereoEyeTransforms[0].inverse(); mInverseStereoEyeTransforms[1].inverse(); }

/// Set the current eye offset used during stereo rendering. Assumes NumStereoPorts are available.
void setFovPort(const FovPort *ports) { dMemcpy(mFovPorts, ports, sizeof(mFovPorts)); }
void setStereoFovPort(const FovPort *ports) { dMemcpy(mFovPorts, ports, sizeof(mFovPorts)); }

/// Get the current eye offset used during stereo rendering
const FovPort* getSteroFovPort() { return mFovPorts; }
const FovPort* getStereoFovPort() { return mFovPorts; }

/// Sets stereo viewports
void setSteroViewports(const RectI *ports) { dMemcpy(mStereoViewports, ports, sizeof(RectI) * NumStereoPorts); }
Expand Down
110 changes: 85 additions & 25 deletions Engine/source/gui/3d/guiTSControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ GuiTSCtrl::GuiTSCtrl()
mLastCameraQuery.nearPlane = 0.01f;

mLastCameraQuery.projectionOffset = Point2F::Zero;
mLastCameraQuery.hasFovPort = false;
mLastCameraQuery.hasStereoTargets = false;

mLastCameraQuery.ortho = false;
}
Expand Down Expand Up @@ -312,6 +314,46 @@ F32 GuiTSCtrl::calculateViewDistance(F32 radius)

//-----------------------------------------------------------------------------

static FovPort CalculateFovPortForCanvas(const RectI viewport, const CameraQuery &cameraQuery)
{
F32 wwidth;
F32 wheight;
F32 renderWidth = viewport.extent.x;
F32 renderHeight = viewport.extent.y;
F32 aspectRatio = renderWidth / renderHeight;

// Use the FOV to calculate the viewport height scale
// then generate the width scale from the aspect ratio.
if(!cameraQuery.ortho)
{
wheight = /*cameraQuery.nearPlane * */ mTan(cameraQuery.fov / 2.0f);
wwidth = aspectRatio * wheight;
}
else
{
wheight = cameraQuery.fov;
wwidth = aspectRatio * wheight;
}

F32 hscale = wwidth * 2.0f / renderWidth;
F32 vscale = wheight * 2.0f / renderHeight;

F32 left = 0.0f * hscale - wwidth;
F32 right = renderWidth * hscale - wwidth;
F32 top = wheight - vscale * 0.0f;
F32 bottom = wheight - vscale * renderHeight;

FovPort fovPort;
fovPort.upTan = top;
fovPort.downTan = -bottom;
fovPort.leftTan = -left;
fovPort.rightTan = right;

return fovPort;
}

//-----------------------------------------------------------------------------

void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
{
// Save the current transforms so we can restore
Expand Down Expand Up @@ -340,7 +382,25 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide);
GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset);
GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset);
GFX->setFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes

if (!mLastCameraQuery.hasStereoTargets)
{
// Need to calculate our current viewport here
mLastCameraQuery.stereoViewports[0] = updateRect;
mLastCameraQuery.stereoViewports[0].extent.x /= 2;
mLastCameraQuery.stereoViewports[1] = mLastCameraQuery.stereoViewports[0];
mLastCameraQuery.stereoViewports[1].point.x += mLastCameraQuery.stereoViewports[1].extent.x;
}

if (!mLastCameraQuery.hasFovPort)
{
// Need to make our own fovPort
mLastCameraQuery.fovPort[0] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[0], mLastCameraQuery);
mLastCameraQuery.fovPort[1] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[1], mLastCameraQuery);
}

GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes

GFX->setSteroViewports(mLastCameraQuery.stereoViewports);
GFX->setStereoTargets(mLastCameraQuery.stereoTargets);

Expand Down Expand Up @@ -402,29 +462,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
mLastCameraQuery.cameraMatrix.mul(rotMat);
}

// set up the camera and viewport stuff:
F32 wwidth;
F32 wheight;
F32 renderWidth = F32(renderSize.x);
F32 renderHeight = F32(renderSize.y);
F32 aspectRatio = renderWidth / renderHeight;

// Use the FOV to calculate the viewport height scale
// then generate the width scale from the aspect ratio.
if(!mLastCameraQuery.ortho)
{
wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f);
wwidth = aspectRatio * wheight;
}
else
{
wheight = mLastCameraQuery.fov;
wwidth = aspectRatio * wheight;
}

F32 hscale = wwidth * 2.0f / renderWidth;
F32 vscale = wheight * 2.0f / renderHeight;

Frustum frustum;
if(mRenderStyle == RenderStyleStereoSideBySide)
{
Expand All @@ -433,6 +470,29 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
}
else
{
// set up the camera and viewport stuff:
F32 wwidth;
F32 wheight;
F32 renderWidth = F32(renderSize.x);
F32 renderHeight = F32(renderSize.y);
F32 aspectRatio = renderWidth / renderHeight;

// Use the FOV to calculate the viewport height scale
// then generate the width scale from the aspect ratio.
if(!mLastCameraQuery.ortho)
{
wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f);
wwidth = aspectRatio * wheight;
}
else
{
wheight = mLastCameraQuery.fov;
wwidth = aspectRatio * wheight;
}

F32 hscale = wwidth * 2.0f / renderWidth;
F32 vscale = wheight * 2.0f / renderHeight;

F32 left = (updateRect.point.x - offset.x) * hscale - wwidth;
F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth;
F32 top = wheight - vscale * (updateRect.point.y - offset.y);
Expand Down Expand Up @@ -516,7 +576,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)

Frustum originalFrustum = GFX->getFrustum();
GFXTextureObject *texObject = mStereoGuiTarget->getTexture(0);
const FovPort *currentFovPort = GFX->getSteroFovPort();
const FovPort *currentFovPort = GFX->getStereoFovPort();
const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms();
const MatrixF *worldEyeTransforms = GFX->getInverseStereoEyeTransforms();
const Point3F *eyeOffset = GFX->getStereoEyeOffsets();
Expand Down
2 changes: 2 additions & 0 deletions Engine/source/gui/3d/guiTSControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct CameraQuery
Point3F eyeOffset[2];
MatrixF eyeTransforms[2];
bool ortho;
bool hasFovPort;
bool hasStereoTargets;
MatrixF cameraMatrix;
RectI stereoViewports[2]; // destination viewports
GFXTextureTarget* stereoTargets[2];
Expand Down
2 changes: 1 addition & 1 deletion Engine/source/scene/reflector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ void PlaneReflector::updateReflection( const ReflectParams &params )
RectI originalVP = GFX->getViewport();

Point2F projOffset = GFX->getCurrentProjectionOffset();
const FovPort *currentFovPort = GFX->getSteroFovPort();
const FovPort *currentFovPort = GFX->getStereoFovPort();
MatrixF inverseEyeTransforms[2];

// Calculate world transforms for eyes
Expand Down
2 changes: 1 addition & 1 deletion Engine/source/scene/sceneManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ void SceneManager::renderScene( SceneRenderState* renderState, U32 objectMask, S
Frustum originalFrustum = GFX->getFrustum();

Point2F projOffset = GFX->getCurrentProjectionOffset();
const FovPort *currentFovPort = GFX->getSteroFovPort();
const FovPort *currentFovPort = GFX->getStereoFovPort();
const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms();
const MatrixF *worldEyeTransforms = GFX->getInverseStereoEyeTransforms();

Expand Down

0 comments on commit 6b9e5dd

Please sign in to comment.