From 676e05ad1f11dd40ce220c7f92cdfc72122f216e Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Fri, 20 Sep 2024 16:56:58 -0300 Subject: [PATCH] Fixed GL1 stencil shadow when gl1_stereo = 3 to 5 Disabling stencil for shadowing in these stereo modes, otherwise entities appear behind solid walls. --- doc/040_cvarlist.md | 3 +- src/client/refresh/gl1/gl1_main.c | 59 +++++++++++++++---------------- src/client/refresh/gl1/gl1_mesh.c | 9 +++-- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/doc/040_cvarlist.md b/doc/040_cvarlist.md index 7d11bb62..d72ccc12 100644 --- a/doc/040_cvarlist.md +++ b/doc/040_cvarlist.md @@ -508,7 +508,8 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable` squares. * **gl1_stencilshadow**: If `gl_shadows` is set to `1`, this makes them - look a bit better (no flickering) by using the stencil buffer. + look a bit better (no flickering) by using the stencil buffer. Does + not work when `gl1_stereo` is `3`, `4` or `5`. * **gl1_lightmapcopies**: When enabled (`1`), keep 3 copies of the same lightmap rotating, shifting to another one when drawing a new frame. diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index 75e62fed..9eca3f2b 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -809,53 +809,59 @@ R_SetupGL(void) void R_Clear(void) { - // Check whether the stencil buffer needs clearing, and do so if need be. - GLbitfield stencilFlags = 0; - if (gl_state.stereo_mode >= STEREO_MODE_ROW_INTERLEAVED && gl_state.stereo_mode <= STEREO_MODE_PIXEL_INTERLEAVED) { - glClearStencil(GL_FALSE); - stencilFlags |= GL_STENCIL_BUFFER_BIT; + // Define which buffers need clearing + GLbitfield clearFlags = 0; + GLenum depthFunc = GL_LEQUAL; + + // This breaks stereo modes, but we'll leave that responsibility to the user + if (r_clear->value) + { + clearFlags |= GL_COLOR_BUFFER_BIT; + } + + // No stencil shadows allowed when using certain stereo modes, otherwise "wallhack" happens + if (gl_state.stereo_mode >= STEREO_MODE_ROW_INTERLEAVED && gl_state.stereo_mode <= STEREO_MODE_PIXEL_INTERLEAVED) + { + glClearStencil(0); + clearFlags |= GL_STENCIL_BUFFER_BIT; + } + else if (gl_shadows->value && gl_state.stencil && gl1_stencilshadow->value) + { + glClearStencil(1); + clearFlags |= GL_STENCIL_BUFFER_BIT; } if (gl1_ztrick->value) { static int trickframe; - if (r_clear->value) - { - glClear(GL_COLOR_BUFFER_BIT | stencilFlags); - } - trickframe++; if (trickframe & 1) { gldepthmin = 0; gldepthmax = 0.49999; - glDepthFunc(GL_LEQUAL); } else { gldepthmin = 1; gldepthmax = 0.5; - glDepthFunc(GL_GEQUAL); + depthFunc = GL_GEQUAL; } } else { - if (r_clear->value) - { - glClear(GL_COLOR_BUFFER_BIT | stencilFlags | GL_DEPTH_BUFFER_BIT); - } - else - { - glClear(GL_DEPTH_BUFFER_BIT | stencilFlags); - } + clearFlags |= GL_DEPTH_BUFFER_BIT; gldepthmin = 0; gldepthmax = 1; - glDepthFunc(GL_LEQUAL); } + if (clearFlags) + { + glClear(clearFlags); + } + glDepthFunc(depthFunc); glDepthRange(gldepthmin, gldepthmax); if (gl_zfix->value) @@ -869,13 +875,6 @@ R_Clear(void) glPolygonOffset(-0.05, -1); } } - - /* stencilbuffer shadows */ - if (gl_shadows->value && gl_state.stencil && gl1_stencilshadow->value) - { - glClearStencil(GL_TRUE); - glClear(GL_STENCIL_BUFFER_BIT); - } } void @@ -1872,12 +1871,12 @@ RI_BeginFrame(float camera_separation) gl1_particle_square->modified = false; } -#ifndef YQ2_GL1_GLES /* draw buffer stuff */ if (gl_drawbuffer->modified) { gl_drawbuffer->modified = false; +#ifndef YQ2_GL1_GLES if ((gl_state.camera_separation == 0) || gl_state.stereo_mode != STEREO_MODE_OPENGL) { if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0) @@ -1889,8 +1888,8 @@ RI_BeginFrame(float camera_separation) glDrawBuffer(GL_BACK); } } - } #endif + } /* texturemode stuff */ if (gl_texturemode->modified || (gl_config.anisotropic && gl_anisotropic->modified) diff --git a/src/client/refresh/gl1/gl1_mesh.c b/src/client/refresh/gl1/gl1_mesh.c index b363a2c1..b5fd44e0 100644 --- a/src/client/refresh/gl1/gl1_mesh.c +++ b/src/client/refresh/gl1/gl1_mesh.c @@ -207,6 +207,11 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp) static void R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum) { + // Don't do stencil test on unsupported stereo modes + const qboolean stencilt = ( gl_state.stencil && gl1_stencilshadow->value && + ( gl_state.stereo_mode < STEREO_MODE_ROW_INTERLEAVED + || gl_state.stereo_mode > STEREO_MODE_PIXEL_INTERLEAVED ) ); + int *order; vec3_t point; float height = 0, lheight; @@ -219,7 +224,7 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum) R_UpdateGLBuffer(buf_shadow, 0, 0, 0, 1); /* stencilbuffer shadows */ - if (gl_state.stencil && gl1_stencilshadow->value) + if (stencilt) { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 1, 2); @@ -265,7 +270,7 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum) R_ApplyGLBuffer(); /* stencilbuffer shadows */ - if (gl_state.stencil && gl1_stencilshadow->value) + if (stencilt) { glDisable(GL_STENCIL_TEST); }