summaryrefslogtreecommitdiff
path: root/shaders/combine.frag
diff options
context:
space:
mode:
Diffstat (limited to 'shaders/combine.frag')
-rw-r--r--shaders/combine.frag65
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;
+}