diff --git a/engine/client/render.h b/engine/client/render.h index 74917d786..e286e22e1 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -302,6 +302,7 @@ typedef struct int recurse; /*in a mirror/portal/half way through drawing something else*/ qboolean forcevis; /*if true, vis comes from the forcedvis field instead of recalculated*/ unsigned int flipcull; /*reflected/flipped view, requires inverted culling (should be set to SHADER_CULL_FLIPPED or 0 - its implemented as a xor)*/ + unsigned int colourmask; /*shaderbits mask. anything not here will be forced to 0. this is for red/green type stereo*/ qboolean useperspective; /*not orthographic*/ stereomethod_t stereomethod; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 169473b05..14d4d4926 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -410,6 +410,9 @@ void GL_ForceDepthWritable(void) shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; qglDepthMask(GL_TRUE); } + + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + shaderstate.shaderbits |= SBITS_MASK_BITS; } void GL_SetShaderState2D(qboolean is2d) @@ -2915,6 +2918,7 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) sbits |= SBITS_MISC_DEPTHWRITE; } } + sbits |= r_refdef.colourmask; delta = sbits^shaderstate.shaderbits; diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index c06900e5b..f8338c7cb 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -689,6 +689,7 @@ void GL_Set2D (qboolean flipped) r_refdef.flipcull = SHADER_CULL_FLIP; else r_refdef.flipcull = 0; + r_refdef.colourmask = 0u; GL_SetShaderState2D(true); } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 8ee50e5f3..e2a76f450 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -705,6 +705,7 @@ r_refdef must be set before the first call */ static void R_RenderScene_Internal(void) { + extern qboolean depthcleared; int tmpvisents = cl_numvisedicts; TRACE(("dbg: calling R_SetFrustrum\n")); if (!r_refdef.recurse) @@ -728,9 +729,12 @@ static void R_RenderScene_Internal(void) RQ_RenderBatchClear(); cl_numvisedicts = tmpvisents; + + depthcleared = false; //whatever is in the depth buffer is no longer useful. } static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t axisorigin[4]) { + extern qboolean depthcleared; refdef_t refdef = r_refdef; int pw = vid.fbpwidth; int ph = vid.fbpheight; @@ -741,6 +745,7 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t a r = GLBE_FBO_Update(&fbo_vr, FBO_RB_DEPTH, &rendertarget, 1, r_nulltex, rendertarget->width, rendertarget->height, 0); GL_ForceDepthWritable(); qglClear (GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); + depthcleared = true; vid.fbpwidth = rendertarget->width; vid.fbpheight = rendertarget->height; } @@ -766,8 +771,11 @@ static void R_RenderScene (void) int stereomode; int i; int cull = r_refdef.flipcull; + unsigned int colourmask = r_refdef.colourmask; vec3_t axisorg[4], ang; + extern qboolean depthcleared; + r_refdef.colourmask = 0u; stereomode = r_refdef.stereomethod; if (stereomode == STEREO_QUAD) { @@ -780,7 +788,7 @@ static void R_RenderScene (void) } - if (r_refdef.recurse || !stereomode || !r_stereo_separation.value) + if (r_refdef.recurse || !stereomode)// || !(r_stereo_separation.value||r_stereo_convergence.value)) { stereooffset[0] = 0; stereoframes = 1; @@ -800,7 +808,6 @@ static void R_RenderScene (void) { GL_ForceDepthWritable(); qglClear (GL_DEPTH_BUFFER_BIT); - r_framecount++; R_SetupGL (NULL, NULL, NULL, NULL); R_RenderScene_Internal(); @@ -823,6 +830,7 @@ static void R_RenderScene (void) #endif else for (i = 0; i < stereoframes; i++) { + r_refdef.colourmask = 0u; switch (stereomode) { default: @@ -840,21 +848,21 @@ static void R_RenderScene (void) #endif case STEREO_RED_CYAN: //red/cyan(green+blue) if (stereooffset[i] < 0) - qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + r_refdef.colourmask = (SBITS_MASK_GREEN|SBITS_MASK_BLUE); else - qglColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); + r_refdef.colourmask = SBITS_MASK_RED; break; case STEREO_RED_BLUE: //red/blue if (stereooffset[i] < 0) - qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + r_refdef.colourmask = (SBITS_MASK_GREEN|SBITS_MASK_BLUE); else - qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE); + r_refdef.colourmask = (SBITS_MASK_RED|SBITS_MASK_GREEN); break; case STEREO_RED_GREEN: //red/green if (stereooffset[i] < 0) - qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + r_refdef.colourmask = (SBITS_MASK_GREEN|SBITS_MASK_BLUE); else - qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + r_refdef.colourmask = (SBITS_MASK_RED|SBITS_MASK_BLUE); break; #ifdef FTE_TARGET_WEB case STEREO_WEBVR: @@ -873,17 +881,19 @@ static void R_RenderScene (void) //fixme: depth buffer doesn't need clearing break; } - if (i) + + if (!depthcleared) { GL_ForceDepthWritable(); qglClear (GL_DEPTH_BUFFER_BIT); - r_framecount++; + depthcleared = true; } + r_framecount++; //view position changes, if only slightly. which means we need to rebuild vis info. :( ang[0] = 0; ang[1] = r_stereo_convergence.value * (i?0.5:-0.5); - ang[2] = 0;; - AngleVectors(ang, axisorg[0], axisorg[1], axisorg[2]); + ang[2] = 0; + AngleVectorsFLU(ang, axisorg[0], axisorg[1], axisorg[2]); axisorg[3][0] = 0; axisorg[3][1] = stereooffset[i]; axisorg[3][2] = 0; @@ -904,13 +914,13 @@ static void R_RenderScene (void) case STEREO_RED_BLUE: //green should have already been cleared. case STEREO_RED_GREEN: //blue should have already been cleared. case STEREO_RED_CYAN: - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); break; case 5: break; } r_refdef.flipcull = cull; + r_refdef.colourmask = colourmask; } /*generates a new modelview matrix, as well as vpn vectors*/ static void R_MirrorMatrix(plane_t *plane) @@ -1459,7 +1469,6 @@ void R_Clear (qboolean fbo) { /*tbh, this entire function should be in the backend*/ { - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //FIXME: breaks backend! if (!depthcleared || fbo) { GL_ForceDepthWritable(); @@ -1468,7 +1477,10 @@ void R_Clear (qboolean fbo) //but for multiple scenes, we do need to clear depth still. //fbos always get cleared depth, just in case (colour fbos may contain junk, but hey). if ((fbo && r_clear.ival) || r_refdef.stereomethod==STEREO_RED_BLUE||r_refdef.stereomethod==STEREO_RED_GREEN) + { + qglClearColor(0, 0, 0, 1); qglClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + } else qglClear (GL_DEPTH_BUFFER_BIT); } diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 364ade9f6..3016044b6 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -2331,6 +2331,7 @@ static void Sh_GenShadowFace(dlight_t *l, vec3_t axis[3], int lighttype, shadowm if (lighttype & LSHADER_FAKESHADOWS) r_refdef.flipcull ^= SHADER_CULL_FLIP; + r_refdef.colourmask = 0u; #ifdef SHADOWDBG_COLOURNOTDEPTH BE_SelectMode(BEM_STANDARD); @@ -2448,6 +2449,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, int lighttype, vec3_t axis[3], qbyte *lvi shadowmesh_t *smesh; int sidevisible; int oldflip = r_refdef.flipcull; + unsigned int oldcolourmask = r_refdef.colourmask; int oldexternalview = r_refdef.externalview; int twidth; int theight; @@ -2593,6 +2595,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, int lighttype, vec3_t axis[3], qbyte *lvi r_refdef.pxrect = oprect; r_refdef.flipcull = oldflip; + r_refdef.colourmask = oldcolourmask; r_refdef.externalview = oldexternalview; R_SetFrustum(r_refdef.m_projection_std, r_refdef.m_view);