Lane B (Streetscape): round-3 — scene.environment for PBR peds + budget re-measure with citizens
- lighting.js sets scene.environment (neutral PMREM sky->ground gradient, no asset) in attachRenderer, before CitizenSim constructs; Lane D rig-fleet peds bake their impostor atlas from it and render dark if null. Verified set in street/night/interior + after interior-return. - Re-measured worst continuous-walk view WITH citizens (pop 140, 125 active peds) via window.DBG: 263 scene / 275 total midday, 275 night -- <=300 everywhere. Radius-2 auto already the spawn default. - Round-3 task 3 (furniture GLB footprints) standby: Fable s3.4 manifest upgrade not yet landed. - Docs: LANE_B_NOTES.md + B-progress.md round-3 updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0985b05790
commit
fafd5a700a
@ -4,6 +4,22 @@
|
||||
plus the game shell. It runs on my hand-written fixture **and** auto-integrates with Lane A's
|
||||
`generatePlan` (which landed mid-session). Everything below was verified live in a browser.
|
||||
|
||||
## Round 3 (Fable's ROUND3_INSTRUCTIONS → Lane B) — done
|
||||
- **Task 1 (draw budget, re-measured WITH citizens).** Radius-2 auto is already the spawn default;
|
||||
no config change needed. Drove the real loop (`chunks.update` + `citizens.update`, pop 140, up to
|
||||
**125 active peds**) along the dense corridors via `window.DBG`: worst continuous-walk view
|
||||
**263 scene / 275 total at MIDDAY**, **275 total at NIGHT** — **≤300 everywhere**, ~25 margin.
|
||||
Peds are a batched impostor layer (~1–2 draws). Documented in LANE_B_NOTES.
|
||||
- **Task 2 (`scene.environment`).** Was **null** → Lane D's rig-fleet peds bake their impostor atlas
|
||||
from it (`sim.js`) and would render dark. Set a neutral PMREM'd sky→ground gradient in
|
||||
`lighting.attachRenderer` (before `CitizenSim` constructs; no asset). Verified **set in
|
||||
street / night / interior / after interior-return** (`interior_mode` only swaps `scene.background`).
|
||||
- **Task 3 (furniture GLB footprints)** — **standby**: Fable's §3.4 (manifest GLB upgrade +
|
||||
`?noassets`) hasn't landed (furniture.js still primitives); will verify placement/collision when it does.
|
||||
- **Task 4 (optional polish)** — deferred (fresh generated-city stills / map.html wiring).
|
||||
- Only Lane B file changed this round: `web/js/world/lighting.js` (+ these docs). Committed by exact
|
||||
pathspec (Lanes C/E/F have concurrent uncommitted work in the shared tree — untouched).
|
||||
|
||||
## Session 2 (continuation) — closed the two open Lane-B items Fable flagged
|
||||
- **Draw budget now holds with margin.** Facade texture atlas + awning-merge + shell/trim-merge:
|
||||
worst dense frustum **393 → 265 scene draws**, worst continuous-walk gameplay view **~261 total**
|
||||
|
||||
@ -30,8 +30,14 @@ denser than the fixture the ≤300 gate was sized against.
|
||||
|
||||
Streetscape numbers below are **buildings + ground + furniture only** (what Lane B owns), measured by
|
||||
a scripted continuous walk (real streaming + disposal, so ≤25 live chunks — no orphan-chunk inflation).
|
||||
Lane F's citizens add on top; Fable measures the *integrated* worst main-street view (pop 140) at
|
||||
**~191 draws**, also under gate.
|
||||
|
||||
**Round-3 re-measure WITH Lane D citizens (pop 140, the shipped default).** Driving the real loop
|
||||
(`chunks.update` + `citizens.update`) along the dense corridors via `window.DBG`, up to **125 active
|
||||
peds** at midday: worst continuous-walk view **263 scene / 275 total** at **MIDDAY** and **275 total
|
||||
at NIGHT** — **≤300 everywhere**, ~25 draw margin. Peds are a batched impostor layer (~1–2 draws for
|
||||
the whole near tier), so they cost far less than their count. Radius-2 auto is already the spawn
|
||||
default for a big city; no config change was needed. (Fable's independent integrated read is ~191 on a
|
||||
typical main-street view.)
|
||||
|
||||
| metric | measured | gate | status |
|
||||
|---|---|---|---|
|
||||
@ -85,6 +91,11 @@ exceeds the radius-2 set. Verified day + night, facades still textured, awning c
|
||||
- **Night lighting is faked** (Vuntra-style): window + streetlamp **emissive** toggled by a night
|
||||
flag, plus bloom — no per-streetlight real lights. `ChunkManager.setNight()` re-applies to chunks
|
||||
streamed in while already night.
|
||||
- **`scene.environment` is set** (round 3, `lighting.attachRenderer`): a neutral PMREM'd sky→ground
|
||||
gradient (no asset). Lane D's rig-fleet peds bake their impostor atlas from `scene.environment`
|
||||
(`sim.js`) and go dark if it's null; set here *before* `CitizenSim` constructs. One env for all
|
||||
segments (the atlas bakes once; the mostly-non-metal streetscape is barely affected). Verified set
|
||||
in street/night/interior + after interior-return (`interior_mode` only swaps `scene.background`).
|
||||
- **Shared materials, city-wide** (`skins.js`). Facades share **one atlas material** (all skins in a
|
||||
2048² atlas); shells + parapets + posts are **one** InstancedMesh/chunk (per-instance colour); all
|
||||
awning/canopy skins are **one** InstancedMesh/chunk (per-instance colour). Signs are a per-chunk
|
||||
|
||||
@ -20,6 +20,23 @@ const SEG = [
|
||||
];
|
||||
const HOUR = ['06:30', '09:00', '12:30', '15:30', '18:30', '22:00'];
|
||||
|
||||
// A tiny sky→horizon→ground vertical gradient as an equirect env source (canvas, no asset). PMREM'd
|
||||
// into scene.environment so PBR content is lit by neutral IBL instead of rendering dark — Lane D's
|
||||
// rig-fleet peds bake their impostor atlas from scene.environment (sim.js), and future GLB props read it.
|
||||
function gradientEquirect(THREE) {
|
||||
const c = document.createElement('canvas'); c.width = 8; c.height = 64;
|
||||
const g = c.getContext('2d');
|
||||
const grad = g.createLinearGradient(0, 0, 0, 64);
|
||||
grad.addColorStop(0.00, '#9fb6d6'); // zenith sky
|
||||
grad.addColorStop(0.50, '#cdccc0'); // horizon haze
|
||||
grad.addColorStop(1.00, '#5c5548'); // ground bounce
|
||||
g.fillStyle = grad; g.fillRect(0, 0, 8, 64);
|
||||
const tex = new THREE.CanvasTexture(c);
|
||||
tex.mapping = THREE.EquirectangularReflectionMapping;
|
||||
tex.colorSpace = THREE.SRGBColorSpace; tex.needsUpdate = true;
|
||||
return tex;
|
||||
}
|
||||
|
||||
export function createLighting(scene, plan, skins, { radius = 3, shadows = true } = {}) {
|
||||
const group = new THREE.Group();
|
||||
group.name = 'lighting';
|
||||
@ -54,6 +71,7 @@ export function createLighting(scene, plan, skins, { radius = 3, shadows = true
|
||||
const DAY_SECONDS = 240; // one full cycle
|
||||
let onNightChange = null;
|
||||
let renderer = null;
|
||||
let envRT = null; // PMREM env render target backing scene.environment
|
||||
|
||||
function apply(i) {
|
||||
const [, sunI, sunC, hSky, hGnd, hI, skyTint, fogC, exposure, isNight] = SEG[i];
|
||||
@ -91,10 +109,25 @@ export function createLighting(scene, plan, skins, { radius = 3, shadows = true
|
||||
return { seg, label: SEG[seg][0], hour: HOUR[seg], night, frac };
|
||||
}
|
||||
|
||||
function attachRenderer(r) { renderer = r; r.toneMappingExposure = SEG[seg][8]; }
|
||||
function attachRenderer(r) {
|
||||
renderer = r;
|
||||
r.toneMappingExposure = SEG[seg][8];
|
||||
// set scene.environment now (needs the renderer for PMREM). Called before citizens construct,
|
||||
// so Lane D's ped impostor atlas bakes against a real environment. One neutral env for all
|
||||
// segments — the atlas bakes once, and the mostly-non-metal streetscape is barely affected.
|
||||
if (!envRT) {
|
||||
const pmrem = new THREE.PMREMGenerator(r);
|
||||
const eq = gradientEquirect(THREE);
|
||||
envRT = pmrem.fromEquirectangular(eq);
|
||||
scene.environment = envRT.texture;
|
||||
eq.dispose(); pmrem.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function dispose() {
|
||||
scene.fog = null;
|
||||
scene.environment = null;
|
||||
if (envRT) { envRT.dispose(); envRT = null; }
|
||||
dome.geometry.dispose(); skyMat.dispose();
|
||||
scene.remove(group);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user