Created
October 5, 2020 04:21
-
-
Save classilla/c777e6137a921e56aa03d8202c178338 to your computer and use it in GitHub Desktop.
Convert Quakespasm to use interlaced R-L video for passive 3D monitors. See https://oldvcr.blogspot.com/2020/10/stereoscopic-computing-converting-quake.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- gl_rmain.c.OLD 2020-08-02 16:35:29.798497930 -0700 | |
+++ gl_rmain.c 2020-10-03 23:32:00.309704966 -0700 | |
@@ -77,16 +77,17 @@ | |
cvar_t gl_affinemodels = {"gl_affinemodels","0",CVAR_NONE}; | |
cvar_t gl_polyblend = {"gl_polyblend","1",CVAR_NONE}; | |
cvar_t gl_flashblend = {"gl_flashblend","0",CVAR_ARCHIVE}; | |
cvar_t gl_playermip = {"gl_playermip","0",CVAR_NONE}; | |
cvar_t gl_nocolors = {"gl_nocolors","0",CVAR_NONE}; | |
//johnfitz -- new cvars | |
cvar_t r_stereo = {"r_stereo","0",CVAR_NONE}; | |
+cvar_t r_stereomode = {"r_stereomode","3",CVAR_NONE}; | |
cvar_t r_stereodepth = {"r_stereodepth","128",CVAR_NONE}; | |
cvar_t r_clearcolor = {"r_clearcolor","2",CVAR_ARCHIVE}; | |
cvar_t r_drawflat = {"r_drawflat","0",CVAR_NONE}; | |
cvar_t r_flatlightstyles = {"r_flatlightstyles", "0", CVAR_NONE}; | |
cvar_t gl_fullbrights = {"gl_fullbrights", "1", CVAR_ARCHIVE}; | |
cvar_t gl_farclip = {"gl_farclip", "16384", CVAR_ARCHIVE}; | |
cvar_t gl_overbright = {"gl_overbright", "1", CVAR_ARCHIVE}; | |
cvar_t gl_overbright_models = {"gl_overbright_models", "1", CVAR_ARCHIVE}; | |
@@ -109,16 +110,65 @@ | |
cvar_t r_slimealpha = {"r_slimealpha","0",CVAR_NONE}; | |
float map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha; | |
qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz | |
cvar_t r_scale = {"r_scale", "1", CVAR_ARCHIVE}; | |
+qboolean stenciled = false; | |
+ | |
+// 3D interlace using stencil buffer | |
+void | |
+RB_InterlaceStencil() | |
+{ | |
+ GLint gliY; | |
+ if (stenciled) return; | |
+ | |
+ // r_stereomode 1: old anaglyph | |
+ // r_stereomode 2: left-right, r_stereo 3: right-left | |
+ | |
+ // init draw coordinates for stencil buffer | |
+ glViewport(0,0,glwidth,glheight); | |
+ glMatrixMode(GL_MODELVIEW); | |
+ glLoadIdentity(); | |
+ glMatrixMode (GL_PROJECTION); | |
+ glLoadIdentity(); | |
+ glOrtho(0.0,glwidth-1,0.0,glheight-1,-1,1); | |
+ glMatrixMode(GL_MODELVIEW); | |
+ glLoadIdentity(); | |
+ | |
+ // draw interlaced stencil | |
+ glEnable(GL_STENCIL_TEST); | |
+ glDisable(GL_DEPTH_TEST); | |
+ glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
+ glClearStencil(0); | |
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); | |
+ glDepthMask(GL_FALSE); | |
+ glStencilFunc(GL_NEVER, 1, 0xff); | |
+ glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); | |
+ glStencilMask(0xff); | |
+ glClear(GL_STENCIL_BUFFER_BIT); | |
+ | |
+ for (gliY=(r_stereo.value == 3 ? 1 : 0); gliY<glheight; gliY+=2) | |
+ { | |
+ glLineWidth(1); | |
+ glBegin(GL_LINES); | |
+ glVertex2f(0,gliY); | |
+ glVertex2f(glwidth,gliY); | |
+ glEnd(); | |
+ } | |
+ | |
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
+ glDepthMask(GL_TRUE); | |
+ glStencilMask(0x00); | |
+ stenciled = true; | |
+} | |
+ | |
//============================================================================== | |
// | |
// GLSL GAMMA CORRECTION | |
// | |
//============================================================================== | |
static GLuint r_gamma_texture; | |
static GLuint r_gamma_program; | |
@@ -518,19 +568,16 @@ | |
R_Clear -- johnfitz -- rewritten and gutted | |
============= | |
*/ | |
void R_Clear (void) | |
{ | |
unsigned int clearbits; | |
clearbits = GL_DEPTH_BUFFER_BIT; | |
- // from mh -- if we get a stencil buffer, we should clear it, even though we don't use it | |
- if (gl_stencilbits) | |
- clearbits |= GL_STENCIL_BUFFER_BIT; | |
if (gl_clear.value) | |
clearbits |= GL_COLOR_BUFFER_BIT; | |
glClear (clearbits); | |
} | |
/* | |
=============== | |
R_SetupScene -- johnfitz -- this is the stuff that needs to be done once per eye in stereo mode | |
@@ -870,42 +917,29 @@ | |
*/ | |
void R_DrawShadows (void) | |
{ | |
int i; | |
if (!r_shadows.value || !r_drawentities.value || r_drawflat_cheatsafe || r_lightmap_cheatsafe) | |
return; | |
- // Use stencil buffer to prevent self-intersecting shadows, from Baker (MarkV) | |
- if (gl_stencilbits) | |
- { | |
- glClear(GL_STENCIL_BUFFER_BIT); | |
- glStencilFunc(GL_EQUAL, 0, ~0); | |
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); | |
- glEnable(GL_STENCIL_TEST); | |
- } | |
- | |
for (i=0 ; i<cl_numvisedicts ; i++) | |
{ | |
currententity = cl_visedicts[i]; | |
if (currententity->model->type != mod_alias) | |
continue; | |
if (currententity == &cl.viewent) | |
return; | |
GL_DrawAliasShadow (currententity); | |
} | |
- if (gl_stencilbits) | |
- { | |
- glDisable(GL_STENCIL_TEST); | |
- } | |
} | |
/* | |
================ | |
R_RenderScene | |
================ | |
*/ | |
void R_RenderScene (void) | |
@@ -1082,36 +1116,65 @@ | |
if (r_stereo.value) | |
{ | |
float eyesep = CLAMP(-8.0f, r_stereo.value, 8.0f); | |
float fdepth = CLAMP(32.0f, r_stereodepth.value, 1024.0f); | |
AngleVectors (r_refdef.viewangles, vpn, vright, vup); | |
//render left eye (red) | |
- glColorMask(1, 0, 0, 1); | |
+ if (r_stereomode.value == 1) | |
+ { | |
+ glColorMask(1, 0, 0, 1); | |
+ } | |
+ else | |
+ { | |
+ // 0 = first line (2), 1 = second (3) | |
+ RB_InterlaceStencil(); | |
+ glStencilFunc(GL_EQUAL, | |
+ (r_stereomode.value == 2) ? 0 : 1, | |
+ 0xff); | |
+ } | |
VectorMA (r_refdef.vieworg, -0.5f * eyesep, vright, r_refdef.vieworg); | |
frustum_skew = 0.5 * eyesep * NEARCLIP / fdepth; | |
srand((int) (cl.time * 1000)); //sync random stuff between eyes | |
R_RenderScene (); | |
//render right eye (cyan) | |
glClear (GL_DEPTH_BUFFER_BIT); | |
- glColorMask(0, 1, 1, 1); | |
+ | |
+ if (r_stereomode.value == 1) | |
+ { | |
+ glColorMask(0, 1, 1, 1); | |
+ } | |
+ else | |
+ { | |
+ glStencilFunc(GL_EQUAL, | |
+ (r_stereomode.value == 2) ? 1 : 0, | |
+ 0xff); | |
+ } | |
VectorMA (r_refdef.vieworg, 1.0f * eyesep, vright, r_refdef.vieworg); | |
frustum_skew = -frustum_skew; | |
srand((int) (cl.time * 1000)); //sync random stuff between eyes | |
R_RenderScene (); | |
//restore | |
- glColorMask(1, 1, 1, 1); | |
+ if (r_stereomode.value == 1) | |
+ { | |
+ glColorMask(1, 1, 1, 1); | |
+ } | |
+ else | |
+ { | |
+ glStencilFunc(GL_ALWAYS, 1, 0xff); | |
+ } | |
+ | |
VectorMA (r_refdef.vieworg, -0.5f * eyesep, vright, r_refdef.vieworg); | |
frustum_skew = 0.0f; | |
} | |
else | |
{ | |
R_RenderScene (); | |
} | |
//johnfitz | |
--- gl_rmisc.c.OLD 2020-10-04 18:40:48.710076545 -0700 | |
+++ gl_rmisc.c 2020-10-03 23:34:15.643555455 -0700 | |
@@ -21,16 +21,17 @@ | |
*/ | |
// r_misc.c | |
#include "quakedef.h" | |
//johnfitz -- new cvars | |
extern cvar_t r_stereo; | |
+extern cvar_t r_stereomode; | |
extern cvar_t r_stereodepth; | |
extern cvar_t r_clearcolor; | |
extern cvar_t r_drawflat; | |
extern cvar_t r_flatlightstyles; | |
extern cvar_t gl_fullbrights; | |
extern cvar_t gl_farclip; | |
extern cvar_t gl_overbright; | |
extern cvar_t gl_overbright_models; | |
@@ -200,16 +201,17 @@ | |
Cvar_RegisterVariable (&gl_affinemodels); | |
Cvar_RegisterVariable (&gl_polyblend); | |
Cvar_RegisterVariable (&gl_flashblend); | |
Cvar_RegisterVariable (&gl_playermip); | |
Cvar_RegisterVariable (&gl_nocolors); | |
//johnfitz -- new cvars | |
Cvar_RegisterVariable (&r_stereo); | |
+ Cvar_RegisterVariable (&r_stereomode); | |
Cvar_RegisterVariable (&r_stereodepth); | |
Cvar_RegisterVariable (&r_clearcolor); | |
Cvar_SetCallback (&r_clearcolor, R_SetClearColor_f); | |
Cvar_RegisterVariable (&r_waterquality); | |
Cvar_RegisterVariable (&r_oldwater); | |
Cvar_RegisterVariable (&r_waterwarp); | |
Cvar_RegisterVariable (&r_drawflat); | |
Cvar_RegisterVariable (&r_flatlightstyles); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment