Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed Skybox rendering for OpenVR #196

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions OgreMain/include/OgreCamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,22 @@ namespace Ogre {
struct VrData
{
Matrix4 mHeadToEye[2];
Matrix4 mEyeToHead[2];
Matrix4 mProjectionMatrix[2];
//Matrix4 mLeftToRight;
Matrix4 mProjectionMatrixInverse[2];
Vector3 mLeftToRight;

// The corners are ordered as follows: top-right far, top-left far, bottom-left far, bottom-right far.
Vector3 mWorldSpaceFarCorners[2][4];

void set( const Matrix4 eyeToHead[2], const Matrix4 projectionMatrix[2] )
{
for( int i=0; i<2; ++i )
{
mHeadToEye[i] = eyeToHead[i];
mEyeToHead[i] = eyeToHead[i];
mProjectionMatrix[i] = projectionMatrix[i];
mHeadToEye[i] = mHeadToEye[i].inverseAffine();
mProjectionMatrixInverse[i] = projectionMatrix[i].inverse();
mHeadToEye[i] = mEyeToHead[i].inverseAffine();
}
mLeftToRight = (mHeadToEye[0] * eyeToHead[1]).getTrans();
}
Expand Down Expand Up @@ -244,6 +249,8 @@ namespace Ogre {
static void setDefaultSortMode( CameraSortMode sortMode ) { msDefaultSortMode = sortMode; }
static CameraSortMode getDefaultSortMode( void ) { return msDefaultSortMode; }

/// Recalculate Vr world space corners for Sky rendering
void updateVrWorldSpaceFarCorners();
protected:
// Internal functions for calcs
bool isViewOutOfDate(void) const;
Expand Down Expand Up @@ -700,6 +707,11 @@ namespace Ogre {
bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
/// @copydoc Frustum::getWorldSpaceCorners
const Vector3* getWorldSpaceCorners(void) const;
/** Gets the 4 far world space corners of the frustum.
@remarks
The corners are ordered as follows: top-right far, top-left far, bottom-left far, bottom-right far.
*/
const Vector3* getVrWorldSpaceFarCorners(size_t eyeIdx) const;
/// @copydoc Frustum::getFrustumPlane
const Plane& getFrustumPlane( unsigned short plane ) const;
/// @copydoc Frustum::projectSphere
Expand Down
5 changes: 3 additions & 2 deletions OgreMain/include/OgreRectangle2D2.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ namespace Ogre

bool mChanged;
uint32 mGeometryFlags;
Vector3 mNormals[NumCorners];

Vector3 mNormals[NumCorners*2];
Vector2 mPosition;
Vector2 mSize;

Expand All @@ -93,6 +92,8 @@ namespace Ogre

void setNormals( const Vector3 &upperLeft, const Vector3 &bottomLeft, //
const Vector3 &upperRight, const Vector3 &bottomRight );
void setStereoNormals( const Vector3 &upperLeft, const Vector3 &bottomLeft, //
const Vector3 &upperRight, const Vector3 &bottomRight );

void setHollowRectRadius( Real radius );
Real getHollowRectRadius( void ) const { return mNormals[0].x; }
Expand Down
10 changes: 10 additions & 0 deletions OgreMain/include/OgreSceneManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ namespace Ogre {
/// For VR optimization
RadialDensityMask *mRadialDensityMask;

bool mSkyStereo{false};

// Fog
FogMode mFogMode;
ColourValue mFogColour;
Expand Down Expand Up @@ -1178,6 +1180,14 @@ namespace Ogre {
void setRadialDensityMask( bool bEnabled, const float radius[3] );
RadialDensityMask* getRadialDensityMask(void) const { return mRadialDensityMask; }

/**
* Must be used before setSky. Activates instanced stereo mode for OpenVR applications
*/
void setSkyStereoMode (bool bEnabled)
{
mSkyStereo = bEnabled;
}

/** Gets the SceneNode at the root of the scene hierarchy.
@remarks
The entire scene is held as a hierarchy of nodes, which
Expand Down
72 changes: 72 additions & 0 deletions OgreMain/src/OgreCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,73 @@ namespace Ogre {
return getProjectionMatrixWithRSDepth();
}
//-----------------------------------------------------------------------
void Camera::updateVrWorldSpaceFarCorners()
{
if( !mVrData )
{
return;
}

updateView();
Matrix4 eyeToWorld = mViewMatrix.inverseAffine();

// Note: Even though we can dealing with general projection matrix here,
// but because it's incompatibly with infinite far plane, thus, we
// still need to working with projection parameters.

// Calc near plane corners

for( size_t eyeIdx=0u; eyeIdx<2u; ++eyeIdx )
{
Real nearLeft, nearRight, nearBottom, nearTop;

Matrix4 invProj = mVrData->mProjectionMatrixInverse[eyeIdx];

Vector4 topLeft( -1.0f, 1.0f, -1.0f, 1.0f );
Vector4 topRight( 1.0f, 1.0f, -1.0f, 1.0f );
Vector4 bottomRight( 1.0f, -1.0f, -1.0f, 1.0f );
Vector4 bottomLeft( -1.0f, -1.0f, -1.0f, 1.0f );

topLeft = invProj * topLeft;
topRight = invProj * topRight;
bottomLeft = invProj * bottomLeft;
bottomRight = invProj * bottomRight;

// Rotate the view according to the HeadToEye matrix from OpenVR.
// Important for asymmetrical frustums which are present for some
// Oculus headsets and Windows Mixed Reality
Matrix4 eyeToHead= mVrData->mEyeToHead[eyeIdx];
eyeToHead.setTrans(Vector3::ZERO);

topLeft = eyeToHead * topLeft;
topRight = eyeToHead * topRight;
bottomLeft = eyeToHead * bottomLeft;
bottomRight = eyeToHead * bottomRight;

Vector4 nearTopLeft = topLeft * mNearDist;
Vector4 nearTopRight = topRight * mNearDist;
Vector4 nearBottomLeft = bottomLeft * mNearDist;
Vector4 nearBottomRight = bottomRight * mNearDist;

// Treat infinite fardist as some arbitrary far value
Real farDist = (mFarDist == 0) ? 100000 : mFarDist;

// Calc far plane corners
Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
Vector4 farTopLeft = nearTopLeft * radio;
Vector4 farTopRight = nearTopRight * radio;
Vector4 farBottomLeft = nearBottomLeft * radio;
Vector4 farBottomRight = nearBottomRight * radio;

// far
mVrData->mWorldSpaceFarCorners[eyeIdx][0] = eyeToWorld.transformAffine(Vector3(farTopRight.x, farTopRight.y, -farDist));
mVrData->mWorldSpaceFarCorners[eyeIdx][1] = eyeToWorld.transformAffine(Vector3(farTopLeft.x, farTopLeft.y, -farDist));
mVrData->mWorldSpaceFarCorners[eyeIdx][2] = eyeToWorld.transformAffine(Vector3(farBottomLeft.x, farBottomLeft.y, -farDist));
mVrData->mWorldSpaceFarCorners[eyeIdx][3] = eyeToWorld.transformAffine(Vector3(farBottomRight.x, farBottomRight.y, -farDist));
}

}
//-----------------------------------------------------------------------
bool Camera::getAutoAspectRatio(void) const
{
return mAutoAspectRatio;
Expand Down Expand Up @@ -894,6 +961,11 @@ namespace Ogre {
}
}
//-----------------------------------------------------------------------
const Vector3* Camera::getVrWorldSpaceFarCorners(size_t eyeIdx) const
{
return mVrData ? mVrData->mWorldSpaceFarCorners[eyeIdx] : nullptr;
}
//-----------------------------------------------------------------------
const Plane& Camera::getFrustumPlane( unsigned short plane ) const
{
if (mCullFrustum)
Expand Down
4 changes: 2 additions & 2 deletions OgreMain/src/OgreFrustum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ namespace Ogre {
// Treat infinite fardist as some arbitrary far value
Real farDist = (mFarDist == 0) ? 100000 : mFarDist;

// Calc far palne corners
// Calc far plane corners
Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
Real farLeft = nearLeft * radio;
Real farRight = nearRight * radio;
Expand Down Expand Up @@ -940,7 +940,7 @@ namespace Ogre {
// Treat infinite fardist as some arbitrary far value
Real farDist = (customFarPlane == 0) ? 100000 : customFarPlane;

// Calc far palne corners
// Calc far plane corners
Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
Real farLeft = nearLeft * radio;
Real farRight = nearRight * radio;
Expand Down
20 changes: 16 additions & 4 deletions OgreMain/src/OgreRectangle2D2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ namespace Ogre
if( bHasNormals )
{
for( size_t j = 0u; j < 3u; ++j )
*vertexData++ = mNormals[0][j];
*vertexData++ = mNormals[0 + 4 * i][j];
}

// Top left
Expand All @@ -250,7 +250,7 @@ namespace Ogre
if( bHasNormals )
{
for( size_t j = 0u; j < 3u; ++j )
*vertexData++ = mNormals[1][j];
*vertexData++ = mNormals[1 + 4 * i][j];
}

// Bottom right
Expand All @@ -261,7 +261,7 @@ namespace Ogre
if( bHasNormals )
{
for( size_t j = 0u; j < 3u; ++j )
*vertexData++ = mNormals[2][j];
*vertexData++ = mNormals[2 + 4 * i][j];
}

if( isQuad() )
Expand All @@ -274,7 +274,7 @@ namespace Ogre
if( bHasNormals )
{
for( size_t j = 0u; j < 3u; ++j )
*vertexData++ = mNormals[3][j];
*vertexData++ = mNormals[3 + 4 * i][j];
}
}
}
Expand Down Expand Up @@ -302,6 +302,18 @@ namespace Ogre
mNormals[CornerUpperRight] = upperRight;
mChanged = true;
}

void Rectangle2D::setStereoNormals( const Vector3 &upperLeft, const Vector3 &bottomLeft,
const Vector3 &upperRight, const Vector3 &bottomRight )
{
OGRE_ASSERT_MEDIUM( getBufferType() != BT_IMMUTABLE || mVaoPerLod[0].empty() );
OGRE_ASSERT_MEDIUM( hasNormals() || mVaoPerLod[0].empty() );
mNormals[4 + CornerBottomLeft] = bottomLeft;
mNormals[4 + CornerUpperLeft] = upperLeft;
mNormals[4 + CornerBottomRight] = bottomRight;
mNormals[4 + CornerUpperRight] = upperRight;
mChanged = true;
}
//-----------------------------------------------------------------------------------
void Rectangle2D::setHollowRectRadius( Real radius )
{
Expand Down
55 changes: 46 additions & 9 deletions OgreMain/src/OgreSceneManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,13 @@ void SceneManager::setSky( bool bEnabled, SkyMethod skyMethod, TextureGpu *textu
&mEntityMemoryManager[SCENE_STATIC], this );
// We can't use BT_DYNAMIC_* because the scene may be rendered from multiple cameras
// in the same frame, and dynamic supports only one set of values per frame
mSky->initialize( BT_DEFAULT,
Rectangle2D::GeometryFlagQuad | Rectangle2D::GeometryFlagNormals );

uint32 skyGeometryFlags=Rectangle2D::GeometryFlagQuad | Rectangle2D::GeometryFlagNormals;

if (mSkyStereo)
skyGeometryFlags|=Rectangle2D::GeometryFlagStereo;

mSky->initialize( BT_DEFAULT,skyGeometryFlags);
mSky->setGeometry( -Ogre::Vector2::UNIT_SCALE, Ogre::Vector2( 2.0f ) );
mSky->setRenderQueueGroup( 212u ); // Render after most stuff
mSceneRoot[SCENE_STATIC]->attachObject( mSky );
Expand Down Expand Up @@ -1064,6 +1069,13 @@ void SceneManager::setSky( bool bEnabled, SkyMethod skyMethod, TextureGpu *textu
tu->setTexture( texture );

mSky->setMaterial( mSkyMaterial );

GpuProgramParametersSharedPtr vsParams = pass->getVertexProgramParameters();
vsParams->setNamedConstant( "ogreBaseVertex", (float)mSky->getVaos( VpNormal )
.back()
->getBaseVertexBuffer()
->_getFinalBufferStart() );

}
else
{
Expand Down Expand Up @@ -1381,18 +1393,43 @@ void SceneManager::_renderPhase02(Camera* camera, const Camera *lodCamera,

if( mSky && mIlluminationStage != IRS_RENDER_TO_TEXTURE )
{
const Vector3 *corners = camera->getWorldSpaceCorners();
const Vector3 *corners;
const Vector3 &cameraPos = camera->getDerivedPosition();

const Real invFarPlane = 1.0f / camera->getFarClipDistance();
Vector3 cameraDirs[4];
cameraDirs[0] = ( corners[5] - cameraPos ) * invFarPlane;
cameraDirs[1] = ( corners[6] - cameraPos ) * invFarPlane;
cameraDirs[2] = ( corners[4] - cameraPos ) * invFarPlane;
cameraDirs[3] = ( corners[7] - cameraPos ) * invFarPlane;

mSky->setNormals( cameraDirs[0], cameraDirs[1], cameraDirs[2], cameraDirs[3] );
if (!mSky->isStereo())
{
corners = camera->getWorldSpaceCorners();
cameraDirs[0] = ( corners[5] - cameraPos ) * invFarPlane;
cameraDirs[1] = ( corners[6] - cameraPos ) * invFarPlane;
cameraDirs[2] = ( corners[4] - cameraPos ) * invFarPlane;
cameraDirs[3] = ( corners[7] - cameraPos ) * invFarPlane;

mSky->setNormals( cameraDirs[0], cameraDirs[1], cameraDirs[2], cameraDirs[3] );
mSky->setStereoNormals( cameraDirs[0], cameraDirs[1], cameraDirs[2], cameraDirs[3] );
}
else
{
camera->updateVrWorldSpaceFarCorners();

corners = camera->getVrWorldSpaceFarCorners(0);
cameraDirs[0] = ( corners[1] - cameraPos ) * invFarPlane;
cameraDirs[1] = ( corners[2] - cameraPos ) * invFarPlane;
cameraDirs[2] = ( corners[0] - cameraPos ) * invFarPlane;
cameraDirs[3] = ( corners[3] - cameraPos ) * invFarPlane;
mSky->setNormals( cameraDirs[0], cameraDirs[1], cameraDirs[2], cameraDirs[3] );

corners = camera->getVrWorldSpaceFarCorners(1);
cameraDirs[0] = ( corners[1] - cameraPos ) * invFarPlane;
cameraDirs[1] = ( corners[2] - cameraPos ) * invFarPlane;
cameraDirs[2] = ( corners[0] - cameraPos ) * invFarPlane;
cameraDirs[3] = ( corners[3] - cameraPos ) * invFarPlane;
mSky->setStereoNormals( cameraDirs[0], cameraDirs[1], cameraDirs[2], cameraDirs[3] );
}

mSky->update();

}

if( mRadialDensityMask && mIlluminationStage != IRS_RENDER_TO_TEXTURE &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@
#define nullptr (0)
#endif
#endif

#ifdef __MINGW32__
// For compilation on Windows with MinGW a special header must be used
#include "openvr_mingw.hpp"
#else
#include "openvr.h"
#endif


#if __cplusplus <= 199711L
#ifdef OgreDemoNullptrDefined
#undef OgreDemoNullptrDefined
Expand Down
7 changes: 7 additions & 0 deletions Samples/2.0/Tutorials/Tutorial_OpenVR/Tutorial_OpenVR.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@
#define nullptr (0)
#endif
#endif

#ifdef __MINGW32__
// For compilation on Windows with MinGW a special header must be used
#include "openvr_mingw.hpp"
#else
#include "openvr.h"
#endif

#if __cplusplus <= 199711L
#ifdef OgreDemoNullptrDefined
#undef OgreDemoNullptrDefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ namespace Demo
mCameraController = new CameraController( mGraphicsSystem, false );

TutorialGameState::createScene01();

sceneManager->setSkyStereoMode(true);
sceneManager->setSky(true, Ogre::SceneManager::SkyCubemap, "SaintPetersBasilica.dds",
Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
}
//-----------------------------------------------------------------------------------
void Tutorial_OpenVRGameState::update( float timeSinceLast )
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#version ogre_glsl_ver_330
#extension GL_ARB_shader_viewport_layer_array : require

vulkan_layout( OGRE_POSITION ) in vec2 vertex;
vulkan_layout( OGRE_NORMAL ) in vec3 normal;

in int gl_InstanceID;

vulkan( layout( ogre_P0 ) uniform Params { )
uniform float ogreBaseVertex;
uniform vec2 rsDepthRange;
uniform mat4 worldViewProj;
vulkan( }; )
Expand All @@ -22,7 +26,13 @@ out block
void main()
{
gl_Position.xy = (worldViewProj * vec4( vertex.xy, 0, 1.0f )).xy;

// TODO Move the second instance aside. There must be a way to make this more clean. But how?
gl_Position.x += 3.5f*gl_InstanceID;

gl_Position.z = rsDepthRange.y;
gl_Position.w = 1.0f;
outVs.cameraDir.xyz = normal.xyz;

gl_ViewportIndex = (gl_VertexID - ogreBaseVertex) >= 2 ? 1 : 0;
}