From 593b76fda1150140597bae6a111594a11de22232 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 24 Apr 2026 20:42:59 +0200 Subject: [PATCH] sky(phase-8.1): CLAMP_TO_EDGE on static sky meshes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dome is 5 flat quads meeting at edges. Under GL_REPEAT + LINEAR filtering, the edge pixels of each wall wrap-sample to the OPPOSITE edge of the SAME texture (repeat wraps 1.0→0.0). Those opposite-edge pixels never match the adjacent wall's border, so every dome seam showed up as a visible line — four vertical wall lines plus the top cap formed a huge cube-outline in the sky. Switch to GL_CLAMP_TO_EDGE for any sky submesh whose SkyObject has TexVelocityX == TexVelocityY == 0 (i.e. not a scrolling cloud layer). Scrolling clouds keep GL_REPEAT because their UV-offset accumulates and needs seamless wrap. One-line heuristic on TexVelocity picks the mode per-object per draw. User confirmed both the cube-edges artifact and the "huge square in the sky" artifact are gone after this change. Both were the same bug — the square was the four wall seams forming a closed rectangle across the view. --- src/AcDream.App/Rendering/Sky/SkyRenderer.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/AcDream.App/Rendering/Sky/SkyRenderer.cs b/src/AcDream.App/Rendering/Sky/SkyRenderer.cs index 86c8d7f..48ac917 100644 --- a/src/AcDream.App/Rendering/Sky/SkyRenderer.cs +++ b/src/AcDream.App/Rendering/Sky/SkyRenderer.cs @@ -221,6 +221,23 @@ public sealed unsafe class SkyRenderer : IDisposable uint tex = _textures.GetOrUpload(sub.SurfaceId); _gl.ActiveTexture(TextureUnit.Texture0); _gl.BindTexture(TextureTarget.Texture2D, tex); + + // Sky meshes need per-object wrap mode. The dome is 5 flat + // walls meeting at edges — under GL_REPEAT any UV drift + // past [0,1] wraps to the opposite edge of the texture, + // drawing a visible line along each wall seam. Static + // sky GfxObjs (dome, sun, moon, stars) should use + // CLAMP_TO_EDGE to avoid that bleed. Scrolling cloud + // layers (TexVelocity != 0) still need REPEAT so the + // animated UV offset wraps correctly. Detection heuristic: + // non-zero TexVelocity on either axis ⇒ scrolling layer. + bool scrolling = obj.TexVelocityX != 0f || obj.TexVelocityY != 0f; + int wrapMode = scrolling + ? (int)TextureWrapMode.Repeat + : (int)TextureWrapMode.ClampToEdge; + _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, wrapMode); + _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, wrapMode); + _gl.BindVertexArray(sub.Vao); _gl.DrawElements(PrimitiveType.Triangles, (uint)sub.IndexCount,