class_name UrbanLighting extends RefCounted static func build(parent: Node3D) -> void: var world := WorldEnvironment.new() world.name = "DistrictAtmosphere" var env := Environment.new() env.background_mode = Environment.BG_SKY var sky := Sky.new() var sky_mat := ProceduralSkyMaterial.new() sky_mat.sky_top_color = Color("557c9d") sky_mat.sky_horizon_color = Color("c6c5b4") sky_mat.ground_horizon_color = Color("c6c5b4") sky_mat.ground_bottom_color = Color("806c52") sky.sky_material = sky_mat sky.radiance_size = Sky.RADIANCE_SIZE_256 env.sky = sky env.sky_rotation.y = 0.8 env.background_energy_multiplier = 0.62 env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR # Keep indirect light cool and modest: the sandstone is warmed by the sun, # while loading bays and the backs of cliffs still read as shaded spaces. env.ambient_light_color = Color("b9c5cf") env.ambient_light_sky_contribution = 0.7 env.ambient_light_energy = 0.32 env.reflected_light_source = Environment.REFLECTION_SOURCE_SKY env.tonemap_mode = Environment.TONE_MAPPER_ACES env.tonemap_exposure = 0.95 env.ssao_enabled = RenderingServer.get_current_rendering_method() == "forward_plus" env.ssao_radius = 1.4 env.ssao_intensity = 1.25 env.ssao_power = 1.25 env.ssao_detail = 0.75 env.ssao_light_affect = 0.15 env.fog_enabled = true env.fog_light_color = Color("c5b79c") env.fog_light_energy = 0.7 env.fog_density = 0.0006 env.fog_sky_affect = 0.12 env.fog_aerial_perspective = 0.24 env.glow_enabled = RenderingServer.get_current_rendering_method() == "forward_plus" env.glow_intensity = 0.14 env.glow_bloom = 0.0 world.environment = env parent.add_child(world) var sun := DirectionalLight3D.new() sun.name = "LateAfternoonSun" sun.rotation_degrees = Vector3(-52, -38, 0) sun.light_color = Color("ffe5c3") sun.light_energy = 1.65 sun.light_angular_distance = 0.55 sun.shadow_enabled = true # Balance contact shadows against self-shadow artifacts on large batched surfaces. sun.shadow_bias = 0.05 sun.shadow_normal_bias = 0.5 sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS sun.directional_shadow_max_distance = 95 parent.add_child(sun) PortraitSun.apply(env, sun) # Shadowless fill represents scattered skylight inside the open loading bays. # It lifts local detail without flattening the exterior's sunlight and shade. for x in [-11, 11]: for z in [-18, 18]: var bounce := OmniLight3D.new() bounce.position = Vector3(x, 2.65, z) bounce.name = "WarehouseSkyBounce_%s_%s" % [x, z] bounce.light_color = Color("a6c4d5") bounce.light_energy = 0.16 bounce.omni_range = 7 bounce.omni_attenuation = 1.7 bounce.shadow_enabled = false parent.add_child(bounce)