Give the event banners a top-down night gradient so they read as lit cloth
No files matched your search
@@ -8,6 +8,7 @@ Semantic Versioning.
|
||||
|
||||
### Fixed
|
||||
|
||||
- The red event banners are lit from the top down at night instead of reading as flat red cards.
|
||||
- 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
|
||||
frame by less than one 255th of a level; it now throws a visible pool on the door and the pavement
|
||||
|
||||
@@ -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
|
||||
(`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.
|
||||
- **Emissive materials can carry a per-material night energy.** `set_night_mode` used to write one
|
||||
multiplier into every `_marquee_emissive` entry, which flattens any gradient. It now reads
|
||||
`mat.get_meta("night_energy", 2.0)`, so a multi-strip panel can keep its top-to-bottom ratio
|
||||
(the event banners: 2.6 → 1.4).
|
||||
- **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
|
||||
|
||||
@@ -961,8 +961,10 @@ scorecard source, this milestone is the actionable list.
|
||||
20 m range and a 14° cone changed the frame by **0.1/255**. Now 10 energy, 45 m, 24°, tilted 5°
|
||||
down — the aimed region goes 13.5 → 29.7 and the near pavement 3.7 → 11.7 (0–255), and the
|
||||
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
|
||||
luminance against the reference night board and adjust only if it still clips.
|
||||
- [x] **Event banners read as lit cloth.** Measured flat top-to-bottom (114 → 125/255) with no
|
||||
clipping, so the problem was not brightness but the missing gradient: four stacked strips
|
||||
with night energies 2.6/2.2/1.8/1.4 now run 135 → 84, carried per material via `night_energy`
|
||||
metadata so `set_night_mode` keeps the ratio. Daylight is unchanged and nothing clips.
|
||||
- [x] **Street-lamp pools.** Added a `lamp_late` shot that frames a lamp, and made the lamps
|
||||
`StreetLamp_*` so they tune apart from the sconces. Attenuation must stay 1.0 (the venue test
|
||||
requires physical falloff), so the pool comes from range and energy: 16 m/2.2 → **10 m/8.0**
|
||||
|
||||
@@ -334,7 +334,21 @@ and energy:
|
||||
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.
|
||||
### Event banners read as lit cloth (2026-11-06)
|
||||
|
||||
The banners were one flat emissive panel, so they measured the same luminance from the mounting bar
|
||||
to the hem (114/121/122/125 down the panel) and read as a painted red card rather than lit fabric.
|
||||
They are now four stacked strips with a night gradient (energies 2.6 / 2.2 / 1.8 / 1.4), carried per
|
||||
material through `night_energy` metadata so `set_night_mode` keeps the ratio instead of flattening it.
|
||||
|
||||
| | Before | After |
|
||||
| --- | --- | --- |
|
||||
| Vertical profile down a banner | 114 → 125 (flat) | 135 → 84 |
|
||||
| Clipping (p99 / pixels ≥ 250) | 192 / 0.2 % | 192 / 0.2 % |
|
||||
| Daylight read | uniform | uniform (strips flush, no seam) |
|
||||
|
||||
No clipping in either state, and the Compatibility renderer draws it with the same flat emissive
|
||||
material as before — the change is geometry plus per-material energy, not a new shader.
|
||||
|
||||
## Scorecard skeleton
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 899 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 740 KiB After Width: | Height: | Size: 731 KiB |
|
Before Width: | Height: | Size: 564 KiB After Width: | Height: | Size: 562 KiB |
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 439 KiB After Width: | Height: | Size: 666 KiB |
|
Before Width: | Height: | Size: 462 KiB After Width: | Height: | Size: 455 KiB |
|
Before Width: | Height: | Size: 757 KiB After Width: | Height: | Size: 757 KiB |
|
Before Width: | Height: | Size: 384 KiB After Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 615 KiB After Width: | Height: | Size: 615 KiB |
|
Before Width: | Height: | Size: 968 KiB After Width: | Height: | Size: 969 KiB |
|
Before Width: | Height: | Size: 529 KiB After Width: | Height: | Size: 529 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
@@ -1159,10 +1159,21 @@ func _add_masonic_banner(parent: Node3D, x: float, front: float, text: String) -
|
||||
# The reference night photo keeps the event banners readable against the dark
|
||||
# stone: a low warm self-light that the day/night cycle brightens (not a
|
||||
# glowing neon box). Registered with `_marquee_emissive` in `set_night_mode`.
|
||||
var cloth := _add_box(parent, Vector3(2.62, 5.55, 0.06), Vector3(x, 8.2, front + 0.73),
|
||||
red, true, null, Vector2.ONE, "cloth")
|
||||
cloth.material_override = Materials.emissive(red, 0.14)
|
||||
_marquee_emissive.append(cloth.material_override)
|
||||
# Four stacked strips so the banner is brightest at the top, where the mounting bar
|
||||
# and the wash lights are, and falls off towards the hem. A single flat emissive
|
||||
# panel measured the same luminance top to bottom and read as a painted card
|
||||
# (measured: 114/121/122/125 down the panel before this).
|
||||
var strips := 4
|
||||
var strip_height := 5.55 / float(strips)
|
||||
var night_energy := [2.6, 2.2, 1.8, 1.4]
|
||||
for index in strips:
|
||||
var centre_y := 8.2 + 5.55 * 0.5 - strip_height * (float(index) + 0.5)
|
||||
var strip := _add_box(parent, Vector3(2.62, strip_height, 0.06),
|
||||
Vector3(x, centre_y, front + 0.73), red, true, null, Vector2.ONE, "cloth")
|
||||
var strip_mat := Materials.emissive(red, 0.14)
|
||||
strip_mat.set_meta("night_energy", float(night_energy[index]))
|
||||
strip.material_override = strip_mat
|
||||
_marquee_emissive.append(strip_mat)
|
||||
for y in [5.55, 10.85]:
|
||||
_add_box(parent, Vector3(2.82, 0.10, 0.12), Vector3(x, y, front + 0.75),
|
||||
Color(0.78, 0.62, 0.28), true, null, Vector2.ONE, "metal")
|
||||
@@ -2394,7 +2405,10 @@ func set_night_mode(night: bool) -> void:
|
||||
if _ovation_sign:
|
||||
_ovation_sign.modulate = Color(0.90, 0.84, 0.70) if night else Color(0.16, 0.14, 0.12)
|
||||
for mat in _marquee_emissive:
|
||||
mat.emission_energy_multiplier = (2.0 if night else 0.2)
|
||||
# Each marquee material can carry its own night energy: the event banners use a
|
||||
# top-to-bottom gradient so they read as lit cloth instead of a red rectangle.
|
||||
mat.emission_energy_multiplier = (float(mat.get_meta("night_energy", 2.0))
|
||||
if night else 0.2)
|
||||
# Light most, not all, of the windows: a fully lit grid reads as a light box
|
||||
# instead of an occupied building.
|
||||
for i in _window_mats.size():
|
||||
|
||||