98 lines
3.1 KiB
Plaintext
98 lines
3.1 KiB
Plaintext
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
|
|
|
|
[sub_resource type="Shader" id=1]
|
|
code = "shader_type canvas_item;
|
|
render_mode unshaded;
|
|
|
|
uniform sampler2D noise_img;
|
|
|
|
uniform mat4 global_transform;
|
|
uniform mat4 viewport_transform;
|
|
uniform sampler2D light_data;
|
|
uniform int n_lights = 0;
|
|
uniform vec4 default_light_color : hint_color;
|
|
uniform float light_level : hint_range(0.0, 1.0) = 0.0;
|
|
uniform float offset_modifier : hint_range(0.0, 8.0) = 1.0;
|
|
uniform int n_light_bands : hint_range(1, 13) = 7;
|
|
uniform bool will_smooth_shade = false;
|
|
uniform float band_decay_rate : hint_range(0.0, 1.0, 0.05) = 0.5;
|
|
uniform float light_strength_modifier : hint_range(0.0, 1.0) = 1.0;
|
|
|
|
varying vec2 world_position;
|
|
|
|
void vertex() {
|
|
world_position = (viewport_transform * (global_transform * vec4(VERTEX, 0.0, 1.0))).xy;
|
|
}
|
|
|
|
void fragment() {
|
|
vec4 col = texture(TEXTURE, UV);
|
|
if (col.a <= 0.0){
|
|
COLOR = col;
|
|
}
|
|
else{
|
|
// floor() the world_position so that it matches the native resolution
|
|
vec2 frag_position = floor(world_position);
|
|
float m_value = 0.0; // 0.0 == dark, 1.0 == light
|
|
vec4 light_color = default_light_color;
|
|
// Iterate through every light source.
|
|
for(int i = 0; i < n_lights; i++) {
|
|
// Get the data for this light source as passed in via texture
|
|
vec4 texel = texelFetch(light_data, ivec2(i, 0), 0);
|
|
vec2 texel_pos = (viewport_transform * (global_transform * vec4(texel.xy, 0.0, 1.0))).xy;
|
|
vec2 texel_pos2 = texel.xy;
|
|
|
|
// How far the light source extends
|
|
float radius = texel.a;
|
|
// How bright the light source is
|
|
float strength = texel.b;
|
|
// Distance from this pixel to the light source then normalize
|
|
float dist = distance(texel_pos, frag_position);
|
|
dist = min(dist / radius, 1.0);
|
|
|
|
// offset so that light source doesn't fade immediately
|
|
dist = max((dist * offset_modifier) - (offset_modifier - 1.0), 0.0);
|
|
|
|
float value = 0.0;
|
|
if(will_smooth_shade) {
|
|
value = (1.0 - dist) * strength * light_strength_modifier + value;
|
|
}
|
|
else {
|
|
// decay offset so that max value == 1.0
|
|
float offset = pow(band_decay_rate, float(n_light_bands));
|
|
for(int p = 0; p < n_light_bands; p++) {
|
|
// Get max radius for this light band
|
|
float radius_check = 1.0 - pow(band_decay_rate, float(p + 1)) + offset;
|
|
// if pixel is less than the band's radius, then it's in the pth band
|
|
if(dist < radius_check) {
|
|
// Set it's value to the position of the band before this one
|
|
value = (pow(band_decay_rate, float(p)) - offset)
|
|
* strength * light_strength_modifier;
|
|
// Nearest band was found, so break the loop
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
value = clamp(value, 0.0, 1.0);
|
|
if(value > m_value) {
|
|
m_value = value;
|
|
light_color = texelFetch(light_data, ivec2(i, 1), 0);
|
|
}
|
|
}
|
|
|
|
COLOR = col + m_value * light_color;
|
|
}
|
|
}"
|
|
|
|
[resource]
|
|
shader = SubResource( 1 )
|
|
shader_param/global_transform = null
|
|
shader_param/viewport_transform = null
|
|
shader_param/n_lights = 0
|
|
shader_param/default_light_color = null
|
|
shader_param/light_level = 0.0
|
|
shader_param/offset_modifier = 1.0
|
|
shader_param/n_light_bands = 7
|
|
shader_param/will_smooth_shade = false
|
|
shader_param/band_decay_rate = 0.5
|
|
shader_param/light_strength_modifier = 1.0
|