128 lines
4.0 KiB
Plaintext
128 lines
4.0 KiB
Plaintext
shader_type canvas_item;
|
|
render_mode blend_premul_alpha;
|
|
|
|
uniform sampler2D depth_mask : source_color, filter_linear;
|
|
uniform sampler2D albedo_map : source_color, filter_linear;
|
|
|
|
uniform float flicker_speed : hint_range(0.0, 100.0) = 5.0;
|
|
uniform float flicker_strength : hint_range(0.0, 1.0) = 0.3;
|
|
uniform float flicker_scale : hint_range(0.0, 10.0) = 1.0;
|
|
|
|
uniform bool use_time = true;
|
|
|
|
uniform vec4 day_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
|
|
uniform vec4 morning_color : source_color = vec4(0.8207547, 0.6465379, 0.8050903, 1.0);
|
|
uniform vec4 night_color : source_color = vec4(0.0, 0.13673696, 0.20754719, 1.0);
|
|
uniform vec4 evening_color : source_color = vec4(0.81671757, 0.7075472, 0.9433962, 1.0);
|
|
uniform vec4 time_weights = vec4(0.0, 1.0, 0.0, 0.0);
|
|
|
|
uniform float light_intensity : hint_range(0.0, 10.0) = 2.0;
|
|
uniform float light_falloff : hint_range(0.0, 10.0) = 3.0;
|
|
uniform float light_radius_scale : hint_range(0.0, 10.0) = 1.0;
|
|
|
|
uniform vec2 light_positions[11];
|
|
uniform vec4 light_colors[11];
|
|
uniform float light_radii[11];
|
|
uniform float light_influence[11];
|
|
uniform int light_count;
|
|
|
|
varying vec2 world_pos;
|
|
|
|
float rand(vec2 co) {
|
|
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
|
|
}
|
|
|
|
vec3 calculate_light_color(vec2 wp, out float total_influence) {
|
|
vec3 combined_color = vec3(0.0, 0.0, 0.0);
|
|
total_influence = 0.0;
|
|
|
|
for (int i = 0; i < 11; i++) {
|
|
if (i >= light_count)
|
|
break;
|
|
|
|
vec2 light_pos = light_positions[i];
|
|
float light_radius = light_radii[i] * light_radius_scale;
|
|
vec3 light_col = light_colors[i].rgb;
|
|
|
|
float dist = distance(wp, light_pos);
|
|
float influence = clamp(1.0 - dist / light_radius, 0.0, 1.0);
|
|
// Avoid pow with negative base
|
|
if (influence <= 0.0)
|
|
continue;
|
|
influence = pow(influence, light_falloff);
|
|
|
|
float flicker_seed = light_pos.x * 1.357 + light_pos.y * 2.468 + float(i) * 3.579;
|
|
|
|
float discrete_time = floor(TIME * flicker_speed * 3.0 + flicker_seed) / 3.0;
|
|
|
|
float t1 = discrete_time * 2.0;
|
|
float t2 = discrete_time * 3.0 + 1.2;
|
|
float t3 = discrete_time * 4.0 + 2.4;
|
|
|
|
float flicker1 = floor((sin(t1) * 0.5 + 0.5) * 4.0) / 3.0;
|
|
float flicker2 = floor((sin(t2) * 0.3 + 0.5) * 3.0) / 2.0;
|
|
float flicker3 = floor((sin(t3) * 0.2 + 0.5) * 3.0) / 2.0;
|
|
|
|
float flicker = flicker1 * 0.5 + flicker2 * 0.3 + flicker3 * 0.2;
|
|
|
|
float noise_seed = floor(TIME * flicker_speed * 2.0 + flicker_seed);
|
|
float noise_val = rand(vec2(noise_seed, flicker_seed)) * 0.15;
|
|
|
|
flicker = floor((flicker + noise_val) * 5.0) / 4.0;
|
|
flicker = clamp(flicker, 0.0, 1.0);
|
|
|
|
float flicker_factor = 0.7 + flicker * 0.6 * flicker_strength;
|
|
flicker_factor = floor(flicker_factor * 8.0) / 7.0;
|
|
|
|
influence *= flicker_factor;
|
|
|
|
combined_color += light_col * influence * light_intensity * light_influence[i];
|
|
total_influence += influence * light_intensity * light_influence[i];
|
|
}
|
|
|
|
return combined_color;
|
|
}
|
|
|
|
void vertex() {
|
|
world_pos = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
|
|
}
|
|
|
|
void fragment() {
|
|
vec4 color = texture(TEXTURE, UV) * COLOR;
|
|
float a = color.a;
|
|
|
|
float depth = texture(depth_mask, UV).r;
|
|
float albedo = texture(albedo_map, UV).r;
|
|
|
|
#ifdef ALPHA_CLIP
|
|
if (color.a < 0.001)
|
|
discard;
|
|
#endif
|
|
|
|
if (!use_time) {
|
|
COLOR = color;
|
|
} else {
|
|
vec4 weights = time_weights;
|
|
|
|
vec4 time_color = morning_color * weights.x
|
|
+ day_color * weights.y
|
|
+ evening_color * weights.z
|
|
+ night_color * weights.w;
|
|
|
|
float total_influence;
|
|
vec3 light_col = calculate_light_color(world_pos, total_influence);
|
|
total_influence = clamp(total_influence, 0.0, 1.0);
|
|
|
|
float light_infl = clamp(mix(light_col.r, 0.0, weights.y + weights.x + weights.z) * depth, 0.0, 1.0);
|
|
|
|
float pixel_luma = max(dot(color.rgb, vec3(0.299, 0.587, 0.114)), 0.01);
|
|
float target_luma = max(albedo, pixel_luma);
|
|
float lift = mix(1.0, target_luma / pixel_luma, light_infl);
|
|
|
|
vec3 lit_result = min(color.rgb * lift * light_col, 1.0);
|
|
|
|
COLOR.rgb = mix(color.rgb * time_color.rgb, lit_result, light_infl);
|
|
COLOR.a = a;
|
|
}
|
|
}
|