commit 33f59f22a0a7b35966e1e829f5cda6d0144a65db
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon May 21 18:17:11 2018 +0100

    OIT: move towards 4 passes ( clear - build - collapse - render )

diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index 2710cf4..1466563 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -68,6 +68,18 @@ public class DistortedEffects
     mQuadPositions.put(positionData).position(0);
     }
 
+  /// OIT SSBO BUFFER ///
+  private static int[] mLinkedListSSBO = new int[1];
+  private static int[] mAtomicCounter = new int[1];
+
+  static
+    {
+    mLinkedListSSBO[0]= -1;
+    mAtomicCounter[0] = -1;
+    }
+
+  private static int mBufferSize=(0x1<<23);  // 8 million entries
+
   /// OIT CLEAR PROGRAM ///
   private static DistortedProgram mOITClearProgram;
   private static int mOITClearDepthH;
@@ -83,21 +95,15 @@ public class DistortedEffects
   private static int mOITBuildSizeH;
   private static int mOITBuildNumRecordsH;
 
-  private static int[] mLinkedListSSBO = new int[1];
-  private static int[] mAtomicCounter = new int[1];
-
-  static
-    {
-    mLinkedListSSBO[0]= -1;
-    mAtomicCounter[0] = -1;
-    }
-
-  private static int mBufferSize=(0x1<<23);  // 8 million entries
+  /// OIT COLLAPSE PROGRAM ///
+  private static DistortedProgram mOITCollapseProgram;
+  private static int mOITCollapseDepthTextureH;
+  private static int mOITCollapseDepthH;
+  private static int mOITCollapseTexCorrH;
+  private static int mOITCollapseSizeH;
 
   /// OIT RENDER PROGRAM ///
   private static DistortedProgram mOITRenderProgram;
-  private static int mOITRenderTextureH;
-  private static int mOITRenderDepthTextureH;
   private static int mOITRenderDepthH;
   private static int mOITRenderTexCorrH;
   private static int mOITRenderSizeH;
@@ -235,7 +241,27 @@ public class DistortedEffects
       GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0);
       }
 
-    // BLIT DEPTH RENDER PROGRAM ///////////////////////////
+    // OIT COLLAPSE PROGRAM ///////////////////////////
+    final InputStream oitCollapseVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
+    final InputStream oitCollapseFragStream = resources.openRawResource(R.raw.oit_collapse_fragment_shader);
+
+    try
+      {
+      mOITCollapseProgram = new DistortedProgram(oitCollapseVertStream,oitCollapseFragStream,Distorted.GLSL_VERSION,Distorted.GLSL_VERSION, Distorted.GLSL);
+      }
+    catch(Exception e)
+      {
+      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile OIT COLLAPSE program: "+e.getMessage());
+      throw new RuntimeException(e.getMessage());
+      }
+
+    int oitCollapseProgramH   = mOITCollapseProgram.getProgramHandle();
+    mOITCollapseDepthTextureH = GLES31.glGetUniformLocation( oitCollapseProgramH, "u_DepthTexture");
+    mOITCollapseDepthH        = GLES31.glGetUniformLocation( oitCollapseProgramH, "u_Depth");
+    mOITCollapseTexCorrH      = GLES31.glGetUniformLocation( oitCollapseProgramH, "u_TexCorr");
+    mOITCollapseSizeH         = GLES31.glGetUniformLocation( oitCollapseProgramH, "u_Size");
+
+    // OIT RENDER PROGRAM ///////////////////////////
     final InputStream oitRenderVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
     final InputStream oitRenderFragStream = resources.openRawResource(R.raw.oit_render_fragment_shader);
 
@@ -250,8 +276,6 @@ public class DistortedEffects
       }
 
     int oitRenderProgramH   = mOITRenderProgram.getProgramHandle();
-    mOITRenderTextureH      = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Texture");
-    mOITRenderDepthTextureH = GLES31.glGetUniformLocation( oitRenderProgramH, "u_DepthTexture");
     mOITRenderDepthH        = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Depth");
     mOITRenderTexCorrH      = GLES31.glGetUniformLocation( oitRenderProgramH, "u_TexCorr");
     mOITRenderSizeH         = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Size");
@@ -470,17 +494,29 @@ public class DistortedEffects
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// Pass3 of the OIT algorithm. Render all the transparent pixels from the per-pixel linked lists.
+// Pass3 of the OIT algorithm. Cut occluded parts of the linked list.
+
+  static void oitCollapse(DistortedOutputSurface surface, float corrW, float corrH)
+    {
+    mOITCollapseProgram.useProgram();
+
+    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
+    GLES31.glUniform1i(mOITCollapseDepthTextureH, 1);
+    GLES31.glUniform2f(mOITCollapseTexCorrH, corrW, corrH );
+    GLES31.glUniform2f(mOITCollapseSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform1f( mOITCollapseDepthH , 1.0f-surface.mNear);
+    GLES31.glVertexAttribPointer(mOITCollapseProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
+    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Pass4 of the OIT algorithm. Render all the transparent pixels from the per-pixel linked lists.
 
   static void oitRender(DistortedOutputSurface surface, float corrW, float corrH)
     {
     mOITRenderProgram.useProgram();
 
-    //analyzeBuffer(surface.mWidth, surface.mHeight);
-
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
-    GLES31.glUniform1i(mOITRenderTextureH, 0);
-    GLES31.glUniform1i(mOITRenderDepthTextureH, 1);
     GLES31.glUniform2f(mOITRenderTexCorrH, corrW, corrH );
     GLES31.glUniform2f(mOITRenderSizeH, surface.mWidth, surface.mHeight);
     GLES31.glUniform1f( mOITRenderDepthH , 1.0f-surface.mNear);
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index 314fb84..ee4f939 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -71,7 +71,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   // Global buffers used for postprocessing.
   private static DistortedOutputSurface[] mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH];
-  private static DistortedOutputSurface   mBufferOIT;
 
   private long mTime;
   private float mFOV;
@@ -211,8 +210,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
       {
       mBuffer[j] = null;
       }
-
-    mBufferOIT = null;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -259,58 +256,8 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   private static void oitClear(DistortedOutputSurface buffer)
     {
-    if( mBufferOIT==null )
-      {
-      mBufferOIT = new DistortedFramebuffer(1, BOTH_DEPTH_STENCIL, TYPE_SYST, buffer.mWidth, buffer.mHeight);
-      mBufferOIT.mMipmap = 1.0f;
-      mBufferOIT.mNear = buffer.mNear;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
-      mBufferOIT.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
-
-      DistortedObject.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
-      }
-
-    if( mBufferOIT.mWidth != buffer.mWidth || mBufferOIT.mHeight != buffer.mHeight )
-      {
-      mBufferOIT.mWidth  = (int)(buffer.mWidth *mBufferOIT.mMipmap);
-      mBufferOIT.mHeight = (int)(buffer.mHeight*mBufferOIT.mMipmap);
-
-      mBufferOIT.mNear   = buffer.mNear;  // Near plane is independent of the mipmap level
-
-      //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
-
-      mBufferOIT.createProjection();
-
-      int maxw = mBufferOIT.mWidth  > mBufferOIT.mRealWidth  ? mBufferOIT.mWidth  : mBufferOIT.mRealWidth;
-      int maxh = mBufferOIT.mHeight > mBufferOIT.mRealHeight ? mBufferOIT.mHeight : mBufferOIT.mRealHeight;
-
-      if (maxw > mBufferOIT.mRealWidth || maxh > mBufferOIT.mRealHeight)
-        {
-        mBufferOIT.mRealWidth = maxw;
-        mBufferOIT.mRealHeight = maxh;
-
-        mBufferOIT.recreate();
-        mBufferOIT.create();
-        }
-      }
-
-    if( mBufferOIT.mNear != buffer.mNear || mBufferOIT.mFOV != buffer.mFOV )
-      {
-      mBufferOIT.mNear = buffer.mNear;
-      mBufferOIT.mFOV  = buffer.mFOV;
-      mBufferOIT.createProjection();
-      }
-
-    GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mBufferOIT.mFBOH[0]);
-    DistortedRenderState.colorDepthStencilOn();
-    GLES31.glClearColor(buffer.mClearR, buffer.mClearG, buffer.mClearB, buffer.mClearA);
-    GLES31.glClearDepthf(buffer.mClearDepth);
-    GLES31.glClearStencil(buffer.mClearStencil);
-    GLES31.glClear(buffer.mClear);
-    DistortedRenderState.colorDepthStencilRestore();
-
     DistortedEffects.zeroOutAtomic();
     DistortedEffects.oitClear(buffer);
-
     GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT|GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
     }
 
@@ -344,29 +291,28 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// two phases: 1. collapse the SSBO 2. blend the ssbo's color
 
   private int oitRender(long currTime, DistortedOutputSurface buffer)
     {
-    if( buffer==this )
-      {
-      android.util.Log.e("surface", "feedback loop in oitRender!");
-      return 0;
-      }
+    float corrW = buffer.getWidthCorrection();
+    float corrH = buffer.getHeightCorrection();
 
     GLES31.glViewport(0, 0, mWidth, mHeight);
     setAsOutput(currTime);
-    GLES31.glActiveTexture(GLES31.GL_TEXTURE0);
-    GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mColorH[0]);
     GLES31.glActiveTexture(GLES31.GL_TEXTURE1);
     GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mDepthStencilH[0]);
 
-    DistortedRenderState.disableStencil();
-    DistortedEffects.oitRender(this, buffer.getWidthCorrection(), buffer.getHeightCorrection() );
-    DistortedRenderState.restoreStencil();
+    DistortedRenderState.switchOffColorDepthStencil();
+    DistortedEffects.oitCollapse(this, corrW, corrH );
 
     GLES31.glActiveTexture(GLES31.GL_TEXTURE1);
     GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
 
+    DistortedRenderState.switchColorDepthOnStencilOff();
+    DistortedEffects.oitRender(this, corrW, corrH);
+    DistortedRenderState.restoreColorDepthStencil();
+
     return 1;
     }
 
@@ -414,7 +360,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     int quality=0, internalQuality = 0, numRenders = 0, bucketChange = 0;
     DistortedNode child1, child2;
     EffectQueuePostprocess lastQueue=null, currQueue;
-    long lastBucket=0, currBucket=0;
+    long lastBucket=0, currBucket;
 
     oitClear(this);
 
@@ -426,8 +372,8 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
       if( currBucket==0 )
         {
-        GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mBufferOIT.mFBOH[0]);
-        numRenders += child1.draw(time, mBufferOIT);
+        GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
+        numRenders += child1.draw(time, this);
 
         //setAsOutput(time);
         //numRenders += child1.draw(time,this);
@@ -451,7 +397,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
               }
 
             numRenders += lastQueue.postprocess(mBuffer);
-            numRenders += mBufferOIT.oitBuild(mBuffer[quality]);
+            numRenders += oitBuild(mBuffer[quality]);
             clearBuffer(mBuffer[quality]);
             }
 
@@ -472,9 +418,9 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
             }
 
           numRenders += currQueue.postprocess(mBuffer);
-          numRenders += mBufferOIT.oitBuild(mBuffer[quality]);
+          numRenders += oitBuild(mBuffer[quality]);
           GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT);
-          numRenders += oitRender(time,mBufferOIT);  // merge the OIT linked list
+          numRenders += oitRender(time,this);  // merge the OIT linked list
           clearBuffer(mBuffer[quality]);
           }
         } // end else (postprocessed child)
@@ -483,11 +429,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
       lastBucket= currBucket;
       } // end main for loop
 
-    if( currBucket==0 ) // there was no postprocessing - we need to merge the main buffer
-      {
-      numRenders += oitRender(time,mBufferOIT);
-      }
-
     return numRenders;
     }
 
diff --git a/src/main/java/org/distorted/library/main/DistortedRenderState.java b/src/main/java/org/distorted/library/main/DistortedRenderState.java
index 3526149..dcdfde3 100644
--- a/src/main/java/org/distorted/library/main/DistortedRenderState.java
+++ b/src/main/java/org/distorted/library/main/DistortedRenderState.java
@@ -231,6 +231,168 @@ public class DistortedRenderState
     GLES31.glDisable(GLES31.GL_SCISSOR_TEST);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void switchOffColorDepthStencil()
+    {
+    sState.stencilTest = cState.stencilTest;
+
+    if( cState.stencilTest!=0 )
+      {
+      cState.stencilTest = 0;
+      //android.util.Log.d("State", "stencil test off");
+      GLES31.glDisable(GLES31.GL_STENCIL_TEST);
+      }
+
+    sState.depthTest = cState.depthTest;
+
+    if( cState.depthTest!=0 )
+      {
+      cState.depthTest = 0;
+      //android.util.Log.d("State", "depth test off");
+      GLES31.glDisable(GLES31.GL_DEPTH_TEST);
+      }
+
+    sState.colorMaskR = cState.colorMaskR;
+    sState.colorMaskG = cState.colorMaskG;
+    sState.colorMaskB = cState.colorMaskB;
+    sState.colorMaskA = cState.colorMaskA;
+
+    if( cState.colorMaskR!=0 || cState.colorMaskG!=0 || cState.colorMaskB!=0 || cState.colorMaskA!=0 )
+      {
+      cState.colorMaskR = 0;
+      cState.colorMaskG = 0;
+      cState.colorMaskB = 0;
+      cState.colorMaskA = 0;
+      //android.util.Log.d("State", "switch off color writing");
+      GLES31.glColorMask(false,false,false,false);
+      }
+
+    sState.depthMask = cState.depthMask;
+
+    if( cState.depthMask!=0 )
+      {
+      cState.depthMask = 0;
+      //android.util.Log.d("State", "switch off depth writing");
+      GLES31.glDepthMask(false);
+      }
+
+    sState.stencilMask = cState.stencilMask;
+
+    if( cState.stencilMask!= 0x00 )
+      {
+      cState.stencilMask = 0x00;
+      //android.util.Log.d("State", "stencil mask off");
+      GLES31.glStencilMask(cState.stencilMask);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void switchColorDepthOnStencilOff()
+    {
+    sState.stencilTest = cState.stencilTest;
+
+    if( cState.stencilTest!=0 )
+      {
+      cState.stencilTest = 0;
+      //android.util.Log.d("State", "stencil test off");
+      GLES31.glDisable(GLES31.GL_STENCIL_TEST);
+      }
+
+    sState.depthTest = cState.depthTest;
+
+    if( cState.depthTest!=0 )
+      {
+      cState.depthTest = 0;
+      //android.util.Log.d("State", "depth test off");
+      GLES31.glDisable(GLES31.GL_DEPTH_TEST);
+      }
+
+    sState.colorMaskR = cState.colorMaskR;
+    sState.colorMaskG = cState.colorMaskG;
+    sState.colorMaskB = cState.colorMaskB;
+    sState.colorMaskA = cState.colorMaskA;
+
+    if( cState.colorMaskR!=1 || cState.colorMaskG!=1 || cState.colorMaskB!=1 || cState.colorMaskA!=1 )
+      {
+      cState.colorMaskR = 1;
+      cState.colorMaskG = 1;
+      cState.colorMaskB = 1;
+      cState.colorMaskA = 1;
+      //android.util.Log.d("State", "switch on color writing");
+      GLES31.glColorMask(true,true,true,true);
+      }
+
+    sState.depthMask = cState.depthMask;
+
+    if( cState.depthMask!=1 )
+      {
+      cState.depthMask = 1;
+      //android.util.Log.d("State", "switch on depth writing");
+      GLES31.glDepthMask(true);
+      }
+
+    sState.stencilMask = cState.stencilMask;
+
+    if( cState.stencilMask!= 0x00 )
+      {
+      cState.stencilMask = 0x00;
+      //android.util.Log.d("State", "stencil mask off");
+      GLES31.glStencilMask(cState.stencilMask);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void restoreColorDepthStencil()
+    {
+    if( sState.stencilTest!=cState.stencilTest )
+      {
+      cState.stencilTest = sState.stencilTest;
+
+      if (cState.stencilTest == 0)
+        {
+        GLES31.glDisable(GLES31.GL_STENCIL_TEST);
+        }
+      else
+        {
+        GLES31.glEnable(GLES31.GL_STENCIL_TEST);
+        }
+      }
+    if( sState.depthTest!=cState.depthTest )
+      {
+      cState.depthTest = sState.depthTest;
+
+      if (cState.depthTest == 0)
+        {
+        GLES31.glDisable(GLES31.GL_DEPTH_TEST);
+        }
+      else
+        {
+        GLES31.glEnable(GLES31.GL_DEPTH_TEST);
+        }
+      }
+    if( sState.colorMaskR!=cState.colorMaskR || sState.colorMaskG!=cState.colorMaskG || sState.colorMaskB!=cState.colorMaskB || sState.colorMaskA!=cState.colorMaskA)
+      {
+      cState.colorMaskR = sState.colorMaskR;
+      cState.colorMaskG = sState.colorMaskG;
+      cState.colorMaskB = sState.colorMaskB;
+      cState.colorMaskA = sState.colorMaskA;
+      GLES31.glColorMask(cState.colorMaskR==1,cState.colorMaskG==1,cState.colorMaskB==1,cState.colorMaskA==1);
+      }
+    if( sState.depthMask!=cState.depthMask )
+      {
+      cState.depthMask = sState.depthMask;
+      GLES31.glDepthMask(cState.depthMask==1);
+      }
+    if( sState.stencilMask!=cState.stencilMask )
+      {
+      cState.stencilMask = sState.stencilMask;
+      GLES31.glStencilMask(cState.stencilMask);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void disableStencil()
diff --git a/src/main/res/raw/oit_collapse_fragment_shader.glsl b/src/main/res/raw/oit_collapse_fragment_shader.glsl
new file mode 100644
index 0000000..027c2b3
--- /dev/null
+++ b/src/main/res/raw/oit_collapse_fragment_shader.glsl
@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2018 Leszek Koltunski                                                          //
+//                                                                                          //
+// This file is part of Distorted.                                                          //
+//                                                                                          //
+// Distorted is free software: you can redistribute it and/or modify                        //
+// it under the terms of the GNU General Public License as published by                     //
+// the Free Software Foundation, either version 2 of the License, or                        //
+// (at your option) any later version.                                                      //
+//                                                                                          //
+// Distorted is distributed in the hope that it will be useful,                             //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                           //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                            //
+// GNU General Public License for more details.                                             //
+//                                                                                          //
+// You should have received a copy of the GNU General Public License                        //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                       //
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+precision highp float;
+precision highp int;
+
+out vec4 fragColor;           // The output color
+in vec2 v_TexCoordinate;      // Interpolated texture coordinate per fragment.
+in vec2 v_Pixel;              // location of the current fragment, in pixels
+
+uniform sampler2D u_DepthTexture;
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+// per-pixel linked list. Order Independent Transparency.
+
+uniform vec2 u_Size;
+
+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).
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Pass3 of the OIT algorithm - traverse the per-pixel LinkedList and cut occluded fragments.
+
+void main()                    		
+  {
+  uint prev = uint(v_Pixel.x + v_Pixel.y * u_Size.x);
+  uint curr = u_Records[prev];
+
+  if (curr != 0u)
+    {
+    const float S= 2147483647.0;
+    float depth = texture(u_DepthTexture, v_TexCoordinate).r;
+    uint texdepth = uint(S*(1.0-depth)/2.0);
+    uint linkedlistdepth = u_Records[curr+1u];
+
+    while( curr != 0u && linkedlistdepth > texdepth )
+      {
+      prev = curr;
+      curr = u_Records[curr];
+      linkedlistdepth = u_Records[curr+1u];
+      }
+
+    if( curr != 0u )
+      {
+      u_Records[prev] = 0u;
+      }
+    }
+  else discard;
+  }
\ No newline at end of file
diff --git a/src/main/res/raw/oit_render_fragment_shader.glsl b/src/main/res/raw/oit_render_fragment_shader.glsl
index e6112b9..c108e94 100644
--- a/src/main/res/raw/oit_render_fragment_shader.glsl
+++ b/src/main/res/raw/oit_render_fragment_shader.glsl
@@ -24,9 +24,6 @@ out vec4 fragColor;           // The output color
 in vec2 v_TexCoordinate;      // Interpolated texture coordinate per fragment.
 in vec2 v_Pixel;              // location of the current fragment, in pixels
 
-uniform sampler2D u_Texture;
-uniform sampler2D u_DepthTexture;
-
 //////////////////////////////////////////////////////////////////////////////////////////////
 // per-pixel linked list. Order Independent Transparency.
 
@@ -54,39 +51,26 @@ vec4 blend(vec4 clr,vec4 srf)
   }
 
 //////////////////////////////////////////////////////////////////////////////////////////////
-// Pass3 of the OIT algorithm - traverse the per-pixel LinkedList and build the final color.
+// Pass4 of the OIT algorithm - keep traversing the linked list, build the final color and blend it.
 
 void main()                    		
   {
-  float texdepth = texture(u_DepthTexture, v_TexCoordinate).r;
-  vec4  color    = texture(u_Texture     , v_TexCoordinate);
-  uint  index    = uint(v_Pixel.x + v_Pixel.y * u_Size.x);
-  uint  curr     = u_Records[index];
+  uint prev = uint(v_Pixel.x + v_Pixel.y * u_Size.x);
+  uint curr = u_Records[prev];
 
   if (curr != 0u)
     {
     const float S= 2147483647.0;
-    uint depth = u_Records[curr+1u];
-    uint texdepthuint = uint(S*(1.0-texdepth)/2.0);
-    texdepth = 1.0 -2.0*float(depth)/S;
+    gl_FragDepth = 1.0 - 2.0*float(u_Records[curr+1u])/S;
+    vec4 color   = convert(u_Records[curr+2u]);
 
-    if( depth >= texdepthuint )
+    while (curr != 0u)
       {
-      vec4 clr= convert(u_Records[curr+2u]);
       curr = u_Records[curr];
-
-      while (curr > 0u)
-        {
-        depth= u_Records[curr+1u];                       // keep walking the linked list
-        if( depth < texdepthuint ) break;                // until we reach scene depth
-        clr= blend( clr, convert(u_Records[curr+2u]) );  // and blending the colors in
-        curr = u_Records[curr];
-        }
-
-      color = blend( clr, color);
+      color = blend( color , convert(u_Records[curr+2u]) );
       }
-    }
 
-  gl_FragDepth = texdepth;
-  fragColor    = color;
+    fragColor = color;
+    }
+  else discard;
   }
\ No newline at end of file
