feat: full cel treatment for Neon Alley — flat toon colors + ink outlines

- LevelMaterials.flat(): toon-banded FLAT color material (no greybox grid
  texture) for dressed maps; cached per tint, rim/spec off
- Neon Alley overrides _box_static: every structure renders flat cel color;
  prop-scale pieces (<10m) get an inverted-hull ink outline scaled to their
  size. Building-scale boxes skip the hull — the inflated plates smear into
  black voids at close range (found via fixed street-camera capture)
- Pylon wires render as flat ink lines; warmer wood + hotter vermilion for
  flat shading (the grid multiply used to brighten tints)
- visual_capture: deterministic street-level shot after the aerial for
  style comparisons

Street capture now reads properly BoomerangX: flat lavender asphalt, hard
light bands, torii framed down the underpass, neon strips + sign glow.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nicholas Butzke
2026-07-18 14:23:37 -04:00
co-authored by Claude Fable 5
parent 0813d0b40d
commit 233f88aee3
3 changed files with 48 additions and 4 deletions
+21 -4
View File
@@ -21,9 +21,9 @@ const ASPHALT := Color(0.24, 0.24, 0.31)
const PAVING := Color(0.4, 0.38, 0.44)
const CONCRETE := Color(0.52, 0.5, 0.55)
const CONCRETE_DARK := Color(0.38, 0.37, 0.44)
const WOOD := Color(0.45, 0.3, 0.18)
const WOOD_DARK := Color(0.32, 0.21, 0.13)
const VERMILION := Color(0.82, 0.25, 0.16) # torii / shrine red
const WOOD := Color(0.52, 0.34, 0.2)
const WOOD_DARK := Color(0.36, 0.24, 0.15)
const VERMILION := Color(0.88, 0.26, 0.16) # torii / shrine red
const METAL := Color(0.42, 0.46, 0.52)
const GLASS := Color(0.6, 0.78, 0.82)
const ROOF_TILE := Color(0.25, 0.3, 0.42)
@@ -39,6 +39,23 @@ const SPAWNS: Array[Vector3] = [
]
## Full cel treatment: every structure gets a FLAT toon color (no greybox
## grid texture) plus an ink outline hull scaled to its size — the same
## inked-silhouette language as the characters. Ground-scale slabs skip the
## outline (a hull around an 80m floor just z-fights the sidewalks).
func _box_static(pos: Vector3, size: Vector3, color: Color, node_name: String = "",
acoustic: String = "") -> StaticBody3D:
var body := super._box_static(pos, size, color, node_name, acoustic)
for mi in body.find_children("*", "MeshInstance3D", false, false):
mi.mesh.surface_set_material(0, LevelMaterials.flat(color))
# Ink outlines on prop-scale pieces only: on building-scale boxes the
# inflated hull plates read as smears at close range.
if maxf(size.x, maxf(size.y, size.z)) < 10.0:
var w := clampf(maxf(size.x, maxf(size.y, size.z)) * 0.008, 0.02, 0.05)
mi.material_overlay = LevelMaterials.outline(w)
return body
func _build_environment() -> void:
var env := LevelEnvironment.add_to(self, "sunset")
# The sunset sky is too dark to light street canyons — use a fixed dusk
@@ -242,7 +259,7 @@ func _build_pylons() -> void:
var wire := MeshInstance3D.new()
var wm := BoxMesh.new()
wm.size = Vector3(0.06, 0.06, 16.0)
wm.material = LevelMaterials.tinted(Color(0.1, 0.1, 0.12))
wm.material = LevelMaterials.flat(Color(0.08, 0.07, 0.1)) # ink line in the sky
wire.mesh = wm
wire.position = Vector3(x - 7.5 * side, 10.0, z + 9.0)
add_child(wire)