#[compute] #version 450 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(rgba16, set = 0, binding = 0) uniform restrict readonly image2D inputImage; layout(rgba16, set = 1, binding = 0) uniform restrict readonly image2D originalImage; layout(rgba16, set = 2, binding = 0) uniform restrict writeonly image2D outputImage; layout(std430, set = 3, binding = 0) buffer restrict readonly OutlinesSizeBuffer { int size; } osb; void main() { ivec2 current_position = ivec2(gl_GlobalInvocationID.xy); vec4 current_pixel = imageLoad(inputImage, current_position); ivec2 current_seed_position = ivec2(packUnorm2x16(current_pixel.xy), packUnorm2x16(current_pixel.zw)); // The "rough" outline generated by the Jump Flood Algorithm contains all the pixels of the desired outline + some more // If the current pixel is not a seed, then it can't be part of the outline if (current_seed_position.x == 0 && current_seed_position.y == 0) { imageStore(outputImage, current_position, vec4(0.0f)); return; } float distance_to_seed = distance(vec2(current_position), vec2(current_seed_position)); float outlinesSize = float(osb.size); // The current pixel is outside the outline range if (distance_to_seed > outlinesSize) { imageStore(outputImage, current_position, vec4(0.0f)); return; } vec4 original_pixel = imageLoad(originalImage, current_seed_position); // The current pixel is on the edge of the outline, outer side if (distance_to_seed > outlinesSize - 1.0f) { float smoothing = 1.0f - (distance_to_seed - (outlinesSize - 1.0f)); imageStore(outputImage, current_position, vec4(original_pixel.xyz, smoothing)); return; } // The current pixel is part of the object to outline if (distance_to_seed == 0.0f) { imageStore(outputImage, current_position, vec4(0.0f)); return; } // The current pixel is on the edge of the outline, inner side if (distance_to_seed < 1.0f) { float smoothing = distance_to_seed; imageStore(outputImage, current_position, vec4(original_pixel.xyz, smoothing)); return; } // The current pixel is part of the outline imageStore(outputImage, current_position, vec4(original_pixel.xyz, original_pixel.a)); }