leafy_grass ist roh sandfarben (Mittel der Diffuse-Kachel R 151, G 131,
B 89). Seit der Park seine echte Fläche als eigene Schicht trägt (102 790
statt 16 798 m² im Parkrechteck), las er sich aus der Vogelperspektive wie
eine Brache, während ihn die Minimap grün zeichnet. PARK_TINT 0xb4dc94
tönt Rot und Blau stärker ab als Grün; die Felder behalten ihren helleren
FIELD_TINT und heben sich weiter ab.
Im Browser abgestimmt (Task 12, Schritt 7) und vom Nutzer so gewählt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Himmel: 4k-HDRI von Poly Haven (CC0, tools/assets/hdri.mjs) statt Sky-Shader. Kuppel zeigt das Foto
ab 12°, darunter weiches Band und Dunst in Nebelfarbe; Umgebungslicht und Spiegelungen per PMREM;
Sonne aus dem Bild gekappt und als Licht übernommen (77°, Stärke 2,5)
- Schatten: CSM mit vier Stufen (25/100/350/1000 m, je 2048²), Schutznetz für beleuchtete Materialien,
Normal-Bias 1,5 Texel je Stufe gegen Streifen auf doppelseitigen Materialien (Figur, Autos)
- Startfigur wirft Schatten, Palmen und Laternen empfangen Schatten, Wasser als ruhige See
- Debug-Panel: Sonne, Himmelslicht, Himmelshelligkeit; Namensnennung um das HDRI ergänzt
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Downtown aus der Luft: Boden, Stadtfläche, Park, Strand und Straße lagen 1-2 cm
auseinander (geometry.js: SURFACE_OFFSET=0.02 für alle drei Flächen gleich,
ROAD_OFFSET=0.03), bei 150-300 m Kameraabstand unter der Auflösung eines
24-Bit-Tiefenpuffers (~1,3 cm bei 150 m, ~5 cm bei 300 m, gemessen mit dem alten
Nahwert 0.1) — Strand/Park/Stadtfläche lagen zusätzlich exakt aufeinander und
fighteten unabhängig von der Entfernung. Die Brückenoberkante lag exakt auf der
Bodenoberkante (beide y=0).
Vier Änderungen, freigegebener Entwurf:
- Kamera-Nahwert 0.1 -> 0.5 m (src/main.js): fünffache Tiefenauflösung auf jede
Entfernung, far bleibt 2500.
- src/world/materials.js: POLYGON_OFFSETS/POLYGON_OFFSET_ORDER, eine feste,
streng zunehmend negative Stufe je Schicht (Boden 0, Stadt -1, Park -2, Strand -3,
Straße -4, für Faktor und Units gleich) — wirkt im Tiefenpuffer selbst, hält die
Rangfolge deshalb auf jede Entfernung, unabhängig vom geometrischen Abstand.
applyPolygonOffsets() ist eine separate, reine Funktion, damit sie ohne
createMaterials()/Texturladen testbar ist und beweisbar nur diese fünf Materialien
trifft (Brücken/Gebäude/Wasser/Meeresboden bleiben unberührt).
- Strand, Park und Stadtfläche bekommen dabei je eine eigene Stufe, statt sich wie
bisher (SURFACE_OFFSET) eine zu teilen.
- src/world/geometry.js: Brückendeck-Oberkante jetzt BRIDGE_OFFSET (=SURFACE_OFFSET,
0.02 m) statt 0 — derselbe Größenordnungsentscheid wie bei den Flächen, klein genug
für einen unbemerkten Schritt, groß genug für die Tiefenpuffer-Auflösung bei 300 m.
TDD: Rangfolge/Kein-Teilen-Regeln sind rein und zuerst als fehlschlagende Tests
geschrieben (tests/materials.test.js, 5 neue), ebenso die Brückenanhebung
(tests/geometry.test.js, 1 neu) — beide zunächst rot, dann grün. 65 -> 71 Tests,
alle grün.
Browser-Verifikation (Downtown, Chunk 2_9, gleiche Kameraposition vorher/nachher):
das zuvor durchgängig zackige/zerstückelte Straßen-/Flächenbild ist jetzt glatt und
durchgängig lesbar. Ego-Perspektive dicht an einer Gebäudewand zeigt mit near=0.5
kein sichtbares Durchsehen. Details, Screenshot-Pfade und offene Punkte (Brücken-
Nahaufnahme nicht separat bestätigt) im Bericht:
.superpowers/sdd/2026-09-12-leonida-vice-slice/schichten-report.md
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ruling 55: asphalt_02 maß roh heller (Ø 89.5) als concrete_pavement_03 (Ø 65.9) und
ließ Stadtflächen wie dunkle Flecken auf der Straße wirken. material.color kann eine
Textur nur abdunkeln, also wird die Straße auf 0x999999 abgetönt statt die Stadtfläche
zu verändern. Gemessen im gerenderten Bild an denselben Bildschirmregionen: Straße
93.0 -> 42.5, Stadtfläche 63.2 -> 63.0 (unverändert) — die Straße kommt jetzt deutlich
dunkler heraus als die Stadtfläche, nicht nur als vorher sie selbst.
Ruling 56: Brücken sind in den Daten dasselbe Straßenstück, nur über Wasser
(geometry.js trennt sie einzig über roads.filter(r => r.bridge)) und bekommen jetzt
asphalt_02 und denselben Farbton wie roads statt der Stadtflächentextur, damit an
keinem Straße-Brücke-Übergang mehr eine Farbnaht entsteht. Neuer Test dafür (RED vor
der Änderung, GREEN danach) plus ein erreichtes Brückenstück im Browser (Chunk 11_7)
fotografiert.
Ruling 57: metalnessMap entfernt. metalness steht fest auf 0, three multipliziert
texelMetalness nur noch dazu (metalnessmap_fragment.glsl.js) und könnte das Ergebnis
nie von 0 wegbewegen — reine Kosten ohne Wirkung.
Ruling 58: anisotropy als optionaler Parameter von createMaterials()/loadSet() statt
eines globalen Renderer-Zugriffs; main.js übergibt jetzt
renderer.capabilities.getMaxAnisotropy(). Laufzeit bestätigt: alle drei Texturtypen
auf allen Materialien tragen anisotropy 16 (= getMaxAnisotropy() auf diesem Gerät).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>