From b9262943a4ff88558a4b032b8c983e6690f8a63c Mon Sep 17 00:00:00 2001 From: llbraughler Date: Mon, 6 Oct 2025 19:51:16 -0400 Subject: [PATCH] Fix flare visibility in mirrors Compute the flare's depth with the same projection used for the scene, then compare it to the depth we read. --- code/renderergl2/tr_flares.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/code/renderergl2/tr_flares.c b/code/renderergl2/tr_flares.c index 0ad12be0..06277e2c 100644 --- a/code/renderergl2/tr_flares.c +++ b/code/renderergl2/tr_flares.c @@ -276,7 +276,8 @@ void RB_TestFlare( flare_t *f ) { float depth; qboolean visible; float fade; - float screenZ; + float flareDepth; + FBO_t *oldFbo; backEnd.pc.c_flareTests++; @@ -301,10 +302,22 @@ void RB_TestFlare( flare_t *f ) { FBO_Bind(oldFbo); } - screenZ = backEnd.viewParms.projectionMatrix[14] / - ( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] ); + // Project flare origin with the CURRENT view (handles oblique near plane) + vec4_t eyePos, clipPos; + R_TransformModelToClip(f->origin, + backEnd.or.modelMatrix, + backEnd.viewParms.projectionMatrix, + eyePos, clipPos); + if (clipPos[3] <= 0.0f) { + visible = qfalse; // behind eye + } else { + // Treat near-equal depths as visible, tiny margin to avoid false occlusion from rounding + const float depthBias = 1e-5f; // ~256 / 2^24 - visible = ( -f->eyeZ - -screenZ ) < 24; + float clipDepth = clipPos[2] / clipPos[3]; // [-1,1] + flareDepth = clipDepth * 0.5f + 0.5f; // 0..1 + visible = (flareDepth - depthBias) <= depth; // in front (with margin) + } if ( visible ) { if ( !f->visible ) { @@ -555,7 +568,3 @@ void RB_RenderFlares (void) { GL_SetModelviewMatrix(oldmodelview); } - - - -