138 lines
5.5 KiB
Plaintext
138 lines
5.5 KiB
Plaintext
shader_type spatial;
|
|
render_mode specular_disabled, cull_disabled, ambient_light_disabled;
|
|
|
|
global uniform float global_wind_speed;
|
|
global uniform vec2 global_wind_direction;
|
|
global uniform float global_wind_scale;
|
|
global uniform float global_wind_strength;
|
|
global uniform float global_wind_fade;
|
|
global uniform float global_snow_start_time = -1.0;
|
|
global uniform float global_snow_accumulation_speed = 0.005;
|
|
global uniform float global_snow_melt_time = -1.0;
|
|
global uniform float global_snow_melt_speed = 0.1;
|
|
global uniform float global_snow_amount = 0.0;
|
|
global uniform vec4 global_snow_color;
|
|
global uniform float global_rain_intensity;
|
|
const float LEAVES_FULL_SNOW_START = 0.58;
|
|
const float LEAVES_FULL_SNOW_END = 0.86;
|
|
|
|
uniform sampler2D wind_noise : filter_linear_mipmap;
|
|
uniform bool billboard_enabled = true;
|
|
uniform bool wind_enabled = true;
|
|
uniform vec4 base_color : source_color = vec4(0.2, 0.6, 0.3, 1.0);
|
|
uniform sampler2D alpha_texture : source_color, filter_nearest;
|
|
uniform float leaves_scale = 1.0;
|
|
uniform float rotation_degrees = 0.0;
|
|
uniform vec2 texture_offset = vec2(0.0, 0.0);
|
|
uniform float opacity : hint_range(0.0, 1.0) = 1.0;
|
|
uniform float height_min = 0.0;
|
|
uniform float height_max = 5.0;
|
|
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.5;
|
|
uniform float highlight_intensity : hint_range(0.0, 1.0) = 0.3;
|
|
uniform float light_steps : hint_range(1.0, 10.0) = 4.0;
|
|
uniform float random_mix : hint_range(0.0, 1.0) = 0.3;
|
|
uniform float cast_shadow_strength : hint_range(0.0, 1.0) = 0.6;
|
|
uniform float wetness_darkening : hint_range(0.0, 0.5) = 0.25;
|
|
uniform float snow_visibility : hint_range(0.0, 1.0) = 1.0;
|
|
|
|
varying vec3 v_final_color;
|
|
varying float v_shade_factor;
|
|
|
|
float hash(vec3 p) {
|
|
p = fract(p * 0.1031);
|
|
p += dot(p, p.yzx + 33.33);
|
|
return fract((p.x + p.y) * p.z);
|
|
}
|
|
|
|
float get_snow_progress() {
|
|
float snow_progress = clamp(global_snow_amount, 0.0, 1.0);
|
|
|
|
if (global_snow_start_time >= 0.0) {
|
|
float timed_progress = clamp((TIME - global_snow_start_time) * global_snow_accumulation_speed, 0.0, 1.0);
|
|
snow_progress = max(snow_progress, timed_progress);
|
|
}
|
|
if (global_snow_melt_time >= 0.0) {
|
|
float melt = clamp((TIME - global_snow_melt_time) * global_snow_melt_speed, 0.0, 1.0);
|
|
snow_progress = min(snow_progress, 1.0 - melt);
|
|
}
|
|
|
|
return snow_progress;
|
|
}
|
|
|
|
void vertex() {
|
|
vec3 instance_pos = MODEL_MATRIX[3].xyz;
|
|
|
|
float total_angle = radians(rotation_degrees);
|
|
if (wind_enabled && global_wind_speed > 0.0 && global_wind_strength > 0.0 && global_wind_fade > 0.0) {
|
|
float time = TIME * global_wind_speed;
|
|
vec2 noise_uv = (instance_pos.xz * global_wind_scale) + (time * global_wind_direction * 0.5);
|
|
float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
|
|
float sway = sin(time + (noise_val * 10.0));
|
|
total_angle += (sway * global_wind_strength * global_wind_fade);
|
|
}
|
|
|
|
float h_factor = clamp((instance_pos.y - height_min) / (height_max - height_min), 0.0, 1.0);
|
|
float leaf_rand = hash(instance_pos);
|
|
float combined_factor = mix(h_factor, leaf_rand, random_mix);
|
|
combined_factor = ceil(combined_factor * light_steps) / light_steps;
|
|
|
|
v_shade_factor = combined_factor;
|
|
|
|
vec3 dark_color = base_color.rgb * (1.0 - shadow_intensity);
|
|
vec3 light_color = base_color.rgb + (vec3(1.0) - base_color.rgb) * highlight_intensity;
|
|
v_final_color = mix(dark_color, light_color, combined_factor);
|
|
|
|
if (billboard_enabled) {
|
|
vec3 view_pos_origin = (VIEW_MATRIX * vec4(instance_pos, 1.0)).xyz;
|
|
vec2 offset = (UV - 0.5) * leaves_scale;
|
|
float c = cos(total_angle);
|
|
float s = sin(total_angle);
|
|
vec2 rotated_offset = vec2(offset.x * c - offset.y * s, offset.x * s + offset.y * c);
|
|
|
|
vec3 final_pos = view_pos_origin + vec3(rotated_offset.x, rotated_offset.y, 0.0);
|
|
MODELVIEW_MATRIX = mat4(1.0);
|
|
MODELVIEW_MATRIX[3].xyz = final_pos;
|
|
VERTEX = vec3(0.0);
|
|
} else {
|
|
float c = cos(total_angle);
|
|
float s = sin(total_angle);
|
|
vec2 local_v = VERTEX.xy * leaves_scale;
|
|
VERTEX.x = local_v.x * c - local_v.y * s;
|
|
VERTEX.y = local_v.x * s + local_v.y * c;
|
|
}
|
|
}
|
|
|
|
void fragment() {
|
|
vec2 shifted_uv = UV + texture_offset;
|
|
vec4 tex = texture(alpha_texture, shifted_uv);
|
|
|
|
// Snow accumulation
|
|
float snow_amount = pow(get_snow_progress(), 0.55);
|
|
|
|
float top_mask = 1.0 - shifted_uv.y;
|
|
float snow_mask = smoothstep(1.0 - snow_amount * 1.35, 1.08 - snow_amount * 1.35, top_mask) * snow_visibility;
|
|
snow_mask *= step(0.01, snow_amount);
|
|
float full_snow_mask = smoothstep(LEAVES_FULL_SNOW_START, LEAVES_FULL_SNOW_END, snow_amount) * clamp(snow_visibility, 0.0, 1.0);
|
|
float final_snow_mask = max(snow_mask, full_snow_mask);
|
|
|
|
float snow_light = mix(0.82, 1.0, max(v_shade_factor, 0.35));
|
|
vec3 shaded_snow = clamp(global_snow_color.rgb * snow_light, 0.0, 1.0);
|
|
vec3 final_albedo = mix(v_final_color, shaded_snow, final_snow_mask);
|
|
|
|
// Rain wetness: darken and make shinier
|
|
float rain_int = clamp(global_rain_intensity, 0.0, 1.0);
|
|
final_albedo *= mix(1.0, 1.0 - wetness_darkening, rain_int);
|
|
float final_roughness = mix(0.02, 0.005, rain_int);
|
|
|
|
ALBEDO = final_albedo;
|
|
ALPHA = tex.r * opacity;
|
|
ALPHA_SCISSOR_THRESHOLD = 0.5;
|
|
ROUGHNESS = final_roughness;
|
|
}
|
|
|
|
void light() {
|
|
float shadow_factor = mix(1.0 - cast_shadow_strength, 1.0, ATTENUATION);
|
|
float cutoff_mask = smoothstep(0.0, 0.05, ATTENUATION);
|
|
DIFFUSE_LIGHT += (shadow_factor * LIGHT_COLOR) * cutoff_mask;
|
|
}
|