71 lines
2.8 KiB
Plaintext
71 lines
2.8 KiB
Plaintext
// Adapted for The Steward from the bundled Terrain3D particle-grass example.
|
|
shader_type spatial;
|
|
|
|
render_mode skip_vertex_transform, cull_disabled, blend_mix;
|
|
|
|
const int MAX_INTERACTORS = 8;
|
|
|
|
uniform vec2 wind_direction = vec2(1.0, 0.7);
|
|
uniform vec3 base_color : source_color = vec3(0.16, 0.31, 0.08);
|
|
uniform vec3 tip_color : source_color = vec3(0.54, 0.68, 0.24);
|
|
uniform float wind_amount : hint_range(0.0, 1.0) = 0.34;
|
|
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_strength : hint_range(0.0, 2.0) = 0.75;
|
|
|
|
varying vec4 grass_data;
|
|
varying float pressed_weight;
|
|
|
|
|
|
void vertex() {
|
|
grass_data[2] = VERTEX.y + 0.55;
|
|
grass_data[2] *= grass_data[2];
|
|
VERTEX.xz *= 1.0 - grass_data[2];
|
|
COLOR = mix(COLOR, vec4(1.0), smoothstep(0.9, 1.0, grass_data[2]));
|
|
COLOR *= INSTANCE_CUSTOM[3] < 0.35 ? 1.0 : mix(1.0, 0.75, smoothstep(0.35, 0.0, grass_data[2]));
|
|
grass_data.rg = INSTANCE_CUSTOM.rg;
|
|
|
|
vec3 world_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
|
float scale = pow(INSTANCE_CUSTOM[3] * INSTANCE_CUSTOM[3], 0.707);
|
|
float force = INSTANCE_CUSTOM[2] * grass_data[2] * scale * wind_amount;
|
|
force -= fract(force * 256.0) * force * 0.05;
|
|
force = pow(max(force, 0.0), 0.707);
|
|
float lateral_wobble = sin(TIME * 2.0 * (1.0 + grass_data.r + grass_data.g)) * 0.2 * (1.0 - INSTANCE_CUSTOM[2]);
|
|
vec2 direction = normalize(wind_direction);
|
|
world_vertex.xz -= (vec2(-direction.y, direction.x) * lateral_wobble + direction) * force;
|
|
world_vertex.y -= INSTANCE_CUSTOM[2] * force * grass_data[2];
|
|
grass_data[3] = force;
|
|
|
|
pressed_weight = 0.0;
|
|
for (int index = 0; index < MAX_INTERACTORS; index++) {
|
|
if (index >= interactor_count) {
|
|
break;
|
|
}
|
|
vec2 offset = world_vertex.xz - interactor_positions[index].xz;
|
|
float distance_to_actor = length(offset);
|
|
float influence = 1.0 - smoothstep(0.25, interaction_radius, distance_to_actor);
|
|
vec2 away = offset / max(distance_to_actor, 0.08);
|
|
world_vertex.xz += away * influence * interaction_strength * grass_data[2];
|
|
world_vertex.y -= influence * 0.28 * grass_data[2];
|
|
pressed_weight = max(pressed_weight, influence);
|
|
}
|
|
|
|
VERTEX = (VIEW_MATRIX * vec4(world_vertex, 1.0)).xyz;
|
|
NORMAL = MODELVIEW_NORMAL_MATRIX * NORMAL;
|
|
BINORMAL = MODELVIEW_NORMAL_MATRIX * BINORMAL;
|
|
TANGENT = MODELVIEW_NORMAL_MATRIX * TANGENT;
|
|
}
|
|
|
|
|
|
void fragment() {
|
|
vec3 color = mix(base_color, tip_color, grass_data[2] * 0.62);
|
|
color.rg *= grass_data.rg * 0.18 + 0.91;
|
|
color *= pow(COLOR.rgb, vec3(2.2));
|
|
ALBEDO = mix(color, base_color * 0.72, pressed_weight * 0.42);
|
|
float specular_roughness = clamp(max(grass_data[2], grass_data[3]), 0.0, 1.0);
|
|
ROUGHNESS = 1.0 - specular_roughness * 0.22;
|
|
SPECULAR = clamp(specular_roughness * 0.2, 0.0, 0.12);
|
|
BACKLIGHT = tip_color * 0.24;
|
|
}
|