80 lines
2.5 KiB
GLSL
80 lines
2.5 KiB
GLSL
#[compute]
|
|
#version 450
|
|
|
|
// Adapted from https://john-chapman-graphics.blogspot.com/2013/02/pseudo-lens-flare.html
|
|
|
|
// Invocations in the (x, y, z) dimension
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
|
|
layout(rgba16f, set = 0, binding = 0) uniform image2D downsampled_image;
|
|
layout(rgba16f, set = 1, binding = 0) uniform image2D color_image;
|
|
layout(set = 2, binding = 0) uniform sampler2D lens_color_ramp;
|
|
|
|
// Our push constant
|
|
layout(push_constant, std430) uniform Params {
|
|
vec2 raster_size;
|
|
int ghost_count;
|
|
float ghost_dispersal;
|
|
float ca_scale;
|
|
float halo_width;
|
|
float halo_weight_power;
|
|
} params;
|
|
|
|
vec3 imageDistorted(
|
|
in ivec2 texcoord,
|
|
in vec2 direction, // direction of distortion
|
|
in vec3 distortion // per-channel distortion factor
|
|
) {
|
|
return vec3(
|
|
imageLoad(downsampled_image, texcoord + ivec2(direction * distortion.r)).r,
|
|
imageLoad(downsampled_image, texcoord + ivec2(direction * distortion.g)).g,
|
|
imageLoad(downsampled_image, texcoord + ivec2(direction * distortion.b)).b
|
|
);
|
|
}
|
|
|
|
// The code we want to execute in each invocation
|
|
void main() {
|
|
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
|
|
ivec2 size = ivec2(params.raster_size);
|
|
|
|
if (uv.x >= size.x || uv.y >= size.y) {
|
|
return;
|
|
}
|
|
|
|
vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
|
|
|
|
vec2 resolution = params.raster_size;
|
|
|
|
vec2 texelSize = 1.0 / vec2(resolution);
|
|
|
|
vec2 uv_norm = uv / resolution;
|
|
vec2 texcoord = vec2(1.0) - uv_norm;
|
|
|
|
vec2 ghost_vec = (vec2(0.5) - texcoord) * params.ghost_dispersal;
|
|
|
|
vec3 distortion = vec3(-1.0, 0.0, 1.0) * params.ca_scale;
|
|
vec2 direction = normalize(ghost_vec);
|
|
|
|
vec3 result = vec3(0.0);
|
|
for (int i = 0; i < params.ghost_count; ++i) {
|
|
vec2 offset = fract(texcoord + ghost_vec * float(i));
|
|
|
|
float weight = length(vec2(0.5) - offset) / length(vec2(0.5));
|
|
weight = pow(1.0 - weight, 2.0);
|
|
|
|
result += imageDistorted(ivec2(offset * resolution), direction, distortion).rgb * (1.0 / weight);
|
|
}
|
|
|
|
// sample halo:
|
|
vec2 haloVec = normalize(ghost_vec) * params.halo_width;
|
|
float weight = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));
|
|
weight = pow(1.0 - weight, params.halo_weight_power);
|
|
result += imageDistorted(ivec2((texcoord + haloVec) * resolution), direction, distortion).rgb * weight;
|
|
|
|
result *= texture(lens_color_ramp, vec2((length(vec2(0.5) - texcoord) / length(vec2(0.5))), 0.0)).rgb;
|
|
|
|
color.rgb = result.rgb;
|
|
|
|
imageStore(color_image, uv, color);
|
|
}
|