From 9be9547ddc8823cfbf9bfda391b01ac2f2148d1b Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 31 May 2026 09:11:06 +0200 Subject: [PATCH] =?UTF-8?q?fix(render):=20Phase=20U.4=20=E2=80=94=20EnvCel?= =?UTF-8?q?lRenderer=20sets=20its=20own=20BLEND=20+=20DepthMask=20per=20pa?= =?UTF-8?q?ss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second self-contained-GL-state fix (after uViewProjection): EnvCellRenderer.Render set BlendFunc per-batch but never the BLEND enable or DepthMask. The opaque shell pass — drawn after terrain (which sets neither) and after particles / last frame's transparent pass — inherited whatever left GL_BLEND enabled, making opaque walls composite their sub-1.0-alpha textures against the bluish clear color (terrain Skip'd indoors) → "transparent walls / only background," flickering with per-frame ordering. Mirror the working WbDrawDispatcher: Disable(Blend)+DepthMask(true) opaque, Enable(Blend)+ DepthMask(false) transparent, restore opaque defaults after the draw loop. Does NOT address the threshold "flap" (OutsideView instability from the per-frame view-dependent BFS) — that is a distinct, deeper root cause tracked separately. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Rendering/Wb/EnvCellRenderer.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs b/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs index 0307c13..592b26a 100644 --- a/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs +++ b/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs @@ -959,6 +959,27 @@ public sealed unsafe class EnvCellRenderer : IDisposable shader.Use(); shader.SetInt("uFilterByCell", 0); + // Phase U.4 ROOT-CAUSE FIX (cell-shell "transparent walls / only bluish + // background, flickering when moving"): establish this pass's BLEND + DepthMask + // state OURSELVES rather than inheriting it. Render(Opaque) runs right after the + // terrain draw (which sets neither) and after particles / last frame's transparent + // pass — so whatever left GL_BLEND enabled made the OPAQUE shells composite their + // (often sub-1.0 alpha) wall textures against the bluish clear color (terrain is + // Skip'd indoors), toggling with per-frame ordering → flicker. Mirror the working + // WbDrawDispatcher passes (Disable(Blend)+DepthMask(true) opaque; + // Enable(Blend)+DepthMask(false) transparent). Restored to opaque defaults at the + // end of the draw loop so a Transparent pass can't leak into later draws. + if (renderPass == WbRenderPass.Transparent) + { + _gl.Enable(EnableCap.Blend); + _gl.DepthMask(false); + } + else + { + _gl.Disable(EnableCap.Blend); + _gl.DepthMask(true); + } + // WB BaseObjectRenderManager.cs:718-740: group batches by CullMode + additive flag. var batchesByCullMode = new Dictionary>(); int totalDraws = 0; @@ -1174,6 +1195,12 @@ public sealed unsafe class EnvCellRenderer : IDisposable currentDrawOffset += numDraws; } + // Phase U.4: leave a clean opaque-default render state (mirrors WbDrawDispatcher's + // post-transparent restore) so a Transparent pass's Blend-on / DepthMask-off does + // not leak into particles or the next frame's draws. + _gl.Disable(EnableCap.Blend); + _gl.DepthMask(true); + // WB BaseObjectRenderManager.cs:845-847: shader.SetInt("uDrawIDOffset", 0); _gl.BindBuffer(GLEnum.DrawIndirectBuffer, 0);