commit 5e331bc8752bbe6362289283b2c7d6d86d0c8fe7
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Jul 1 23:07:36 2018 +0100

    Update the 'main' shaders for OIT.

diff --git a/src/main/res/raw/main_fragment_shader.glsl b/src/main/res/raw/main_fragment_shader.glsl
index 084f7f5..60999f1 100644
--- a/src/main/res/raw/main_fragment_shader.glsl
+++ b/src/main/res/raw/main_fragment_shader.glsl
@@ -19,23 +19,31 @@
 
 precision highp float;
 
-#if __VERSION__ != 100
 in vec3 v_Position;                     // Interpolated position for this fragment.
 in vec3 v_Normal;                       // Interpolated normal for this fragment.
 in vec2 v_TexCoordinate;                // Interpolated texture coordinate per fragment.
+
 out vec4 fragColor;                     // The output color
-#define TEXTURE texture
-#define FRAG_COLOR fragColor
-#else
-varying vec3 v_Position;                // Interpolated position for this fragment.
-varying vec3 v_Normal;                  // Interpolated normal for this fragment.
-varying vec2 v_TexCoordinate;           // Interpolated texture coordinate per fragment.
-#define TEXTURE texture2D
-#define FRAG_COLOR gl_FragColor
-#endif
 
 uniform sampler2D u_Texture;            // The input texture.
 
+#ifdef OIT
+//////////////////////////////////////////////////////////////////////////////////////////////
+// per-pixel linked list. Order Independent Transparency.
+
+in vec2 v_Pixel;                        // location of the current fragment, in pixels
+uniform uvec2 u_Size;
+uniform uint u_numRecords;
+
+layout (binding=0, offset=0) uniform atomic_uint u_Counter;
+
+layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
+  {                                          // one for each pixel in the Output rectangle.
+  uint u_Records[];                          //
+  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
+                                             // triplets of (pointer,depth,rgba).
+#endif
+
 #if NUM_FRAGMENT>0
 uniform int fNumEffects;                // total number of fragment effects
 uniform int fName[NUM_FRAGMENT];        // their namess.
@@ -43,11 +51,55 @@ uniform vec4 fUniforms[2*NUM_FRAGMENT]; // i-th effect is 2 consecutive vec4's:
                                         // next describes the Region, i.e. area over which the effect is active.
 #endif    // NUM_FRAGMENT>0
 
+#ifdef OIT
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Concurrent insert to a linked list. Tim Harris, 'pragmatic implementation of non-blocking
+// linked-lists', 2001.
+// This arranges fragments by decreasing 'depth', so one would think - from back to front, but
+// in main() below the depth is mapped with S*(1-depth)/2, so it is really front to back.
+
+void insert( vec2 ij, uint depth, uint rgba )
+  {
+  uint ptr = atomicCounterIncrement(u_Counter);
+
+  if( ptr<u_numRecords )
+    {
+    ptr = 3u*ptr + u_Size.x*u_Size.y;
+
+    u_Records[ptr+1u] = depth;
+    u_Records[ptr+2u] = rgba;
+
+    memoryBarrier();
+
+    uint prev = uint(ij.x) + uint(ij.y) * u_Size.x;
+    uint curr = u_Records[prev];
+
+    while (true)
+      {
+      if ( curr==0u || depth > u_Records[curr+1u] )  // need to insert here
+        {
+        u_Records[ptr] = curr;     // next of new record is curr
+        memoryBarrier();
+        uint res = atomicCompSwap( u_Records[prev], curr, ptr );
+
+        if (res==curr) break;      // done!
+        else           curr = res; // could not insert! retry from same place in list
+        }
+      else                         // advance in list
+        {
+        prev = curr;
+        curr = u_Records[prev];
+        }
+      }
+    }
+  }
+#endif   // OIT
+
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 void main()                    		
   {  
-  vec4 color = TEXTURE(u_Texture,v_TexCoordinate);
+  vec4 color = texture(u_Texture,v_TexCoordinate);
 
 #if NUM_FRAGMENT>0
   vec2 diff;
@@ -65,5 +117,21 @@ void main()
     }
 #endif
 
-  FRAG_COLOR = vec4(color.rgb * (1.0 + 7.0*v_Normal.z) * 0.125, color.a);
+#ifdef OIT
+  if( frag.a > 0.95 )
+    {
+    fragColor= vec4(color.rgb * (1.0 + 7.0*v_Normal.z) * 0.125, color.a);
+    }
+  else
+    {
+    if( frag.a > 0.0 )
+      {
+      const float S= 2147483647.0; // max signed int. Could probably be max unsigned int but this is enough.
+      insert(v_Pixel, uint(S*(1.0-depth)/2.0), convert(frag) );
+      }
+    discard;
+    }
+#else
+  fragColor = vec4(color.rgb * (1.0 + 7.0*v_Normal.z) * 0.125, color.a);
+#endif
   }
\ No newline at end of file
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 78f2267..0b7f689 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -19,7 +19,6 @@
 
 precision highp float;
 
-#if __VERSION__ != 100
 in vec3 a_Position;                  // Per-vertex position.
 in vec3 a_Normal;                    // Per-vertex normal vector.
 in vec2 a_TexCoordinate;             // Per-vertex texture coordinate.
@@ -27,14 +26,10 @@ out vec3 v_Position;                 //
 out vec3 v_endPosition;              // for Transform Feedback only
 out vec3 v_Normal;                   //
 out vec2 v_TexCoordinate;            //
-#else
-attribute vec3 a_Position;           // Per-vertex position.
-attribute vec3 a_Normal;             // Per-vertex normal vector.
-attribute vec2 a_TexCoordinate;      // Per-vertex texture coordinate.
-varying vec3 v_Position;             //
-varying vec3 v_endPosition;          // for Transform Feedback only
-varying vec3 v_Normal;               //
-varying vec2 v_TexCoordinate;        //
+
+#ifdef OIT
+out vec2 v_Pixel;                    // 2D pixel coords in window space
+uniform uvec2 u_Size;                // size of the output surface, in pixels.
 #endif
 
 uniform vec3 u_objD;                 // half of object width x half of object height X half the depth;
@@ -165,6 +160,11 @@ void main()
 #endif
    
   v_Position      = v;
+
+#ifdef OIT
+  v_Pixel         = (a_Position.xy + 0.5) * vec2(u_Size);
+#endif
+
   v_endPosition   = v + (0.3*u_objD.x)*n;
   v_TexCoordinate = a_TexCoordinate;
   v_Normal        = normalize(vec3(u_MVMatrix*vec4(n,0.0)));
