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);