commit c1a38ba3756b73fca71396b903a1b721c037b793
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Jul 2 00:21:30 2018 +0100

    Progress with non-postprocessed OIT.
    
    Status: compiles, but fails to work on both Adreno and Mali. Crashes the app (Adreno) or the whole system (Mali)

diff --git a/src/main/java/org/distorted/library/main/Distorted.java b/src/main/java/org/distorted/library/main/Distorted.java
index a073c20..e469b24 100644
--- a/src/main/java/org/distorted/library/main/Distorted.java
+++ b/src/main/java/org/distorted/library/main/Distorted.java
@@ -120,14 +120,14 @@ public class Distorted
       {
       if( version.contains("r12") )
         {
-        android.util.Log.e("DISTORTED", "You are running this on a ARM Mali driver r12. This is a buggy driver, please update to r22. Problems with flashing expected.");
+        android.util.Log.e("DISTORTED", "You are running this on a ARM Mali driver r12.\nThis is a buggy driver, please update to r22. Problems with flashing expected.");
         }
       }
     else if( vendor.contains("Imagination") )
       {
       if( renderer.contains("GE8") )
         {
-        android.util.Log.e("DISTORTED", "You are running this on a PowerVR GE8XXX. Due to a buggy compiler OIT rendering will not work");
+        android.util.Log.e("DISTORTED", "You are running this on a PowerVR GE8XXX.\nDue to a buggy compiler OIT rendering will not work");
         }
       }
     }
diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index 060d778..8f3e95a 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -70,6 +70,10 @@ public class DistortedEffects
   private static int mBlitDepthDepthH;
   private static int mBlitDepthTexCorrH;
 
+  /// NORMAL PROGRAM /////
+  private static DistortedProgram mNormalProgram;
+  private static int mNormalMVPMatrixH;
+
   /// OIT SSBO BUFFER ///
   private static int[] mLinkedListSSBO = new int[1];
   private static int[] mAtomicCounter = new int[1];
@@ -113,9 +117,11 @@ public class DistortedEffects
   private static int mOITRenderTexCorrH;
   private static int mOITRenderSizeH;
 
-  /// NORMAL PROGRAM /////
-  private static DistortedProgram mNormalProgram;
-  private static int mNormalMVPMatrixH;
+  /// MAIN OIT PROGRAM ///
+  private static DistortedProgram mMainOITProgram;
+  private static int mMainOITTextureH;
+  private static int mMainOITSizeH;
+  private static int mMainOITNumRecordsH;
   /// END PROGRAMS //////
 
   private static long mNextID =0;
@@ -228,6 +234,42 @@ public class DistortedEffects
 
   static void createProgramsOIT(Resources resources)
     {
+    // MAIN OIT PROGRAM ////////////////////////////////
+    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
+    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
+
+    int numF = FragmentEffect.getNumEnabled();
+    int numV = VertexEffect.getNumEnabled();
+
+    String mainVertHeader= Distorted.GLSL_VERSION +
+                           ("#define NUM_VERTEX "   + ( numV>0 ? getMax(EffectType.VERTEX  ) : 0 ) + "\n") +
+                           ("#define OIT\n");
+    String mainFragHeader= Distorted.GLSL_VERSION +
+                           ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n") +
+                           ("#define OIT\n");
+
+    String enabledEffectV= VertexEffect.getGLSL();
+    String enabledEffectF= FragmentEffect.getGLSL();
+
+    try
+      {
+      mMainOITProgram = new DistortedProgram(mainVertStream, mainFragStream, mainVertHeader, mainFragHeader,
+          enabledEffectV, enabledEffectF, Distorted.GLSL, null);
+      }
+    catch(Exception e)
+      {
+      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile MAIN OIT program: "+e.getMessage());
+      throw new RuntimeException(e.getMessage());
+      }
+
+    int mainOITProgramH = mMainOITProgram.getProgramHandle();
+    EffectQueueFragment.getUniformsOIT(mainOITProgramH);
+    EffectQueueVertex.getUniformsOIT(mainOITProgramH);
+    EffectQueueMatrix.getUniformsOIT(mainOITProgramH);
+    mMainOITTextureH    = GLES31.glGetUniformLocation( mainOITProgramH, "u_Texture");
+    mMainOITSizeH       = GLES31.glGetUniformLocation( mainOITProgramH, "u_Size");
+    mMainOITNumRecordsH = GLES31.glGetUniformLocation( mainOITProgramH, "u_numRecords");
+
     // OIT CLEAR PROGRAM ////////////////////////////////////
     final InputStream oitClearVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
     final InputStream oitClearFragStream = resources.openRawResource(R.raw.oit_clear_fragment_shader);
@@ -414,6 +456,39 @@ public class DistortedEffects
     GLES31.glDrawArrays(GLES31.GL_LINES, 0, 2*mesh.numVertices);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void drawPrivOIT(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime, float marginInPixels)
+    {
+    float halfZ = halfW*mesh.zFactor;
+
+    mM.compute(currTime);
+    mV.compute(currTime,halfW,halfH,halfZ);
+    mF.compute(currTime,halfW,halfH);
+    mP.compute(currTime);
+
+    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
+
+    mMainOITProgram.useProgram();
+    GLES31.glUniform1i(mMainOITTextureH, 0);
+    GLES31.glUniform2ui(mMainOITSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform1ui(mMainOITNumRecordsH, (mBufferSize-surface.mWidth*surface.mHeight)/3 );  // see the fragment shader
+
+    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttVBO[0]);
+    GLES31.glVertexAttribPointer(mMainOITProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET0);
+    GLES31.glVertexAttribPointer(mMainOITProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET1);
+    GLES31.glVertexAttribPointer(mMainOITProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
+    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
+
+    mM.sendOIT(surface,halfW,halfH,halfZ,marginInPixels);
+    mV.sendOIT();
+    mF.sendOIT();
+
+    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
+
+    if( mesh.mShowNormals ) displayNormals(mesh);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime, float marginInPixels)
diff --git a/src/main/java/org/distorted/library/main/DistortedNode.java b/src/main/java/org/distorted/library/main/DistortedNode.java
index a61e9af..3a9c8b0 100644
--- a/src/main/java/org/distorted/library/main/DistortedNode.java
+++ b/src/main/java/org/distorted/library/main/DistortedNode.java
@@ -293,6 +293,23 @@ public class DistortedNode implements DistortedMaster.Slave
     return 0;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Use the Order Independent Transparency method to draw a non-postprocessed child.
+
+  int drawOIT(long currTime, DistortedOutputSurface surface)
+    {
+    DistortedInputSurface input = mNumChildren[0]==0 ? mSurface : mData.mFBO;
+
+    if( input.setAsInput() )
+      {
+      mState.apply();
+      mEffects.drawPrivOIT(mSurface.getWidth()/2.0f, mSurface.getHeight()/2.0f, mMesh, surface, currTime, 0);
+      return 1;
+      }
+
+    return 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // return the total number of render calls issued
 
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index a6daa13..fd05bab 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -395,6 +395,11 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     EffectQueuePostprocess lastQueue=null, currQueue;
     long lastBucket=0, currBucket;
 
+    if( oit && numChildren>0 )
+      {
+      oitClear(this);
+      }
+
     for(int i=0; i<numChildren; i++)
       {
       child1 = children.get(i);
@@ -404,7 +409,16 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
       if( currBucket==0 )
         {
         setAsOutputFBO(time,fbo);
-        numRenders += child1.draw(time,this);
+
+        if( oit )
+          {
+          numRenders += child1.drawOIT(time, this);
+          GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
+          }
+        else
+          {
+          numRenders += child1.draw(time, this);
+          }
         }
       else
         {
@@ -415,11 +429,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
           if( lastBucket==0 )
             {
             clonePostprocessingViewport(this);
-
-            if( oit )
-              {
-              oitClear(this);
-              }
             }
           else
             {
@@ -467,7 +476,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
             {
             numRenders += oitBuild(time, mBuffer[quality], fbo);
             GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
-            numRenders += oitRender(time, fbo);  // merge the OIT linked list
             mBuffer[quality].clearBuffer(fbo);
             }
           else
@@ -481,6 +489,11 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
       lastBucket= currBucket;
       } // end main for loop
 
+    if( oit && numChildren>0 )
+      {
+      numRenders += oitRender(time, fbo);  // merge the OIT linked list
+      }
+
     return numRenders;
     }
 
diff --git a/src/main/java/org/distorted/library/main/EffectQueueFragment.java b/src/main/java/org/distorted/library/main/EffectQueueFragment.java
index 7e0fbb3..ca0d7fa 100644
--- a/src/main/java/org/distorted/library/main/EffectQueueFragment.java
+++ b/src/main/java/org/distorted/library/main/EffectQueueFragment.java
@@ -31,10 +31,15 @@ class EffectQueueFragment extends EffectQueue
   {
   private static final int NUM_UNIFORMS = FragmentEffect.NUM_UNIFORMS;
   private static final int INDEX = EffectType.FRAGMENT.ordinal();
+
   private static int mNumEffectsH;
   private static int mNameH;
   private static int mUniformsH;
-  
+
+  private static int mNumEffectsOITH;
+  private static int mNameOITH;
+  private static int mUniformsOITH;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
   EffectQueueFragment(long id)
@@ -51,6 +56,15 @@ class EffectQueueFragment extends EffectQueue
     mUniformsH  = GLES31.glGetUniformLocation( mProgramH, "fUniforms");
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void getUniformsOIT(int mProgramH)
+    {
+    mNumEffectsOITH= GLES31.glGetUniformLocation( mProgramH, "fNumEffects");
+    mNameOITH      = GLES31.glGetUniformLocation( mProgramH, "fName");
+    mUniformsOITH  = GLES31.glGetUniformLocation( mProgramH, "fUniforms");
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
   void compute(long currTime,float halfX, float halfY)
@@ -95,4 +109,17 @@ class EffectQueueFragment extends EffectQueue
       GLES31.glUniform4fv( mUniformsH,(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
       }  
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void sendOIT()
+    {
+    GLES31.glUniform1i( mNumEffectsOITH, mNumEffects);
+
+    if( mNumEffects>0 )
+      {
+      GLES31.glUniform1iv( mNameOITH    ,                 mNumEffects, mName    ,0);
+      GLES31.glUniform4fv( mUniformsOITH,(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
+      }
+    }
   }
diff --git a/src/main/java/org/distorted/library/main/EffectQueueMatrix.java b/src/main/java/org/distorted/library/main/EffectQueueMatrix.java
index 22c0dad..a4768e8 100644
--- a/src/main/java/org/distorted/library/main/EffectQueueMatrix.java
+++ b/src/main/java/org/distorted/library/main/EffectQueueMatrix.java
@@ -43,9 +43,13 @@ class EffectQueueMatrix extends EffectQueue
   private static float mMiny;
   private static float mMaxy;
 
-  private static int mObjDH;      // This is a handle to half a Object dimensions
-  private static int mMVPMatrixH; // the transformation matrix
-  private static int mMVMatrixH;  // the modelview matrix.
+  private static int mObjDH;         // This is a handle to half a Object dimensions
+  private static int mMVPMatrixH;    // the transformation matrix
+  private static int mMVMatrixH;     // the modelview matrix.
+
+  private static int mObjDOITH;      //
+  private static int mMVPMatrixOITH; // Same like above, but in main OIT program.
+  private static int mMVMatrixOITH;  //
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
@@ -108,6 +112,15 @@ class EffectQueueMatrix extends EffectQueue
     mMVMatrixH = GLES31.glGetUniformLocation(mProgramH, "u_MVMatrix"); 
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void getUniformsOIT(int mProgramH)
+    {
+    mObjDOITH     = GLES31.glGetUniformLocation(mProgramH, "u_objD");
+    mMVPMatrixOITH= GLES31.glGetUniformLocation(mProgramH, "u_MVPMatrix");
+    mMVMatrixOITH = GLES31.glGetUniformLocation(mProgramH, "u_MVMatrix");
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void compute(long currTime)
@@ -162,4 +175,24 @@ class EffectQueueMatrix extends EffectQueue
     GLES31.glUniformMatrix4fv(mMVMatrixH , 1, false, mViewMatrix, 0);
     GLES31.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0);
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void sendOIT(DistortedOutputSurface projection, float halfX, float halfY, float halfZ, float marginInPixels)
+    {
+    Matrix.setIdentityM(mViewMatrix, 0);
+    Matrix.translateM(mViewMatrix, 0, -projection.mWidth/2, projection.mHeight/2, -projection.mDistance);
+    float mipmap = projection.mMipmap;
+    if( mipmap!=1 ) Matrix.scaleM(mViewMatrix, 0, mipmap, mipmap, mipmap);
+
+    for(int i=0; i<mNumEffects; i++) ((MatrixEffect)mEffects[i]).apply(mViewMatrix,mUniforms,i);
+
+    Matrix.translateM(mViewMatrix, 0, halfX,-halfY,-halfZ);
+    if( marginInPixels!=0 ) magnify(projection,halfX,halfY,halfZ, marginInPixels);
+    Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mViewMatrix, 0);
+
+    GLES31.glUniform3f( mObjDOITH , halfX, halfY, halfZ);
+    GLES31.glUniformMatrix4fv(mMVMatrixOITH , 1, false, mViewMatrix, 0);
+    GLES31.glUniformMatrix4fv(mMVPMatrixOITH, 1, false, mMVPMatrix , 0);
+    }
   }
diff --git a/src/main/java/org/distorted/library/main/EffectQueueVertex.java b/src/main/java/org/distorted/library/main/EffectQueueVertex.java
index 9909201..1b10c12 100644
--- a/src/main/java/org/distorted/library/main/EffectQueueVertex.java
+++ b/src/main/java/org/distorted/library/main/EffectQueueVertex.java
@@ -31,10 +31,15 @@ class EffectQueueVertex extends EffectQueue
   { 
   private static final int NUM_UNIFORMS = VertexEffect.NUM_UNIFORMS;
   private static final int INDEX = EffectType.VERTEX.ordinal();
+
   private static int mNumEffectsH;
   private static int mNameH;
   private static int mUniformsH;
-  
+
+  private static int mNumEffectsOITH;
+  private static int mNameOITH;
+  private static int mUniformsOITH;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
   EffectQueueVertex(long id)
@@ -51,6 +56,15 @@ class EffectQueueVertex extends EffectQueue
     mUniformsH  = GLES31.glGetUniformLocation( mProgramH, "vUniforms");
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void getUniformsOIT(int mProgramH)
+    {
+    mNumEffectsOITH= GLES31.glGetUniformLocation( mProgramH, "vNumEffects");
+    mNameOITH      = GLES31.glGetUniformLocation( mProgramH, "vName");
+    mUniformsOITH  = GLES31.glGetUniformLocation( mProgramH, "vUniforms");
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
   void compute(long currTime,float halfX, float halfY, float halfZ)
@@ -96,4 +110,17 @@ class EffectQueueVertex extends EffectQueue
       GLES31.glUniform4fv( mUniformsH,(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
       }
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void sendOIT()
+    {
+    GLES31.glUniform1i( mNumEffectsOITH, mNumEffects);
+
+    if( mNumEffects>0 )
+      {
+      GLES31.glUniform1iv( mNameOITH    ,                 mNumEffects, mName    ,0);
+      GLES31.glUniform4fv( mUniformsOITH,(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
+      }
+    }
   }
diff --git a/src/main/res/raw/main_fragment_shader.glsl b/src/main/res/raw/main_fragment_shader.glsl
index 60999f1..52ad3dd 100644
--- a/src/main/res/raw/main_fragment_shader.glsl
+++ b/src/main/res/raw/main_fragment_shader.glsl
@@ -18,6 +18,7 @@
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 precision highp float;
+precision highp int;
 
 in vec3 v_Position;                     // Interpolated position for this fragment.
 in vec3 v_Normal;                       // Interpolated normal for this fragment.
@@ -93,6 +94,14 @@ void insert( vec2 ij, uint depth, uint rgba )
       }
     }
   }
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+uint convert(vec4 c)
+  {
+  return ((uint(255.0*c.r))<<24u) + ((uint(255.0*c.g))<<16u) + ((uint(255.0*c.b))<<8u) + uint(255.0*c.a);
+  }
+
 #endif   // OIT
 
 //////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,16 +127,16 @@ void main()
 #endif
 
 #ifdef OIT
-  if( frag.a > 0.95 )
+  if( color.a > 0.95 )
     {
     fragColor= vec4(color.rgb * (1.0 + 7.0*v_Normal.z) * 0.125, color.a);
     }
   else
     {
-    if( frag.a > 0.0 )
+    if( color.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) );
+      insert(v_Pixel, uint(S*(1.0-gl_FragCoord.z)/2.0), convert(color) );
       }
     discard;
     }
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 0b7f689..1c16d47 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -18,6 +18,7 @@
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 precision highp float;
+precision highp int;
 
 in vec3 a_Position;                  // Per-vertex position.
 in vec3 a_Normal;                    // Per-vertex normal vector.
diff --git a/src/main/res/raw/oit_build_fragment_shader.glsl b/src/main/res/raw/oit_build_fragment_shader.glsl
index d1faf2c..2cbcbe2 100644
--- a/src/main/res/raw/oit_build_fragment_shader.glsl
+++ b/src/main/res/raw/oit_build_fragment_shader.glsl
@@ -95,20 +95,20 @@ uint convert(vec4 c)
 
 void main()                    		
   {
-  vec4  frag = texture(u_Texture     , v_TexCoordinate);
+  vec4  color= texture(u_Texture     , v_TexCoordinate);
   float depth= texture(u_DepthTexture, v_TexCoordinate).r;
 
-  if( frag.a > 0.95 )
+  if( color.a > 0.95 )
     {
     gl_FragDepth = depth;
-    fragColor    = frag;
+    fragColor    = color;
     }
   else
     {
-    if( frag.a > 0.0 )
+    if( color.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) );
+      insert(v_Pixel, uint(S*(1.0-depth)/2.0), convert(color) );
       }
     discard;
     }
