Give the street lamps real pools: 10 m range and 8 energy at physical falloff
Full build / Import + headless tests (push) Successful in 37s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-06 20:29:26 +01:00
1 parent 16dc1dfea4
commit 7546092c01
21 files changed
+40 -7

No files matched your search

+1
View File
@@ -8,6 +8,7 @@ Semantic Versioning.
### Fixed ### Fixed
- Street lamps now throw a warm pool on the pavement instead of dimly washing the whole walkway.
- The flashlight actually lights what it points at. It was tuned to a beam so weak it changed the - The flashlight actually lights what it points at. It was tuned to a beam so weak it changed the
frame by less than one 255th of a level; it now throws a visible pool on the door and the pavement frame by less than one 255th of a level; it now throws a visible pool on the door and the pavement
ahead, in both venues. ahead, in both venues.
+4
View File
@@ -130,6 +130,10 @@ canonical implemented-features list in `docs/project/development-status.md`.
gear library. The procedural library + MakeHuman head stay in the tree as the tested fallback gear library. The procedural library + MakeHuman head stay in the tree as the tested fallback
(`build --source procedural`), not in the shipped roster. Silhouette variety is the known (`build --source procedural`), not in the shipped roster. Silhouette variety is the known
regression — three meshes for twelve roles — and the modular part library is the `0.9.10` fix. regression — three meshes for twelve roles — and the modular part library is the `0.9.10` fix.
- **Venue lights must keep `omni_attenuation == 1.0`** — `test_world.test_venue_lights_use_physical_falloff`
enforces physical falloff on every Omni/Spot in all three venues, so a "pool" cannot come from
sharpening the curve. Use `omni_range` + energy instead: 10 m / energy 8 gives a brighter pool and
a darker gap than the old 16 m / 2.2.
- **Tune lights against a measurement, not a look (2026-11-06):** the shipped flashlight changed the - **Tune lights against a measurement, not a look (2026-11-06):** the shipped flashlight changed the
late-night frame by 0.1/255 and nobody noticed. `capture_realism.gd --stages=late --flashlight` late-night frame by 0.1/255 and nobody noticed. `capture_realism.gd --stages=late --flashlight`
renders the same frame with the lamp on and off; mean luminance of the aimed region and the near renders the same frame with the lamp on and off; mean luminance of the aimed region and the near
+4 -3
View File
@@ -963,9 +963,10 @@ scorecard source, this milestone is the actionable list.
committed `06-night-flashlight` shot shows the beam on the steps and the NPC in front. committed `06-night-flashlight` shot shows the beam on the steps and the NPC in front.
- [ ] Marquee/event-banner emissive read under the Compatibility renderer: measure the banner - [ ] Marquee/event-banner emissive read under the Compatibility renderer: measure the banner
luminance against the reference night board and adjust only if it still clips. luminance against the reference night board and adjust only if it still clips.
- [ ] Street-lamp pools: the night ground sits at 3.8/255 away from the sconces. Raising the lamp - [x] **Street-lamp pools.** Added a `lamp_late` shot that frames a lamp, and made the lamps
energy was rejected once for washing the sidewalk grey, so this needs a capture-driven `StreetLamp_*` so they tune apart from the sconces. Attenuation must stay 1.0 (the venue test
range/attenuation change rather than more energy. requires physical falloff), so the pool comes from range and energy: 16 m/2.2 → **10 m/8.0**
takes the pool 14.1 → 16.0 and the gap between poles 2.7 → 1.3, pool/gap 5.2 → 12.3.
- [x] Refresh `docs/screenshots/` for the whole roster and the new flashlight; `check_screenshots.sh` - [x] Refresh `docs/screenshots/` for the whole roster and the new flashlight; `check_screenshots.sh`
reports 21 good / 0 bad. reports 21 good / 0 bad.
- [ ] Set dressing: fix the Joke Shop queue story (podium/stanchion line at the door), rope - [ ] Set dressing: fix the Joke Shop queue story (podium/stanchion line at the door), rope
+18 -3
View File
@@ -317,9 +317,24 @@ it was effectively off. The shipped values are 10 energy, 45 m, 24°, tilted 5°
on the door or person being checked *and* puts a pool on the pavement in front, without flooding the on the door or person being checked *and* puts a pool on the pavement in front, without flooding the
facade. Verified in both venues (Hollywood facade and the Joke Shop door). facade. Verified in both venues (Hollywood facade and the Joke Shop door).
Still open from the milestone: marquee emissive under Compatibility, and the street-lamp pools — the ### Street-lamp pools, measured
night ground sits at 3.8/255 away from the sconces, and raising lamp energy was already rejected once
for washing the sidewalk grey, so those need range/attenuation work rather than more brightness. A new `lamp_late` shot frames a street lamp so the pool under it can be sampled. The lamp is
`StreetLamp_*` (named so `set_night_mode` can tune it apart from the sconce and marquee glows).
Attenuation stays at 1.0 — the venue test requires physical falloff — so the pool is made by range
and energy:
| Setting | Pool | Gap | Pool/gap |
| --- | --- | --- | --- |
| old: 16 m, energy 2.2 | 14.1 | 2.7 | 5.2 |
| 16 m, energy 4.0 | 21.1 | 6.5 | 3.3 (washed) |
| 8.5 m, energy 6.5 | 11.5 | 1.3 | 8.9 |
| **10 m, energy 8.0 (shipped)** | **16.0** | **1.3** | **12.3** |
Mean luminance 0–255. The shipped values brighten the pool past the old setting while darkening the
gap between poles, which is what "pools, not a wash" means numerically.
Still open from the milestone: marquee emissive under Compatibility.
## Scorecard skeleton ## Scorecard skeleton
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 899 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 KiB

After

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 KiB

After

Width:  |  Height:  |  Size: 564 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 KiB

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 KiB

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 KiB

After

Width:  |  Height:  |  Size: 757 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 KiB

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 KiB

After

Width:  |  Height:  |  Size: 615 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 KiB

After

Width:  |  Height:  |  Size: 968 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 529 KiB

After

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

+10 -1
View File
@@ -1953,8 +1953,12 @@ func _build_street_furniture() -> void:
180.0 if lamp_pos.x < 0.0 else 0.0) 180.0 if lamp_pos.x < 0.0 else 0.0)
holder.name = "Lamp_%d" % index holder.name = "Lamp_%d" % index
var omni := OmniLight3D.new() var omni := OmniLight3D.new()
# Named so `set_night_mode` can tune the street pools on their own: a long
# range at low energy lit the whole walkway flat, which the night pass
# rejected as "washed grey". Short range + more energy makes pools.
omni.name = "StreetLamp_%d" % index
omni.position = Vector3(-0.85, 4.65, 0) omni.position = Vector3(-0.85, 4.65, 0)
omni.omni_range = 16.0 if Materials.modern_light_falloff() else 12.0 omni.omni_range = 10.0 if Materials.modern_light_falloff() else 7.0
omni.omni_attenuation = 1.0 omni.omni_attenuation = 1.0
omni.light_energy = 0.0 omni.light_energy = 0.0
omni.light_color = Color(1, 0.93, 0.75) omni.light_color = Color(1, 0.93, 0.75)
@@ -2349,6 +2353,11 @@ func set_night_mode(night: bool) -> void:
var lamp_energy := 2.2 var lamp_energy := 2.2
if omni.name == "LanternGlow": if omni.name == "LanternGlow":
lamp_energy = 3.0 if venue_id == "joke_shop" else 1.3 lamp_energy = 3.0 if venue_id == "joke_shop" else 1.3
elif omni.name.begins_with("StreetLamp"):
# Measured on the late-night avenue: the walkway sat at 4/255 with a 16 m
# range, so the pools never read. A short range with higher energy puts a
# warm pool under each pole and keeps the gaps dark.
lamp_energy = 8.0
omni.light_energy = (lamp_energy if night else 0.0) omni.light_energy = (lamp_energy if night else 0.0)
if _hill_mat != null: if _hill_mat != null:
# The unshaded hillside has no real lighting, so its tint follows the # The unshaded hillside has no real lighting, so its tint follows the
+3
View File
@@ -51,6 +51,9 @@ const SHOTS_EVENING := [
const SHOTS_LATE := [ const SHOTS_LATE := [
{"name": "entrance_late", "pos": Vector3(0, 0.1, 9.0), "yaw": 0.0, "pitch": 3.0}, {"name": "entrance_late", "pos": Vector3(0, 0.1, 9.0), "yaw": 0.0, "pitch": 3.0},
{"name": "street_late", "pos": Vector3(0, 0.1, 10.5), "yaw": 180.0, "pitch": 2.0}, {"name": "street_late", "pos": Vector3(0, 0.1, 10.5), "yaw": 180.0, "pitch": 2.0},
# Framed on a street lamp so the light pool under it is measurable; the avenue
# shots above look past the poles.
{"name": "lamp_late", "pos": Vector3(0, 0.1, 12.0), "yaw": -65.0, "pitch": 1.0},
] ]
const SHOTS_JOKE := [ const SHOTS_JOKE := [
{"name": "joke_shop_door", "pos": Vector3(-2.0, 0.1, 13.2), "yaw": 12.0, "pitch": 12.0}, {"name": "joke_shop_door", "pos": Vector3(-2.0, 0.1, 13.2), "yaw": 12.0, "pitch": 12.0},