feat(environment): add painterly skies and living meadows
This commit is contained in:
@@ -48,6 +48,9 @@ func _build_ribbon(
|
||||
var uvs := PackedVector2Array()
|
||||
var indices := PackedInt32Array()
|
||||
var row_size := width_segments + 1
|
||||
var pool := $PlungePool as MeshInstance3D
|
||||
var pool_mesh := pool.mesh as PlaneMesh
|
||||
var pool_radii := pool_mesh.size * Vector2(pool.scale.x, pool.scale.z) * 0.5
|
||||
for z_index in segment_count + 1:
|
||||
var progress := float(z_index) / float(segment_count)
|
||||
var world_z := lerpf(start_z, end_z, progress)
|
||||
@@ -61,16 +64,30 @@ func _build_ribbon(
|
||||
if is_upper
|
||||
else Watercourse.downstream_half_width(world_z)
|
||||
)
|
||||
if not is_upper:
|
||||
# The outlet continues the existing pool silhouette without drawing a
|
||||
# second, coplanar sheet on top of the pool's transparent material.
|
||||
var pool_progress := (world_z - Watercourse.PLUNGE_POOL_CENTER.y) / pool_radii.y
|
||||
if absf(pool_progress) < 1.0:
|
||||
var pool_width := pool_radii.x * sqrt(1.0 - pool_progress * pool_progress)
|
||||
half_width = maxf(half_width, pool_width)
|
||||
# A stream has one surface across its width. Sampling each bank separately
|
||||
# wraps the water mesh up the terrain and makes it read as a solid ramp.
|
||||
var terrain_height := terrain.data.get_height(Vector3(center_x, 0.0, world_z))
|
||||
if is_nan(terrain_height):
|
||||
terrain_height = global_position.y
|
||||
var surface_height := terrain_height + water_offset
|
||||
var left_x := _shoreline_x(
|
||||
terrain, center_x, center_x - half_width, world_z, surface_height
|
||||
)
|
||||
var right_x := _shoreline_x(
|
||||
terrain, center_x, center_x + half_width, world_z, surface_height
|
||||
)
|
||||
for x_index in width_segments + 1:
|
||||
var across := float(x_index) / float(width_segments)
|
||||
var world_x := center_x + lerpf(-half_width, half_width, across)
|
||||
var world_x := lerpf(left_x, right_x, across)
|
||||
var world_sample := Vector3(world_x, 0.0, world_z)
|
||||
var terrain_height := terrain.data.get_height(world_sample)
|
||||
if is_nan(terrain_height):
|
||||
terrain_height = global_position.y
|
||||
vertices.append(
|
||||
to_local(Vector3(world_sample.x, terrain_height + water_offset, world_sample.z))
|
||||
)
|
||||
vertices.append(to_local(Vector3(world_sample.x, surface_height, world_sample.z)))
|
||||
normals.append(Vector3.UP)
|
||||
uvs.append(Vector2(across, progress))
|
||||
|
||||
@@ -96,8 +113,37 @@ func _build_ribbon(
|
||||
return mesh
|
||||
|
||||
|
||||
func _shoreline_x(
|
||||
terrain: Terrain3D, center_x: float, edge_x: float, world_z: float, surface_height: float
|
||||
) -> float:
|
||||
var edge_height := terrain.data.get_height(Vector3(edge_x, 0.0, world_z))
|
||||
if is_nan(edge_height) or edge_height <= surface_height:
|
||||
return edge_x
|
||||
# The carved basin is wider on one side. Stop its visible surface at the
|
||||
# shore instead of extending the pool's ideal ellipse metres under a hill.
|
||||
var wet_x := center_x
|
||||
var dry_x := edge_x
|
||||
for step in range(1, 17):
|
||||
var sample_x := lerpf(center_x, edge_x, float(step) / 16.0)
|
||||
var sample_height := terrain.data.get_height(Vector3(sample_x, 0.0, world_z))
|
||||
if is_nan(sample_height) or sample_height > surface_height:
|
||||
dry_x = sample_x
|
||||
break
|
||||
wet_x = sample_x
|
||||
for _step in 10:
|
||||
var sample_x := (wet_x + dry_x) * 0.5
|
||||
var sample_height := terrain.data.get_height(Vector3(sample_x, 0.0, world_z))
|
||||
if is_nan(sample_height) or sample_height > surface_height:
|
||||
dry_x = sample_x
|
||||
else:
|
||||
wet_x = sample_x
|
||||
return wet_x
|
||||
|
||||
|
||||
func _align_pool_to_terrain(terrain: Terrain3D) -> void:
|
||||
var pool := $PlungePool as MeshInstance3D
|
||||
var pool_material := pool.mesh.surface_get_material(0) as ShaderMaterial
|
||||
pool_material.set_shader_parameter("pool_outlet_z", Watercourse.DOWNSTREAM_START_Z)
|
||||
var pool_sample := Vector3(
|
||||
Watercourse.PLUNGE_POOL_CENTER.x, 0.0, Watercourse.PLUNGE_POOL_CENTER.y
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user