feat(foliage): add recovering grass trails and bush contact
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
shader_type spatial;
|
||||
render_mode skip_vertex_transform, cull_disabled, specular_disabled;
|
||||
|
||||
#include "foliage_trail.gdshaderinc"
|
||||
|
||||
const int MAX_INTERACTORS = 8;
|
||||
uniform vec2 wind_direction = vec2(1.0, 0.7);
|
||||
uniform vec3 base_color : source_color = vec3(0.23, 0.40, 0.22);
|
||||
@@ -9,7 +11,7 @@ uniform vec3 tip_color : source_color = vec3(0.53, 0.67, 0.35);
|
||||
uniform float wind_amount : hint_range(0.0, 1.0) = 0.24;
|
||||
uniform int interactor_count : hint_range(0, 8) = 0;
|
||||
uniform vec3 interactor_positions[MAX_INTERACTORS];
|
||||
uniform float interaction_radius : hint_range(0.25, 4.0) = 1.8;
|
||||
uniform float interaction_radius : hint_range(0.25, 4.0) = 1.1;
|
||||
uniform float interaction_strength : hint_range(0.0, 2.0) = 0.55;
|
||||
uniform int clearing_count = 0;
|
||||
uniform vec4 clearing_segments[4];
|
||||
@@ -36,7 +38,10 @@ void vertex() {
|
||||
vec3 world_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
float phase = dot(anchor.xz, vec2(0.38, 0.29));
|
||||
float gust = sin(TIME * 1.15 + phase) * 0.65 + sin(TIME * 0.58 + phase * 0.42) * 0.35;
|
||||
world_vertex.xz += normalize(wind_direction) * gust * wind_amount * tip_weight;
|
||||
vec3 trail = sample_foliage_trail(anchor);
|
||||
world_vertex.xz += normalize(wind_direction) * gust * wind_amount * tip_weight * (1.0 - trail.z * 0.75);
|
||||
vec2 contact_bend = trail.xy * 0.72;
|
||||
float pressure = trail.z;
|
||||
shade_variation = sin(anchor.x * 0.30 + anchor.z * 0.21) * 0.5 + 0.5;
|
||||
pressed_weight = 0.0;
|
||||
for (int index = 0; index < MAX_INTERACTORS; index++) {
|
||||
@@ -44,11 +49,17 @@ void vertex() {
|
||||
vec2 offset = anchor.xz - interactor_positions[index].xz;
|
||||
float distance_to_actor = length(offset);
|
||||
float influence = 1.0 - smoothstep(0.25, interaction_radius, distance_to_actor);
|
||||
influence *= 1.0 - smoothstep(0.55, 1.35, abs(anchor.y - interactor_positions[index].y));
|
||||
vec2 away = offset / max(distance_to_actor, 0.08);
|
||||
world_vertex.xz += away * influence * interaction_strength * tip_weight;
|
||||
world_vertex.y -= influence * 0.18 * tip_weight;
|
||||
pressed_weight = max(pressed_weight, influence);
|
||||
if (influence > pressure) {
|
||||
contact_bend = away * influence * interaction_strength;
|
||||
pressure = influence;
|
||||
}
|
||||
}
|
||||
world_vertex.xz += contact_bend * tip_weight;
|
||||
// Lower relative to the blade's own root so short tufts stay above the ground.
|
||||
world_vertex.y -= max(world_vertex.y - anchor.y, 0.0) * pressure * 0.78 * blade_height;
|
||||
pressed_weight = pressure;
|
||||
VERTEX = (VIEW_MATRIX * vec4(world_vertex, 1.0)).xyz;
|
||||
NORMAL = normalize((VIEW_MATRIX * vec4(0.0, 1.0, 0.0, 0.0)).xyz);
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ shader_parameter/tip_color = Color(0.53, 0.67, 0.35, 1)
|
||||
shader_parameter/wind_amount = 0.24
|
||||
shader_parameter/interactor_count = 0
|
||||
shader_parameter/interactor_positions = PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
shader_parameter/interaction_radius = 1.8
|
||||
shader_parameter/interaction_radius = 1.1
|
||||
shader_parameter/interaction_strength = 0.55
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Per-world data texture, deliberately not a global shader parameter.
|
||||
uniform bool foliage_trails_enabled = false;
|
||||
uniform sampler2D foliage_trail_map : filter_linear, repeat_disable;
|
||||
uniform vec4 foliage_trail_rect = vec4(0.0, 0.0, 64.0, 64.0);
|
||||
|
||||
vec3 sample_foliage_trail(vec3 ground_position) {
|
||||
if (!foliage_trails_enabled) { return vec3(0.0); }
|
||||
vec2 uv = (ground_position.xz - foliage_trail_rect.xy) / foliage_trail_rect.zw;
|
||||
if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) { return vec3(0.0); }
|
||||
vec4 trail = textureLod(foliage_trail_map, uv, 0.0);
|
||||
float foot_height = trail.a / max(trail.b, 0.0001);
|
||||
// Walkers on a bridge or above a slope do not press plants underneath them.
|
||||
float same_level = 1.0 - smoothstep(0.55, 1.35, abs(ground_position.y - foot_height));
|
||||
float edge = smoothstep(0.0, 0.025, min(min(uv.x, uv.y), min(1.0 - uv.x, 1.0 - uv.y)));
|
||||
return trail.rgb * same_level * edge;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://b6e1cvtl55oyv
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user