class_name QuarryRealism extends RefCounted const ASSETS := "res://assets/scan/quarry_realism/" static var scenes: Dictionary = {} static func place(parent: Node3D, id: String, bottom: Vector3, dimensions: Vector3, yaw: float = 0.0) -> Node3D: if not scenes.has(id): scenes[id] = load(ASSETS + id + "/model.scn") var model: Node3D = scenes[id].instantiate() var entries: Array = [] QuarryLandscape.collect(model, Transform3D.IDENTITY, entries) var bounds := AABB() var first := true for entry: Array in entries: var aabb: AABB = entry[1] * entry[0].get_aabb() bounds = aabb if first else bounds.merge(aabb) first = false var fit := dimensions / bounds.size model.scale = fit model.position = -Vector3(bounds.get_center().x, bounds.position.y, bounds.get_center().z) * fit var anchor := Node3D.new() anchor.name = "Scan_" + id anchor.position = bottom anchor.rotation.y = yaw parent.add_child(anchor) anchor.add_child(model) for mesh in model.find_children("*", "MeshInstance3D", true, false): mesh.visibility_range_end = 85 mesh.visibility_range_end_margin = 10 return anchor static func apply(arena: RelayArena) -> void: if arena.map_id != "quarry" or DisplayServer.get_name() == "headless": return var replacements: Dictionary = {} for key: String in UrbanMaterials.cache: var asset := "" if key.begins_with("asphalt"): asset = "aerial_asphalt_01" elif key.begins_with("concrete") or key.begins_with("plaster"): asset = "concrete_wall_007" elif key.begins_with("metal"): asset = "rusty_metal_02" if asset.is_empty(): continue var source: StandardMaterial3D = UrbanMaterials.cache[key] var mat := (load("res://assets/textures/quarry_realism/" + asset + "/surface.tres") as StandardMaterial3D).duplicate() as StandardMaterial3D mat.albedo_color = source.albedo_color.lerp(Color.WHITE, 0.5) if asset == "rusty_metal_02": mat.albedo_color = source.albedo_color.darkened(0.3) if asset == "aerial_asphalt_01": mat.albedo_color = Color("757575") mat.normal_scale = 0.45 replacements[source.get_instance_id()] = mat for node in arena.find_children("*", "MeshInstance3D", true, false): for surface in node.mesh.get_surface_count(): var original: Material = node.get_active_material(surface) if original != null and replacements.has(original.get_instance_id()): if node.material_override != null: node.material_override = replacements[original.get_instance_id()] else: node.set_surface_override_material(surface, replacements[original.get_instance_id()]) var detail := Node3D.new() detail.name = "PhotogrammetryDressing" arena.add_child(detail) # Replace only the art enclosed by existing solid cover bounds. for child in arena.get_children(): if not child is Node3D: continue if str(child.name).begins_with("UrbanSaloon"): child.visible = false place(detail, "covered_car", child.position, Vector3(2.29,1.91,4.58)) if child.visible and child.find_child("ConcreteBarrier*", true, false) != null: child.visible = false place(detail, "concrete_road_barrier", child.position - Vector3(0,0.7,0), Vector3(3.2,1.4,1.5)) for origin in arena.building_origins: place(detail, "portable_generator", origin + Vector3(-2,0,0), Vector3(1.65,1.28,2.3), 0) # Recessed against a solid facade pier: never inside an entrance opening. place(detail, "Barrel_02", origin + Vector3(3.35,0.03,5.38), Vector3(0.58,0.88,0.58), origin.z) # Low, flat discarded tyres hug exterior wall piers, away from doorways. place(detail, "old_tyre", origin + Vector3(3.9,0.04,5.95), Vector3(0.65,0.16,0.65), origin.x) var freight := arena.get_node_or_null("DepotDetails") if freight != null: for location: Vector3 in DepotDetails.FREIGHT_POSITIONS: # Scanned timber replaces the visually repeated flat cargo faces. for side in [-1,1]: place(detail, "wooden_crate_02", location + Vector3(side * 0.8,-0.7,0), Vector3(1.58,1.4,1.5)) lighting(arena) static func lighting(arena: RelayArena) -> void: var world := arena.get_node("DistrictAtmosphere") as WorldEnvironment var env := world.environment var sky := Sky.new() var panorama := PanoramaSkyMaterial.new() panorama.panorama = load("res://assets/sky/relay_clouds.hdr") sky.sky_material = panorama sky.radiance_size = Sky.RADIANCE_SIZE_256 env.sky = sky env.sky_rotation = Vector3(0,0.8,0) env.background_energy_multiplier = 0.85 env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY env.ambient_light_sky_contribution = 1.0 env.ambient_light_energy = 0.3 env.tonemap_exposure = 0.9 env.ssao_radius = 1.0 env.ssao_intensity = 1.1 env.ssao_detail = 0.65 env.fog_density = 0.0008 env.fog_light_color = Color("bac6cd") env.fog_aerial_perspective = 0.35 var sun := arena.get_node("LateAfternoonSun") as DirectionalLight3D sun.light_color = Color("fff3de") sun.light_energy = 1.35 sun.light_angular_distance = 0.8 sun.shadow_normal_bias = 0.3 static func quality(arena: RelayArena, level: int) -> void: if arena.map_id != "quarry": return var world := arena.get_node_or_null("DistrictAtmosphere") as WorldEnvironment if world == null: return var forward := RenderingServer.get_current_rendering_method() == "forward_plus" world.environment.ssil_enabled = forward and level == 2 world.environment.ssil_intensity = 0.65 world.environment.ssr_enabled = forward and level == 2