mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 15:44:36 +00:00
PlaneReflector Support for Side-by-Side Rendering
- The PlaneReflector class now supports side-by-side rendering. This does mean that while in this rendering style that all planar reflections are rendered twice, as reflection is a screen space effect from the eye point of view. - Planar reflections now work in the Oculus Rift. - Modified GuiTSCtrl::onRender() to move up where the rendering style is defined to just before the reflection manager has its turn.
This commit is contained in:
parent
15673810c6
commit
2fc5adb536
3 changed files with 153 additions and 72 deletions
|
|
@ -316,6 +316,21 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up the appropriate render style
|
||||||
|
U32 prevRenderStyle = GFX->getCurrentRenderStyle();
|
||||||
|
Point2F prevProjectionOffset = GFX->getCurrentProjectionOffset();
|
||||||
|
Point3F prevEyeOffset = GFX->getStereoEyeOffset();
|
||||||
|
if(mRenderStyle == RenderStyleStereoSideBySide)
|
||||||
|
{
|
||||||
|
GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide);
|
||||||
|
GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset);
|
||||||
|
GFX->setStereoEyeOffset(mLastCameraQuery.eyeOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setCurrentRenderStyle(GFXDevice::RS_Standard);
|
||||||
|
}
|
||||||
|
|
||||||
if ( mReflectPriority > 0 )
|
if ( mReflectPriority > 0 )
|
||||||
{
|
{
|
||||||
// Get the total reflection priority.
|
// Get the total reflection priority.
|
||||||
|
|
@ -338,21 +353,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||||
mLastCameraQuery.cameraMatrix.mul(rotMat);
|
mLastCameraQuery.cameraMatrix.mul(rotMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the appropriate render style
|
|
||||||
U32 prevRenderStyle = GFX->getCurrentRenderStyle();
|
|
||||||
Point2F prevProjectionOffset = GFX->getCurrentProjectionOffset();
|
|
||||||
Point3F prevEyeOffset = GFX->getStereoEyeOffset();
|
|
||||||
if(mRenderStyle == RenderStyleStereoSideBySide)
|
|
||||||
{
|
|
||||||
GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide);
|
|
||||||
GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset);
|
|
||||||
GFX->setStereoEyeOffset(mLastCameraQuery.eyeOffset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GFX->setCurrentRenderStyle(GFXDevice::RS_Standard);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up the camera and viewport stuff:
|
// set up the camera and viewport stuff:
|
||||||
F32 wwidth;
|
F32 wwidth;
|
||||||
F32 wheight;
|
F32 wheight;
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,12 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
// store current matrices
|
// store current matrices
|
||||||
GFXTransformSaver saver;
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
F32 aspectRatio = F32( params.viewportExtent.x ) / F32( params.viewportExtent.y );
|
Point2I viewport(params.viewportExtent);
|
||||||
|
if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide)
|
||||||
|
{
|
||||||
|
viewport.x *= 0.5f;
|
||||||
|
}
|
||||||
|
F32 aspectRatio = F32( viewport.x ) / F32( viewport.y );
|
||||||
|
|
||||||
Frustum frustum;
|
Frustum frustum;
|
||||||
frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane);
|
frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane);
|
||||||
|
|
@ -562,12 +567,138 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
mLastDir = params.query->cameraMatrix.getForwardVector();
|
mLastDir = params.query->cameraMatrix.getForwardVector();
|
||||||
mLastPos = params.query->cameraMatrix.getPosition();
|
mLastPos = params.query->cameraMatrix.getPosition();
|
||||||
|
|
||||||
|
setGFXMatrices( params.query->cameraMatrix );
|
||||||
|
|
||||||
|
// Adjust the detail amount
|
||||||
|
F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
|
||||||
|
TSShapeInstance::smDetailAdjust *= mDesc->detailAdjust;
|
||||||
|
|
||||||
|
|
||||||
|
if(reflectTarget.isNull())
|
||||||
|
reflectTarget = GFX->allocRenderToTextureTarget();
|
||||||
|
reflectTarget->attachTexture( GFXTextureTarget::Color0, reflectTex );
|
||||||
|
reflectTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff );
|
||||||
|
GFX->pushActiveRenderTarget();
|
||||||
|
GFX->setActiveRenderTarget( reflectTarget );
|
||||||
|
|
||||||
|
U32 objTypeFlag = -1;
|
||||||
|
SceneCameraState reflectCameraState = SceneCameraState::fromGFX();
|
||||||
|
LIGHTMGR->registerGlobalLights( &reflectCameraState.getFrustum(), false );
|
||||||
|
|
||||||
|
// Since we can sometime be rendering a reflection for 1 or 2 frames before
|
||||||
|
// it gets updated do to the lag associated with getting the results from
|
||||||
|
// a HOQ we can sometimes see into parts of the reflection texture that
|
||||||
|
// have nothing but clear color ( eg. under the water ).
|
||||||
|
// To make this look less crappy use the ambient color of the sun.
|
||||||
|
//
|
||||||
|
// In the future we may want to fix this instead by having the scatterSky
|
||||||
|
// render a skirt or something in its lower half.
|
||||||
|
//
|
||||||
|
ColorF clearColor = gClientSceneGraph->getAmbientLightColor();
|
||||||
|
GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, clearColor, 1.0f, 0 );
|
||||||
|
|
||||||
|
if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide)
|
||||||
|
{
|
||||||
|
// Store previous values
|
||||||
|
RectI originalVP = GFX->getViewport();
|
||||||
|
|
||||||
|
Point2F projOffset = GFX->getCurrentProjectionOffset();
|
||||||
|
Point3F eyeOffset = GFX->getStereoEyeOffset();
|
||||||
|
|
||||||
|
// Render left half of display
|
||||||
|
RectI leftVP = originalVP;
|
||||||
|
leftVP.extent.x *= 0.5;
|
||||||
|
GFX->setViewport(leftVP);
|
||||||
|
|
||||||
|
MatrixF leftWorldTrans(true);
|
||||||
|
leftWorldTrans.setPosition(Point3F(eyeOffset.x, eyeOffset.y, eyeOffset.z));
|
||||||
|
MatrixF leftWorld(params.query->cameraMatrix);
|
||||||
|
leftWorld.mulL(leftWorldTrans);
|
||||||
|
|
||||||
|
Frustum gfxFrustum = GFX->getFrustum();
|
||||||
|
gfxFrustum.setProjectionOffset(Point2F(projOffset.x, projOffset.y));
|
||||||
|
GFX->setFrustum(gfxFrustum);
|
||||||
|
|
||||||
|
setGFXMatrices( leftWorld );
|
||||||
|
|
||||||
|
SceneCameraState cameraStateLeft = SceneCameraState::fromGFX();
|
||||||
|
SceneRenderState renderStateLeft( gClientSceneGraph, SPT_Reflect, cameraStateLeft );
|
||||||
|
renderStateLeft.setSceneRenderStyle(SRS_SideBySide);
|
||||||
|
renderStateLeft.setSceneRenderField(0);
|
||||||
|
renderStateLeft.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
|
||||||
|
renderStateLeft.setDiffuseCameraTransform( params.query->cameraMatrix );
|
||||||
|
renderStateLeft.disableAdvancedLightingBins(true);
|
||||||
|
|
||||||
|
gClientSceneGraph->renderSceneNoLights( &renderStateLeft, objTypeFlag );
|
||||||
|
|
||||||
|
// Render right half of display
|
||||||
|
RectI rightVP = originalVP;
|
||||||
|
rightVP.extent.x *= 0.5;
|
||||||
|
rightVP.point.x += rightVP.extent.x;
|
||||||
|
GFX->setViewport(rightVP);
|
||||||
|
|
||||||
|
MatrixF rightWorldTrans(true);
|
||||||
|
rightWorldTrans.setPosition(Point3F(-eyeOffset.x, eyeOffset.y, eyeOffset.z));
|
||||||
|
MatrixF rightWorld(params.query->cameraMatrix);
|
||||||
|
rightWorld.mulL(rightWorldTrans);
|
||||||
|
|
||||||
|
gfxFrustum = GFX->getFrustum();
|
||||||
|
gfxFrustum.setProjectionOffset(Point2F(-projOffset.x, projOffset.y));
|
||||||
|
GFX->setFrustum(gfxFrustum);
|
||||||
|
|
||||||
|
setGFXMatrices( rightWorld );
|
||||||
|
|
||||||
|
SceneCameraState cameraStateRight = SceneCameraState::fromGFX();
|
||||||
|
SceneRenderState renderStateRight( gClientSceneGraph, SPT_Reflect, cameraStateRight );
|
||||||
|
renderStateRight.setSceneRenderStyle(SRS_SideBySide);
|
||||||
|
renderStateRight.setSceneRenderField(1);
|
||||||
|
renderStateRight.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
|
||||||
|
renderStateRight.setDiffuseCameraTransform( params.query->cameraMatrix );
|
||||||
|
renderStateRight.disableAdvancedLightingBins(true);
|
||||||
|
|
||||||
|
gClientSceneGraph->renderSceneNoLights( &renderStateRight, objTypeFlag );
|
||||||
|
|
||||||
|
// Restore previous values
|
||||||
|
gfxFrustum.clearProjectionOffset();
|
||||||
|
GFX->setFrustum(gfxFrustum);
|
||||||
|
GFX->setViewport(originalVP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SceneRenderState reflectRenderState
|
||||||
|
(
|
||||||
|
gClientSceneGraph,
|
||||||
|
SPT_Reflect,
|
||||||
|
SceneCameraState::fromGFX()
|
||||||
|
);
|
||||||
|
|
||||||
|
reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
|
||||||
|
reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix );
|
||||||
|
reflectRenderState.disableAdvancedLightingBins(true);
|
||||||
|
|
||||||
|
gClientSceneGraph->renderSceneNoLights( &reflectRenderState, objTypeFlag );
|
||||||
|
}
|
||||||
|
|
||||||
|
LIGHTMGR->unregisterAllLights();
|
||||||
|
|
||||||
|
// Clean up.
|
||||||
|
reflectTarget->resolve();
|
||||||
|
GFX->popActiveRenderTarget();
|
||||||
|
|
||||||
|
// Restore detail adjust amount.
|
||||||
|
TSShapeInstance::smDetailAdjust = detailAdjustBackup;
|
||||||
|
|
||||||
|
mIsRendering = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaneReflector::setGFXMatrices( const MatrixF &camTrans )
|
||||||
|
{
|
||||||
if ( objectSpace )
|
if ( objectSpace )
|
||||||
{
|
{
|
||||||
// set up camera transform relative to object
|
// set up camera transform relative to object
|
||||||
MatrixF invObjTrans = mObject->getRenderTransform();
|
MatrixF invObjTrans = mObject->getRenderTransform();
|
||||||
invObjTrans.inverse();
|
invObjTrans.inverse();
|
||||||
MatrixF relCamTrans = invObjTrans * params.query->cameraMatrix;
|
MatrixF relCamTrans = invObjTrans * camTrans;
|
||||||
|
|
||||||
MatrixF camReflectTrans = getCameraReflection( relCamTrans );
|
MatrixF camReflectTrans = getCameraReflection( relCamTrans );
|
||||||
MatrixF camTrans = mObject->getRenderTransform() * camReflectTrans;
|
MatrixF camTrans = mObject->getRenderTransform() * camReflectTrans;
|
||||||
|
|
@ -586,8 +717,6 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MatrixF camTrans = params.query->cameraMatrix;
|
|
||||||
|
|
||||||
// set world mat from new camera view
|
// set world mat from new camera view
|
||||||
MatrixF camReflectTrans = getCameraReflection( camTrans );
|
MatrixF camReflectTrans = getCameraReflection( camTrans );
|
||||||
camReflectTrans.inverse();
|
camReflectTrans.inverse();
|
||||||
|
|
@ -598,60 +727,9 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms )
|
||||||
MatrixF clipProj = getFrustumClipProj( camReflectTrans );
|
MatrixF clipProj = getFrustumClipProj( camReflectTrans );
|
||||||
GFX->setProjectionMatrix( clipProj );
|
GFX->setProjectionMatrix( clipProj );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the detail amount
|
|
||||||
F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
|
|
||||||
TSShapeInstance::smDetailAdjust *= mDesc->detailAdjust;
|
|
||||||
|
|
||||||
|
|
||||||
if(reflectTarget.isNull())
|
|
||||||
reflectTarget = GFX->allocRenderToTextureTarget();
|
|
||||||
reflectTarget->attachTexture( GFXTextureTarget::Color0, reflectTex );
|
|
||||||
reflectTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff );
|
|
||||||
GFX->pushActiveRenderTarget();
|
|
||||||
GFX->setActiveRenderTarget( reflectTarget );
|
|
||||||
|
|
||||||
SceneRenderState reflectRenderState
|
|
||||||
(
|
|
||||||
gClientSceneGraph,
|
|
||||||
SPT_Reflect,
|
|
||||||
SceneCameraState::fromGFX()
|
|
||||||
);
|
|
||||||
|
|
||||||
reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial );
|
|
||||||
reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix );
|
|
||||||
reflectRenderState.disableAdvancedLightingBins(true);
|
|
||||||
|
|
||||||
U32 objTypeFlag = -1;
|
|
||||||
LIGHTMGR->registerGlobalLights( &reflectRenderState.getFrustum(), false );
|
|
||||||
|
|
||||||
// Since we can sometime be rendering a reflection for 1 or 2 frames before
|
|
||||||
// it gets updated do to the lag associated with getting the results from
|
|
||||||
// a HOQ we can sometimes see into parts of the reflection texture that
|
|
||||||
// have nothing but clear color ( eg. under the water ).
|
|
||||||
// To make this look less crappy use the ambient color of the sun.
|
|
||||||
//
|
|
||||||
// In the future we may want to fix this instead by having the scatterSky
|
|
||||||
// render a skirt or something in its lower half.
|
|
||||||
//
|
|
||||||
ColorF clearColor = reflectRenderState.getAmbientLightColor();
|
|
||||||
GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, clearColor, 1.0f, 0 );
|
|
||||||
|
|
||||||
gClientSceneGraph->renderSceneNoLights( &reflectRenderState, objTypeFlag );
|
|
||||||
|
|
||||||
LIGHTMGR->unregisterAllLights();
|
|
||||||
|
|
||||||
// Clean up.
|
|
||||||
reflectTarget->resolve();
|
|
||||||
GFX->popActiveRenderTarget();
|
|
||||||
|
|
||||||
// Restore detail adjust amount.
|
|
||||||
TSShapeInstance::smDetailAdjust = detailAdjustBackup;
|
|
||||||
|
|
||||||
mIsRendering = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixF PlaneReflector::getCameraReflection( MatrixF &camTrans )
|
MatrixF PlaneReflector::getCameraReflection( const MatrixF &camTrans )
|
||||||
{
|
{
|
||||||
Point3F normal = refplane;
|
Point3F normal = refplane;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,8 +202,11 @@ public:
|
||||||
virtual F32 calcScore( const ReflectParams ¶ms );
|
virtual F32 calcScore( const ReflectParams ¶ms );
|
||||||
virtual void updateReflection( const ReflectParams ¶ms );
|
virtual void updateReflection( const ReflectParams ¶ms );
|
||||||
|
|
||||||
|
/// Set up the GFX matrices
|
||||||
|
void setGFXMatrices( const MatrixF &camTrans );
|
||||||
|
|
||||||
/// Set up camera matrix for a reflection on the plane
|
/// Set up camera matrix for a reflection on the plane
|
||||||
MatrixF getCameraReflection( MatrixF &camTrans );
|
MatrixF getCameraReflection( const MatrixF &camTrans );
|
||||||
|
|
||||||
/// Oblique frustum clipping - use near plane of zbuffer as a clip plane
|
/// Oblique frustum clipping - use near plane of zbuffer as a clip plane
|
||||||
MatrixF getFrustumClipProj( MatrixF &modelview );
|
MatrixF getFrustumClipProj( MatrixF &modelview );
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue