Banner lettering (JIMMY KIMMEL LIVE): new Tools/gen/generate_banner_texture.py
draws the exact title with Pillow + Liberation Sans Bold - an image model would
mangle a trademark string, and Qwen-Image 2.1 is research-only. Gold JIMMY /
KIMMEL / LIVE stacked on a crimson ground. ue_hero_facade_import.py generalises
import_albedo to import_texture and wires the banner into M_Facade_Banner_Ref as
Base Color (tiling 1.0), replacing the flat dark tint with a brighter red per the
owner's 'less dark, more bright'.
Re-rendered all three ReviewMap staging shots (front, oblique, portals) and
updated their Screenshots/README.md status rows.
The hero facade rework is now closed at 'surface detail that reads at 45 m'. The
remaining elevation work - volute capital depth, lattice grille depth, and the
full realism pass - is deferred to 0.9.0 per the owner, and the 0.9.0 hero item
records the hand-off.
The motto band and moulded surround had the same burial as the medallions: offset
0.06 left their front face at Y -0.44, inside the 1.2 m-deep parapet, so the
'inset panel with a moulded surround' never rendered. Only the inscription (moved
to 0.40 in the previous commit) read.
- Band recessed at offset 0.34 (Y -0.16), surround proud at 0.43 (Y -0.07),
inscription stays 0.40 (Y -0.10).
- Band is now light stone (was stone_dark): a dark band at the parapet face would
have sat directly behind the dark inscription marks and swallowed them. The
reference is dark incised lettering on a pale band.
- Removed the dead duplicate 'Hero_MottoBand 0.40' entry - the earlier 0.06 match
won, so the 0.40 was silently ignored.
Rendered and judged; the advisory judge no longer flags the band.
The medallions were not just flat - they were buried. seat_on_front put
Hero_Medallion at offset 0.08 (front Y -0.42) while the 1.2 m-deep parapet stands
at Y -0.15, so both discs sat inside the parapet and never rendered. The motto
band and surround have the same burial (offset 0.06) and are a separate follow-up.
- Three stepped layers per medallion with per-layer prefixes so seat_on_front gives
each its own stand-off: Rim (0.55 m, dark, offset 0.36 -> Y -0.14), Field
(0.38 m, light, offset 0.43 -> Y -0.07), Boss (0.15 m, dark, offset 0.50 -> Y 0.00).
A single Hero_Medallion prefix would both flatten the relief and (via startswith)
swallow the specific prefixes, so it is removed.
- Moved from +/-6.2 (inside the inscription text, which spans +/-6.87) to +/-9.8.
- Fixed Tools/review/hero_iterate.sh, which still had the pre-tools-move
'cd dirname/..' and landed in Tools/ instead of the repo root.
Rendered and judged; the advisory two-model judge (no, 0.93) no longer flags the
medallions. Owner review pending.
The reference's most distinctive architectural feature is three lines of incised capitals across the attic.
inscription() lays 112 letter marks in three lines, in the shadow stone so they read as dark incisions at 45 m
rather than disappearing into a same-colour relief - which is exactly what the first attempt did.
Positioning was the lesson: the parapet is 1.2 m deep and stands in FRONT of the wall plane, so marks seated on
FRONT_Y were hidden behind it and rendered invisible. They are now seated on the parapet face (FRONT_Y + 0.40),
which is where the reference puts the lettering too.
Still open in the architectural pass, recorded in TODO.md: medallion relief (the discs are flush and empty),
banner lettering (needs a texture, not geometry), and depth on the capitals and window grilles.
Rows 4-6 re-rendered and pending.
The owner rejected the previous pass on three counts - too saturated, too dark, and the albedo was wrong for the
building. All three were true, and the reason the colour work kept missing is that the albedo never reached the
material: import_albedo() resolved the repository root one level short after the tools move, so every 'stone'
render was the flat tint alone. That is fixed first.
Then measured instead of guessed: the reference's sunlit stone samples sRGB ~0.49 (linear ~0.19), attic
highlight ~0.75, shaded recess ~0.43, and it is nearly neutral, not warm. New albedo generated for a pale
low-contrast marble-limestone ashlar (two checkpoints compared, AlbedoBase won) and the tint moved to
(0.47, 0.455, 0.43) with the shadow at (0.30, 0.29, 0.27), which lands lit stone around 0.62 sRGB - brighter
than the last pass and close to the photographs.
The elevation now reads as pale, low-saturation concrete/marble with thin-jointed ashlar. Row 4-6 re-rendered
and pending. The architectural pass the owner also asked for - carved inscription, medallions, banner lettering,
capital and grille depth - is untouched and recorded as the next step.
THIRD_PARTY_NOTICES carries the new seed and prompt.
The generated ashlar albedo never showed for two reasons that had nothing to do with the material graph,
which was verified correct the whole time (TextureSampleParameter2D -> Multiply -> Base Color, colour sampler,
texture set, 6x UV tiling):
1. **The map overrode every hero slot.** The generic per-slot material pass in ue_build_demo_map.py assigned
the facade KIT's flat stone to every actor whose slot names looked like stone, banner, glass - including
Hero_Facade. Whatever the import authored was replaced at map build time. The hero is now excluded and gets
its own materials.
2. **Mesh slot assignment does not persist.** Assigning to mesh.get_editor_property('static_materials') returns a
copy; after a reload the mesh still pointed at the original imported materials (measured twice). Component
level overrides do persist in the saved map, so apply_hero_materials() sets them in both builders.
The elevation now renders as coursed, grainy warm limestone with banners, window bays and recessed portals.
Rows 4-6 re-rendered and pending review; the comparison plate is regenerated. Still missing against the
reference: carved inscription, medallion relief, banner lettering, crimson banner tone. The two-model judge
returns no/no (0.90/0.95) - it wants the text and detail that are still absent, which is at least the right
complaint this time.
Used the workflow integration from the previous step for real: generated a warm limestone ashlar albedo
with two profiles compared (AlbedoBase 17.04 vs Krea-2 13.90, AlbedoBase won), saved it as
Art/textures/generated/T_FacadeAshlar_AI.png beside its provenance sidecar, and imported it to
/Game/Hollywood/Textures.
ue_hero_facade_import.py now imports that albedo and, for the two stone slots, builds a material with
TextureSampleParameter2D -> Multiply(tint) -> Base Color, tiling the UVs 6x, so the map carries the coursing
and the tint keeps the value inside the reference's range.
Two real bugs fixed on the way:
- the albedo path was resolved against unreal.Paths.project_dir() (Game/GigLine), not the repository root, so
the import silently skipped;
- the authored materials were never saved - only the mesh was - so after a reload the slots pointed at
nothing and the elevation fell back to one default colour.
Honest status: the nodes are verified present and saved (Constant3Vector, TextureSampleParameter2D,
TextureCoordinate, Multiply) and the source mesh has UVs, but the render still shows the flat tint. Recorded
in TODO.md with the next probe: read the compiled Base Color pin instead of the node list.
THIRD_PARTY_NOTICES.md gains the AlbedoBase row (commercial use, credit required).
Iterated the loop five times against Art/reference/hero-masonic/. What took the iterations was the material,
not the geometry:
- M_FacadeStone in /Game/Hollywood/Site is the KIT stone; the hero does not use it, so warming it changed
nothing.
- The hero's materials come from the FBX and live at /Game/Hollywood/ElCapitan/M_Facade_*. Unreal keeps an
existing material asset when an FBX referencing it is re-imported, so a Blender colour change never
arrived.
- Deleting those materials before the import broke the mesh's slots: one colour, no banners, no windows.
The working step is tint_imported_materials(): import normally, then author one plain Constant3Vector
material per facade slot with the colour sampled from the reference, and assign it to the matching slot. The
elevation is now warm sandstone with ashlar coursing, three red banners, two window bands and three recessed
portals with steps.
Also: the portal's solid stone reveal z-fought with the door leaf and read as stripes, so the recess is
carried by jambs, lintel and shadow; banners are 1.35 x 6.2 m hung from 7.2 m instead of 1.55 x 5.4.
Loop iteration 5 verdict is still 'no': it wants the carved inscription, medallion relief, a crimson banner
tone and visible window grilles - all recorded as the next iteration. Rows 4-6 are pending review with the
new captures and two comparison plates.
Tools/hero_facade_build.py builds the north elevation parametrically and writes
a JSON report naming the evidence behind every part: the 25.75 m frontage and
14.5 m height are measured, the 4.96 m column bay comes from the sibling notes
and matches that frontage, the three portal flights follow the photographs (five
risers, overturning the inherited eight-step, 12 m wide claim), and the rest is
labelled assumption.
Tools/ue_hero_facade_import.py imports it with the ue_metric_v1 preset
(2604 x 1257 x 1450 cm, 1892 tris, 4 materials) and places it on the measured
building line of /Game/Hollywood/DemoMap.
Two new review shots at review-04 and review-05, both pending approval. Camera
placement cost four renders: the first two sat inside the facade body, and the
frontage faces Unreal -Y, so a camera has to stand at Y < -1450 cm, not north of
the building line in project terms.