feat(world): Poly-Haven-Materialien, Wasser, Himmel und mitlaufende Schatten
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
289bbbba1d
commit
fb0d19c2e5
25 files changed
+160
-14
No files matched your search
+43
-14
@@ -1,9 +1,11 @@
|
||||
import { ACESFilmicToneMapping, AmbientLight, DirectionalLight, MeshStandardMaterial,
|
||||
PerspectiveCamera, Scene, Timer, Vector3, WebGLRenderer } from "three";
|
||||
import { ACESFilmicToneMapping, AmbientLight, BoxGeometry, DirectionalLight, Fog, Mesh,
|
||||
PerspectiveCamera, PlaneGeometry, Scene, Timer, Vector3, WebGLRenderer } from "three";
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import { Sky } from "three/examples/jsm/objects/Sky.js";
|
||||
import { playerController } from "three-player-controller";
|
||||
import { ChunkStreamer } from "./world/streaming.js";
|
||||
import { createMaterials } from "./world/materials.js";
|
||||
|
||||
const container = document.querySelector("#container");
|
||||
const scene = new Scene();
|
||||
@@ -23,18 +25,25 @@ sun.position.set(60, 120, 40);
|
||||
sun.castShadow = true;
|
||||
scene.add(sun);
|
||||
|
||||
// Ein Material je Schicht aus buildChunkGeometry() (Task 7). buildings trägt die dort erzeugten
|
||||
// Vertexfarben (Pastellton pro Gebäude) und bleibt deshalb weiß grundiert; die übrigen Schichten
|
||||
// sind reine Auflagen/Landmassen ohne Vertexfarben und bekommen je einen flachen Grundton.
|
||||
const materials = {
|
||||
ground: new MeshStandardMaterial({ color: 0x6d7a52, roughness: 1 }),
|
||||
roads: new MeshStandardMaterial({ color: 0x3a3a3d, roughness: 0.9 }),
|
||||
bridges: new MeshStandardMaterial({ color: 0x8a8a8a, roughness: 0.8 }),
|
||||
buildings: new MeshStandardMaterial({ vertexColors: true, roughness: 0.85 }),
|
||||
sand: new MeshStandardMaterial({ color: 0xd9c48c, roughness: 1 }),
|
||||
park: new MeshStandardMaterial({ color: 0x4f7a3d, roughness: 1 }),
|
||||
urban: new MeshStandardMaterial({ color: 0xa8a8a0, roughness: 0.9 }),
|
||||
};
|
||||
// Ein Material je Schicht aus buildChunkGeometry() (Task 7), jetzt mit echten Poly-Haven-
|
||||
// Texturen statt Flächenfarben (Task 9, src/world/materials.js). buildings trägt zusätzlich
|
||||
// die dort erzeugten Vertexfarben (Pastellton pro Gebäude) über der Stuckputz-Textur.
|
||||
const materials = await createMaterials();
|
||||
|
||||
// Himmel und Nebel über der Szene; sunPosition zeigt in dieselbe Richtung wie das Sonnenlicht.
|
||||
const sky = new Sky();
|
||||
sky.scale.setScalar(45000);
|
||||
scene.add(sky);
|
||||
sky.material.uniforms.turbidity.value = 8;
|
||||
sky.material.uniforms.rayleigh.value = 1.6;
|
||||
sky.material.uniforms.sunPosition.value.copy(sun.position.clone().normalize());
|
||||
scene.fog = new Fog(0xbcd7ea, 500, 2200);
|
||||
|
||||
// Meer rund um den Ausschnitt: eine einzige große Ebene unter/um die Chunks, keine je Chunk.
|
||||
const water = new Mesh(new PlaneGeometry(4000, 4000), materials.water);
|
||||
water.rotation.x = -Math.PI / 2;
|
||||
water.position.set(500, -0.6, -1000);
|
||||
scene.add(water);
|
||||
|
||||
// Vice Beach; Task 8, Schritt 5. Auch initPos, damit der Streamer von Anfang an den richtigen
|
||||
// Chunk anfragt statt erst nach dem späteren reset() umzuschwenken.
|
||||
@@ -53,6 +62,24 @@ await player.init({
|
||||
},
|
||||
});
|
||||
|
||||
// Meeresboden: man watet hinein, statt endlos zu fallen. Einmalig, nicht je Chunk.
|
||||
const seafloor = new Mesh(new BoxGeometry(4000, 1, 4000), materials.seafloor);
|
||||
seafloor.position.set(500, -3.0, -1000); // Oberkante bei y = -2,5
|
||||
scene.add(seafloor);
|
||||
seafloor.updateMatrixWorld(true);
|
||||
player.addCollider({ motion: "static", shape: { kind: "mesh", source: seafloor } });
|
||||
|
||||
// Schattenkamera folgt dem Spieler, statt eine feste Box zu benutzen.
|
||||
function updateShadow(target) {
|
||||
sun.position.set(target.x + 120, 240, target.z + 80);
|
||||
sun.target.position.copy(target);
|
||||
sun.target.updateMatrixWorld();
|
||||
sun.shadow.camera.left = -150; sun.shadow.camera.right = 150;
|
||||
sun.shadow.camera.top = 150; sun.shadow.camera.bottom = -150;
|
||||
sun.shadow.camera.far = 600;
|
||||
sun.shadow.camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
// Chunk-Collider treffen erst nach und nach ein (Fetch + asynchroner BVH-Bau, siehe
|
||||
// streaming.js). setSkipCapsuleCollision(true) schaltet nur das horizontale Herausdrücken
|
||||
// ab; applyGravity läuft im Controller unabhängig davon weiter (CharacterMovement.ts), die
|
||||
@@ -99,6 +126,8 @@ renderer.setAnimationLoop((t) => {
|
||||
const delta = Math.min(timer.getDelta(), 1 / 40);
|
||||
player.update(delta);
|
||||
tick(delta);
|
||||
updateShadow(player.playerCapsule.position);
|
||||
materials.water.normalMap.offset.x += delta * 0.01;
|
||||
renderer.render(scene, camera);
|
||||
});
|
||||
addEventListener("resize", () => {
|
||||
|
||||
Reference in new issue
Block a user