feat(foliage): add recovering grass trails and bush contact

This commit is contained in:
Rijad Zuzo
2026-09-05 19:30:46 +02:00
parent da3bed67a0
commit 7899d36f03
21 changed files with 673 additions and 18 deletions
+36
View File
@@ -1,6 +1,8 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
#include "foliage_trail.gdshaderinc"
uniform vec2 wind_direction = vec2(0.94, 0.34);
uniform float wind_strength : hint_range(0.0, 0.2) = 0.07;
uniform float wind_speed : hint_range(0.0, 2.0) = 0.55;
@@ -10,6 +12,10 @@ uniform float flutter_strength : hint_range(0.0, 0.05) = 0.012;
uniform float wind_phase : hint_range(0.0, 6.2832) = 0.0;
uniform vec3 albedo : source_color = vec3(0.19, 0.38, 0.17);
uniform float roughness : hint_range(0.0, 1.0) = 0.9;
uniform vec3 contact_root = vec3(0.0);
uniform float contact_strength = 0.0;
uniform int interactor_count = 0;
uniform vec3 interactor_positions[8];
varying vec3 paint_position;
void vertex() {
@@ -28,6 +34,36 @@ void vertex() {
VERTEX.xz += direction * bend * height_factor;
VERTEX.xz += crosswind * flutter * height_factor;
if (foliage_trails_enabled && contact_strength > 0.0) {
// One bend for the whole bush, including fruit; its base remains planted.
vec3 contact = sample_foliage_trail(contact_root);
vec3 edge_contact = sample_foliage_trail(contact_root + vec3(0.45, 0.0, 0.0));
if (edge_contact.z > contact.z) { contact = edge_contact; }
edge_contact = sample_foliage_trail(contact_root - vec3(0.45, 0.0, 0.0));
if (edge_contact.z > contact.z) { contact = edge_contact; }
edge_contact = sample_foliage_trail(contact_root + vec3(0.0, 0.0, 0.45));
if (edge_contact.z > contact.z) { contact = edge_contact; }
edge_contact = sample_foliage_trail(contact_root - vec3(0.0, 0.0, 0.45));
if (edge_contact.z > contact.z) { contact = edge_contact; }
vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
float rooted = smoothstep(0.0, 1.25, world_position.y - contact_root.y);
// Bushes spring back faster than the flattened meadow trail.
float spring = pow(contact.z, 5.0);
vec2 bend_direction = contact.xy / max(length(contact.xy), 0.001);
for (int index = 0; index < 8; index++) {
if (index >= interactor_count) { break; }
vec2 offset = contact_root.xz - interactor_positions[index].xz;
float distance_to_actor = length(offset);
float influence = 1.0 - smoothstep(0.25, 1.8, distance_to_actor);
influence *= 1.0 - smoothstep(0.55, 1.35, abs(contact_root.y - interactor_positions[index].y));
if (influence > spring) {
spring = influence;
bend_direction = offset / max(distance_to_actor, 0.001);
}
}
vec3 displacement = vec3(bend_direction.x, -0.18, bend_direction.y) * spring * contact_strength * rooted;
VERTEX += (inverse(MODEL_MATRIX) * vec4(displacement, 0.0)).xyz;
}
}
void fragment() {