104 lines
4.2 KiB
Plaintext
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);
|
|
} |