#version 450 #define LIST_END ~0x0 #define SORT_MAX 32 layout (location = 0) out vec4 color; layout(binding = 0) uniform mvp { mat4 model; mat4 view; mat4 proj; uint count; } ubo; layout(binding = 1) buffer fragment_buffer { uvec3 fragments[]; }; layout(binding = 2, r32ui) uniform uimage2D head; layout(binding = 3) buffer counter { int data; }; vec4 blend_colors(uint packed_color, vec4 dst_color) { const vec4 src_color = unpackUnorm4x8(packed_color); return vec4(mix(dst_color.rgb, src_color.rgb, src_color.a), dst_color.a * (1.0f - src_color.a)); } void main() { color = vec4(0, 0, 0, 1); uint idx = imageLoad(head, ivec2(gl_FragCoord.xy)).r; imageStore(head, ivec2(gl_FragCoord.xy), ivec4(LIST_END, 0, 0, 0)); uvec2 sorted[SORT_MAX]; uint sorted_count = 0; // TODO: use a proper struct while (idx != LIST_END) { const uvec3 fragment = fragments[idx]; idx = fragment.x; if (sorted_count < SORT_MAX) { uint i = sorted_count; for(; i > 0 && fragment.z > sorted[i - 1].y; i--) { sorted[i] = sorted[i - 1]; } sorted[i] = fragment.yz; sorted_count++; } else if (fragment.z > sorted[0].y) { color = blend_colors(sorted[0].x, color); uint i = 0; for (; i < SORT_MAX - 1 && fragment.z < sorted[i + 1].y; i++) { sorted[i] = sorted[i + 1]; } sorted[i] = fragment.yz; } else { color = blend_colors(fragment.y, color); } } for (int i = 0; i < sorted_count; i++) { color = blend_colors(sorted[i].x, color); } color.a = 1.0f - color.a; }