Project GUI into space

This commit is contained in:
kaetemi 2014-08-01 15:44:12 +02:00
parent 6de844b43c
commit 9e23a689ae
4 changed files with 215 additions and 56 deletions

View file

@ -53,6 +53,9 @@ public:
/// Get the HMD orientation /// Get the HMD orientation
virtual NLMISC::CQuat getOrientation() const = 0; virtual NLMISC::CQuat getOrientation() const = 0;
/// Set the GUI reference
virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix) = 0;
/// Get GUI center (1 = width, 1 = height, 0 = center) /// Get GUI center (1 = width, 1 = height, 0 = center)
virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const = 0; virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const = 0;

View file

@ -123,6 +123,9 @@ public:
/// Get the HMD orientation /// Get the HMD orientation
virtual NLMISC::CQuat getOrientation() const; virtual NLMISC::CQuat getOrientation() const;
/// Set the GUI reference
virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix);
/// Get GUI center (1 = width, 1 = height, 0 = center) /// Get GUI center (1 = width, 1 = height, 0 = center)
virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const; virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const;
@ -134,21 +137,23 @@ public:
/// Set the scale of the game in units per meter /// Set the scale of the game in units per meter
virtual void setScale(float s); virtual void setScale(float s);
/// Calculates internal camera information based on the reference camera
void initCamera(uint cid, const NL3D::UCamera *camera);
/// Render GUI
void renderGUI();
/// Checks if the device used by this class was actually created
bool isDeviceCreated();
static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut); static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut);
static bool isLibraryInUse(); static bool isLibraryInUse();
static void releaseLibrary(); static void releaseLibrary();
/// Calculates internal camera information based on the reference camera
void initCamera(uint cid, const NL3D::UCamera *camera);
/// Checks if the device used by this class was actually created
bool isDeviceCreated();
private: private:
CStereoOVRDevicePtr *m_DevicePtr; CStereoOVRDevicePtr *m_DevicePtr;
int m_Stage; int m_Stage;
int m_SubStage; int m_SubStage;
CViewport m_RegularViewport;
CViewport m_LeftViewport; CViewport m_LeftViewport;
CViewport m_RightViewport; CViewport m_RightViewport;
CFrustum m_ClippingFrustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_ClippingFrustum[NL_STEREO_MAX_USER_CAMERAS];
@ -156,12 +161,13 @@ private:
CFrustum m_RightFrustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_RightFrustum[NL_STEREO_MAX_USER_CAMERAS];
CFrustum m_OriginalFrustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_OriginalFrustum[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_InterfaceCameraMatrix;
mutable bool m_OrientationCached; mutable bool m_OrientationCached;
mutable NLMISC::CQuat m_OrientationCache; mutable NLMISC::CQuat m_OrientationCache;
UDriver *m_Driver; UDriver *m_Driver;
NLMISC::CSmartPtr<NL3D::ITexture> m_BarrelTex; NL3D::CTextureUser *m_SceneTexture;
NL3D::CTextureUser *m_BarrelTexU;
NL3D::UMaterial m_BarrelMat; NL3D::UMaterial m_BarrelMat;
NL3D::CTextureUser *m_GUITexture;
NLMISC::CQuadUV m_BarrelQuadLeft; NLMISC::CQuadUV m_BarrelQuadLeft;
NLMISC::CQuadUV m_BarrelQuadRight; NLMISC::CQuadUV m_BarrelQuadRight;
NLMISC::CRefPtr<CPixelProgramOVR> m_PixelProgram; NLMISC::CRefPtr<CPixelProgramOVR> m_PixelProgram;

View file

@ -169,7 +169,7 @@ public:
OVR::HMDInfo HMDInfo; OVR::HMDInfo HMDInfo;
}; };
CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_BarrelTexU(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f) CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f)
{ {
++s_DeviceCounter; ++s_DeviceCounter;
m_DevicePtr = new CStereoOVRDevicePtr(); m_DevicePtr = new CStereoOVRDevicePtr();
@ -213,9 +213,6 @@ CStereoOVR::~CStereoOVR()
m_BarrelMat.getObjectPtr()->setTexture(0, NULL); m_BarrelMat.getObjectPtr()->setTexture(0, NULL);
m_Driver->deleteMaterial(m_BarrelMat); m_Driver->deleteMaterial(m_BarrelMat);
} }
delete m_BarrelTexU;
m_BarrelTexU = NULL;
m_BarrelTex = NULL; // CSmartPtr
delete m_PixelProgram; delete m_PixelProgram;
m_PixelProgram = NULL; m_PixelProgram = NULL;
@ -340,7 +337,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
{ {
m_Driver = driver; m_Driver = driver;
m_BarrelTex = new CTextureBloom(); // lol bloom /*m_BarrelTex = new CTextureBloom(); // lol bloom
m_BarrelTex->setRenderTarget(true); m_BarrelTex->setRenderTarget(true);
m_BarrelTex->setReleasable(false); m_BarrelTex->setReleasable(false);
m_BarrelTex->resize(m_DevicePtr->HMDInfo.HResolution, m_DevicePtr->HMDInfo.VResolution); m_BarrelTex->resize(m_DevicePtr->HMDInfo.HResolution, m_DevicePtr->HMDInfo.VResolution);
@ -348,7 +345,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
m_BarrelTex->setWrapS(ITexture::Clamp); m_BarrelTex->setWrapS(ITexture::Clamp);
m_BarrelTex->setWrapT(ITexture::Clamp); m_BarrelTex->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*m_BarrelTex); drvInternal->setupTexture(*m_BarrelTex);
m_BarrelTexU = new CTextureUser(m_BarrelTex); m_BarrelTexU = new CTextureUser(m_BarrelTex);*/
m_BarrelMat = m_Driver->createMaterial(); m_BarrelMat = m_Driver->createMaterial();
m_BarrelMat.initUnlit(); m_BarrelMat.initUnlit();
@ -361,7 +358,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
barrelMat->setZWrite(false); barrelMat->setZWrite(false);
barrelMat->setZFunc(CMaterial::always); barrelMat->setZFunc(CMaterial::always);
barrelMat->setDoubleSided(true); barrelMat->setDoubleSided(true);
barrelMat->setTexture(0, m_BarrelTex); // barrelMat->setTexture(0, m_BarrelTex);
m_BarrelQuadLeft.V0 = CVector(0.f, 0.f, 0.5f); m_BarrelQuadLeft.V0 = CVector(0.f, 0.f, 0.5f);
m_BarrelQuadLeft.V1 = CVector(0.5f, 0.f, 0.5f); m_BarrelQuadLeft.V1 = CVector(0.5f, 0.f, 0.5f);
@ -373,7 +370,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
m_BarrelQuadRight.V2 = CVector(1.f, 1.f, 0.5f); m_BarrelQuadRight.V2 = CVector(1.f, 1.f, 0.5f);
m_BarrelQuadRight.V3 = CVector(0.5f, 1.f, 0.5f); m_BarrelQuadRight.V3 = CVector(0.5f, 1.f, 0.5f);
nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed // nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed
m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f); m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f);
m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f); m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f);
@ -448,53 +445,59 @@ bool CStereoOVR::nextPass()
// Do not allow weird stuff. // Do not allow weird stuff.
uint32 width, height; uint32 width, height;
m_Driver->getWindowSize(width, height); m_Driver->getWindowSize(width, height);
nlassert(width == m_DevicePtr->HMDInfo.HResolution); // nlassert(width == m_DevicePtr->HMDInfo.HResolution);
nlassert(height == m_DevicePtr->HMDInfo.VResolution); // nlassert(height == m_DevicePtr->HMDInfo.VResolution);
if (m_Driver->getPolygonMode() == UDriver::Filled) if (m_Driver->getPolygonMode() == UDriver::Filled)
{ {
switch (m_Stage) switch (m_Stage) // Previous stage
{ {
case 0: case 0:
++m_Stage; m_Stage += 2;
m_SubStage = 0;
// stage 1:
// (initBloom)
// clear buffer
// draw scene left
return true;
case 1:
++m_Stage;
m_SubStage = 0; m_SubStage = 0;
// stage 2: // stage 2:
// draw scene right // draw interface 2d (onto render target)
return true; return true;
case 2: case 2:
++m_Stage; ++m_Stage;
m_SubStage = 0; m_SubStage = 0;
// stage 3: // stage 3:
// (endBloom) // (initBloom)
// draw interface 3d left // clear buffer
// draw scene left
return true; return true;
case 3: case 3:
++m_Stage; ++m_Stage;
m_SubStage = 0; m_SubStage = 0;
// stage 4: // stage 4:
// draw interface 3d right // draw scene right
return true; return true;
case 4: case 4:
++m_Stage; ++m_Stage;
m_SubStage = 0; m_SubStage = 0;
// stage 5: // stage 5:
// (endInterfacesDisplayBloom) // (endBloom)
// draw interface 2d left // draw interface 3d left
return true; return true;
case 5: case 5:
++m_Stage; ++m_Stage;
m_SubStage = 0; m_SubStage = 0;
// stage 6: // stage 6:
// draw interface 2d right // draw interface 3d right
return true; return true;
/*case 6:
++m_Stage;
m_SubStage = 0;
// stage 7:
// (endInterfacesDisplayBloom)
// draw interface 2d left
return true;
case 7:
++m_Stage;
m_SubStage = 0;
// stage 8:
// draw interface 2d right
return true;*/
case 6: case 6:
m_Stage = 0; m_Stage = 0;
m_SubStage = 0; m_SubStage = 0;
@ -526,26 +529,30 @@ bool CStereoOVR::nextPass()
const NL3D::CViewport &CStereoOVR::getCurrentViewport() const const NL3D::CViewport &CStereoOVR::getCurrentViewport() const
{ {
if (m_Stage % 2) return m_LeftViewport; if (m_Stage == 2) return m_RegularViewport;
else if (m_Stage % 2) return m_LeftViewport;
else return m_RightViewport; else return m_RightViewport;
} }
const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const
{ {
if (m_Stage % 2) return m_LeftFrustum[cid]; if (m_Stage == 2) return m_OriginalFrustum[cid];
else if (m_Stage % 2) return m_LeftFrustum[cid];
else return m_RightFrustum[cid]; else return m_RightFrustum[cid];
} }
void CStereoOVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const void CStereoOVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const
{ {
if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]); if (m_Stage == 2) camera->setFrustum(m_OriginalFrustum[cid]);
else if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]);
else camera->setFrustum(m_RightFrustum[cid]); else camera->setFrustum(m_RightFrustum[cid]);
} }
void CStereoOVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const void CStereoOVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const
{ {
CMatrix translate; CMatrix translate;
if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f)); if (m_Stage == 2) { }
else if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f));
else translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f)); else translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f));
CMatrix mat = m_CameraMatrix[cid] * translate; CMatrix mat = m_CameraMatrix[cid] * translate;
if (camera->getTransformMode() == NL3D::UTransformable::RotQuat) if (camera->getTransformMode() == NL3D::UTransformable::RotQuat)
@ -564,7 +571,7 @@ bool CStereoOVR::wantClear()
{ {
switch (m_Stage) switch (m_Stage)
{ {
case 1: case 3:
m_SubStage = 1; m_SubStage = 1;
return true; return true;
} }
@ -575,8 +582,8 @@ bool CStereoOVR::wantScene()
{ {
switch (m_Stage) switch (m_Stage)
{ {
case 1: case 3:
case 2: case 4:
m_SubStage = 2; m_SubStage = 2;
return true; return true;
} }
@ -587,8 +594,8 @@ bool CStereoOVR::wantInterface3D()
{ {
switch (m_Stage) switch (m_Stage)
{ {
case 3: case 5:
case 4: case 6:
m_SubStage = 3; m_SubStage = 3;
return true; return true;
} }
@ -599,37 +606,163 @@ bool CStereoOVR::wantInterface2D()
{ {
switch (m_Stage) switch (m_Stage)
{ {
case 5: case 2:
case 6:
m_SubStage = 4; m_SubStage = 4;
return true; return true;
} }
return m_Driver->getPolygonMode() != UDriver::Filled; return m_Driver->getPolygonMode() != UDriver::Filled;
} }
/// Returns non-NULL if a new render target was set /// Returns non-NULL if a new render target was set
bool CStereoOVR::beginRenderTarget() bool CStereoOVR::beginRenderTarget()
{ {
// render target always set before driver clear // render target always set before driver clear
// nlassert(m_SubStage <= 1); // nlassert(m_SubStage <= 1);
if (m_Driver && m_Stage == 1 && (m_Driver->getPolygonMode() == UDriver::Filled))
// Set GUI render target
if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled))
{ {
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0); nlassert(!m_GUITexture);
uint32 width, height;
m_Driver->getWindowSize(width, height);
m_GUITexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height, true, UTexture::RGBA8888);
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_GUITexture);
m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 0, 0));
return true; return true;
} }
// Begin 3D scene render target
if (m_Driver && m_Stage == 3 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
nlassert(!m_SceneTexture);
uint32 width, height;
m_Driver->getWindowSize(width, height); // Temporary limitation, TODO: scaling!
m_SceneTexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_SceneTexture);
return true;
}
return false; return false;
} }
void CStereoOVR::setInterfaceMatrix(const NL3D::CMatrix &matrix)
{
m_InterfaceCameraMatrix = matrix;
}
void CStereoOVR::renderGUI()
{
/*CMatrix mat;
mat.translate(m_InterfaceCameraMatrix.getPos());
CVector dir = m_InterfaceCameraMatrix.getJ();
dir.z = 0;
dir.normalize();
if (dir.y < 0)
mat.rotateZ(float(NLMISC::Pi+asin(dir.x)));
else
mat.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x)));
m_Driver->setModelMatrix(mat);*/
m_Driver->setModelMatrix(m_InterfaceCameraMatrix);
{
nlassert(m_GUITexture);
NLMISC::CQuadUV quad;
NL3D::UMaterial umat = m_Driver->createMaterial();
umat.initUnlit();
umat.setColor(NLMISC::CRGBA::White);
umat.setDoubleSided(true);
umat.setBlend(true);
umat.setAlphaTest(false);
NL3D::CMaterial *mat = umat.getObjectPtr();
mat->setShader(NL3D::CMaterial::Normal);
mat->setBlendFunc(CMaterial::one, CMaterial::TBlend::invsrcalpha);
mat->setZWrite(false);
// mat->setZFunc(CMaterial::always); // Not nice
mat->setDoubleSided(true);
mat->setTexture(0, m_GUITexture->getITexture());
// user options
float height = 6.0f;
float distance = 3.0f;
uint32 winw, winh;
m_Driver->getWindowSize(winw, winh);
float width = height * (float)winw / (float)winh;
NLMISC::CQuadUV quadUV;
quadUV.V0 = CVector(-(width * 0.5f), distance, -(height * 0.5f));
quadUV.V1 = CVector((width * 0.5f), distance, -(height * 0.5f));
quadUV.V2 = CVector((width * 0.5f), distance, (height * 0.5f));
quadUV.V3 = CVector(-(width * 0.5f), distance, (height * 0.5f));
quadUV.Uv0 = CUV(0.f, 0.f);
quadUV.Uv1 = CUV(1.f, 0.f);
quadUV.Uv2 = CUV(1.f, 1.f);
quadUV.Uv3 = CUV(0.f, 1.f);
m_Driver->drawQuad(quadUV, umat);
m_Driver->deleteMaterial(umat);
}
{
NLMISC::CLine line(NLMISC::CVector(0, 3, -3), NLMISC::CVector(0, 3, 3));
NL3D::UMaterial mat = m_Driver->createMaterial();
mat.setZWrite(false);
mat.setZFunc(UMaterial::always);
mat.setDoubleSided(true);
mat.setColor(NLMISC::CRGBA::Red);
mat.setBlend(false);
m_Driver->drawLine(line, mat);
m_Driver->deleteMaterial(mat);
}
}
/// Returns true if a render target was fully drawn /// Returns true if a render target was fully drawn
bool CStereoOVR::endRenderTarget() bool CStereoOVR::endRenderTarget()
{ {
// after rendering of course // after rendering of course
// nlassert(m_SubStage > 1); // nlassert(m_SubStage > 1);
// End GUI render target
if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// End GUI render target
nlassert(m_GUITexture);
CTextureUser texNull;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(texNull);
}
// End of 3D Interface pass left
if (m_Driver && m_Stage == 5 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// Render 2D GUI in 3D space, assume existing camera is OK
renderGUI();
}
// End of 3D Interface pass right
if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// Render 2D GUI in 3D space, assume existing camera is OK
renderGUI();
// Recycle render target
m_Driver->getRenderTargetManager().recycleRenderTarget(m_GUITexture);
m_GUITexture = NULL;
}
// End 3D scene render target
if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui
{ {
CTextureUser cu; nlassert(m_SceneTexture);
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
CTextureUser texNull;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(texNull);
bool fogEnabled = m_Driver->fogEnabled(); bool fogEnabled = m_Driver->fogEnabled();
m_Driver->enableFog(false); m_Driver->enableFog(false);
@ -640,7 +773,7 @@ bool CStereoOVR::endRenderTarget()
m_Driver->getWindowSize(width, height); m_Driver->getWindowSize(width, height);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver(); NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr(); NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setTexture(0, m_BarrelTex); barrelMat->setTexture(0, m_SceneTexture->getITexture());
drvInternal->activePixelProgram(m_PixelProgram); drvInternal->activePixelProgram(m_PixelProgram);
@ -705,8 +838,13 @@ bool CStereoOVR::endRenderTarget()
drvInternal->activePixelProgram(NULL); drvInternal->activePixelProgram(NULL);
m_Driver->enableFog(fogEnabled); m_Driver->enableFog(fogEnabled);
// Recycle render target
m_Driver->getRenderTargetManager().recycleRenderTarget(m_SceneTexture);
m_SceneTexture = NULL;
return true; return true;
} }
return false; return false;
} }

View file

@ -1386,8 +1386,20 @@ bool mainLoop()
MainCam.setRotQuat(View.currentViewQuat()); MainCam.setRotQuat(View.currentViewQuat());
if (StereoHMD) if (StereoHMD)
{ {
CMatrix camMatrix;
camMatrix.translate(MainCam.getMatrix().getPos());
CVector dir = MainCam.getMatrix().getJ();
dir.z = 0;
dir.normalize();
if (dir.y < 0)
camMatrix.rotateZ(float(NLMISC::Pi+asin(dir.x)));
else
camMatrix.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x)));
StereoHMD->setInterfaceMatrix(camMatrix);
NLMISC::CQuat hmdOrient = StereoHMD->getOrientation(); NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
NLMISC::CMatrix camMatrix = MainCam.getMatrix(); // NLMISC::CMatrix camMatrix = MainCam.getMatrix();
NLMISC::CMatrix hmdMatrix; NLMISC::CMatrix hmdMatrix;
hmdMatrix.setRot(hmdOrient); hmdMatrix.setRot(hmdOrient);
NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
@ -1645,7 +1657,7 @@ bool mainLoop()
{ {
if (Render) if (Render)
{ {
if (ClientCfg.Bloom) if (!StereoDisplay && ClientCfg.Bloom) // NO VR BLOOMZ
{ {
nlassert(bloomStage == 0); nlassert(bloomStage == 0);
// set bloom parameters before applying bloom effect // set bloom parameters before applying bloom effect
@ -1695,7 +1707,7 @@ bool mainLoop()
// Render // Render
if (Render) if (Render)
{ {
if (ClientCfg.Bloom && bloomStage == 1) if (!StereoDisplay && ClientCfg.Bloom && bloomStage == 1) // NO VR BLOOMZ
{ {
// End the actual bloom effect visible in the scene. // End the actual bloom effect visible in the scene.
if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
@ -1822,7 +1834,7 @@ bool mainLoop()
// special case in OpenGL : all scene has been display in render target, // special case in OpenGL : all scene has been display in render target,
// now, final texture is display with a quad // now, final texture is display with a quad
if (!ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) if (!StereoDisplay && !ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) // NO VR BLOOMZ
{ {
// End bloom effect system after drawing the 3d interface (z buffer related). // End bloom effect system after drawing the 3d interface (z buffer related).
if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); if (StereoDisplay) Driver->setViewport(NL3D::CViewport());