feat(world): HDRI-Himmel „Nowhere Road" mit Umgebungslicht und scharfen Kaskaden-Schatten

- 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>
This commit is contained in:
knsoandClaude Opus 5 committed 2026-09-13 15:38:44 +02:00
1 parent 034b12537a
commit f76e97b69d
15 files changed
+762 -41

No files matched your search

+17 -2
View File
@@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import { AnimationClip, Quaternion, QuaternionKeyframeTrack, VectorKeyframeTrack } from "three";
import { CHARACTERS, retargetClips, teleportTargets } from "../src/characters/index.js";
import { AnimationClip, BoxGeometry, Group, Mesh, MeshStandardMaterial, Quaternion, QuaternionKeyframeTrack,
VectorKeyframeTrack } from "three";
import { CHARACTERS, createCharacterModule, retargetClips, teleportTargets } from "../src/characters/index.js";
const rest = (q) => new Map([["arm", { position: { x: 0, y: 1, z: 0 }, quaternion: q }]]);
@@ -64,3 +65,17 @@ describe("teleportTargets", () => {
expect(targets[0].z).toBe(-20);
});
});
describe("createCharacterModule", () => {
// Befund (Schatten-Spec): enableModelShadows lief nur in applyCharacter — das Startmodell
// (ual.glb, Mannequin) warf bis zum ersten Figurenwechsel keinen Schatten.
it("schaltet Schatten schon für das Startmodell ein", () => {
const body = new Mesh(new BoxGeometry(), new MeshStandardMaterial());
const playerModel = new Group().add(body);
createCharacterModule({ playerModel, playerModelConfig: { animations: [] } });
expect(body.castShadow).toBe(true);
expect(body.receiveShadow).toBe(true);
});
});