feat(A.5 T20): MSAA 4x + alpha-to-coverage on foliage

Per Phase A.5 spec §4.9.2: ClipMap foliage uses binary alpha-cutoff.
At N₂=12 horizon distance the pixel-stepped silhouettes are visible.
A2C with MSAA 4x produces smooth retail-faithful tree edges.

GL context now requests Samples=4. WbDrawDispatcher's opaque pass
toggles GL_SAMPLE_ALPHA_TO_COVERAGE on/off around the multi-draw
indirect call. mesh_modern.frag's opaque pass now discards only
truly-empty (α<0.05) so the GPU derives sample mask from coverage;
transparent pass boundary logic is unchanged.

MSAA audit: no custom FBOs found — all rendering uses default
framebuffer. Sky/particles/ImGui are all MSAA-compatible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-10 08:25:59 +02:00
parent 4b84e5650b
commit 26b2871b10
3 changed files with 10 additions and 1 deletions

View file

@ -488,6 +488,10 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
{
_gl.Disable(EnableCap.Blend);
_gl.DepthMask(true);
// A.5 T20: enable A2C for ClipMap foliage — GPU derives sample mask
// from the alpha written by mesh_modern.frag so foliage edges are
// smooth under MSAA 4x. A no-op for fully-opaque (α=1) batches.
_gl.Enable(EnableCap.SampleAlphaToCoverage);
_shader.SetInt("uRenderPass", 0);
_gl.BindBuffer(BufferTargetARB.DrawIndirectBuffer, _indirectBuffer);
if (diag && _gpuQueriesInitialized) _gl.BeginQuery(QueryTarget.TimeElapsed, _gpuQueryOpaque);
@ -498,6 +502,7 @@ public sealed unsafe class WbDrawDispatcher : IDisposable
(uint)_opaqueDrawCount,
(uint)DrawCommandStride);
if (diag && _gpuQueriesInitialized) _gl.EndQuery(QueryTarget.TimeElapsed);
_gl.Disable(EnableCap.SampleAlphaToCoverage);
}
// ── Phase 8: transparent pass ────────────────────────────────────────