From fafe5d66e81f0331d475283183324867a3097edc Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 10 Jun 2026 08:18:26 +0200 Subject: [PATCH] =?UTF-8?q?diag(render):=20=C2=A74=20flap=20apparatus=20?= =?UTF-8?q?=E2=80=94=20eye-vs-terrain=20field=20+=20GL-state=20tripwire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two probe additions from the §4 outdoor full-world flap investigation (world turns to fog-tinted clear color at specific outdoor spots; strobes then holds; camera rotation recovers; forward-walk triggers): - [pv-input] gains terrZ=/eyeAbove= (terrain height under the camera eye) — used to REFUTE the buried-eye hypothesis (eyeAbove stayed +1.6..2.1 m through every held-flap block). - [gl-state] (ACDREAM_PROBE_GLSTATE=1): snapshots the GL fixed-function state entering the world passes (depth, blend, cull, scissor + box, viewport, FBO, color/clip masks, glGetError), printing on change. Delivered the frame-exact flap-onset marker: the leftover scissor box flips from full-screen to a drifting 9x21 px doorway footprint at the exact frame the nearby building flood merges in (pv-input flood 1->5). Both probes are gated and zero-cost when off. Strip with the rest of the §4 apparatus when the flap ships. Co-Authored-By: Claude Fable 5 --- src/AcDream.App/Rendering/GameWindow.cs | 67 ++++++++++++++++++- .../Rendering/RenderingDiagnostics.cs | 12 ++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index fc9483cb..d9702b3c 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -7102,6 +7102,11 @@ public sealed class GameWindow : IDisposable _gl.CullFace(TriangleFace.Back); _gl.FrontFace(FrontFaceDirection.CW); + // §4 flap apparatus: GL-state tripwire — one [gl-state] line whenever the + // state entering the world passes differs from the previous frame. + if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeGlStateEnabled) + EmitGlStateTripwireIfChanged(); + // Phase N.6 slice 1: one-shot surface-format histogram dump under // ACDREAM_DUMP_SURFACES=1. Zero cost when off. _textureCache?.TickSurfaceHistogramDumpIfEnabled(); @@ -7615,8 +7620,16 @@ public sealed class GameWindow : IDisposable // flickers while idle, exactly one of {eye, player, rawPlayer, yaw} is the varying input. var pvRawPlayer = _playerController?.Position ?? playerViewPos; float pvYaw = _playerController?.Yaw ?? 0f; + // §4 outdoor flap (2026-06-09): terrain height under the EYE — if the + // camera boom is buried in a hillside (eyeAbove < 0), every nearby + // terrain triangle backface-culls and the view punches through the + // world to the clear color. Pin or refute eye-under-terrain. + float? pvTerrZ = _physicsEngine.SampleTerrainZ(camPos.X, camPos.Y); + string pvTerr = pvTerrZ is { } tz + ? System.FormattableString.Invariant($"terrZ={tz:F3} eyeAbove={camPos.Z - tz:F3}") + : "terrZ=n/a eyeAbove=n/a"; Console.WriteLine(System.FormattableString.Invariant( - $"[pv-input] outRoot={pvOutRoot} flood={pvFrame.OrderedVisibleCells.Count} eye=({camPos.X:F6},{camPos.Y:F6},{camPos.Z:F6}) player=({playerViewPos.X:F6},{playerViewPos.Y:F6},{playerViewPos.Z:F6}) rawPlayer=({pvRawPlayer.X:F6},{pvRawPlayer.Y:F6},{pvRawPlayer.Z:F6}) yaw={pvYaw:F8} vp=[{vp.M11:F6} {vp.M13:F6} {vp.M22:F6} {vp.M31:F6} {vp.M33:F6} {vp.M41:F6} {vp.M42:F6} {vp.M43:F6}]")); + $"[pv-input] outRoot={pvOutRoot} flood={pvFrame.OrderedVisibleCells.Count} eye=({camPos.X:F6},{camPos.Y:F6},{camPos.Z:F6}) player=({playerViewPos.X:F6},{playerViewPos.Y:F6},{playerViewPos.Z:F6}) rawPlayer=({pvRawPlayer.X:F6},{pvRawPlayer.Y:F6},{pvRawPlayer.Z:F6}) yaw={pvYaw:F8} {pvTerr} vp=[{vp.M11:F6} {vp.M13:F6} {vp.M22:F6} {vp.M31:F6} {vp.M33:F6} {vp.M41:F6} {vp.M42:F6} {vp.M43:F6}]")); } sigPvFrame = pviewResult.PortalFrame; @@ -9535,6 +9548,58 @@ public sealed class GameWindow : IDisposable } } + // §4 flap apparatus (2026-06-09): GL-state tripwire. Snapshots the fixed-function + // state entering the world passes; prints [gl-state] only when it CHANGES from the + // previous frame. Every CPU-side input is probe-exonerated for the outdoor + // full-world flap; this pins or refutes the leaked-GL-state family + // (feedback_render_self_contained_gl_state — 3 prior hits). Throwaway. + private string? _lastGlStateSig; + private long _glStateFrame; + private long _glStateStable; + + private void EmitGlStateTripwireIfChanged() + { + var gl = _gl; + if (gl is null) return; + + _glStateFrame++; + Span sbox = stackalloc int[4]; + Span vp = stackalloc int[4]; + gl.GetInteger(GetPName.ScissorBox, sbox); + gl.GetInteger(GetPName.Viewport, vp); + + int clipBits = 0; + for (int i = 0; i < ClipFrame.MaxPlanes; i++) + if (gl.IsEnabled(EnableCap.ClipDistance0 + i)) clipBits |= 1 << i; + + var err = gl.GetError(); + // All-integer fields — culture-safe with plain interpolation. + string sig = + $"depth={(gl.IsEnabled(EnableCap.DepthTest) ? 1 : 0)} " + + $"dmask={(gl.GetBoolean(GetPName.DepthWritemask) ? 1 : 0)} " + + $"dfunc=0x{gl.GetInteger(GetPName.DepthFunc):X} " + + $"blend={(gl.IsEnabled(EnableCap.Blend) ? 1 : 0)} " + + $"bsrc=0x{gl.GetInteger(GetPName.BlendSrcRgb):X} bdst=0x{gl.GetInteger(GetPName.BlendDstRgb):X} " + + $"cull={(gl.IsEnabled(EnableCap.CullFace) ? 1 : 0)} cmode=0x{gl.GetInteger(GetPName.CullFaceMode):X} " + + $"fface=0x{gl.GetInteger(GetPName.FrontFace):X} " + + $"scis={(gl.IsEnabled(EnableCap.ScissorTest) ? 1 : 0)} sbox=({sbox[0]},{sbox[1]},{sbox[2]},{sbox[3]}) " + + $"vp=({vp[0]},{vp[1]},{vp[2]},{vp[3]}) " + + $"fbo={gl.GetInteger(GetPName.DrawFramebufferBinding)} " + + $"a2c={(gl.IsEnabled(EnableCap.SampleAlphaToCoverage) ? 1 : 0)} " + + $"stencil={(gl.IsEnabled(EnableCap.StencilTest) ? 1 : 0)} " + + $"clip=0x{clipBits:X2} err=0x{(int)err:X}"; + + if (sig == _lastGlStateSig) + { + _glStateStable++; + return; + } + + Console.WriteLine($"[gl-state] frame={_glStateFrame} stable={_glStateStable} {sig}"); + _lastGlStateSig = sig; + _glStateStable = 0; + } + private void EnableClipDistances() { for (int i = 0; i < ClipFrame.MaxPlanes; i++) diff --git a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs index 33ad9c97..911b20ce 100644 --- a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs +++ b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs @@ -143,6 +143,18 @@ public static class RenderingDiagnostics public static bool ProbePvInputEnabled { get; set; } = Environment.GetEnvironmentVariable("ACDREAM_PROBE_PVINPUT") == "1"; + /// + /// §4 outdoor full-world flap apparatus (2026-06-09). When true, GameWindow snapshots the + /// GL fixed-function state entering the world passes each frame (depth test/mask/func, blend + /// + factors, cull, front-face, scissor + box, viewport, draw-FBO, color mask, glGetError) + /// and emits one [gl-state] line whenever the snapshot CHANGES. Pins or refutes the + /// "leaked GL state" family for the flap (every CPU-side input — matrix, flood, clip planes, + /// scissor box, membership, eye-vs-terrain — is already probe-exonerated). Throwaway + /// apparatus — strip once §4 ships. Initial state from ACDREAM_PROBE_GLSTATE=1. + /// + public static bool ProbeGlStateEnabled { get; set; } = + Environment.GetEnvironmentVariable("ACDREAM_PROBE_GLSTATE") == "1"; + /// /// Bounded-propagation port apparatus (2026-06-08). When true, PortalVisibilityBuilder.Build emits /// one [portal-churn] summary line per call: per-cell pop count (re-pops = churn), total re-enqueues,