Initial implementation of five 3D modes -- some bugs remain.

This commit is contained in:
Christopher Bruns 2015-10-30 20:51:35 -04:00
parent 694dff67e4
commit 0874455faf
16 changed files with 219 additions and 172 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
*.cpp text

1
.gitignore vendored
View file

@ -40,3 +40,4 @@
/zlib/x64/ /zlib/x64/
/build_vc2013_64bit /build_vc2013_64bit
/build_vc2015 /build_vc2015
/build_cmake

View file

@ -762,6 +762,7 @@ file( GLOB HEADER_FILES
gl/models/*.h gl/models/*.h
gl/renderer/*.h gl/renderer/*.h
gl/scene/*.h gl/scene/*.h
gl/stereo3d/*.h
gl/shaders/*.h gl/shaders/*.h
gl/system/*.h gl/system/*.h
gl/textures/*.h gl/textures/*.h
@ -1120,6 +1121,11 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
gl/scene/gl_walls_draw.cpp gl/scene/gl_walls_draw.cpp
gl/scene/gl_vertex.cpp gl/scene/gl_vertex.cpp
gl/scene/gl_spritelight.cpp gl/scene/gl_spritelight.cpp
gl/stereo3d/gl_stereo3d.cpp
gl/stereo3d/gl_stereo_cvars.cpp
gl/stereo3d/gl_stereo_leftright.cpp
gl/stereo3d/scoped_view_shifter.cpp
gl/stereo3d/gl_anaglyph.cpp
gl/dynlights/gl_dynlight.cpp gl/dynlights/gl_dynlight.cpp
gl/dynlights/gl_glow.cpp gl/dynlights/gl_glow.cpp
gl/dynlights/gl_dynlight1.cpp gl/dynlights/gl_dynlight1.cpp
@ -1371,6 +1377,7 @@ source_group("OpenGL Renderer\\HQ Resize Assembly version" REGULAR_EXPRESSION "^
source_group("OpenGL Renderer\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/models/.+") source_group("OpenGL Renderer\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/models/.+")
source_group("OpenGL Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/renderer/.+") source_group("OpenGL Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/renderer/.+")
source_group("OpenGL Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/scene/.+") source_group("OpenGL Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/scene/.+")
source_group("OpenGL Renderer\\Stereo3D" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/stereo3d/.+")
source_group("OpenGL Renderer\\Shaders" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/shaders/.+") source_group("OpenGL Renderer\\Shaders" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/shaders/.+")
source_group("OpenGL Renderer\\System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/system/.+") source_group("OpenGL Renderer\\System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/system/.+")
source_group("OpenGL Renderer\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/textures/.+") source_group("OpenGL Renderer\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/textures/.+")

View file

@ -5,6 +5,7 @@
#include "v_video.h" #include "v_video.h"
#include "vectors.h" #include "vectors.h"
#include "r_renderer.h" #include "r_renderer.h"
#include "gl/data/gl_matrix.h"
struct particle_t; struct particle_t;
class FCanvasTexture; class FCanvasTexture;
@ -120,6 +121,7 @@ public:
void Flush() {} void Flush() {}
void SetProjection(float fov, float ratio, float fovratio); void SetProjection(float fov, float ratio, float fovratio);
void SetProjection(FLOATTYPE matrix[4][4]); // raw matrix input from stereo 3d modes
void SetViewMatrix(fixed_t viewx, fixed_t viewy, fixed_t viewz, bool mirror, bool planemirror); void SetViewMatrix(fixed_t viewx, fixed_t viewy, fixed_t viewz, bool mirror, bool planemirror);
void ProcessScene(bool toscreen = false); void ProcessScene(bool toscreen = false);

View file

@ -56,6 +56,7 @@
#include "gl/utility/gl_clock.h" #include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h" #include "gl/utility/gl_templates.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/stereo3d/scoped_color_mask.h"
FDrawInfo * gl_drawinfo; FDrawInfo * gl_drawinfo;
@ -1009,31 +1010,33 @@ void FDrawInfo::SetupFloodStencil(wallseg * ws)
int recursion = GLPortal::GetRecursion(); int recursion = GLPortal::GetRecursion();
// Create stencil // Create stencil
glStencilFunc(GL_EQUAL,recursion,~0); // create stencil glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); // increment stencil of valid pixels glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
glColorMask(0,0,0,0); // don't write to the graphics buffer {
gl_RenderState.EnableTexture(false); // Use revertible color mask, to avoid stomping on anaglyph 3D state
gl_RenderState.ResetColor(); ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
glEnable(GL_DEPTH_TEST); gl_RenderState.EnableTexture(false);
glDepthMask(true); gl_RenderState.ResetColor();
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
gl_RenderState.Apply(); gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0);
ptr++; ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
glStencilFunc(GL_EQUAL,recursion+1,~0); // draw sky into stencil glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
glColorMask(1,1,1,1); // don't write to the graphics buffer } // glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
gl_RenderState.EnableTexture(true); gl_RenderState.EnableTexture(true);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(false); glDepthMask(false);
@ -1045,26 +1048,28 @@ void FDrawInfo::ClearFloodStencil(wallseg * ws)
glStencilOp(GL_KEEP,GL_KEEP,GL_DECR); glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
gl_RenderState.EnableTexture(false); gl_RenderState.EnableTexture(false);
glColorMask(0,0,0,0); // don't write to the graphics buffer {
gl_RenderState.ResetColor(); // Use revertible color mask, to avoid stomping on anaglyph 3D state
ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0,0,0,0); // don't write to the graphics buffer
gl_RenderState.ResetColor();
gl_RenderState.Apply(); gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0);
ptr++; ptr++;
ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0);
ptr++; ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
// restore old stencil op. // restore old stencil op.
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL,recursion,~0); glStencilFunc(GL_EQUAL, recursion, ~0);
gl_RenderState.EnableTexture(true); gl_RenderState.EnableTexture(true);
glColorMask(1,1,1,1); } // glColorMask(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(true); glDepthMask(true);
} }

View file

@ -59,6 +59,7 @@
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h" #include "gl/scene/gl_portal.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/stereo3d/scoped_color_mask.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
#include "gl/utility/gl_clock.h" #include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h" #include "gl/utility/gl_templates.h"
@ -197,7 +198,7 @@ bool GLPortal::Start(bool usestencil, bool doquery)
// Create stencil // Create stencil
glStencilFunc(GL_EQUAL,recursion,~0); // create stencil glStencilFunc(GL_EQUAL,recursion,~0); // create stencil
glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); // increment stencil of valid pixels glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); // increment stencil of valid pixels
glColorMask(0,0,0,0); // don't write to the graphics buffer // glColorMask(0,0,0,0); // don't write to the graphics buffer
gl_RenderState.SetEffect(EFF_STENCIL); gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false); gl_RenderState.EnableTexture(false);
gl_RenderState.ResetColor(); gl_RenderState.ResetColor();
@ -206,34 +207,36 @@ bool GLPortal::Start(bool usestencil, bool doquery)
if (NeedDepthBuffer()) if (NeedDepthBuffer())
{ {
glDepthMask(false); // don't write to Z-buffer!
if (!NeedDepthBuffer()) doquery = false; // too much overhead and nothing to gain.
else if (gl_noquery) doquery = false;
// If occlusion query is supported let's use it to avoid rendering portals that aren't visible
if (!QueryObject) glGenQueries(1, &QueryObject);
if (QueryObject)
{ {
glBeginQuery(GL_SAMPLES_PASSED, QueryObject); ScopedColorMask colorMask(0, 0, 0, 0);
} glDepthMask(false); // don't write to Z-buffer!
else doquery = false; // some kind of error happened if (!NeedDepthBuffer()) doquery = false; // too much overhead and nothing to gain.
else if (gl_noquery) doquery = false;
DrawPortalStencil(); // If occlusion query is supported let's use it to avoid rendering portals that aren't visible
if (!QueryObject) glGenQueries(1, &QueryObject);
if (QueryObject)
{
glBeginQuery(GL_SAMPLES_PASSED, QueryObject);
}
else doquery = false; // some kind of error happened
glEndQuery(GL_SAMPLES_PASSED); DrawPortalStencil();
// Clear Z-buffer glEndQuery(GL_SAMPLES_PASSED);
glStencilFunc(GL_EQUAL,recursion+1,~0); // draw sky into stencil
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil
glDepthMask(true); // enable z-buffer again
glDepthRange(1,1);
glDepthFunc(GL_ALWAYS);
DrawPortalStencil();
// set normal drawing mode // Clear Z-buffer
gl_RenderState.EnableTexture(true); glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
glDepthFunc(GL_LESS); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
glColorMask(1,1,1,1); glDepthMask(true); // enable z-buffer again
glDepthRange(1, 1);
glDepthFunc(GL_ALWAYS);
DrawPortalStencil();
// set normal drawing mode
gl_RenderState.EnableTexture(true);
glDepthFunc(GL_LESS);
} // glColorMask(1, 1, 1, 1);
gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.SetEffect(EFF_NONE);
glDepthRange(0, 1); glDepthRange(0, 1);
@ -258,12 +261,13 @@ bool GLPortal::Start(bool usestencil, bool doquery)
// than the benefit. // than the benefit.
// Note: We must draw the stencil with z-write enabled here because there is no second pass! // Note: We must draw the stencil with z-write enabled here because there is no second pass!
ScopedColorMask colorMask(0, 0, 0, 0);
glDepthMask(true); glDepthMask(true);
DrawPortalStencil(); DrawPortalStencil();
glStencilFunc(GL_EQUAL,recursion+1,~0); // draw sky into stencil glStencilFunc(GL_EQUAL,recursion+1,~0); // draw sky into stencil
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil
gl_RenderState.EnableTexture(true); gl_RenderState.EnableTexture(true);
glColorMask(1,1,1,1); // glColorMask(1,1,1,1);
gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.SetEffect(EFF_NONE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(false); // don't write to Z-buffer! glDepthMask(false); // don't write to Z-buffer!
@ -369,38 +373,39 @@ void GLPortal::End(bool usestencil)
viewangle=savedviewangle; viewangle=savedviewangle;
GLRenderer->mViewActor=savedviewactor; GLRenderer->mViewActor=savedviewactor;
in_area=savedviewarea; in_area=savedviewarea;
GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
glColorMask(0,0,0,0); // no graphics
gl_RenderState.SetEffect(EFF_NONE);
gl_RenderState.ResetColor();
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
if (needdepth)
{ {
// first step: reset the depth buffer to max. depth ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0, 0, 0, 0); // no graphics
glDepthRange(1,1); // always gl_RenderState.SetEffect(EFF_NONE);
glDepthFunc(GL_ALWAYS); // write the farthest depth value gl_RenderState.ResetColor();
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
if (needdepth)
{
// first step: reset the depth buffer to max. depth
glDepthRange(1, 1); // always
glDepthFunc(GL_ALWAYS); // write the farthest depth value
DrawPortalStencil();
}
else
{
glEnable(GL_DEPTH_TEST);
}
// second step: restore the depth buffer to the previous values and reset the stencil
glDepthFunc(GL_LEQUAL);
glDepthRange(0, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
glStencilFunc(GL_EQUAL, recursion, ~0); // draw sky into stencil
DrawPortalStencil(); DrawPortalStencil();
} glDepthFunc(GL_LESS);
else
{
glEnable(GL_DEPTH_TEST);
}
// second step: restore the depth buffer to the previous values and reset the stencil
glDepthFunc(GL_LEQUAL);
glDepthRange(0,1);
glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
glStencilFunc(GL_EQUAL,recursion,~0); // draw sky into stencil
DrawPortalStencil();
glDepthFunc(GL_LESS);
gl_RenderState.EnableTexture(true); gl_RenderState.EnableTexture(true);
gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.SetEffect(EFF_NONE);
glColorMask(1, 1, 1, 1); } // glColorMask(1, 1, 1, 1);
recursion--; recursion--;
// restore old stencil op. // restore old stencil op.
@ -433,14 +438,15 @@ void GLPortal::End(bool usestencil)
gl_RenderState.ResetColor(); gl_RenderState.ResetColor();
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glDepthRange(0,1); glDepthRange(0, 1);
glColorMask(0,0,0,0); // no graphics {
gl_RenderState.SetEffect(EFF_STENCIL); ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0,0,0,0); // no graphics
gl_RenderState.EnableTexture(false); gl_RenderState.SetEffect(EFF_STENCIL);
DrawPortalStencil(); gl_RenderState.EnableTexture(false);
gl_RenderState.SetEffect(EFF_NONE); DrawPortalStencil();
gl_RenderState.EnableTexture(true); gl_RenderState.SetEffect(EFF_NONE);
glColorMask(1,1,1,1); gl_RenderState.EnableTexture(true);
} // glColorMask(1, 1, 1, 1);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
} }
PortalAll.Unclock(); PortalAll.Unclock();

View file

@ -71,6 +71,8 @@
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h" #include "gl/scene/gl_portal.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/stereo3d/scoped_view_shifter.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
#include "gl/utility/gl_clock.h" #include "gl/utility/gl_clock.h"
#include "gl/utility/gl_convert.h" #include "gl/utility/gl_convert.h"
@ -254,6 +256,13 @@ void FGLRenderer::SetProjection(float fov, float ratio, float fovratio)
gl_RenderState.Set2DMode(false); gl_RenderState.Set2DMode(false);
} }
// raw matrix input from stereo 3d modes
void FGLRenderer::SetProjection(FLOATTYPE matrix[4][4])
{
gl_RenderState.mProjectionMatrix.loadMatrix(&matrix[0][0]);
gl_RenderState.Set2DMode(false);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Setup the modelview matrix // Setup the modelview matrix
@ -802,18 +811,36 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
retval = viewsector; retval = viewsector;
SetViewport(bounds); // Render (potentially) multiple views for stereo 3d
mCurrentFoV = fov; FLOATTYPE projectionMatrix[4][4];
SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper float viewShift[3];
SetViewAngle(viewangle); const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
SetViewMatrix(viewx, viewy, viewz, false, false); stereo3dMode.SetUp();
gl_RenderState.ApplyMatrices(); s3d::Stereo3DMode::const_iterator eye;
for (eye = stereo3dMode.begin(); eye != stereo3dMode.end(); ++eye)
{
(*eye)->SetUp();
// TODO: stereo specific viewport - needed when implementing side-by-side modes etc.
SetViewport(bounds);
mCurrentFoV = fov;
// Stereo mode specific perspective projection
(*eye)->GetProjection(fov, ratio, fovratio, projectionMatrix);
SetProjection(projectionMatrix);
SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper
SetViewAngle(viewangle);
// Stereo mode specific viewpoint adjustment - temporarily shifts global viewx, viewy, viewz
(*eye)->GetViewShift(GLRenderer->mAngles.Yaw, viewShift);
s3d::ScopedViewShifter viewShifter(viewShift);
SetViewMatrix(viewx, viewy, viewz, false, false);
gl_RenderState.ApplyMatrices();
clipper.Clear(); clipper.Clear();
angle_t a1 = FrustumAngle(); angle_t a1 = FrustumAngle();
clipper.SafeAddClipRangeRealAngles(viewangle+a1, viewangle-a1); clipper.SafeAddClipRangeRealAngles(viewangle + a1, viewangle - a1);
ProcessScene(toscreen); ProcessScene(toscreen);
}
stereo3dMode.TearDown();
gl_frameCount++; // This counter must be increased right before the interpolations are restored. gl_frameCount++; // This counter must be increased right before the interpolations are restored.
interpolator.RestoreInterpolations (); interpolator.RestoreInterpolations ();

View file

@ -11,7 +11,7 @@ MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters)
/* static */ /* static */
const GreenMagenta& GreenMagenta::getInstance(float ipd) const GreenMagenta& GreenMagenta::getInstance(FLOATTYPE ipd)
{ {
static GreenMagenta instance(ipd); static GreenMagenta instance(ipd);
return instance; return instance;
@ -19,7 +19,7 @@ const GreenMagenta& GreenMagenta::getInstance(float ipd)
/* static */ /* static */
const RedCyan& RedCyan::getInstance(float ipd) const RedCyan& RedCyan::getInstance(FLOATTYPE ipd)
{ {
static RedCyan instance(ipd); static RedCyan instance(ipd);
return instance; return instance;

View file

@ -3,6 +3,7 @@
#include "gl_stereo3d.h" #include "gl_stereo3d.h"
#include "gl_stereo_leftright.h" #include "gl_stereo_leftright.h"
#include "gl/system/gl_system.h"
namespace s3d { namespace s3d {

View file

@ -6,24 +6,23 @@ namespace s3d {
/* virtual */ /* virtual */
void EyePose::GetProjection(float fov, float aspectRatio, float fovRatio, GLdouble m[4][4]) const void EyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE m[4][4]) const
{ {
// Lifted from gl_scene.cpp FGLRenderer::SetProjection() // Lifted from gl_scene.cpp FGLRenderer::SetProjection()
float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); double fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio));
const double zNear = 5.0; const FLOATTYPE zNear = 5.0;
const double zFar = 65536.0; const FLOATTYPE zFar = 65536.0;
double sine, cotangent, deltaZ;
double radians = fovy / 2 * M_PI / 180; double radians = fovy / 2 * M_PI / 180;
deltaZ = zFar - zNear; FLOATTYPE deltaZ = zFar - zNear;
sine = sin(radians); double sine = sin(radians);
if ((deltaZ == 0) || (sine == 0) || (aspectRatio == 0)) { if ((deltaZ == 0) || (sine == 0) || (aspectRatio == 0)) {
return; return;
} }
cotangent = cos(radians) / sine; FLOATTYPE cotangent = FLOATTYPE(cos(radians) / sine);
memset(m, 0, 16*sizeof(GLdouble)); memset(m, 0, 16*sizeof(FLOATTYPE));
m[0][0] = cotangent / aspectRatio; m[0][0] = cotangent / aspectRatio;
m[1][1] = cotangent; m[1][1] = cotangent;
m[2][2] = -(zFar + zNear) / deltaZ; m[2][2] = -(zFar + zNear) / deltaZ;
@ -40,7 +39,7 @@ Viewport EyePose::GetViewport(const Viewport& fullViewport) const
/* virtual */ /* virtual */
void EyePose::GetViewShift(float yaw, float outViewShift[3]) const void EyePose::GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const
{ {
// pass-through for Mono view // pass-through for Mono view
outViewShift[0] = 0; outViewShift[0] = 0;

View file

@ -2,7 +2,7 @@
#define GL_STEREO3D_H_ #define GL_STEREO3D_H_
#include <vector> #include <vector>
#include "gl/system/gl_system.h" #include "gl/data/gl_matrix.h"
/* stereoscopic 3D API */ /* stereoscopic 3D API */
@ -24,9 +24,9 @@ class EyePose
public: public:
EyePose() {} EyePose() {}
virtual ~EyePose() {} virtual ~EyePose() {}
virtual void GetProjection(float fov, float aspectRatio, float fovRatio, GLdouble outMatrix[4][4]) const; virtual void GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE outMatrix[4][4]) const;
virtual Viewport GetViewport(const Viewport& fullViewport) const; virtual Viewport GetViewport(const Viewport& fullViewport) const;
virtual void GetViewShift(float yaw, float outViewShift[3]) const; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const;
virtual void SetUp() const {}; virtual void SetUp() const {};
virtual void TearDown() const {}; virtual void TearDown() const {};
}; };

View file

@ -33,10 +33,11 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode()
case 2: case 2:
setCurrentMode(RedCyan::getInstance(vr_ipd)); setCurrentMode(RedCyan::getInstance(vr_ipd));
break; break;
case 3: // TODO: missing indices 3, 4 for not-yet-implemented side-by-side modes, to match values from GZ3Doom
case 5:
setCurrentMode(LeftEyeView::getInstance(vr_ipd)); setCurrentMode(LeftEyeView::getInstance(vr_ipd));
break; break;
case 4: case 6:
setCurrentMode(RightEyeView::getInstance(vr_ipd)); setCurrentMode(RightEyeView::getInstance(vr_ipd));
break; break;
case 0: case 0:

View file

@ -11,10 +11,10 @@ namespace s3d {
/* virtual */ /* virtual */
void ShiftedEyePose::GetProjection(float fov, float aspectRatio, float fovRatio, GLdouble m[4][4]) const void ShiftedEyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE m[4][4]) const
{ {
// Lifted from gl_scene.cpp FGLRenderer::SetProjection() // Lifted from gl_scene.cpp FGLRenderer::SetProjection()
float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); FLOATTYPE fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio));
double zNear = 5.0; double zNear = 5.0;
double zFar = 65536.0; double zFar = 65536.0;
@ -33,7 +33,7 @@ void ShiftedEyePose::GetProjection(float fov, float aspectRatio, float fovRatio,
double top = fH; double top = fH;
double deltaZ = zFar - zNear; double deltaZ = zFar - zNear;
memset(m, 0, 16 * sizeof(GLdouble)); // set all elements to zero, cleverly memset(m, 0, 16 * sizeof(FLOATTYPE)); // set all elements to zero, cleverly
// https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml // https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml
m[0][0] = 2 * zNear / (right - left); m[0][0] = 2 * zNear / (right - left);
@ -48,10 +48,10 @@ void ShiftedEyePose::GetProjection(float fov, float aspectRatio, float fovRatio,
/* virtual */ /* virtual */
void ShiftedEyePose::GetViewShift(float yaw, float outViewShift[3]) const void ShiftedEyePose::GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const
{ {
float dx = cos(DEG2RAD(yaw)) * vr_hunits_per_meter * shift; FLOATTYPE dx = cos(DEG2RAD(yaw)) * vr_hunits_per_meter * shift;
float dy = sin(DEG2RAD(yaw)) * vr_hunits_per_meter * shift; FLOATTYPE dy = sin(DEG2RAD(yaw)) * vr_hunits_per_meter * shift;
outViewShift[0] = dx; outViewShift[0] = dx;
outViewShift[1] = dy; outViewShift[1] = dy;
outViewShift[2] = 0; outViewShift[2] = 0;
@ -59,7 +59,7 @@ void ShiftedEyePose::GetViewShift(float yaw, float outViewShift[3]) const
/* static */ /* static */
const LeftEyeView& LeftEyeView::getInstance(float ipd) const LeftEyeView& LeftEyeView::getInstance(FLOATTYPE ipd)
{ {
static LeftEyeView instance(ipd); static LeftEyeView instance(ipd);
instance.setIpd(ipd); instance.setIpd(ipd);
@ -68,7 +68,7 @@ const LeftEyeView& LeftEyeView::getInstance(float ipd)
/* static */ /* static */
const RightEyeView& RightEyeView::getInstance(float ipd) const RightEyeView& RightEyeView::getInstance(FLOATTYPE ipd)
{ {
static RightEyeView instance(ipd); static RightEyeView instance(ipd);
instance.setIpd(ipd); instance.setIpd(ipd);

View file

@ -9,31 +9,31 @@ namespace s3d {
class ShiftedEyePose : public EyePose class ShiftedEyePose : public EyePose
{ {
public: public:
ShiftedEyePose(float shift) : shift(shift) {}; ShiftedEyePose(FLOATTYPE shift) : shift(shift) {};
float getShift() const { return shift; } FLOATTYPE getShift() const { return shift; }
void setShift(float shift) { this->shift = shift; } void setShift(FLOATTYPE shift) { this->shift = shift; }
virtual void GetProjection(float fov, float aspectRatio, float fovRatio, GLdouble outMatrix[4][4]) const; virtual void GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE outMatrix[4][4]) const;
virtual void GetViewShift(float yaw, float outViewShift[3]) const; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const;
protected: protected:
float shift; FLOATTYPE shift;
}; };
class LeftEyePose : public ShiftedEyePose class LeftEyePose : public ShiftedEyePose
{ {
public: public:
LeftEyePose(float ipd) : ShiftedEyePose(-0.5*ipd) {} LeftEyePose(FLOATTYPE ipd) : ShiftedEyePose( FLOATTYPE(-0.5) * ipd) {}
float getIpd() const { return -2.0*getShift(); } FLOATTYPE getIpd() const { return FLOATTYPE(-2.0)*getShift(); }
void setIpd(float ipd) { setShift(-0.5*ipd); } void setIpd(FLOATTYPE ipd) { setShift(FLOATTYPE(-0.5)*ipd); }
}; };
class RightEyePose : public ShiftedEyePose class RightEyePose : public ShiftedEyePose
{ {
public: public:
RightEyePose(float ipd) : ShiftedEyePose(+0.5*ipd) {} RightEyePose(FLOATTYPE ipd) : ShiftedEyePose(FLOATTYPE(+0.5)*ipd) {}
float getIpd() const { return +2.0*shift; } FLOATTYPE getIpd() const { return FLOATTYPE(+2.0)*shift; }
void setIpd(float ipd) { setShift(+0.5*ipd); } void setIpd(FLOATTYPE ipd) { setShift(FLOATTYPE(+0.5)*ipd); }
}; };
@ -43,11 +43,11 @@ public:
class LeftEyeView : public Stereo3DMode class LeftEyeView : public Stereo3DMode
{ {
public: public:
static const LeftEyeView& getInstance(float ipd); static const LeftEyeView& getInstance(FLOATTYPE ipd);
LeftEyeView(float ipd) : eye(ipd) { eye_ptrs.push_back(&eye); } LeftEyeView(FLOATTYPE ipd) : eye(ipd) { eye_ptrs.push_back(&eye); }
float getIpd() const { return eye.getIpd(); } FLOATTYPE getIpd() const { return eye.getIpd(); }
void setIpd(float ipd) { eye.setIpd(ipd); } void setIpd(FLOATTYPE ipd) { eye.setIpd(ipd); }
protected: protected:
LeftEyePose eye; LeftEyePose eye;
}; };
@ -56,11 +56,11 @@ protected:
class RightEyeView : public Stereo3DMode class RightEyeView : public Stereo3DMode
{ {
public: public:
static const RightEyeView& getInstance(float ipd); static const RightEyeView& getInstance(FLOATTYPE ipd);
RightEyeView(float ipd) : eye(ipd) { eye_ptrs.push_back(&eye); } RightEyeView(FLOATTYPE ipd) : eye(ipd) { eye_ptrs.push_back(&eye); }
float getIpd() const { return eye.getIpd(); } FLOATTYPE getIpd() const { return eye.getIpd(); }
void setIpd(float ipd) { eye.setIpd(ipd); } void setIpd(FLOATTYPE ipd) { eye.setIpd(ipd); }
protected: protected:
RightEyePose eye; RightEyePose eye;
}; };

View file

@ -1,7 +1,7 @@
#ifndef GL_STEREO3D_SCOPED_COLOR_MASK_H_ #ifndef GL_STEREO3D_SCOPED_COLOR_MASK_H_
#define GL_STEREO3D_SCOPED_COLOR_MASK_H_ #define GL_STEREO3D_SCOPED_COLOR_MASK_H_
#include "gl/glew.h" #include "gl/system/gl_system.h"
/** /**
* Temporarily change color mask * Temporarily change color mask
@ -10,28 +10,15 @@ class ScopedColorMask
{ {
public: public:
ScopedColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) ScopedColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a)
: isPushed(false)
{ {
setColorMask(r, g, b, a); glGetBooleanv(GL_COLOR_WRITEMASK, saved);
}
~ScopedColorMask() {
revert();
}
void setColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
if (!isPushed) {
glPushAttrib(GL_COLOR_BUFFER_BIT);
isPushed = true;
}
glColorMask(r, g, b, a); glColorMask(r, g, b, a);
} }
void revert() { ~ScopedColorMask() {
if (isPushed) { glColorMask(saved[0], saved[1], saved[2], saved[3]);
glPopAttrib();
isPushed = false;
}
} }
private: private:
bool isPushed; GLboolean saved[4];
}; };

View file

@ -124,6 +124,15 @@ OptionValue "FuzzStyle"
//5, "Jagged fuzz" I can't see any difference between this and 4 so it's disabled for now. //5, "Jagged fuzz" I can't see any difference between this and 4 so it's disabled for now.
} }
OptionValue VRMode
{
0, "Normal"
1, "Green/Magenta"
2, "Red/Cyan"
5, "Left Eye"
6, "Right Eye"
}
OptionMenu "GLTextureGLOptions" OptionMenu "GLTextureGLOptions"
{ {
Title "TEXTURE OPTIONS" Title "TEXTURE OPTIONS"
@ -173,5 +182,6 @@ OptionMenu "GLPrefOptions"
Option "Particle style", gl_particles_style, "Particles" Option "Particle style", gl_particles_style, "Particles"
Slider "Ambient light level", gl_light_ambient, 1.0, 255.0, 5.0 Slider "Ambient light level", gl_light_ambient, 1.0, 255.0, 5.0
Option "Rendering quality", gl_render_precise, "Precision" Option "Rendering quality", gl_render_precise, "Precision"
Option "Stereo 3D VR", vr_mode, "VRMode"
} }