feat(world): depth-coloured water column fog and de-tiled sand ripples

A FogVolume covering the site carries a fog shader whose scattering albedo
follows the same spectral transmittance as the seabed and whose density
grows below the reference depth, so haze darkens and turns indigo with
depth around every object; the global volumetric density moves into the
volume and the far depth fog only covers what lies beyond 128 m. Sand
ripples are bent by a slow domain warp, blended with a larger ripple
scale and faded out between 40 and 60 m, which hides the 3.2 m tiling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Fable 5.1 committed 2026-10-06 23:44:04 +02:00
1 parent 61ef4a892d
commit d7e50f8879
11 files changed
+82 -15

No files matched your search

@@ -19,7 +19,7 @@ const DIVE_SITE_SCENE = preload("res://game/world/sites/dive_site.tscn")
const ZONE1_SITE_PATH := "res://content/sites/zone1_vigilant.tres"
const SHOWCASE_SITE_PATH := "res://content/sites/terrain_showcase.tres"
const GROOVE_PROBE_OFFSET_M := 25.0
const TEST_COUNT := 40
const TEST_COUNT := 41
var _failures: Array[String] = []
@@ -179,6 +179,12 @@ func _test_dive_site_scene() -> void:
await physics_frame
await physics_frame
_expect(site.terrain().tile_count() > 0, "site builds its terrain tiles")
var water_column := site.get_node_or_null("WaterColumn") as FogVolume
_expect(
water_column != null and water_column.material is ShaderMaterial
and (water_column.material as ShaderMaterial).shader != null,
"site carries a water-column fog volume with its depth shader"
)
_expect(site.placeholder_count() == 2, "calibration target and beacon are placed")
var target := site.get_node_or_null("%Placements/calibration_target") as StaticBody3D
_expect(target != null and int(target.get_meta("sonar_material")) == SonarMaterial.Value.METAL, "wreck placeholder is a metal sonar body")