MagicNStuff/source/tools/lightbeam/lightbeam.gdshader
SchimmelSpreu83 7e8f8a1d4d Changed the way materials are stored on some dev models
- also adjusted some stuff and added a few passivestar plugins/tools.
2025-10-14 20:15:05 +02:00

104 lines
4.2 KiB
Plaintext

shader_type spatial;
render_mode unshaded, blend_add;
uniform vec4 color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform bool use_second_color = false;
uniform vec4 second_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float cone_start_width : hint_range(0.0, 1.0, 0.01) = 0.02;
uniform float cone_curve : hint_range(0, 1.0, 0.01) = 0.3;
uniform float beam_sharpness : hint_range(0.01, 1.0, 0.01) = 0.25;
uniform float beam_fade : hint_range(0.1, 10.0, 0.1) = 4.0;
uniform bool use_gradient = false;
uniform sampler2D gradient: source_color, repeat_disable;
uniform float proximity_fade_distance : hint_range(0.0, 4096.0, 0.01) = 0.75;
uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
uniform float z_fade_start : hint_range(0.0, 1.0, 0.01) = 0.5;
uniform float z_fade_end : hint_range(0.0, 1.0, 0.01) = 0.8;
uniform bool use_noise = false;
uniform sampler2D noise_texture : source_color, filter_linear_mipmap, repeat_enable;
uniform float noise_scale : hint_range(0.1, 10.0, 0.1) = 1.0;
uniform float noise_intensity : hint_range(0.0, 1.0, 0.01) = 0.5;
uniform vec2 noise_scroll_speed = vec2(0.01, 0.01);
uniform float noise_distortion_intensity : hint_range(0.0, 0.1, 0.001) = 0.01;
uniform vec2 noise_distortion_scroll_speed = vec2(-0.02, -0.01);
varying float z_axis_fade;
void vertex() {
vec3 local_z = normalize(MODEL_MATRIX[2].xyz);
vec3 to_camera = normalize(CAMERA_POSITION_WORLD - NODE_POSITION_WORLD);
vec3 local_x = normalize(cross(to_camera, local_z));
vec3 local_y = normalize(cross(local_z, local_x));
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
vec4(local_x * length(MODEL_MATRIX[0].xyz), 0.0),
vec4(local_y * length(MODEL_MATRIX[1].xyz), 0.0),
MODEL_MATRIX[2],
MODEL_MATRIX[3]
);
z_axis_fade = smoothstep(z_fade_end, z_fade_start, abs(dot(to_camera, local_z)));
}
void fragment() {
vec2 uv = UV;
vec3 input_color;
float input_alpha;
if (use_second_color) {
input_color = mix(color.rgb, second_color.rgb, uv.y);
input_alpha = mix(color.a, second_color.a, uv.y);
} else {
input_color = color.rgb;
input_alpha = color.a;
}
// Calculate cone width at current position along the cone length
float cone_progress_y = pow(uv.y, 1.0 - cone_curve);
float width = mix(cone_start_width, 1.0, cone_progress_y);
float half_width = width * 0.5;
// Create horizontal mask
float distance_from_center_x = abs(uv.x - 0.5);
float beam_edge_start = half_width - (half_width * (1.0 - beam_sharpness));
float horizontal_mask = 1.0 - smoothstep(beam_edge_start, half_width, distance_from_center_x);
// Create vertical mask
float vertical_mask = pow(max(1.0 - uv.y, 0.001), beam_fade);
vertical_mask *= smoothstep(0.0, cone_start_width * 0.5, uv.y);
// Overlay gradient
if (use_gradient) {
float gradient_coord = distance_from_center_x / half_width;
float gradient_value = texture(gradient, vec2(gradient_coord, 0.5)).r;
horizontal_mask *= mix(1.0, gradient_value, 1.0 - (vertical_mask * vertical_mask));
}
// Overlay noise
if (use_noise) {
vec2 distortion_offset = noise_distortion_scroll_speed * TIME + NODE_POSITION_WORLD.xz;
vec2 distortion_sample = texture(noise_texture, uv * noise_scale + distortion_offset).rg;
vec2 distortion_uv = uv + (distortion_sample - 0.5) * 2.0 * noise_distortion_intensity;
vec2 scroll_offset1 = noise_scroll_speed * TIME + NODE_POSITION_WORLD.xz;
vec2 scroll_offset2 = vec2(-noise_scroll_speed.x * 0.7, noise_scroll_speed.y * 1.3) * TIME + NODE_POSITION_WORLD.xz;
float noise_sample1 = texture(noise_texture, distortion_uv * noise_scale + scroll_offset1).r;
float noise_sample2 = texture(noise_texture, distortion_uv * noise_scale + scroll_offset2).r;
float combined_noise = mix(1.0, noise_sample1 * noise_sample2, 1.0 - vertical_mask);
horizontal_mask *= mix(1.0, combined_noise, noise_intensity);
}
ALBEDO = input_color;
ALPHA = horizontal_mask * vertical_mask * input_alpha * z_axis_fade;
// Proximity Fade
float proximity_depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r;
vec4 proximity_view_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, proximity_depth_tex, 1.0);
proximity_view_pos.xyz /= proximity_view_pos.w;
ALPHA *= clamp(1.0 - smoothstep(proximity_view_pos.z + proximity_fade_distance, proximity_view_pos.z, VERTEX.z), 0.0, 1.0);
}