From c6fa01dfbffa145b955db86a79b826e7127769a0 Mon Sep 17 00:00:00 2001 From: Christopher Bruns Date: Sat, 9 Apr 2016 15:40:55 -0400 Subject: [PATCH] Reimplement blue/yellow and quadbuffered stereo, this time with an additional CVAR gate on quadbuffered, for better hardware compatibility.obj Something is terribly wrong with the separation in all stereo modes now though. --- src/CMakeLists.txt | 1 + src/gl/stereo3d/gl_anaglyph.cpp | 8 +++ src/gl/stereo3d/gl_anaglyph.h | 10 ++- src/gl/stereo3d/gl_quadstereo.cpp | 67 ++++++++++++++++++++ src/gl/stereo3d/gl_quadstereo.h | 97 +++++++++++++++++++++++++++++ src/gl/stereo3d/gl_stereo_cvars.cpp | 16 ++++- src/win32/win32gliface.cpp | 32 ++++++---- wadsrc/static/menudef.z | 3 + 8 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 src/gl/stereo3d/gl_quadstereo.cpp create mode 100644 src/gl/stereo3d/gl_quadstereo.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc67f4f51..05dc97c5e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1079,6 +1079,7 @@ set( FASTMATH_SOURCES gl/stereo3d/gl_stereo_leftright.cpp gl/stereo3d/scoped_view_shifter.cpp gl/stereo3d/gl_anaglyph.cpp + gl/stereo3d/gl_quadstereo.cpp gl/dynlights/gl_dynlight.cpp gl/dynlights/gl_glow.cpp gl/dynlights/gl_dynlight1.cpp diff --git a/src/gl/stereo3d/gl_anaglyph.cpp b/src/gl/stereo3d/gl_anaglyph.cpp index 4b3d4d00e..7cc66e28b 100644 --- a/src/gl/stereo3d/gl_anaglyph.cpp +++ b/src/gl/stereo3d/gl_anaglyph.cpp @@ -61,4 +61,12 @@ const RedCyan& RedCyan::getInstance(FLOATTYPE ipd) } +/* static */ +const AmberBlue& AmberBlue::getInstance(FLOATTYPE ipd) +{ + static AmberBlue instance(ipd); + return instance; +} + + } /* namespace s3d */ diff --git a/src/gl/stereo3d/gl_anaglyph.h b/src/gl/stereo3d/gl_anaglyph.h index d60506dde..a82ce0f3b 100644 --- a/src/gl/stereo3d/gl_anaglyph.h +++ b/src/gl/stereo3d/gl_anaglyph.h @@ -115,10 +115,18 @@ public: GreenMagenta(float ipd) : MaskAnaglyph(ColorMask(false, true, false), ipd) {} }; +class AmberBlue : public MaskAnaglyph +{ +public: + static const AmberBlue& getInstance(float ipd); + + AmberBlue(float ipd) : MaskAnaglyph(ColorMask(true, true, false), ipd) {} +}; + // TODO matrix anaglyph -} /* namespace st3d */ +} /* namespace s3d */ #endif /* GL_ANAGLYPH_H_ */ diff --git a/src/gl/stereo3d/gl_quadstereo.cpp b/src/gl/stereo3d/gl_quadstereo.cpp new file mode 100644 index 000000000..63bbbedc1 --- /dev/null +++ b/src/gl/stereo3d/gl_quadstereo.cpp @@ -0,0 +1,67 @@ +/* +** gl_quadstereo.cpp +** Quad-buffered OpenGL stereoscopic 3D mode for GZDoom +** +**--------------------------------------------------------------------------- +** Copyright 2015 Christopher Bruns +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "gl_quadstereo.h" + +namespace s3d { + +QuadStereo::QuadStereo(double ipdMeters) + : leftEye(ipdMeters), rightEye(ipdMeters) +{ + // Check whether quad-buffered stereo is supported in the current context + // We are assuming the OpenGL context is already current at this point, + // i.e. this constructor is called "just in time". + GLboolean supportsStereo, supportsBuffered; + glGetBooleanv(GL_STEREO, &supportsStereo); + glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered); + bool bQuadStereoSupported = supportsStereo && supportsBuffered; + leftEye.bQuadStereoSupported = bQuadStereoSupported; + rightEye.bQuadStereoSupported = bQuadStereoSupported; + + eye_ptrs.Push(&leftEye); + // If stereo is not supported, just draw scene once (left eye view only) + if (bQuadStereoSupported) { + eye_ptrs.Push(&rightEye); + } +} + +/* static */ +const QuadStereo& QuadStereo::getInstance(float ipd) +{ + static QuadStereo instance(ipd); + return instance; +} + +} /* namespace s3d */ diff --git a/src/gl/stereo3d/gl_quadstereo.h b/src/gl/stereo3d/gl_quadstereo.h new file mode 100644 index 000000000..615746ae7 --- /dev/null +++ b/src/gl/stereo3d/gl_quadstereo.h @@ -0,0 +1,97 @@ +/* +** gl_quadstereo.h +** Quad-buffered OpenGL stereoscopic 3D mode for GZDoom +** +**--------------------------------------------------------------------------- +** Copyright 2016 Christopher Bruns +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#ifndef GL_QUADSTEREO_H_ +#define GL_QUADSTEREO_H_ + +#include "gl_stereo3d.h" +#include "gl_stereo_leftright.h" +#include "gl/system/gl_system.h" + +namespace s3d { + + +class QuadStereoLeftPose : public LeftEyePose +{ +public: + QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {} + virtual void SetUp() const { + if (bQuadStereoSupported) + glDrawBuffer(GL_BACK_LEFT); + } + virtual void TearDown() const { + if (bQuadStereoSupported) + glDrawBuffer(GL_BACK); + } + bool bQuadStereoSupported; +}; + +class QuadStereoRightPose : public RightEyePose +{ +public: + QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){} + virtual void SetUp() const { + if (bQuadStereoSupported) + glDrawBuffer(GL_BACK_RIGHT); + } + virtual void TearDown() const { + if (bQuadStereoSupported) + glDrawBuffer(GL_BACK); + } + bool bQuadStereoSupported; +}; + +// To use Quad-buffered stereo mode with nvidia 3d vision glasses, +// you must either: +// A) be using a Quadro series video card, OR +// +// B) be using nvidia driver version 314.07 or later +// AND have your monitor set to 120 Hz refresh rate +// AND have gzdoom in true full screen mode +class QuadStereo : public Stereo3DMode +{ +public: + QuadStereo(double ipdMeters); + static const QuadStereo& QuadStereo::getInstance(float ipd); +private: + QuadStereoLeftPose leftEye; + QuadStereoRightPose rightEye; +}; + + +} /* namespace s3d */ + + +#endif /* GL_QUADSTEREO_H_ */ diff --git a/src/gl/stereo3d/gl_stereo_cvars.cpp b/src/gl/stereo3d/gl_stereo_cvars.cpp index 56895bbc6..9f1f30505 100644 --- a/src/gl/stereo3d/gl_stereo_cvars.cpp +++ b/src/gl/stereo3d/gl_stereo_cvars.cpp @@ -36,11 +36,14 @@ #include "gl/stereo3d/gl_stereo3d.h" #include "gl/stereo3d/gl_stereo_leftright.h" #include "gl/stereo3d/gl_anaglyph.h" +#include "gl/stereo3d/gl_quadstereo.h" #include "gl/system/gl_cvars.h" // Set up 3D-specific console variables: CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG) +EXTERN_CVAR(Bool, vr_enable_quadbuffered) + // intraocular distance in meters CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS @@ -80,7 +83,18 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode() case 6: setCurrentMode(RightEyeView::getInstance(vr_ipd)); break; - case 0: + case 7: + if (vr_enable_quadbuffered) { + setCurrentMode(QuadStereo::getInstance(vr_ipd)); + } + else { + setCurrentMode(MonoView::getInstance()); + } + break ; + // TODO: 8: Oculus Rift + case 9: + setCurrentMode(AmberBlue::getInstance(vr_ipd)); + break; case 0: default: setCurrentMode(MonoView::getInstance()); break; diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index ca6800de8..1fab45406 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -47,6 +47,11 @@ CUSTOM_CVAR(Int, gl_vid_multisample, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_ CVAR(Bool, gl_debug, false, 0) +// For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode. +// Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo, +// but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo +CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + EXTERN_CVAR(Int, vid_refreshrate) //========================================================================== @@ -620,7 +625,7 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) { int colorDepth; HDC deskDC; - int attributes[26]; + int attributes[28]; int pixelFormat; unsigned int numFormats; float attribsFloat[] = {0.0f, 0.0f}; @@ -651,26 +656,31 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) attributes[16] = WGL_DOUBLE_BUFFER_ARB; attributes[17] = true; - attributes[18] = WGL_ACCELERATION_ARB; //required to be FULL_ACCELERATION_ARB - attributes[19] = WGL_FULL_ACCELERATION_ARB; + // [BB] Starting with driver version 314.07, NVIDIA GeForce cards support OpenGL quad buffered + // stereo rendering with 3D Vision hardware. Select the corresponding attribute here. + attributes[18] = vr_enable_quadbuffered ? WGL_STEREO_ARB : 0; + attributes[19] = true; + + attributes[20] = WGL_ACCELERATION_ARB; //required to be FULL_ACCELERATION_ARB + attributes[21] = WGL_FULL_ACCELERATION_ARB; if (multisample > 0) { - attributes[20] = WGL_SAMPLE_BUFFERS_ARB; - attributes[21] = true; - attributes[22] = WGL_SAMPLES_ARB; - attributes[23] = multisample; + attributes[22] = WGL_SAMPLE_BUFFERS_ARB; + attributes[23] = true; + attributes[24] = WGL_SAMPLES_ARB; + attributes[25] = multisample; } else { - attributes[20] = 0; - attributes[21] = 0; attributes[22] = 0; attributes[23] = 0; + attributes[24] = 0; + attributes[25] = 0; } - attributes[24] = 0; - attributes[25] = 0; + attributes[26] = 0; + attributes[27] = 0; if (!myWglChoosePixelFormatARB(m_hDC, attributes, attribsFloat, 1, &pixelFormat, &numFormats)) { diff --git a/wadsrc/static/menudef.z b/wadsrc/static/menudef.z index 1f35a7651..5f607bf69 100644 --- a/wadsrc/static/menudef.z +++ b/wadsrc/static/menudef.z @@ -132,8 +132,10 @@ OptionValue VRMode 0, "Normal" 1, "Green/Magenta" 2, "Red/Cyan" + 9, "Amber/Blue" 5, "Left Eye" 6, "Right Eye" + 7, "Quad-buffered" } OptionMenu "GLTextureGLOptions" @@ -186,5 +188,6 @@ OptionMenu "GLPrefOptions" Slider "Ambient light level", gl_light_ambient, 1.0, 255.0, 5.0 Option "Rendering quality", gl_render_precise, "Precision" Option "Stereo 3D VR", vr_mode, "VRMode" + Option "Enable Quad Stereo", vr_enable_quadbuffered, "OnOff" }