lighting: fixed daytime rig, real surface materials, crossing fix
Fixed daytime lighting and basic ambience for the DemoMap: - Sun pitch -50 / yaw 120 (intensity 4, warm), sky light 2.6 with real-time capture, sky atmosphere, height fog, and an unbound post-process volume with fixed exposure (min = max brightness) so no shot washes out or crushes to black depending on how much sky it frames. - Root cause of the washed-out look was NOT the sun: Blender's flat diffuse colours do not survive the FBX->Unreal import. Every site material arrived white and the terrain arrived with WorldGridMaterial. The demo builder now creates and assigns M_Asphalt / M_Concrete / M_Ground / M_RoadPaint. - Crossing fix: each zebra band was its own object, so Blender renamed the duplicates .001/.002 and site assembly (exact-name append) kept only one. All bands are now a single Crossing_Markings mesh (36 verts, 3 bands). - Terrain gets a Ground_Earth material in the builder so it stops importing as a white grid. - Demo cameras: street-level no longer sits inside the facade body (was rendering its back face), and the crossing camera aims at the designated s=130.1 crossing (UE X -14956) looking along the crosswalk. Screenshots re-rendered; the four demo views are marked needs-review for the owner's approval. MEMORY.md records the material-import, exposure, light_color, band-naming and camera-bounds traps.
This commit is contained in:
1 parent
121c0398b0
commit
830ce596fa
37 files changed
+241
-82
No files matched your search
+121
-8
@@ -50,6 +50,29 @@ def spawn(cls, loc, label, rot=None):
|
||||
return actor
|
||||
|
||||
|
||||
def ensure_material(asset_name, rgb):
|
||||
"""Create/reuse a flat-colour material under /Game/Hollywood/Site.
|
||||
|
||||
Used where the FBX material round-trip does not survive import: the terrain
|
||||
arrives with WorldGridMaterial (UE's bright default grid), which reads as a
|
||||
blown-out white field under the demo sun.
|
||||
"""
|
||||
path = f"/Game/Hollywood/Site/{asset_name}"
|
||||
if unreal.EditorAssetLibrary.does_asset_exist(path):
|
||||
return unreal.EditorAssetLibrary.load_asset(path)
|
||||
mat = unreal.AssetToolsHelpers.get_asset_tools().create_asset(
|
||||
asset_name, "/Game/Hollywood/Site", unreal.Material, unreal.MaterialFactoryNew())
|
||||
node = unreal.MaterialEditingLibrary.create_material_expression(
|
||||
mat, unreal.MaterialExpressionConstant3Vector)
|
||||
node.set_editor_property("constant", unreal.LinearColor(rgb[0], rgb[1], rgb[2], 1.0))
|
||||
unreal.MaterialEditingLibrary.connect_material_property(
|
||||
node, "", unreal.MaterialProperty.MP_BASE_COLOR)
|
||||
unreal.MaterialEditingLibrary.recompile_material(mat)
|
||||
unreal.EditorAssetLibrary.save_loaded_asset(mat)
|
||||
log(f"created material {asset_name} rgb={rgb}")
|
||||
return mat
|
||||
|
||||
|
||||
def clear(prefixes=()):
|
||||
removed = 0
|
||||
for actor in unreal.EditorLevelLibrary.get_all_level_actors():
|
||||
@@ -74,12 +97,87 @@ def build():
|
||||
removed = clear(("Demo_", "PlayerStart", "Hero_Facade"))
|
||||
log(f"cleared {removed} previous demo actors")
|
||||
|
||||
# --- lighting ---------------------------------------------------------
|
||||
spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 2000), "Demo_Sun",
|
||||
unreal.Rotator(pitch=-35.0, yaw=200.0, roll=0.0))
|
||||
spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight")
|
||||
# --- lighting: fixed daytime ------------------------------------------
|
||||
# The demo is a fixed daytime scene, not a time-of-day simulation. Three
|
||||
# things matter and each was wrong before:
|
||||
#
|
||||
# 1. Sun angle. The hero facade front faces -Y and the road faces +Z. A sun
|
||||
# at yaw 120 / pitch -50 shines toward (-X, +Y, down), so it lights both
|
||||
# the facade front and the carriageway instead of raking across them.
|
||||
# 2. Exposure. Auto-exposure made the same road washed-out in one shot and
|
||||
# near-black in the next, because each camera framed a different amount
|
||||
# of sky. A manual-exposure post-process volume pins it.
|
||||
# 3. Ambience. A height fog gives the street depth and hides the terrain
|
||||
# edge that otherwise reads as a black band at the horizon.
|
||||
sun = spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 2000), "Demo_Sun",
|
||||
unreal.Rotator(pitch=-50.0, yaw=120.0, roll=0.0))
|
||||
if sun:
|
||||
comp = sun.get_component_by_class(unreal.DirectionalLightComponent)
|
||||
if comp:
|
||||
for prop, value in (
|
||||
("intensity", 4.0),
|
||||
("light_color", unreal.Color(r=255, g=245, b=230, a=255)),
|
||||
("atmosphere_sun_light", True),
|
||||
):
|
||||
try:
|
||||
comp.set_editor_property(prop, value)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"sun.{prop} not set: {exc!r}")
|
||||
log("staged: Demo_Sun (pitch -50, yaw 120, intensity 4, warm)")
|
||||
|
||||
sky = spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight")
|
||||
if sky:
|
||||
comp = sky.get_component_by_class(unreal.SkyLightComponent)
|
||||
if comp:
|
||||
for prop, value in (("intensity", 2.6), ("real_time_capture", True)):
|
||||
try:
|
||||
comp.set_editor_property(prop, value)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"sky.{prop} not set: {exc!r}")
|
||||
log("staged: Demo_SkyLight (intensity 2.6, real-time capture)")
|
||||
|
||||
spawn(unreal.SkyAtmosphere, unreal.Vector(0, 0, 0), "Demo_Sky")
|
||||
log("staged: sun, sky light, sky atmosphere")
|
||||
log("staged: Demo_Sky (sky atmosphere)")
|
||||
|
||||
fog = spawn(unreal.ExponentialHeightFog, unreal.Vector(0, 0, 0), "Demo_Fog")
|
||||
if fog:
|
||||
comp = fog.get_component_by_class(unreal.ExponentialHeightFogComponent)
|
||||
if comp:
|
||||
for prop, value in (
|
||||
("fog_density", 0.008),
|
||||
("fog_height_falloff", 0.15),
|
||||
("start_distance", 3000.0),
|
||||
):
|
||||
try:
|
||||
comp.set_editor_property(prop, value)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"fog.{prop} not set: {exc!r}")
|
||||
log("staged: Demo_Fog (height fog, density 0.008)")
|
||||
|
||||
# Fixed exposure: without this the same road renders washed out or black
|
||||
# depending on how much sky the camera frames. Pinning min == max brightness
|
||||
# freezes the exposure at one value (the classic fixed-exposure trick);
|
||||
# AEM_MANUAL with a bias was tried first and blew the frame out.
|
||||
ppv = spawn(unreal.PostProcessVolume, unreal.Vector(0, 0, 0), "Demo_PostProcess")
|
||||
if ppv:
|
||||
ppv.set_editor_property("unbound", True)
|
||||
settings = ppv.get_editor_property("settings")
|
||||
for prop, value in (
|
||||
("override_auto_exposure_method", True),
|
||||
("auto_exposure_method", unreal.AutoExposureMethod.AEM_HISTOGRAM),
|
||||
("override_auto_exposure_min_brightness", True),
|
||||
("auto_exposure_min_brightness", 1.0),
|
||||
("override_auto_exposure_max_brightness", True),
|
||||
("auto_exposure_max_brightness", 1.0),
|
||||
("override_auto_exposure_bias", True),
|
||||
("auto_exposure_bias", 0.0),
|
||||
):
|
||||
try:
|
||||
settings.set_editor_property(prop, value)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"pp.{prop} not set: {exc!r}")
|
||||
ppv.set_editor_property("settings", settings)
|
||||
log("staged: Demo_PostProcess (fixed exposure, min=max brightness 1.0)")
|
||||
|
||||
# --- hero facade on the measured building line ------------------------
|
||||
hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade")
|
||||
@@ -93,9 +191,21 @@ def build():
|
||||
log("MISSING: SM_HeroFacade — run Tools/ue_hero_facade_import.py")
|
||||
|
||||
# --- site meshes, if they have been imported --------------------------
|
||||
# Blender's flat diffuse colours do not survive FBX -> Unreal: Interchange
|
||||
# builds a material with a default white base colour, and the terrain even
|
||||
# lands with WorldGridMaterial. Every site surface therefore rendered white,
|
||||
# which is what washed out the demo. Assign explicit colours per mesh here.
|
||||
SURFACE_MATERIALS = {
|
||||
"Terrain_DEM": ("M_Ground", (0.30, 0.28, 0.25)),
|
||||
"Road_Hollywood": ("M_Asphalt", (0.055, 0.055, 0.06)),
|
||||
"Sidewalk_South": ("M_Concrete", (0.52, 0.50, 0.47)),
|
||||
"Sidewalk_North": ("M_Concrete", (0.52, 0.50, 0.47)),
|
||||
"Kerb_South": ("M_Concrete", (0.52, 0.50, 0.47)),
|
||||
"Kerb_North": ("M_Concrete", (0.52, 0.50, 0.47)),
|
||||
"Crossing_Markings": ("M_RoadPaint", (0.80, 0.80, 0.78)),
|
||||
}
|
||||
imported = 0
|
||||
for name in ("Terrain_DEM", "Road_Hollywood", "Sidewalk_South", "Sidewalk_North",
|
||||
"Kerb_South", "Kerb_North", "Crossing_Markings"):
|
||||
for name, (mat_name, rgb) in SURFACE_MATERIALS.items():
|
||||
mesh = unreal.EditorAssetLibrary.load_asset(f"/Game/Hollywood/Site/{name}")
|
||||
if mesh is None:
|
||||
continue
|
||||
@@ -103,8 +213,11 @@ def build():
|
||||
if actor:
|
||||
actor.static_mesh_component.set_static_mesh(mesh)
|
||||
actor.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC)
|
||||
mat = ensure_material(mat_name, rgb)
|
||||
if mat:
|
||||
actor.static_mesh_component.set_material(0, mat)
|
||||
imported += 1
|
||||
log(f"staged {imported} site meshes from /Game/Hollywood/Site")
|
||||
log(f"staged {imported} site meshes with explicit surface materials")
|
||||
|
||||
# --- player start: north sidewalk, facing the hero frontage -------------
|
||||
# Signs were measured from the imported meshes rather than assumed: the FBX
|
||||
|
||||
@@ -258,8 +258,17 @@ try:
|
||||
# 14 m back so the 14.5 m elevation fits: at 2 m the camera sees only
|
||||
# the colonnade's underside.
|
||||
("demo-spawn-view", unreal.Vector(-10722.5, -3500, 165), unreal.Vector(-10722.5, -1450, 700)),
|
||||
("demo-street-level", unreal.Vector(-11000, -400, 165), unreal.Vector(-10722.5, -1450, 500)),
|
||||
("demo-crossing", unreal.Vector(-23750, -1800, 480), unreal.Vector(-24291, -1400, 300)),
|
||||
# Street level, from the north sidewalk: the old camera sat at Y -400,
|
||||
# inside the facade body (which spans Y -1457..-200), so it looked at
|
||||
# the unlit back face. Y -2600 is on the sidewalk in front of the lit
|
||||
# elevation.
|
||||
("demo-street-level", unreal.Vector(-10850, -2600, 170), unreal.Vector(-10722.5, -1450, 400)),
|
||||
# The designated mid-block crossing. Street arc length runs from the
|
||||
# west end (s=0 at X -27966 cm), so s=130.1 m is UE X -14956, not the
|
||||
# -24291 the old camera used (that is the s=36.6 crossing). Camera sits
|
||||
# on the north sidewalk looking along the crosswalk itself, which is
|
||||
# the pedestrian's view and shows the zebra bars as bars.
|
||||
("demo-crossing", unreal.Vector(-15250, -2500, 400), unreal.Vector(-14956, 400, 150)),
|
||||
# the two north-side background buildings (TCL, Tussaud's) seen from
|
||||
# the south sidewalk, across Hollywood Blvd: their frontage and mass.
|
||||
("demo-north-buildings", unreal.Vector(-22800, -1000, 400), unreal.Vector(-22800, 3000, 300)),
|
||||
|
||||
Reference in new issue
Block a user