111 lines
3.2 KiB
GDScript
111 lines
3.2 KiB
GDScript
extends Node3D
|
|
|
|
enum CanopyVariant {
|
|
GREEN,
|
|
DARK_GREEN,
|
|
YELLOW_GREEN,
|
|
}
|
|
|
|
const COLORS := {
|
|
CanopyVariant.GREEN: Color(0.40, 0.62, 0.28),
|
|
CanopyVariant.DARK_GREEN: Color(0.26, 0.51, 0.34),
|
|
CanopyVariant.YELLOW_GREEN: Color(0.55, 0.67, 0.29),
|
|
}
|
|
|
|
const TREE_MODEL := preload("res://assets/painterly/painterly_tree.glb")
|
|
const WIND_SHADER := preload("res://world/jajce/materials/wind.gdshader")
|
|
const WIND_STRENGTH := 0.07
|
|
const WIND_SPEED := 0.55
|
|
|
|
static var _canopy_mesh: Mesh
|
|
static var _trunk_mesh: Mesh
|
|
static var _bark_material: StandardMaterial3D
|
|
|
|
|
|
func _ready() -> void:
|
|
for child in get_children():
|
|
child.queue_free()
|
|
|
|
var hash_seed := hash(global_position)
|
|
var rng := RandomNumberGenerator.new()
|
|
rng.seed = hash_seed
|
|
var canopy_variant := rng.randi() % COLORS.size() as CanopyVariant
|
|
var canopy_radius := 1.25 + rng.randf() * 0.6
|
|
var wind_phase := rng.randf_range(0.0, TAU)
|
|
|
|
_ensure_shared_meshes()
|
|
var trunk := MeshInstance3D.new()
|
|
trunk.name = "Trunk"
|
|
trunk.mesh = _trunk_mesh
|
|
trunk.material_override = _bark_material
|
|
add_child(trunk)
|
|
|
|
var canopy_color: Color = COLORS[canopy_variant]
|
|
var crown_height := 3.7 + (canopy_radius - 1.2) * 0.45
|
|
_add_canopy(
|
|
"Canopy",
|
|
Vector3(0.0, crown_height, 0.0),
|
|
Vector3(canopy_radius * 1.18, canopy_radius * 0.96, canopy_radius * 1.05),
|
|
canopy_color,
|
|
wind_phase
|
|
)
|
|
_add_canopy(
|
|
"CanopyLeft",
|
|
Vector3(-0.94, crown_height - 0.27, 0.14),
|
|
Vector3(canopy_radius * 0.84, canopy_radius * 0.79, canopy_radius * 0.84),
|
|
canopy_color.lightened(0.05),
|
|
wind_phase + 0.12
|
|
)
|
|
_add_canopy(
|
|
"CanopyRight",
|
|
Vector3(0.91, crown_height - 0.08, -0.2),
|
|
Vector3(canopy_radius * 0.82, canopy_radius * 0.73, canopy_radius * 0.79),
|
|
canopy_color.darkened(0.04),
|
|
wind_phase - 0.1
|
|
)
|
|
_add_canopy(
|
|
"CanopyTop",
|
|
Vector3(0.13, crown_height + 0.68, -0.08),
|
|
Vector3(canopy_radius * 0.78, canopy_radius * 0.74, canopy_radius * 0.75),
|
|
canopy_color.lightened(0.08),
|
|
wind_phase + 0.05
|
|
)
|
|
|
|
|
|
static func _ensure_shared_meshes() -> void:
|
|
if _canopy_mesh != null:
|
|
return
|
|
var source := TREE_MODEL.instantiate()
|
|
_canopy_mesh = (source.find_child("Canopy", true, false) as MeshInstance3D).mesh
|
|
_trunk_mesh = (source.find_child("Trunk", true, false) as MeshInstance3D).mesh
|
|
_bark_material = StandardMaterial3D.new()
|
|
_bark_material.vertex_color_use_as_albedo = true
|
|
_bark_material.roughness = 0.95
|
|
_bark_material.specular_mode = BaseMaterial3D.SPECULAR_DISABLED
|
|
source.free()
|
|
|
|
|
|
func _add_canopy(
|
|
canopy_name: String,
|
|
canopy_position: Vector3,
|
|
canopy_scale: Vector3,
|
|
canopy_color: Color,
|
|
wind_phase: float
|
|
) -> void:
|
|
var material := ShaderMaterial.new()
|
|
material.shader = WIND_SHADER
|
|
material.set_shader_parameter("albedo", canopy_color)
|
|
material.set_shader_parameter("roughness", 0.9)
|
|
material.set_shader_parameter("wind_strength", WIND_STRENGTH)
|
|
material.set_shader_parameter("wind_speed", WIND_SPEED)
|
|
material.set_shader_parameter("wind_phase", wind_phase)
|
|
material.set_shader_parameter("painted_vertex_weight", 1.0)
|
|
var canopy := MeshInstance3D.new()
|
|
canopy.name = canopy_name
|
|
canopy.mesh = _canopy_mesh
|
|
canopy.material_override = material
|
|
canopy.position = canopy_position
|
|
canopy.scale = canopy_scale
|
|
canopy.rotation.y = wind_phase * 0.43 + canopy_position.x * 0.31
|
|
add_child(canopy)
|