feat(world): tiled heightfield terrain actor with per-cell sonar materials

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Sonnet 5.5 committed 2026-10-06 20:04:13 +02:00
1 parent 8ab1289d10
commit 0e590f2bc7
4 files changed
+286

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
shader_type spatial;
render_mode cull_disabled, depth_draw_opaque;
uniform vec3 sand_color : source_color = vec3(0.50, 0.46, 0.34);
uniform vec3 rock_color : source_color = vec3(0.21, 0.20, 0.18);
uniform vec3 deep_tint : source_color = vec3(0.04, 0.09, 0.15);
uniform float sand_slope_cosine = 0.9397; // cos(20 deg)
uniform float rock_slope_cosine = 0.7660; // cos(40 deg)
uniform float depth_tint_start_m = 20.0;
uniform float depth_tint_end_m = 90.0;
uniform float ripple_wavelength_m = 1.6;
uniform float ripple_contrast = 0.12;
varying vec3 world_position;
varying vec3 world_normal;
void vertex() {
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
world_normal = normalize((MODEL_MATRIX * vec4(NORMAL, 0.0)).xyz);
}
void fragment() {
float up = clamp(world_normal.y, 0.0, 1.0);
float rockness = 1.0 - smoothstep(rock_slope_cosine, sand_slope_cosine, up);
vec3 albedo = mix(sand_color, rock_color, rockness);
float phase = (world_position.x * 0.8 + world_position.z * 0.6) * TAU / ripple_wavelength_m;
float ripple = sin(phase) * ripple_contrast * (1.0 - rockness);
albedo *= 1.0 + ripple;
float depth_m = -world_position.y;
float tint = smoothstep(depth_tint_start_m, depth_tint_end_m, depth_m);
albedo = mix(albedo, deep_tint, tint * 0.6);
ALBEDO = albedo;
ROUGHNESS = mix(0.95, 0.82, rockness);
METALLIC = 0.0;
}