1
0
Fork 0

src/Viewer/splash: VR splash screen

Use a quad composition layer object from osgXR 0.3.9 to make the splash
screen VR friendly. This allows the OpenXR compositor to redraw the quad
without any updates from flightgear, which is particularly helpful as
flightgear makes no attempt at a reasonable VR frame rate during
initialisation.

The quad is positioned 2 meters from the user, with an aspect ratio
matching the desktop window. The quad is blended using an
unpremultiplied alpha channel which is forced to a given alpha value by
osgXR.

The splash is effectively already rendered to an FBO as non-linear SRGB,
so this is made explicit in the internal texture format, with the
rendering to the desktop window using GL_FRAMEBUFFER_SRGB to ensure it
is properly re-encoded.
This commit is contained in:
James Hogan 2022-06-15 23:57:33 +01:00
parent bb0d7fc0a7
commit b9efba55e7
No known key found for this signature in database
GPG key ID: 35CEE4862B1023F2
3 changed files with 52 additions and 2 deletions

View file

@ -158,7 +158,7 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
endif()
if (ENABLE_VR_DEFAULT)
find_package(osgXR 0.3.3 QUIET)
find_package(osgXR 0.3.9 QUIET)
if (osgXR_FOUND)
set(SYSTEM_OSGXR_DEFAULT 1)
endif()

View file

@ -57,6 +57,7 @@
#include <Main/util.hxx>
#include "splash.hxx"
#include "renderer.hxx"
#include "VRManager.hxx"
#include <sstream>
@ -79,6 +80,19 @@ public:
SplashScreen::SplashScreen() :
_splashAlphaNode(fgGetNode("/sim/startup/splash-alpha", true))
{
#ifdef ENABLE_OSGXR
uint32_t splashW = 1920, splashH = 1080;
float aspect = (float)splashW / splashH;
_splashSwapchain = new osgXR::Swapchain(splashW, splashH);
_splashSwapchain->setAlphaBits(8);
_splashSwapchain->allowRGBEncoding(osgXR::Swapchain::Encoding::ENCODING_SRGB);
_splashLayer = new osgXR::CompositionLayerQuad(flightgear::VRManager::instance());
_splashLayer->setSubImage(_splashSwapchain);
_splashLayer->setSize(osg::Vec2f(aspect, 1.0f));
_splashLayer->setPosition(osg::Vec3f(0, 0, -2.0f));
_splashLayer->setAlphaMode(osgXR::CompositionLayer::BLEND_ALPHA_UNPREMULT);
#endif
setName("splashGroup");
setUpdateCallback(new SplashScreenUpdateCallback);
}
@ -91,7 +105,7 @@ void SplashScreen::createNodes()
{
// setup the base geometry
_splashFBOTexture = new osg::Texture2D;
_splashFBOTexture->setInternalFormat(GL_RGB);
_splashFBOTexture->setInternalFormat(GL_SRGB8);
_splashFBOTexture->setResizeNonPowerOfTwoHint(false);
_splashFBOTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
_splashFBOTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
@ -226,6 +240,7 @@ void SplashScreen::createNodes()
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setRenderBinDetails(1000, "RenderBin");
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
stateSet->setMode(GL_FRAMEBUFFER_SRGB, osg::StateAttribute::ON);
geometry = osg::createTexturedQuadGeometry(osg::Vec3(0.0, 0.0, 0.0),
osg::Vec3(1.0, 0.0, 0.0),
@ -244,6 +259,9 @@ void SplashScreen::createNodes()
geode = new osg::Geode;
geode->addDrawable(geometry);
#ifdef ENABLE_OSGXR
_splashSwapchain->attachToMirror(stateSet);
#endif
_splashQuadCamera->addChild(geode);
addChild(_splashQuadCamera);
}
@ -325,6 +343,9 @@ osg::ref_ptr<osg::Camera> SplashScreen::createFBOCamera()
c->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
c->setRenderOrder(osg::Camera::PRE_RENDER);
c->attach(osg::Camera::COLOR_BUFFER, _splashFBOTexture);
#ifdef ENABLE_OSGXR
_splashSwapchain->attachToCamera(c);
#endif
osg::StateSet* stateSet = c->getOrCreateStateSet();
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
@ -570,11 +591,18 @@ void SplashScreen::doUpdate()
removeChild(0, getNumChildren());
_splashFBOCamera = nullptr;
_splashQuadCamera = nullptr;
#ifdef ENABLE_OSGXR
_splashLayer->setVisible(false);
#endif
} else if (getNumChildren() == 0) {
createNodes();
_splashStartTime.stamp();
resize(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
#ifdef ENABLE_OSGXR
_splashLayer->setVisible(true);
_splashSwapchain->setForcedAlpha(alpha);
#endif
} else {
(*_splashFSQuadColor)[0] = osg::Vec4(1.0, 1.0, 1.0, _splashAlphaNode->getFloatValue());
_splashFSQuadColor->dirty();
@ -603,6 +631,9 @@ void SplashScreen::doUpdate()
}
updateSplashSpinner();
updateTipText();
#ifdef ENABLE_OSGXR
_splashSwapchain->setForcedAlpha(alpha);
#endif
}
}
@ -686,6 +717,11 @@ void SplashScreen::resize( int width, int height )
_splashFBOCamera->setViewport(0, 0, width, height);
_splashFBOCamera->setProjectionMatrixAsOrtho2D(-width * 0.5, width * 0.5,
-height * 0.5, height * 0.5);
#ifdef ENABLE_OSGXR
float aspect = (float)width / height;
_splashSwapchain->setSize(width, height);
_splashLayer->setSize(osg::Vec2f(aspect, 1.0f));
#endif
const double screenAspectRatio = static_cast<double>(width) / height;

View file

@ -25,9 +25,16 @@
#ifndef _SPLASH_HXX
#define _SPLASH_HXX
#include <config.h>
#include <osg/Group>
#include <osgText/Text>
#ifdef ENABLE_OSGXR
#include <osgXR/CompositionLayerQuad>
#include <osgXR/Swapchain>
#endif
#include <simgear/props/props.hxx>
#include <simgear/timing/timestamp.hxx>
@ -117,6 +124,13 @@ private:
osg::ref_ptr<osg::Camera> _splashQuadCamera;
std::vector<ImageItem> _imageItems;
#ifdef ENABLE_OSGXR
// Splash as OpenXR composition layer
osg::ref_ptr<osgXR::Swapchain> _splashSwapchain;
osg::ref_ptr<osgXR::CompositionLayerQuad> _splashLayer;
#endif
std::vector<TextItem> _items;
SGTimeStamp _splashStartTime;