117 lines
5.2 KiB
GDScript
117 lines
5.2 KiB
GDScript
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
|