commit b9798977391f22310ba31d908314f4ace1168085
Author: leszek <leszek@koltunski.pl>
Date:   Sun Mar 12 23:02:53 2017 +0000

    Advances in Multiblur - breaks BLUR for now.

diff --git a/src/main/java/org/distorted/library/DistortedEffects.java b/src/main/java/org/distorted/library/DistortedEffects.java
index 54fc04f..afd5b1d 100644
--- a/src/main/java/org/distorted/library/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/DistortedEffects.java
@@ -95,8 +95,6 @@ public class DistortedEffects
   private static long mNextID =0;
   private long mID;
 
-  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,1,1);
-
   private EffectQueueMatrix      mM;
   private EffectQueueFragment    mF;
   private EffectQueueVertex      mV;
@@ -281,6 +279,13 @@ public class DistortedEffects
     GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedFramebuffer getPostprocessingBuffer()
+    {
+    return mP.mNumEffects==0 ? null : mP.mMainBuffer;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime)
@@ -293,50 +298,16 @@ public class DistortedEffects
     float halfZ = halfW*mesh.zFactor;
     GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight);
 
-    if( mP.mNumEffects==0 )
-      {
-      mMainProgram.useProgram();
-      GLES30.glUniform1i(mMainTextureH, 0);
-      surface.setAsOutput();
-      mM.send(surface,halfW,halfH,halfZ);
-      mV.send(halfW,halfH,halfZ);
-      mF.send(halfW,halfH);
-      GLES30.glVertexAttribPointer(mMainProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions);
-      GLES30.glVertexAttribPointer(mMainProgram.mAttribute[1], NORMAL_DATA_SIZE  , GLES30.GL_FLOAT, false, 0, mesh.mMeshNormals);
-      GLES30.glVertexAttribPointer(mMainProgram.mAttribute[2], TEX_DATA_SIZE     , GLES30.GL_FLOAT, false, 0, mesh.mMeshTexture);
-      GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength);
-      }
-    else
-      {
-      if( mV.mNumEffects==0 && mF.mNumEffects==0 && (mesh instanceof MeshFlat) && mM.canUseShortcut() )
-        {
-        mM.constructMatrices(surface,halfW,halfH);
-        mP.render(2*halfW, 2*halfH, mM.getMVP(), surface);
-        }
-      else
-        {
-        mMainProgram.useProgram();
-        GLES30.glUniform1i(mMainTextureH, 0);
-        mBufferFBO.resizeFast(surface.mWidth, surface.mHeight);
-        mBufferFBO.setAsOutput();
-        GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-        GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
-        mM.send(mBufferFBO,halfW,halfH,halfZ);
-        mV.send(halfW,halfH,halfZ);
-        mF.send(halfW,halfH);
-        GLES30.glVertexAttribPointer(mMainProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions);
-        GLES30.glVertexAttribPointer(mMainProgram.mAttribute[1], NORMAL_DATA_SIZE  , GLES30.GL_FLOAT, false, 0, mesh.mMeshNormals);
-        GLES30.glVertexAttribPointer(mMainProgram.mAttribute[2], TEX_DATA_SIZE     , GLES30.GL_FLOAT, false, 0, mesh.mMeshTexture);
-        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength);
-
-        Matrix.setIdentityM(mTmpMatrix, 0);
-        Matrix.translateM(mTmpMatrix, 0, 0, 0, -surface.mDistance);
-        Matrix.multiplyMM(mMVPMatrix, 0, surface.mProjectionMatrix, 0, mTmpMatrix, 0);
-
-        mBufferFBO.setAsInput();
-        mP.render(surface.mWidth, surface.mHeight, mMVPMatrix, surface);
-        }
-      }
+    mMainProgram.useProgram();
+    GLES30.glUniform1i(mMainTextureH, 0);
+    surface.setAsOutput();
+    mM.send(surface,halfW,halfH,halfZ);
+    mV.send(halfW,halfH,halfZ);
+    mF.send(halfW,halfH);
+    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions);
+    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[1], NORMAL_DATA_SIZE  , GLES30.GL_FLOAT, false, 0, mesh.mMeshNormals);
+    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[2], TEX_DATA_SIZE     , GLES30.GL_FLOAT, false, 0, mesh.mMeshTexture);
+    GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength);
 
     /// DEBUG ONLY //////
     // displayBoundingRect(halfInputW, halfInputH, halfZ, df, mM.getMVP(), mesh.getBoundingVertices() );
diff --git a/src/main/java/org/distorted/library/DistortedFramebuffer.java b/src/main/java/org/distorted/library/DistortedFramebuffer.java
index 5ded4fa..b33124a 100644
--- a/src/main/java/org/distorted/library/DistortedFramebuffer.java
+++ b/src/main/java/org/distorted/library/DistortedFramebuffer.java
@@ -31,6 +31,13 @@ import android.opengl.GLES30;
 public class DistortedFramebuffer extends DistortedOutputSurface implements DistortedInputSurface
   {
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedFramebuffer getBuffer()
+    {
+    return this;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Must be called from a thread holding OpenGL Context
 // Watch out - this has the side-effect of binding a Texture and a Framebuffer!
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index 0e35919..c7ac201 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -211,6 +211,13 @@ public class DistortedNode implements DistortedAttacheable
     return 0;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedFramebuffer getPostprocessingBuffer()
+    {
+    return mEffects.getPostprocessingBuffer();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // return the total number of render calls issued
 
diff --git a/src/main/java/org/distorted/library/DistortedOutputSurface.java b/src/main/java/org/distorted/library/DistortedOutputSurface.java
index b01f7cf..d9db081 100644
--- a/src/main/java/org/distorted/library/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/DistortedOutputSurface.java
@@ -39,6 +39,10 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
   int[] mDepthH = new int[1];
   int[] mFBOH   = new int[1];
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  abstract DistortedFramebuffer getBuffer();
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   DistortedOutputSurface(int width, int height, int createColor, int createDepth, int fbo, int type)
@@ -105,10 +109,54 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
   int renderChildren(long time, int num, ArrayList<DistortedNode> children)
     {
     int numRenders = 0;
+    DistortedNode child;
+    DistortedFramebuffer fbo;
+    DistortedOutputSurface buffer;
+
+    // 1. Render all children that have postprocessing effects to their own buffer FBOs
 
     for(int i=0; i<num; i++)
       {
-      numRenders += children.get(i).draw(time,this);
+      child = children.get(i);
+      fbo   = child.getPostprocessingBuffer();
+
+      if( fbo!=null )
+        {
+        fbo.resizeFast(mWidth,mHeight);
+        numRenders += child.draw(time,fbo);
+        }
+      }
+
+    // 2. If we have rendered anything so far, and we are a Screen, then render to an
+    //    intermediate FBO instead.
+
+    buffer = numRenders>0 ? getBuffer() : this;
+
+    // 3. Render all children without postprocessing effects to buffer
+
+    for(int i=0; i<num; i++)
+      {
+      child = children.get(i);
+      fbo   = child.getPostprocessingBuffer();
+
+      if( fbo==null )
+        {
+        numRenders += child.draw(time,buffer);
+        }
+      }
+
+    // 4. For all postprocessing fbo,
+    //       postprocess fbo
+    //       merge to buffer
+
+    // TODO
+
+    // 5. finally blit to this if we have to
+
+    if( buffer!=this && ((DistortedFramebuffer)buffer).setAsInput() )
+      {
+      numRenders++;
+      DistortedEffects.blitPriv(this);
       }
 
     return numRenders;
diff --git a/src/main/java/org/distorted/library/DistortedScreen.java b/src/main/java/org/distorted/library/DistortedScreen.java
index 523e126..0bccd99 100644
--- a/src/main/java/org/distorted/library/DistortedScreen.java
+++ b/src/main/java/org/distorted/library/DistortedScreen.java
@@ -27,6 +27,8 @@ package org.distorted.library;
  */
 public class DistortedScreen extends DistortedOutputSurface
   {
+  DistortedFramebuffer mBuffer = null;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // here we don't manage underlying OpenGL assets ourselves
 
@@ -34,6 +36,23 @@ public class DistortedScreen extends DistortedOutputSurface
   void delete()   {}
   void recreate() {}
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedFramebuffer getBuffer()
+    {
+    if( mBuffer==null )
+      {
+      mBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,mWidth,mHeight);
+      }
+
+    if( mBuffer.mWidth != mWidth || mBuffer.mHeight != mHeight )
+      {
+      mBuffer.resizeFast(mWidth,mHeight);
+      }
+
+    return mBuffer;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
index 321fa0f..aed0bdd 100644
--- a/src/main/java/org/distorted/library/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
@@ -69,7 +69,8 @@ class EffectQueuePostprocess extends EffectQueue
     mQuadTextureInv.put(textureInv).position(0);
     }
 
-  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,1,1);
+  private static DistortedFramebuffer mPostBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,1,1);
+                 DistortedFramebuffer mMainBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,1,1);
 
   private static float[] mMVPMatrix = new float[16];
   private static float[] mTmpMatrix = new float[16];
@@ -245,15 +246,15 @@ class EffectQueuePostprocess extends EffectQueue
     GLES30.glUniform1i( mRadiusH, radius);
     GLES30.glUniform2f( mObjDH , w, h );
 
-    mBufferFBO.resizeFast( (int)w, (int)h);
-    mBufferFBO.setAsOutput();
+    mPostBuffer.resizeFast( (int)w, (int)h);
+    mPostBuffer.setAsOutput();
     GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
     GLES30.glViewport(0, 0, (int)w, (int)h);
 
     Matrix.setIdentityM(mTmpMatrix, 0);
-    Matrix.translateM(mTmpMatrix, 0, 0, 0, -mBufferFBO.mDistance);
-    Matrix.multiplyMM(mMVPMatrix, 0, mBufferFBO.mProjectionMatrix, 0, mTmpMatrix, 0);
+    Matrix.translateM(mTmpMatrix, 0, 0, 0, -mPostBuffer.mDistance);
+    Matrix.multiplyMM(mMVPMatrix, 0, mPostBuffer.mProjectionMatrix, 0, mTmpMatrix, 0);
 
     // horizontal blur
     GLES30.glUniform1fv( mOffsetsH ,radius+1, mOffsets,0);
@@ -262,7 +263,7 @@ class EffectQueuePostprocess extends EffectQueue
     GLES30.glVertexAttribPointer(mBlurProgram.mAttribute[1], TEX_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mQuadTextureInv);
     GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
 
-    mBufferFBO.setAsInput();
+    mPostBuffer.setAsInput();
     surface.setAsOutput();
 
     GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight);
