summaryrefslogtreecommitdiff
path: root/graphics/asymptote/base/shaders/blend.glsl
blob: f3bd26c3935e6a670b8e1c0f68a55b2a0f36fad0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
struct Fragment
{
  vec4 color;
  float depth;
};

layout(binding=1, std430) buffer offsetBuffer {
  uint offset[];
};

layout(binding=2, std430) buffer countBuffer {
  uint count[];
};

layout(binding=3, std430) buffer fragmentBuffer {
  Fragment fragment[];
};

out vec4 outColor;

uniform uint width;
uniform vec4 background;

vec4 blend(vec4 outColor, vec4 color)
{
  return mix(outColor,color,color.a);
}

void main()
{
  uint headIndex=uint(gl_FragCoord.y)*width+uint(gl_FragCoord.x);
  uint size=count[headIndex];
  if(size == 0u) {
#ifdef GPUINDEXING
    offset[headIndex]=0u;
#endif
    discard;
  }
  uint listIndex=offset[headIndex];
  const uint maxSize=16u;

  // Sort the fragments with respect to descending depth
  if(size < maxSize) {
    Fragment sortedList[maxSize];

    sortedList[0]=fragment[listIndex];
    for(uint i=1u; i < size; i++) {
      Fragment temp=fragment[listIndex+i];
      float depth=temp.depth;
      uint j=i;
      Fragment f;
      while(f=sortedList[j-1u], j > 0u && depth > f.depth) {
        sortedList[j]=f;
        j--;
      }
      sortedList[j]=temp;
    }

    outColor=background;
    for(uint i=0u; i < size; i++)
      outColor=blend(outColor,sortedList[i].color);
  } else {
    for(uint i=1u; i < size; i++) {
      Fragment temp=fragment[listIndex+i];
      float depth=temp.depth;
      uint j=i;
      Fragment f;
      while(f=fragment[listIndex+j-1u], j > 0u && depth > f.depth) {
        fragment[listIndex+j]=f;
        j--;
      }
      fragment[listIndex+j]=temp;
    }

    outColor=background;
    uint stop=listIndex+size;
    for(uint i=listIndex; i < stop; i++)
      outColor=blend(outColor,fragment[i].color);
  }
  count[headIndex]=0u;
#ifdef GPUINDEXING
    offset[headIndex]=0u;
#endif
}