#[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));
}
