diff options
Diffstat (limited to 'shaders/combine.frag')
-rw-r--r-- | shaders/combine.frag | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/shaders/combine.frag b/shaders/combine.frag new file mode 100644 index 0000000..4240528 --- /dev/null +++ b/shaders/combine.frag @@ -0,0 +1,65 @@ +#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; +} |