commit ae2802b15f0ffd74af6919ead0d23a82353d6ebe
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Apr 8 22:07:29 2018 +0100

    Postprocessing buffers mBuffer[] are now shared among all postprocessing operations. This saves a lot of memory, but also means that when doing each particular postprocessing, the textures backing up the mBuffer might be too large. We need to fix two things here: when outputting to those too large textures, we need to adjust the Viewport, and when binding those too large textures as input - we need to adjust the TexCoords to compensate.
    
    This commit does just that. Verified as working by the 'PostprocessTree' app.

diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
index 635535a..5aea125 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
@@ -158,6 +158,11 @@ public class PostprocessEffectBlur extends PostprocessEffect
     float h= buffer.getHeight();
     float n= 1.0f - buffer.getNear();
 
+    float corrW = buffer.getWidthCorrection();
+    float corrH = buffer.getHeightCorrection();
+    float offsetCorrW = corrW/w;
+    float offsetCorrH = corrH/h;
+
     int radius = (int)(uniforms[index]*mQualityScale);
     if( radius>=MAX_HALO ) radius = MAX_HALO-1;
     computeGaussianKernel(radius);
@@ -167,23 +172,24 @@ public class PostprocessEffectBlur extends PostprocessEffect
     GLES31.glViewport(0, 0, (int)w, (int)h);
 
     // horizontal blur
-    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w;
+    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
 
     mProgram1.useProgram();
     buffer.bindForOutput(1);
     buffer.setAsInput(0);
 
     GLES31.glUniform1f ( mProgram1.mUniform[0] , n );
-    GLES31.glUniform1i ( mProgram1.mUniform[1] , 0 );
-    GLES31.glUniform1fv( mProgram1.mUniform[2] , radius+1, mOffsets,0);
-    GLES31.glUniform1fv( mProgram1.mUniform[3] , radius+1, weightsCache,offset);
-    GLES31.glUniform1i ( mProgram1.mUniform[4] , radius);
+    GLES31.glUniform2f ( mProgram1.mUniform[1] , corrW, corrH );
+    GLES31.glUniform1i ( mProgram1.mUniform[2] , 0 );
+    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.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 blur
-    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/h;
+    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
 
     mProgram2.useProgram();
     buffer.bindForOutput(0);
@@ -194,10 +200,11 @@ public class PostprocessEffectBlur extends PostprocessEffect
     GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
 
     GLES31.glUniform1f ( mProgram2.mUniform[0] , n );
-    GLES31.glUniform1i ( mProgram2.mUniform[1] , 0 );
-    GLES31.glUniform1fv( mProgram2.mUniform[2] , radius+1, mOffsets,0);
-    GLES31.glUniform1fv( mProgram2.mUniform[3] , radius+1, weightsCache,offset);
-    GLES31.glUniform1i ( mProgram2.mUniform[4] , radius);
+    GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH );
+    GLES31.glUniform1i ( mProgram2.mUniform[2] , 0 );
+    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.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);
@@ -223,10 +230,11 @@ public class PostprocessEffectBlur extends PostprocessEffect
       "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;                       \n"+
+      "  v_TexCoord = a_TexCoord * u_TexCorr;           \n"+
       "  gl_Position= vec4(2.0*a_Position,u_Depth,1.0); \n"+
       "  }";
 
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
index 51a101b..cac6aea 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
@@ -161,6 +161,11 @@ public class PostprocessEffectGlow extends PostprocessEffect
     float h= outBuffer.getHeight();
     float n= 1.0f - outBuffer.getNear();
 
+    float corrW = inBuffer.getWidthCorrection();
+    float corrH = inBuffer.getHeightCorrection();
+    float offsetCorrW = corrW/w;
+    float offsetCorrH = corrH/h;
+
     int radius = (int)(uniforms[index]*mQualityScale);
     if( radius>=MAX_HALO ) radius = MAX_HALO-1;
     computeGaussianKernel(radius);
@@ -172,35 +177,37 @@ public class PostprocessEffectGlow extends PostprocessEffect
     GLES31.glViewport(0, 0, (int)w, (int)h);
 
     // horizontal glow
-    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w;
+    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
 
     mProgram1.useProgram();
     outBuffer.bindForOutput(1);
     inBuffer.setAsInput(0);
 
     GLES31.glUniform1f ( mProgram1.mUniform[0] , n );
-    GLES31.glUniform1i ( mProgram1.mUniform[1] , 0 );
-    GLES31.glUniform1fv( mProgram1.mUniform[2] , radius+1, mOffsets,0);
-    GLES31.glUniform1fv( mProgram1.mUniform[3] , radius+1, weightsCache,offset);
-    GLES31.glUniform1i ( mProgram1.mUniform[4] , radius);
-    GLES31.glUniform4f ( mProgram1.mUniform[5] , uniforms[index+1], uniforms[index+2], uniforms[index+3], uniforms[index+4]);
+    GLES31.glUniform2f ( mProgram1.mUniform[1] , corrW, corrH );
+    GLES31.glUniform1i ( mProgram1.mUniform[2] , 0 );
+    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
-    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/h;
+    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
 
     mProgram2.useProgram();
     outBuffer.bindForOutput(0);
     outBuffer.setAsInput(1);
 
     GLES31.glUniform1f ( mProgram2.mUniform[0] , n );
-    GLES31.glUniform1i ( mProgram2.mUniform[1] , 0 );
-    GLES31.glUniform1fv( mProgram2.mUniform[2] , radius+1, mOffsets,0);
-    GLES31.glUniform1fv( mProgram2.mUniform[3] , radius+1, weightsCache,offset);
-    GLES31.glUniform1i ( mProgram2.mUniform[4] , radius);
-    GLES31.glUniform4f ( mProgram1.mUniform[5] , uniforms[index+1], uniforms[index+2], uniforms[index+3], uniforms[index+4]);
+    GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH );
+    GLES31.glUniform1i ( mProgram2.mUniform[2] , 0 );
+    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);
@@ -235,10 +242,11 @@ public class PostprocessEffectGlow extends PostprocessEffect
       "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;                       \n"+
+      "  v_TexCoord = a_TexCoord * u_TexCorr;           \n"+
       "  gl_Position= vec4(2.0*a_Position,u_Depth,1.0); \n"+
       "  }";
 
diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index a9c0fe5..5a52229 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -73,6 +73,7 @@ public class DistortedEffects
   private static int mBlitDepthTextureH;
   private static int mBlitDepthDepthTextureH;
   private static int mBlitDepthDepthH;
+  private static int mBlitDepthTexCorrH;
 
   /// NORMAL PROGRAM /////
   private static DistortedProgram mNormalProgram;
@@ -162,6 +163,7 @@ public class DistortedEffects
     mBlitDepthTextureH      = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Texture");
     mBlitDepthDepthTextureH = GLES31.glGetUniformLocation( blitDepthProgramH, "u_DepthTexture");
     mBlitDepthDepthH        = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Depth");
+    mBlitDepthTexCorrH      = GLES31.glGetUniformLocation( blitDepthProgramH, "u_TexCorr");
 
     // NORMAL PROGRAM //////////////////////////////////////
     final InputStream normalVertexStream   = resources.openRawResource(R.raw.normal_vertex_shader);
@@ -331,13 +333,14 @@ public class DistortedEffects
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  static void blitDepthPriv(DistortedOutputSurface surface)
+  static void blitDepthPriv(DistortedOutputSurface surface, float corrW, float corrH)
     {
     mBlitDepthProgram.useProgram();
 
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
     GLES31.glUniform1i(mBlitDepthTextureH, 0);
     GLES31.glUniform1i(mBlitDepthDepthTextureH, 1);
+    GLES31.glUniform2f(mBlitDepthTexCorrH, corrW, corrH );
     GLES31.glUniform1f( mBlitDepthDepthH , 1.0f-surface.mNear);
     GLES31.glVertexAttribPointer(mBlitDepthProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index 877dfc3..43ed4ec 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -331,6 +331,10 @@ public static final int DEBUG_FPS = 1;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// The postprocessing buffers mBuffer[] are generally speaking too large (there's just one static
+// set of them) so before we use them for output, we need to adjust the Vieport as if they were
+// smaller. That takes care of outputting pixels to them. When we use them as input, we have to
+// adjust the texture coords - see the get{Width|Height}Correction functions.
 
   private static void cloneViewport(DistortedOutputSurface from)
     {
@@ -347,7 +351,7 @@ public static final int DEBUG_FPS = 1;
 
         surface.mNear   = from.mNear;  // Near plane is independent of the mipmap level
 
-        android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
+        //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
 
         surface.createProjection();
 
@@ -380,7 +384,7 @@ public static final int DEBUG_FPS = 1;
     GLES31.glDisable(GLES31.GL_STENCIL_TEST);
     GLES31.glStencilMask(0x00);
 
-    DistortedEffects.blitDepthPriv(this);
+    DistortedEffects.blitDepthPriv(this, buffer.getWidthCorrection(), buffer.getHeightCorrection() );
     GLES31.glActiveTexture(GLES31.GL_TEXTURE0);
     GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
     GLES31.glActiveTexture(GLES31.GL_TEXTURE1);
@@ -476,6 +480,28 @@ public static final int DEBUG_FPS = 1;
     return mChildren;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Not part of the Public API.
+ *
+ * @y.exclude
+ */
+  public float getWidthCorrection()
+    {
+    return (float)mWidth/mRealWidth;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Not part of the Public API.
+ *
+ * @y.exclude
+ */
+  public float getHeightCorrection()
+    {
+    return (float)mHeight/mRealHeight;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/res/raw/blit_depth_vertex_shader.glsl b/src/main/res/raw/blit_depth_vertex_shader.glsl
index 7080267..a9d3811 100644
--- a/src/main/res/raw/blit_depth_vertex_shader.glsl
+++ b/src/main/res/raw/blit_depth_vertex_shader.glsl
@@ -28,11 +28,15 @@ varying vec2 v_TexCoordinate; //
 #endif
 
 uniform float u_Depth;        // distance from the near plane to render plane, in clip coords
+uniform vec2  u_TexCorr;      // when we blit from postprocessing buffers, the buffers can be
+                              // larger than necessary (there is just one static set being
+                              // reused!) so we need to compensate here by adjusting the texture
+                              // coords.
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 void main()
   {
-  v_TexCoordinate = a_Position + 0.5;
+  v_TexCoordinate = (a_Position + 0.5) * u_TexCorr;
   gl_Position     = vec4(2.0*a_Position,u_Depth,1.0);
   }
