commit 559da65d54b24b72b166f9dfc907829cc61428e0
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Tue May 16 15:41:39 2017 +0100

    Progress with Stencil app. Rendering through an intermediate FBO still doesn't quite work.

diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
index f0a807d..fbfc652 100644
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
@@ -82,8 +82,7 @@ class FBORenderer implements GLSurfaceView.Renderer
 
      // we can also, to save memory, delete/recreate
      // the depth buffer each time. This is optional.
-     DistortedFramebuffer fbo = mRoot.getFramebuffer();
-     if( fbo!=null ) fbo.enableDepthStencil(mDepth ? DistortedFramebuffer.DEPTH_NO_STENCIL:DistortedFramebuffer.NO_DEPTH_STENCIL);
+     mRoot.enableDepthStencil(mDepth ? DistortedFramebuffer.DEPTH_NO_STENCIL:DistortedFramebuffer.NO_DEPTH_NO_STENCIL);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
index d671e09..f8dae8e 100644
--- a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
+++ b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
@@ -70,20 +70,12 @@ class StencilRenderer implements GLSurfaceView.Renderer
         }
       else
         {
-        if( mFBONode==null ) mFBONode = new DistortedNode(mFBOTex,mFBOEffects,mQuad);
-
         mScreen.detachAll();
         mScreen.attach(mFBONode);
         mFBONode.attach(mCube1Node);
-        mFBONode.attach(mCube2Node);
         mFBONode.attach(mFloorNode);
-
-        DistortedFramebuffer fbo = mFBONode.getFramebuffer();
-        if( fbo!=null ) fbo.enableDepthStencil(DistortedFramebuffer.BOTH_DEPTH_STENCIL);
-        else
-          {
-          android.util.Log.e("stencil", "failed to enable STENCIL!");
-          }
+        mFBONode.attach(mCube2Node);
+        mFBONode.enableDepthStencil(DistortedFramebuffer.BOTH_DEPTH_STENCIL);
         }
       }
 
@@ -110,18 +102,28 @@ class StencilRenderer implements GLSurfaceView.Renderer
       mCube1Node = new DistortedNode(mCubeTex ,mCube1Effects,mCubeMesh );
       mCube2Node = new DistortedNode(mCubeTex ,mCube2Effects,mCubeMesh );
       mFloorNode = new DistortedNode(mFloorTex,mFloorEffects,mQuad     );
-
+      mFBONode   = new DistortedNode(mFBOTex  ,mFBOEffects  ,mQuad     );
+
+      ///////////////// The Meat of this App - shamelessly ripped off https://open.gl/depthstencils ///////////////////////
+      /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Stuff to do just before we render the upper Cube
+      // (nothing - i.e. use default OpenGL settings with one difference - in Distorted, Depth test is on by default)
+      /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Stuff to do just before we render the Floor
       mFloorNode.glEnable(GLES30.GL_STENCIL_TEST);                               // Enable Stencil when rendering this Node
       mFloorNode.glStencilFunc(GLES30.GL_ALWAYS, 1, 0xFF);                       // Set any stencil to 1
       mFloorNode.glStencilOp(GLES30.GL_KEEP, GLES30.GL_KEEP, GLES30.GL_REPLACE); // replace with 1 when we fail Depth test
       mFloorNode.glStencilMask(0xFF);                                            // Write to stencil buffer
       mFloorNode.glDepthMask(false);                                             // Don't write to depth buffer
-      mFloorNode.glClear(GLES30.GL_STENCIL_BUFFER_BIT);                          // Clear stencil buffer (0 by default)
+      mFloorNode.glClear(GLES30.GL_STENCIL_BUFFER_BIT);                          // Clear stencil buffer (by default, with a 0)
 
+      /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Stuff to do just before we render the lower Cube
       mCube2Node.glEnable(GLES30.GL_STENCIL_TEST);                               // Enable Stencil when rendering this Node
       mCube2Node.glStencilFunc(GLES30.GL_EQUAL, 1, 0xFF);                        // Pass test if stencil value is 1
       mCube2Node.glStencilMask(0x00);                                            // Don't write anything to stencil buffer
       mCube2Node.glDepthMask(true);                                              // Write to depth buffer
+      /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
       mScreen = new DistortedScreen(mView);
       mScreen.glClearColor(1.0f,1.0f,1.0f,1.0f);
@@ -149,6 +151,9 @@ class StencilRenderer implements GLSurfaceView.Renderer
       float fh = mFloorTex.getHeight();
       float fd = mFloorTex.getDepth(mQuad);
 
+      float bw = mFBOTex.getWidth();
+      float bh = mFBOTex.getHeight();
+
       float cubeScale = 0.4f*(width>height ? height/ch:width/cw);
       float floorScale= 0.8f*(width>height ? height/fh:width/fw);
 
@@ -169,12 +174,27 @@ class StencilRenderer implements GLSurfaceView.Renderer
       Static1D rotSt1 = new Static1D(angle);
       Static1D rotSt2 = new Static1D(angle-90.0f);
 
+      /////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Those Matrix effects, i.e. correct positioning of Objects on the Screen, is admittedly quite hard.
+      // Figured out of experimentation.
+      /////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Upper cube
       mCube1Effects.abortEffects(EffectTypes.MATRIX);
       mCube1Effects.move( new Static3D( (width-cubeScale*cw)/2 , height/2-cubeScale*ch , cubeScale *cd/2) );
       mCube1Effects.scale(cubeScale);
       mCube1Effects.rotate(rotSt1, axisX, cubeCenter);
       mCube1Effects.rotate(rotDyn, axisY, cubeCenter);
 
+      /////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Floor
+      mFloorEffects.abortEffects(EffectTypes.MATRIX);
+      mFloorEffects.move( new Static3D( (width-floorScale*fw)/2 ,height/2-floorScale*fh/2, floorScale*fd/2) );
+      mFloorEffects.scale(floorScale);
+      mFloorEffects.rotate(rotSt2, axisX, floorCenter);
+      mFloorEffects.rotate(rotDyn, axisZ, floorCenter);
+
+      /////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Lower cube
       mCube2Effects.abortEffects(EffectTypes.MATRIX);
       mCube2Effects.move( new Static3D( (width-cubeScale*cw)/2 , height/2-cubeScale*ch , cubeScale *cd/2) );
       mCube2Effects.scale(cubeScale);
@@ -183,22 +203,13 @@ class StencilRenderer implements GLSurfaceView.Renderer
       mCube2Effects.scale(new Static3D(1,-1,1) );
       mCube2Effects.move( new Static3D( 0, -2*ch , 0) );
 
-      mFloorEffects.abortEffects(EffectTypes.MATRIX);
-      mFloorEffects.move( new Static3D( (width-floorScale*fw)/2 ,height/2-floorScale*fh/2, floorScale*fd/2) );
-      mFloorEffects.scale(floorScale);
-      mFloorEffects.rotate(rotSt2, axisX, floorCenter);
-      mFloorEffects.rotate(rotDyn, axisZ, floorCenter);
-
-      if( mFBONode==null ) mFBONode = new DistortedNode(mFBOTex,mFBOEffects,mQuad);
-
-      DistortedFramebuffer fbo = mFBONode.getFramebuffer();
-      if( fbo!=null ) fbo.resize(width,height);
-      else
-        {
-        android.util.Log.e("stencil", "failed to resize FBO!");
-        }
+      /////////////////////////////////////////////////////////////////////////////////////////////////////
+      // Framebuffer
+      mFBOEffects.abortEffects(EffectTypes.MATRIX);
+      mFBOEffects.scale( new Static3D( (float)width/bw, (float)height/bh, 1.0f) );
 
-      mScreen.resize(width, height);
+      mFBONode.resize( (int)((float)width/bw), (int)((float)height/bh) );
+      mScreen.resize( width,height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
