commit 9e771d064b8cc8dcfaaa70e5ab4b84c0f4a27dad
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Jul 26 15:32:57 2018 +0100

    Progress with thr Glow effect - moving glow app looks ok now.

diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffect.java b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
index fef1b83..05dd943 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffect.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
@@ -19,8 +19,8 @@
 
 package org.distorted.library.effect;
 
+import org.distorted.library.main.DistortedFramebuffer;
 import org.distorted.library.main.DistortedMaster;
-import org.distorted.library.main.DistortedOutputSurface;
 import org.distorted.library.program.DistortedProgram;
 
 import java.nio.ByteBuffer;
@@ -139,26 +139,15 @@ public abstract class PostprocessEffect extends Effect implements DistortedMaste
  *
  * @y.exclude
  */
-  public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers);
+  public abstract int apply(float[] uniforms, int index, DistortedFramebuffer buffer);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Only for use by the library itself.
- *
- * @y.exclude
- */
-  public abstract int getQuality();
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Only for use by the library itself.
- *
- * @y.exclude
- */
-  public int getInternalQuality()
-    {
-    return mQualityLevel;
-    }
+  /**
+   * Only for use by the library itself.
+   *
+   * @y.exclude
+   */
+  public abstract boolean getRender();
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   /**
@@ -166,9 +155,9 @@ public abstract class PostprocessEffect extends Effect implements DistortedMaste
    *
    * @y.exclude
    */
-  public int getWriteColor()
+  public int getQuality()
     {
-    return 0;
+    return mQualityLevel;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
index 6f25bea..ea937e1 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
@@ -125,15 +125,15 @@ public class PostprocessEffectBlur extends PostprocessEffect
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Only for use by the library itself.
- *
- * @y.exclude
- */
-  public int getQuality()
-   {
-   return mQualityLevel;
-   }
+  /**
+   * Only for use by the library itself.
+   *
+   * @y.exclude
+   */
+  public boolean getRender()
+    {
+    return false;
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -141,7 +141,7 @@ public class PostprocessEffectBlur extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
+  public int apply(float[] uniforms, int index, DistortedFramebuffer buffer)
     {
     if( mProgram1 ==null)
       {
@@ -158,8 +158,6 @@ public class PostprocessEffectBlur extends PostprocessEffect
 
     DistortedRenderState.useStencilMark();
 
-    DistortedFramebuffer buffer = (DistortedFramebuffer)buffers[mQualityLevel];
-
     buffer.setAsOutput();
 
     float w= buffer.getWidth();
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
index 13cdbe9..dedc039 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
@@ -22,9 +22,7 @@ package org.distorted.library.effect;
 import android.opengl.GLES31;
 
 import org.distorted.library.main.Distorted;
-import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedFramebuffer;
-import org.distorted.library.main.DistortedOutputSurface;
 import org.distorted.library.main.DistortedRenderState;
 import org.distorted.library.program.DistortedProgram;
 import org.distorted.library.type.Data1D;
@@ -129,15 +127,15 @@ public class PostprocessEffectGlow extends PostprocessEffect
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Only for use by the library itself.
- *
- * @y.exclude
- */
-  public int getQuality()
-   {
-   return 0;
-   }
+  /**
+   * Only for use by the library itself.
+   *
+   * @y.exclude
+   */
+  public boolean getRender()
+    {
+    return true;
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -145,7 +143,7 @@ public class PostprocessEffectGlow extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
+  public int apply(float[] uniforms, int index, DistortedFramebuffer buffer)
     {
     if( mProgram1 ==null)
       {
@@ -162,15 +160,14 @@ public class PostprocessEffectGlow extends PostprocessEffect
 
     DistortedRenderState.useStencilMark();
 
-    DistortedFramebuffer  inBuffer = (DistortedFramebuffer)buffers[0];
-    DistortedFramebuffer outBuffer = (DistortedFramebuffer)buffers[mQualityLevel];
+    buffer.setAsOutput();
 
-    float w= outBuffer.getWidth();
-    float h= outBuffer.getHeight();
-    float n= 1.0f - outBuffer.getNear();
+    float w= buffer.getWidth();
+    float h= buffer.getHeight();
+    float n= 1.0f - buffer.getNear();
 
-    float corrW = inBuffer.getWidthCorrection();
-    float corrH = inBuffer.getHeightCorrection();
+    float corrW = buffer.getWidthCorrection();
+    float corrH = buffer.getHeightCorrection();
     float offsetCorrW = corrW/w;
     float offsetCorrH = corrH/h;
 
@@ -180,16 +177,14 @@ public class PostprocessEffectGlow extends PostprocessEffect
 
     int offset = radius + radius*radius/4;
     radius = (radius+1)/2;
-
     GLES31.glViewport(0, 0, (int)w, (int)h);
 
-    // horizontal glow
+    // horizontal blur
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
 
     mProgram1.useProgram();
-    outBuffer.setAsOutput();
-    outBuffer.bindForOutput(1);
-    inBuffer.setAsInput(0);
+    buffer.bindForOutput(1);
+    buffer.setAsInput(0);
 
     GLES31.glColorMask(true,true,true,true);
     GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f);
@@ -201,22 +196,18 @@ public class PostprocessEffectGlow extends PostprocessEffect
     GLES31.glUniform1fv( mProgram1.mUniform[3] , radius+1, mOffsets,0);
     GLES31.glUniform1fv( mProgram1.mUniform[4] , radius+1, weightsCache,offset);
     GLES31.glUniform1i ( mProgram1.mUniform[5] , radius);
-    GLES31.glUniform4f ( mProgram1.mUniform[6] , uniforms[index+1], uniforms[index+2], uniforms[index+3], uniforms[index+4]);
     GLES31.glVertexAttribPointer(mProgram1.mAttribute[0], POS_DATA_SIZE, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glVertexAttribPointer(mProgram1.mAttribute[1], TEX_DATA_SIZE, GLES31.GL_FLOAT, false, 0, mQuadTexture);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
 
-    // vertical glow
+    // vertical blur
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
 
     mProgram2.useProgram();
-    outBuffer.bindForOutput(0);
-    outBuffer.setAsInput(1);
+    buffer.bindForOutput(0);
+    buffer.setAsInput(1);
 
-    if( mQualityLevel==0 )
-      {
-      GLES31.glEnable(GLES31.GL_BLEND);
-      }
+    GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
 
     GLES31.glUniform1f ( mProgram2.mUniform[0] , n );
     GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH );
@@ -224,30 +215,12 @@ public class PostprocessEffectGlow extends PostprocessEffect
     GLES31.glUniform1fv( mProgram2.mUniform[3] , radius+1, mOffsets,0);
     GLES31.glUniform1fv( mProgram2.mUniform[4] , radius+1, weightsCache,offset);
     GLES31.glUniform1i ( mProgram2.mUniform[5] , radius);
-    GLES31.glUniform4f ( mProgram1.mUniform[6] , uniforms[index+1], uniforms[index+2], uniforms[index+3], uniforms[index+4]);
     GLES31.glVertexAttribPointer(mProgram2.mAttribute[0], POS_DATA_SIZE, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glVertexAttribPointer(mProgram2.mAttribute[1], TEX_DATA_SIZE, GLES31.GL_FLOAT, false, 0, mQuadTexture);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
 
-    if( mQualityLevel==0 )
-      {
-      GLES31.glDisable(GLES31.GL_BLEND);
-      }
-
     DistortedRenderState.unuseStencilMark();
 
-    // blit back to inBuffer if we have to
-    if( mQualityLevel>0 )
-      {
-      inBuffer.setAsOutput();
-      inBuffer.bindForOutput(0);
-      outBuffer.setAsInput(0);
-      GLES31.glEnable(GLES31.GL_BLEND);
-      DistortedEffects.blitPriv(inBuffer);
-      GLES31.glDisable(GLES31.GL_BLEND);
-      return 3;
-      }
-
     return 2;
     }
 
@@ -262,66 +235,64 @@ public class PostprocessEffectGlow extends PostprocessEffect
     final String glowVertex =
 
         Distorted.GLSL_VERSION   +
-      "precision lowp float;  \n"+
-      "in vec2 a_Position;    \n"+
-      "in vec2 a_TexCoord;    \n"+
-      "out vec2 v_TexCoord;   \n"+
-      "uniform float u_Depth; \n"+
-      "uniform vec2 u_TexCorr;\n"+
-
-      "void main()                                      \n"+
-      "  {                                              \n"+
-      "  v_TexCoord = a_TexCoord * u_TexCorr;           \n"+
-      "  gl_Position= vec4(2.0*a_Position,u_Depth,1.0); \n"+
-      "  }";
+            "precision lowp float;  \n"+
+            "in vec2 a_Position;    \n"+
+            "in vec2 a_TexCoord;    \n"+
+            "out vec2 v_TexCoord;   \n"+
+            "uniform float u_Depth; \n"+
+            "uniform vec2 u_TexCorr;\n"+
+
+            "void main()                                      \n"+
+            "  {                                              \n"+
+            "  v_TexCoord = a_TexCoord * u_TexCorr;           \n"+
+            "  gl_Position= vec4(2.0*a_Position,u_Depth,1.0); \n"+
+            "  }";
 
     final String glowFragment1 =
 
         Distorted.GLSL_VERSION               +
-      "#define MAX_BLUR "+MAX_HALO+      "\n"+
-      "precision lowp float;              \n"+
-      "in vec2 v_TexCoord;                \n"+
-      "out vec4 fragColor;                \n"+
-      "uniform sampler2D u_ColorTexture;  \n"+
-      "uniform float u_Offsets[MAX_BLUR]; \n"+
-      "uniform float u_Weights[MAX_BLUR]; \n"+
-      "uniform int u_Radius;              \n"+
-      "uniform vec4 u_Color;              \n"+
-
-      "void main()                                                                                           \n"+
-      "  {                                                                                                   \n"+
-      "  vec4 pixel = texture(u_ColorTexture,v_TexCoord) * u_Weights[0];                                     \n"+
-      "  for (int i=1; i<=u_Radius; i+=1)                                                                    \n"+
-      "    {                                                                                                 \n"+
-      "    pixel += ( texture(u_ColorTexture,vec2(v_TexCoord.x+u_Offsets[i],v_TexCoord.y)) +                 \n"+
-      "               texture(u_ColorTexture,vec2(v_TexCoord.x-u_Offsets[i],v_TexCoord.y)) ) * u_Weights[i]; \n"+
-      "    }                                                                                                 \n"+
-      "  fragColor = vec4( 0.5*(pixel.rgb+u_Color.rgb), sqrt(pixel.a*u_Color.a));                            \n"+
-      "  }";
+            "#define MAX_BLUR "+MAX_HALO+      "\n"+
+            "precision lowp float;              \n"+
+            "in vec2 v_TexCoord;                \n"+
+            "out vec4 fragColor;                \n"+
+            "uniform sampler2D u_ColorTexture;  \n"+
+            "uniform float u_Offsets[MAX_BLUR]; \n"+
+            "uniform float u_Weights[MAX_BLUR]; \n"+
+            "uniform int u_Radius;              \n"+
+
+            "void main()                                                                                           \n"+
+            "  {                                                                                                   \n"+
+            "  vec4 pixel= texture(u_ColorTexture,v_TexCoord) * u_Weights[0];                                      \n"+
+            "  for (int i=1; i<=u_Radius; i+=1)                                                                    \n"+
+            "    {                                                                                                 \n"+
+            "    pixel += ( texture(u_ColorTexture,vec2(v_TexCoord.x+u_Offsets[i],v_TexCoord.y)) +                 \n"+
+            "               texture(u_ColorTexture,vec2(v_TexCoord.x-u_Offsets[i],v_TexCoord.y)) ) * u_Weights[i]; \n"+
+            "    }                                                                                                 \n"+
+            "  fragColor = pixel;                                                                                  \n"+
+            "  }";
 
     final String glowFragment2 =
 
         Distorted.GLSL_VERSION               +
-      "#define MAX_BLUR "+MAX_HALO+      "\n"+
-      "precision lowp float;              \n"+
-      "in vec2 v_TexCoord;                \n"+
-      "out vec4 fragColor;                \n"+
-      "uniform sampler2D u_ColorTexture;  \n"+
-      "uniform float u_Offsets[MAX_BLUR]; \n"+
-      "uniform float u_Weights[MAX_BLUR]; \n"+
-      "uniform int u_Radius;              \n"+
-      "uniform vec4 u_Color;              \n"+
-
-      "void main()                                                                                           \n"+
-      "  {                                                                                                   \n"+
-      "  vec4 pixel = texture(u_ColorTexture,v_TexCoord) * u_Weights[0];                                     \n"+
-      "  for (int i=1; i<=u_Radius; i+=1)                                                                    \n"+
-      "    {                                                                                                 \n"+
-      "    pixel += ( texture(u_ColorTexture,vec2(v_TexCoord.x,v_TexCoord.y+u_Offsets[i])) +                 \n"+
-      "               texture(u_ColorTexture,vec2(v_TexCoord.x,v_TexCoord.y-u_Offsets[i])) ) * u_Weights[i]; \n"+
-      "    }                                                                                                 \n"+
-      "  fragColor = vec4( 0.5*(pixel.rgb+u_Color.rgb), sqrt(pixel.a*u_Color.a));                            \n"+
-      "  }";
+            "#define MAX_BLUR "+MAX_HALO+      "\n"+
+            "precision lowp float;              \n"+
+            "in vec2 v_TexCoord;                \n"+
+            "out vec4 fragColor;                \n"+
+            "uniform sampler2D u_ColorTexture;  \n"+
+            "uniform float u_Offsets[MAX_BLUR]; \n"+
+            "uniform float u_Weights[MAX_BLUR]; \n"+
+            "uniform int u_Radius;              \n"+
+
+            "void main()                                                                                           \n"+
+            "  {                                                                                                   \n"+
+            "  vec4 pixel= texture(u_ColorTexture,v_TexCoord) * u_Weights[0];                                      \n"+
+            "  for (int i=1; i<=u_Radius; i+=1)                                                                    \n"+
+            "    {                                                                                                 \n"+
+            "    pixel += ( texture(u_ColorTexture,vec2(v_TexCoord.x,v_TexCoord.y+u_Offsets[i])) +                 \n"+
+            "               texture(u_ColorTexture,vec2(v_TexCoord.x,v_TexCoord.y-u_Offsets[i])) ) * u_Weights[i]; \n"+
+            "    }                                                                                                 \n"+
+            "  fragColor = pixel;                                                                                  \n"+
+            "  }";
 
     mIndex1 = PostprocessEffect.register("GLOW1", glowVertex,glowFragment1);
     mIndex2 = PostprocessEffect.register("GLOW2", glowVertex,glowFragment2);
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index d1922a6..fbca14b 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -71,7 +71,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
   private ArrayList<Job> mJobs = new ArrayList<>();
 
   // Global buffers used for postprocessing.
-  private static DistortedOutputSurface[] mBuffer=null;
+  private static DistortedFramebuffer[] mBuffer=null;
 
   private float mFOV;
   float mDistance, mNear;
@@ -181,7 +181,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   private static void createPostprocessingBuffers(int width, int height, float near)
     {
-    mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH];
+    mBuffer = new DistortedFramebuffer[EffectQuality.LENGTH];
     float mipmap=1.0f;
 
     for (int j=0; j<EffectQuality.LENGTH; j++)
@@ -404,15 +404,13 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     DistortedNode child;
     EffectQueuePostprocess lastQueue=null, currQueue;
     long lastBucket=0, currBucket;
+    boolean renderDirectly=false;
 
     setCurrFBO(fbo);
 
     if( mBuffer!=null )
       {
-      for (int i=0; i<EffectQuality.LENGTH; i++)
-        {
-        mBuffer[i].setCurrFBO(fbo);
-        }
+      for (int i=0; i<EffectQuality.LENGTH; i++) mBuffer[i].setCurrFBO(fbo);
       }
 
     if( oit && numChildren>0 )
@@ -445,11 +443,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
         if( mBuffer==null )
           {
           createPostprocessingBuffers(mWidth,mHeight,mNear);
-
-          for (int j=0; j<EffectQuality.LENGTH; j++)
-            {
-            mBuffer[j].setCurrFBO(fbo);
-            }
+          for (int j=0; j<EffectQuality.LENGTH; j++) mBuffer[j].setCurrFBO(fbo);
           }
 
         if( lastBucket!=currBucket )
@@ -460,8 +454,8 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
             }
           else
             {
-            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( mBuffer,children.get(j) );
-            numRenders += lastQueue.postprocess(mBuffer);
+            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( mBuffer[quality],children.get(j) );
+            numRenders += lastQueue.postprocess(mBuffer[quality]);
 
             if( oit )
               {
@@ -475,17 +469,35 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
             mBuffer[quality].clearBuffer(fbo);
             }
 
-          quality     = currQueue.getQuality();
+          quality= currQueue.getQuality();
           bucketChange= i;
+          renderDirectly = currQueue.getRender();
           }
 
-        mBuffer[quality].setAsOutput(time);
-        child.drawNoBlend(time,mBuffer[quality]);
+        if( renderDirectly )
+          {
+          setAsOutput(time);
+
+          if( oit )
+            {
+            numRenders += child.drawOIT(time, this);
+            GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
+            }
+          else
+            {
+            numRenders += child.draw(time, this);
+            }
+          }
+        else
+          {
+          mBuffer[quality].setAsOutput(time);
+          child.drawNoBlend(time, mBuffer[quality]);
+          }
 
         if( i==numChildren-1 )
           {
-          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( mBuffer,children.get(j) );
-          numRenders += currQueue.postprocess(mBuffer);
+          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( mBuffer[quality],children.get(j) );
+          numRenders += currQueue.postprocess(mBuffer[quality]);
 
           if( oit )
             {
@@ -543,7 +555,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void clearBuffer(int fbo)
+  void clearBuffer(int fbo)
     {
     DistortedRenderState.colorDepthStencilOn();
 
diff --git a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
index 8cf1638..84e3ff0 100644
--- a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
@@ -40,9 +40,11 @@ class EffectQueuePostprocess extends EffectQueue
   private static final int INDEX = EffectType.POSTPROCESS.ordinal();
 
   private int mHalo;
+  private float mR, mG, mB, mA;
 
   private static DistortedProgram mPreProgram;
   private static int mPreColorH;
+  private static int mPreTextureH;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -59,6 +61,7 @@ class EffectQueuePostprocess extends EffectQueue
     if( mTime==0 ) mTime = currTime;
     long step = (currTime-mTime);
 
+    mR = mG = mB = mA = 0.0f;
     mHalo = 0;
     int halo;
 
@@ -84,6 +87,15 @@ class EffectQueuePostprocess extends EffectQueue
       if( halo>mHalo ) mHalo = halo;
       }
 
+    // TODO  (now only really works in case of 1 effect!)
+    if( mNumEffects>0 )
+      {
+      mR = mUniforms[1];
+      mG = mUniforms[2];
+      mB = mUniforms[3];
+      mA = mUniforms[4];
+      }
+
     mTime = currTime;
     }
 
@@ -115,63 +127,45 @@ class EffectQueuePostprocess extends EffectQueue
     int preProgramH = mPreProgram.getProgramHandle();
     EffectQueueVertex.getUniforms( preProgramH,2 );
     EffectQueueMatrix.getUniforms( preProgramH,2 );
-    mPreColorH= GLES31.glGetUniformLocation( preProgramH, "u_Color");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
-
-  private int getWriteColor()
-    {
-    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getWriteColor() : 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private int getHalo()
-    {
-    return mNumEffects>0 ? mHalo : 0;
+    mPreColorH  = GLES31.glGetUniformLocation( preProgramH, "u_Color"  );
+    mPreTextureH= GLES31.glGetUniformLocation( preProgramH, "u_Texture");
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // TODO  (now only really works in case of 1 effect!)
 
-  private int getInternalQuality()
+  int getQuality()
     {
-    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getInternalQuality() : 0;
+    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getQuality() : 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // TODO  (now only really works in case of 1 effect!)
 
-  int getQuality()
+  boolean getRender()
     {
-    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getQuality() : 0;
+    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getRender() : false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  int preprocess(DistortedOutputSurface[] buffers, DistortedNode node)
+  int preprocess(DistortedOutputSurface buffer, DistortedNode node)
     {
-    int quality = getInternalQuality();
-    DistortedOutputSurface surface = buffers[quality];
-
-    surface.setAsOutput();
+    buffer.setAsOutput();
     DistortedSurface input = node.getInternalSurface();
 
     if( input.setAsInput() )
       {
       MeshObject mesh = node.getMesh();
-      int  writeColor = getWriteColor();
-      float    margin = getHalo()*surface.mMipmap;
+      float    margin = mHalo*buffer.mMipmap;
 
       float halfW = input.getWidth() / 2.0f;
       float halfH = input.getHeight()/ 2.0f;
       float halfZ = halfW*mesh.zFactor;
 
-      DistortedRenderState.setUpStencilMark(writeColor!=0);
+      DistortedRenderState.setUpStencilMark(mA!=0.0f);
 
-      GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
+      GLES31.glViewport(0, 0, buffer.mWidth, buffer.mHeight );
 
       mPreProgram.useProgram();
 
@@ -181,20 +175,12 @@ class EffectQueuePostprocess extends EffectQueue
       GLES31.glVertexAttribPointer(mPreProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
       GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
 
-      node.getEffects().send(halfW, halfH, halfZ, margin, surface, 2);
-
-      float a = (writeColor&255);
+      node.getEffects().send(halfW, halfH, halfZ, margin, buffer, 2);
 
-      if( a!=0.0f )
+      if( mA!=0.0f )
         {
-        writeColor = (writeColor>>8);
-        float b = writeColor&255;
-        writeColor = (writeColor>>8);
-        float g = writeColor&255;
-        writeColor = (writeColor>>8);
-        float r = writeColor&255;
-
-        GLES31.glUniform4f(mPreColorH, r, g, b, a);
+        GLES31.glUniform4f(mPreColorH, mR, mG, mB, mA);
+        GLES31.glUniform1i(mPreTextureH, 0);
         }
 
       GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
@@ -208,7 +194,7 @@ class EffectQueuePostprocess extends EffectQueue
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  int postprocess(DistortedOutputSurface[] buffers)
+  int postprocess(DistortedFramebuffer buffer)
     {
     int numRenders = 0;
 
@@ -216,7 +202,7 @@ class EffectQueuePostprocess extends EffectQueue
 
     for(int i=0; i<mNumEffects; i++)
       {
-      numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, buffers);
+      numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, buffer);
       }
 
     GLES31.glEnable(GLES31.GL_BLEND);
diff --git a/src/main/res/raw/preprocess_fragment_shader.glsl b/src/main/res/raw/preprocess_fragment_shader.glsl
index d24ef36..ceafbfa 100644
--- a/src/main/res/raw/preprocess_fragment_shader.glsl
+++ b/src/main/res/raw/preprocess_fragment_shader.glsl
@@ -19,12 +19,23 @@
 
 precision highp float;
 
+in vec2 v_TexCoordinate;                // Interpolated texture coordinate per fragment.
 out vec4 fragColor;
 uniform vec4 u_Color;
+uniform sampler2D u_Texture;            // The input texture.
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 void main()
   {
-  fragColor = u_Color;
+  vec4 color = texture(u_Texture,v_TexCoordinate);
+
+  if( color.a != 0.0 )
+    {
+    fragColor = u_Color;
+    }
+  else
+    {
+    discard;
+    }
   }
\ No newline at end of file
