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,