commit 392e16fd768a62a322c68449d39aab18a3803574
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Thu Dec 15 15:31:41 2016 +0000

    Change in the API: we always have to create a DistortedFramebuffer to render to.

diff --git a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
index 203506b..5920200 100644
--- a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
+++ b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
@@ -26,6 +26,7 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.DistortedTexture;
@@ -43,10 +44,11 @@ import javax.microedition.khronos.opengles.GL10;
 class AroundTheWorldRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
    private DistortedTexture mTexture;
    private GridFlat mGrid;
-   private AroundTheWorldEffectsManager mEffects;
+   private DistortedFramebuffer mScreen;
+   private AroundTheWorldEffectsManager mManager;
    private int mObjWidth, mObjHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -57,16 +59,17 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
       Distorted.setMaxFragment(9);
 
       mView = view;
-      mEffects = new AroundTheWorldEffectsManager();
-      mQueues = new DistortedEffectQueues();
-      mEffects.apply(mQueues);
+      mManager = new AroundTheWorldEffectsManager();
+      mEffects = new DistortedEffectQueues();
+      mManager.apply(mEffects);
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    AroundTheWorldEffectsManager getManager()
      {
-     return mEffects;
+     return mManager;
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -74,31 +77,31 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture, mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
 
       if( (float)mObjHeight/mObjWidth > (float)height/width )
         {
         int w = (height*mObjWidth)/mObjHeight;
         float factor = (float)height/mObjHeight;
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*mObjHeight)/mObjWidth;
         float factor = (float)width/mObjWidth;
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
 
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width,height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index a917bde..c1b3165 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -27,6 +27,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.Distorted;
 import org.distorted.library.DistortedTexture;
@@ -47,7 +48,8 @@ class BeanRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
    private DistortedTexture mTexture;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
+   private DistortedFramebuffer mScreen;
    private GridFlat mGrid;
    private int bmpHeight, bmpWidth;
     
@@ -83,9 +85,11 @@ class BeanRenderer implements GLSurfaceView.Renderer
       dRight.add(p1);
       dRight.add(p1);
 
-      mQueues = new DistortedEffectQueues();
-      mQueues.distort(dLeft , pLeft , rLeft );
-      mQueues.distort(dRight, pRight, rRight);
+      mEffects = new DistortedEffectQueues();
+      mEffects.distort(dLeft , pLeft , rLeft );
+      mEffects.distort(dRight, pRight, rRight);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -93,33 +97,33 @@ class BeanRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture, mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
          
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
 
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
 
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
       
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
index eb8b4b4..737cce0 100644
--- a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
+++ b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
 import org.distorted.library.DistortedEffectQueues;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.GridFlat;
 import org.distorted.library.EffectTypes;
@@ -47,9 +48,10 @@ import android.opengl.GLSurfaceView;
 class CatAndDogRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
     private DistortedTexture mTexture;
     private GridFlat mGrid;
+    private DistortedFramebuffer mScreen;
     private int bmpHeight, bmpWidth;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -59,7 +61,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       mView = v;
 
       mGrid   = new GridFlat(1,1);  // no vertex effects, grid can be a (1x1) quad.
-      mQueues = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
 
       Static4D chromaRegion= new Static4D( 530, 200,100,100);
       Static4D alphaRegion = new Static4D( 230, 200,100,100);
@@ -68,13 +70,15 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       chromaDyn.add(new Static1D(1));
       chromaDyn.add(new Static1D(0));
 
-      mQueues.chroma(chromaDyn, new Static3D(1,0,0), chromaRegion ,true);
+      mEffects.chroma(chromaDyn, new Static3D(1,0,0), chromaRegion ,true);
 
       Dynamic1D alphaDyn = new Dynamic1D(3000,0.0f);
       alphaDyn.add(new Static1D(1));
       alphaDyn.add(new Static1D(0));
 
-      mQueues.alpha( alphaDyn, alphaRegion, false );
+      mEffects.alpha( alphaDyn, alphaRegion, false );
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -82,7 +86,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture, mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -141,12 +145,12 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       diRotate.add(new Static1D(  0));
       diRotate.add(new Static1D(360));
       
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
 
-      mQueues.move(diMove);
-      mQueues.scale(diScale);
-      mQueues.rotate( diRotate, new Static3D(0,0,1), new Static3D(bmpWidth/2,bmpHeight/2,0) );
+      mEffects.move(diMove);
+      mEffects.scale(diScale);
+      mEffects.rotate( diRotate, new Static3D(0,0,1), new Static3D(bmpWidth/2,bmpHeight/2,0) );
 
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 }
diff --git a/src/main/java/org/distorted/examples/check/CheckRenderer.java b/src/main/java/org/distorted/examples/check/CheckRenderer.java
index 19df502..5023fda 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridFlat;
@@ -56,8 +57,9 @@ class CheckRenderer implements GLSurfaceView.Renderer
 
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
     private GridFlat mGrid;
+    private DistortedFramebuffer mScreen;
     private int bmpHeight, bmpWidth;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -65,12 +67,14 @@ class CheckRenderer implements GLSurfaceView.Renderer
     CheckRenderer(GLSurfaceView view)
       { 
       mView = view;
-      mQueues = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
 
       CheckActivity act = (CheckActivity)mView.getContext();
 
       Distorted.setMaxVertex(act.getMaxV());
       Distorted.setMaxFragment(act.getMaxF());
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -78,33 +82,33 @@ class CheckRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture, mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
       
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
 
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
 
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
       
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -146,7 +150,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
       dSwirl.add(new Static3D(        0, bmpHeight/2, 0));
       dSwirl.add(new Static3D( bmpWidth, bmpHeight/2, 0));
 
-      long swirlEffectID = mQueues.swirl( new Static1D(30), dSwirl, new Static4D( 0,0,40,40) );
+      long swirlEffectID = mEffects.swirl( new Static1D(30), dSwirl, new Static4D( 0,0,40,40) );
 
       if( swirlEffectID<0 )
         {
@@ -157,7 +161,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
       dDeform.add(new Static3D( 0,         0,0));
       dDeform.add(new Static3D( 0,-bmpHeight,0));
 
-      long deformEffectID = mQueues.deform(dDeform, new Static3D(bmpWidth/2,0,0) );
+      long deformEffectID = mEffects.deform(dDeform, new Static3D(bmpWidth/2,0,0) );
 
       if( deformEffectID<0 )
         {
@@ -170,7 +174,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
       inter.add(new Static1D(0));
       inter.add(new Static1D(1));
 
-      long chromaEffectID = mQueues.chroma(inter, color);
+      long chromaEffectID = mEffects.chroma(inter, color);
 
       if( chromaEffectID<0 )
         {
diff --git a/src/main/java/org/distorted/examples/cubes/CubesRenderer.java b/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
index dff0843..1f2136a 100644
--- a/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
+++ b/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
@@ -27,6 +27,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridObject;
@@ -47,8 +48,9 @@ class CubesRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
     private GridObject mGrid;
+    private DistortedFramebuffer mScreen;
     private DynamicQuat mQuatInt1, mQuatInt2;
     private int mObjWidth, mObjHeight;
 
@@ -63,7 +65,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
 
       CubesActivity act = (CubesActivity)v.getContext();
 
-      mQueues  = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
       mTexture = act.getTexture();
       mGrid    = act.getGrid();
 
@@ -78,6 +80,8 @@ class CubesRenderer implements GLSurfaceView.Renderer
 
       mQuatInt1.add(mQuat1);
       mQuatInt2.add(mQuat2);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -85,7 +89,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(),mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(),mTexture,mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -94,7 +98,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
       {
       mScreenMin = width<height ? width:height;
     	
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
       float factor;
 
       if( width*mObjHeight > height*mObjWidth ) // screen is more 'horizontal' than the Object
@@ -106,14 +110,14 @@ class CubesRenderer implements GLSurfaceView.Renderer
         factor = (0.8f*width)/mObjWidth;
         }
 
-      mQueues.move( new Static3D( (width-factor*mObjWidth)/2 , (height-factor*mObjHeight)/2 , 0) );
-      mQueues.scale(factor);
+      mEffects.move( new Static3D( (width-factor*mObjWidth)/2 , (height-factor*mObjHeight)/2 , 0) );
+      mEffects.scale(factor);
       Static3D center = new Static3D(mObjWidth/2,mObjHeight/2, 0);
 
-      mQueues.quaternion(mQuatInt1, center);
-      mQueues.quaternion(mQuatInt2, center);
+      mEffects.quaternion(mQuatInt1, center);
+      mEffects.quaternion(mQuatInt2, center);
        
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/deform/DeformRenderer.java b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
index 6050829..e62f44f 100644
--- a/src/main/java/org/distorted/examples/deform/DeformRenderer.java
+++ b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
@@ -23,6 +23,7 @@ import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridObject;
@@ -51,8 +52,9 @@ class DeformRenderer implements GLSurfaceView.Renderer
 
    private GLSurfaceView mView;
    private DistortedTexture fpsTexture, stretchTexture;
-   private DistortedEffectQueues fpsQueues, stretchQueues;
+   private DistortedEffectQueues fpsEffects, stretchEffects;
    private GridObject fpsGrid, stretchGrid;
+   private DistortedFramebuffer mScreen;
    private Static3D touchPoint;
 
    private Dynamic3D mReleasedDistortDynamic;
@@ -90,8 +92,8 @@ class DeformRenderer implements GLSurfaceView.Renderer
       mPaint.setAntiAlias(true);
       mPaint.setTextAlign(Paint.Align.CENTER);
 
-      fpsQueues     = new DistortedEffectQueues();
-      stretchQueues = new DistortedEffectQueues();
+      fpsEffects = new DistortedEffectQueues();
+      stretchEffects = new DistortedEffectQueues();
 
       mRegion = new Static4D(0,0,50,50);
 
@@ -147,6 +149,8 @@ class DeformRenderer implements GLSurfaceView.Renderer
         }
 
       mMovingShearDynamic.add(vShear[0]);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -178,7 +182,7 @@ class DeformRenderer implements GLSurfaceView.Renderer
     
      long time = System.currentTimeMillis();
       
-     stretchQueues.draw(time,stretchTexture,stretchGrid);
+     stretchEffects.draw(time,stretchTexture,stretchGrid,mScreen);
       
      mPaint.setColor(0xffffffff);
      fpsCanvas.drawRect(0, 0, fpsW, fpsH, mPaint);
@@ -186,7 +190,7 @@ class DeformRenderer implements GLSurfaceView.Renderer
      fpsCanvas.drawText(fpsString, fpsW/2, 5*fpsH/6, mPaint);
       
      fpsTexture.setTexture(fpsBitmap);
-     fpsQueues.draw(time,fpsTexture,fpsGrid);
+     fpsEffects.draw(time,fpsTexture,fpsGrid,mScreen);
       
      computeFPS(time);
      }
@@ -198,23 +202,23 @@ class DeformRenderer implements GLSurfaceView.Renderer
      scrHeight = height;
      scrWidth  = width;
 
-     Distorted.onSurfaceChanged(width, height);
-      
      if( !bitmapCreated )
        {
        createBitmap(scrWidth/2,scrHeight/2);
-       stretchQueues.abortAllEffects();
-       fpsQueues.abortAllEffects();
-       stretchQueues.move( new Static3D(scrWidth/4,scrHeight/4,0) );
-       fpsQueues.move( new Static3D(5,5,0) );
+       stretchEffects.abortAllEffects();
+       fpsEffects.abortAllEffects();
+       stretchEffects.move( new Static3D(scrWidth/4,scrHeight/4,0) );
+       fpsEffects.move( new Static3D(5,5,0) );
        bitmapCreated=true;
        }
      else
        {
-       stretchQueues.abortEffects(EffectTypes.VERTEX);
-       stretchQueues.abortEffects(EffectTypes.FRAGMENT);
-       stretchQueues.abortEffects(EffectNames.SHEAR);
+       stretchEffects.abortEffects(EffectTypes.VERTEX);
+       stretchEffects.abortEffects(EffectTypes.FRAGMENT);
+       stretchEffects.abortEffects(EffectNames.SHEAR);
        }
+
+     mScreen.resize(width, height);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -288,13 +292,13 @@ class DeformRenderer implements GLSurfaceView.Renderer
      switch(mMode)
        {
        case DISTORT: vDistort[0].set(0,0,0);
-                     mLastEffect = stretchQueues.distort( mMovingDistortDynamic, touchPoint, mRegion);
+                     mLastEffect = stretchEffects.distort( mMovingDistortDynamic, touchPoint, mRegion);
                      break;
        case DEFORM : vDeform[0].set(0,0,0);
-                     mLastEffect = stretchQueues.deform( mMovingDeformDynamic, touchPoint, mRegion);
+                     mLastEffect = stretchEffects.deform( mMovingDeformDynamic, touchPoint, mRegion);
                      break;
        case SHEAR  : vShear[0].set(0,0,0);
-                     mLastEffect = stretchQueues.shear(mMovingShearDynamic, touchPoint);
+                     mLastEffect = stretchEffects.shear(mMovingShearDynamic, touchPoint);
                      break;
        }
      }
@@ -318,7 +322,7 @@ class DeformRenderer implements GLSurfaceView.Renderer
 
    void up()
      {
-     stretchQueues.abortEffect(mLastEffect);
+     stretchEffects.abortEffect(mLastEffect);
 
      float damp = -0.65f;
 
@@ -329,21 +333,21 @@ class DeformRenderer implements GLSurfaceView.Renderer
                        vDistort[i].set( vDistort[i-1].getX()*damp, vDistort[i-1].getY()*damp );
                        }
                      vDistort[NUM_VECTORS-1].set(0,0);
-                     stretchQueues.distort( mReleasedDistortDynamic, touchPoint, mRegion);
+                     stretchEffects.distort( mReleasedDistortDynamic, touchPoint, mRegion);
                      break;
        case DEFORM : for(int i=1; i<NUM_VECTORS-1; i++)
                        {
                        vDeform[i].set( vDeform[i-1].getX()*damp, vDeform[i-1].getY()*damp );
                        }
                      vDeform[NUM_VECTORS-1].set(0,0);
-                     stretchQueues.deform( mReleasedDeformDynamic, touchPoint, mRegion);
+                     stretchEffects.deform( mReleasedDeformDynamic, touchPoint, mRegion);
                      break;
        case SHEAR  : for(int i=1; i<NUM_VECTORS-1; i++)
                        {
                        vShear[i].set( vShear[i-1].getX()*damp, vShear[i-1].getY()*damp );
                        }
                      vShear[NUM_VECTORS-1].set(0,0);
-                     stretchQueues.shear(mReleasedShearDynamic, touchPoint);
+                     stretchEffects.shear(mReleasedShearDynamic, touchPoint);
                      break;
        }
      }
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index b727be8..b19f402 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridFlat;
@@ -50,8 +51,9 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
    
    private GLSurfaceView mView;
    private DistortedTexture[] mTexture;
-   private DistortedEffectQueues[] mQueues;
+   private DistortedEffectQueues[] mEffects;
    private GridFlat mGrid;
+   private DistortedFramebuffer mScreen;
    private int bmpHeight, bmpWidth;
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -65,15 +67,17 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       dDistort.add(new Static3D(-25,0,0));
       Static3D mPoint = new Static3D(305, 380, 0);
 
-      mQueues = new DistortedEffectQueues[NUM];
-      mQueues[0] = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues[NUM];
+      mEffects[0] = new DistortedEffectQueues();
       for(int i=1; i<NUM; i++)
-        mQueues[i] = new DistortedEffectQueues(mQueues[0], Distorted.CLONE_VERTEX|Distorted.CLONE_FRAGMENT);
+        mEffects[i] = new DistortedEffectQueues(mEffects[0], Distorted.CLONE_VERTEX|Distorted.CLONE_FRAGMENT);
 
       // Add the effects only to the first queue - all VERTEX and FRAGMENT effects are shared!
       // (Matrix effect cannot be shared as we have to display each Texture in a different location)
-      mQueues[0].sink( new Static1D(8), mPoint, new Static4D(0,0,80,80));  // enlarge the nose
-      mQueues[0].distort(dDistort,mPoint);                                 // keep moving the whole bitmap left and right.
+      mEffects[0].sink( new Static1D(8), mPoint, new Static4D(0,0,80,80));  // enlarge the nose
+      mEffects[0].distort(dDistort,mPoint);                                 // keep moving the whole bitmap left and right.
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -107,7 +111,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       
       long time = System.currentTimeMillis();
       
-      for(int i=NUM-1; i>=0; i--) mQueues[i].draw(time, mTexture[i], mGrid);
+      for(int i=NUM-1; i>=0; i--) mEffects[i].draw(time, mTexture[i], mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -116,7 +120,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       {  
       for(int i=NUM-1; i>=0; i--) 
         {   
-        mQueues[i].abortEffects(EffectTypes.MATRIX);
+        mEffects[i].abortEffects(EffectTypes.MATRIX);
         }
       
       if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
@@ -126,8 +130,8 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
 
         for(int i=NUM-1; i>=0; i--) 
           {
-          mQueues[i].move( new Static3D((width-NUM*w)/2 +i*w ,0,0) );
-          mQueues[i].scale(factor);
+          mEffects[i].move( new Static3D((width-NUM*w)/2 +i*w ,0,0) );
+          mEffects[i].scale(factor);
           }
         }
       else
@@ -138,12 +142,12 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
 
         for(int i=NUM-1; i>=0; i--) 
           {
-          mQueues[i].move( new Static3D(i*w,(height-h)/2,0) );
-          mQueues[i].scale(factor);
+          mEffects[i].move( new Static3D(i*w,(height-h)/2,0) );
+          mEffects[i].scale(factor);
           }
         }
          
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index 6f1aff9..4882574 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -50,9 +51,10 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
    private static final int NUM = 3;
    
    private GLSurfaceView mView;
-   private DistortedEffectQueues[] mQueue;
+   private DistortedEffectQueues[] mEffects;
    private DistortedTexture mTexture;
    private GridFlat mGrid;
+   private DistortedFramebuffer mScreen;
    private int bmpHeight, bmpWidth;
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -61,36 +63,38 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       {     
       mView = v;
       
-      // mQueue[0] effects
+      // mEffects[0] effects
       Static3D pLeft = new Static3D(214, 206, 0);
       Static3D pRight= new Static3D(390, 212, 0);
       Static4D RegionEye = new Static4D(0,0,60,60);
       
-      // mQueue[1] effects
+      // mEffects[1] effects
       Dynamic3D dyn = new Dynamic3D(1000,0.0f);
       dyn.add(new Static3D( 50,0,0));
       dyn.add(new Static3D(-50,0,0));
       Static3D pNose1 = new Static3D(305, 340, 0);
       
-      // we don't need to prepare anything for mQueue[2] effects
+      // we don't need to prepare anything for mEffects[2] effects
 
-      mQueue= new DistortedEffectQueues[NUM];
+      mEffects = new DistortedEffectQueues[NUM];
 
-      for(int i=0; i<NUM; i++) mQueue[i] = new DistortedEffectQueues();
+      for(int i=0; i<NUM; i++) mEffects[i] = new DistortedEffectQueues();
 
       Dynamic1D sink = new Dynamic1D(2000,0.0f);
       sink.add(new Static1D( 1));
       sink.add(new Static1D(10));
 
-      mQueue[0].sink(sink, pLeft, RegionEye);
-      mQueue[0].sink(sink, pRight,RegionEye);
-      mQueue[1].distort(dyn, pNose1);
+      mEffects[0].sink(sink, pLeft, RegionEye);
+      mEffects[0].sink(sink, pRight,RegionEye);
+      mEffects[1].distort(dyn, pNose1);
 
       Dynamic1D chromaDyn = new Dynamic1D(3000,0.0f);
       chromaDyn.add(new Static1D(0));
       chromaDyn.add(new Static1D(1));
 
-      mQueue[2].chroma(chromaDyn, new Static3D(0,1,0) );
+      mEffects[2].chroma(chromaDyn, new Static3D(0,1,0) );
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -101,7 +105,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       
      long time = System.currentTimeMillis();
    
-     for(int i=NUM-1; i>=0; i--) mQueue[i].draw(time, mTexture, mGrid);
+     for(int i=NUM-1; i>=0; i--) mEffects[i].draw(time, mTexture, mGrid, mScreen);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -110,7 +114,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
      {
      for(int i=NUM-1; i>=0; i--)
        {
-       mQueue[i].abortEffects(EffectTypes.MATRIX);
+       mEffects[i].abortEffects(EffectTypes.MATRIX);
        }
       
      if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
@@ -120,8 +124,8 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
 
        for(int i=NUM-1; i>=0; i--)
          {
-         mQueue[i].move( new Static3D((width-NUM*w)/2 +i*w , 0, 0) );
-         mQueue[i].scale(factor);
+         mEffects[i].move( new Static3D((width-NUM*w)/2 +i*w , 0, 0) );
+         mEffects[i].scale(factor);
          }
        }
      else
@@ -132,12 +136,12 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
 
        for(int i=NUM-1; i>=0; i--)
          {
-         mQueue[i].move( new Static3D(i*w, (height-h)/2, 0) );
-         mQueue[i].scale(factor);
+         mEffects[i].move( new Static3D(i*w, (height-h)/2, 0) );
+         mEffects[i].scale(factor);
          }
        }
        
-     Distorted.onSurfaceChanged(width, height);
+     mScreen.resize(width, height);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
index 4f172ea..99eadd8 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
@@ -29,6 +29,7 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.DistortedTexture;
@@ -40,7 +41,8 @@ class DynamicRenderer implements GLSurfaceView.Renderer
    {  
    private DynamicSurfaceView mView;
    private DistortedTexture mTexture;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
+   private DistortedFramebuffer mScreen;
    private GridFlat mGrid;
    private Canvas mCanvas;
    private Bitmap mBitmap;
@@ -60,7 +62,8 @@ class DynamicRenderer implements GLSurfaceView.Renderer
       
      mView   = v;
      mGrid   = new GridFlat(1,1);
-     mQueues = new DistortedEffectQueues();
+     mEffects = new DistortedEffectQueues();
+     mScreen = new DistortedFramebuffer(0);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -88,7 +91,7 @@ class DynamicRenderer implements GLSurfaceView.Renderer
      mBitmap = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
      mCanvas = new Canvas(mBitmap);
 
-     Distorted.onSurfaceChanged(texW,texH);
+     mScreen.resize(texW,texH);
      mView.onSurfaceChanged(texW,texH);
      }
    
@@ -103,7 +106,7 @@ class DynamicRenderer implements GLSurfaceView.Renderer
      mCanvas.drawRect(0, 0, texW, texH, mPaint);
      mView.drawCurve(mCanvas,time);
      mTexture.setTexture(mBitmap);
-     mQueues.draw(time,mTexture,mGrid);
+     mEffects.draw(time,mTexture,mGrid,mScreen);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueActivity.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueActivity.java
index 1c4b3fe..5069123 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueActivity.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueActivity.java
@@ -166,10 +166,16 @@ public class EffectQueueActivity extends Activity implements AdapterView.OnItemS
 
   public void removeByID(View view)
     {
-    Long currID = (Long)mID.getItemAtPosition(mPosID);
-
-    EffectQueueSurfaceView v = (EffectQueueSurfaceView) this.findViewById(R.id.effects2dSurfaceView);
-    v.getRenderer().getQueues().abortEffect(currID);
+    try
+      {
+      Long currID = (Long)mID.getItemAtPosition(mPosID);
+      EffectQueueSurfaceView v = (EffectQueueSurfaceView) this.findViewById(R.id.effects2dSurfaceView);
+      v.getRenderer().getQueues().abortEffect(currID);
+      }
+    catch(IndexOutOfBoundsException ex)
+      {
+      android.util.Log.e("effectQueue", "Failure trying to remove "+mPosID);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
index 431c0e0..1350c73 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
@@ -29,6 +29,7 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -53,7 +54,8 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
 
   private DistortedTexture mTexture;
   private GridFlat mGrid;
-  private DistortedEffectQueues mQueues;
+  private DistortedEffectQueues mEffects;
+  private DistortedFramebuffer mScreen;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -71,16 +73,18 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
 
     mGrid    = new GridFlat(80,80*texHeight/texWidth);
     mTexture = new DistortedTexture(texWidth,texHeight);
-    mQueues  = new DistortedEffectQueues();
+    mEffects = new DistortedEffectQueues();
 
-    mQueues.registerForMessages(this);
+    mEffects.registerForMessages(this);
+
+    mScreen = new DistortedFramebuffer(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   DistortedEffectQueues getQueues()
     {
-    return mQueues;
+    return mEffects;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -115,9 +119,9 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
 
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
     {
-    mQueues.abortEffects(EffectTypes.MATRIX);
-    mQueues.scale( new Static3D((float)width/texWidth,(float)height/texHeight,1) );
-    Distorted.onSurfaceChanged(width,height);
+    mEffects.abortEffects(EffectTypes.MATRIX);
+    mEffects.scale( new Static3D((float)width/texWidth,(float)height/texHeight,1) );
+    mScreen.resize(width,height);
     mView.setScreenSize(width,height);
     }
    
@@ -126,7 +130,7 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
   public void onDrawFrame(GL10 glUnused)
     {   
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
-    mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+    mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
index 000cf81..1cf1d6b 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
@@ -26,6 +26,7 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedEffectQueues;
@@ -48,7 +49,8 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedTexture mObjectTexture, mBackgroundTexture, mCenterTexture, mRegionTexture;
-    private DistortedEffectQueues mObjectQueues, mBackgroundQueues, mCenterQueues, mRegionQueues;
+    private DistortedEffectQueues mObjectEffects, mBackgroundEffects, mCenterEffects, mRegionEffects;
+    private DistortedFramebuffer mScreen;
     private GridFlat mQuad;
     private GridObject mObjectGrid;
     private int mObjWidth, mObjHeight, mObjDepth;
@@ -74,14 +76,14 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
       mObjectTexture     = act.getTexture();
       mObjectGrid        = act.getGrid();
-      mObjectQueues      = act.getQueues();
+      mObjectEffects = act.getQueues();
       mBackgroundTexture = new DistortedTexture(100,100);
       mCenterTexture     = new DistortedTexture(100,100);
       mRegionTexture     = new DistortedTexture(100,100);
       mQuad              = new GridFlat(1,1);
-      mBackgroundQueues  = new DistortedEffectQueues();
-      mCenterQueues      = new DistortedEffectQueues();
-      mRegionQueues      = new DistortedEffectQueues();
+      mBackgroundEffects = new DistortedEffectQueues();
+      mCenterEffects = new DistortedEffectQueues();
+      mRegionEffects = new DistortedEffectQueues();
 
       mObjWidth = mObjectTexture.getWidth();
       mObjHeight= mObjectTexture.getHeight();
@@ -107,6 +109,8 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       mRegionScaleInter = new Dynamic3D();
       mRegionScalePoint = new Static3D(0,0,0);
       mRegionScaleInter.add(mRegionScalePoint);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -133,13 +137,13 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
       long time = System.currentTimeMillis();
 
-      mBackgroundQueues.draw(time,mBackgroundTexture,mQuad);
-      mObjectQueues.draw(time,mObjectTexture,mObjectGrid);
+      mBackgroundEffects.draw(time,mBackgroundTexture,mQuad,mScreen);
+      mObjectEffects.draw(time,mObjectTexture,mObjectGrid,mScreen);
 
       if( Effects3DActivity.supportsCenter() )
         {
-        mCenterQueues.draw(time, mCenterTexture,mQuad);
-        if( Effects3DActivity.supportsRegion() ) mRegionQueues.draw(time, mRegionTexture,mQuad);
+        mCenterEffects.draw(time, mCenterTexture,mQuad,mScreen);
+        if( Effects3DActivity.supportsRegion() ) mRegionEffects.draw(time, mRegionTexture,mQuad,mScreen);
         }
       }
 
@@ -149,10 +153,10 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       {
       mScreenMin = width<height ? width:height;
 
-      mObjectQueues.abortEffects(EffectTypes.MATRIX);
-      mBackgroundQueues.abortEffects(EffectTypes.MATRIX);
-      mCenterQueues.abortEffects(EffectTypes.MATRIX);
-      mRegionQueues.abortEffects(EffectTypes.MATRIX);
+      mObjectEffects.abortEffects(EffectTypes.MATRIX);
+      mBackgroundEffects.abortEffects(EffectTypes.MATRIX);
+      mCenterEffects.abortEffects(EffectTypes.MATRIX);
+      mRegionEffects.abortEffects(EffectTypes.MATRIX);
 
       float factorCen;
       int centerSize = mCenterTexture.getWidth();
@@ -178,39 +182,39 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
       Static3D rotateObj = new Static3D(mObjWidth/2,mObjHeight/2, 0);
 
-      mObjectQueues.move( new Static3D( (width-mFactorObj*mObjWidth)/2 , (height-mFactorObj*mObjHeight)/2 , 0) );
-      mObjectQueues.scale(mFactorObj);
-      mObjectQueues.quaternion(mQuatInt1, rotateObj);
-      mObjectQueues.quaternion(mQuatInt2, rotateObj);
+      mObjectEffects.move( new Static3D( (width-mFactorObj*mObjWidth)/2 , (height-mFactorObj*mObjHeight)/2 , 0) );
+      mObjectEffects.scale(mFactorObj);
+      mObjectEffects.quaternion(mQuatInt1, rotateObj);
+      mObjectEffects.quaternion(mQuatInt2, rotateObj);
 
       Static3D rotateCen = new Static3D(width/2,height/2, 0);
 
-      mCenterQueues.quaternion(mQuatInt1, rotateCen);
-      mCenterQueues.quaternion(mQuatInt2, rotateCen);
+      mCenterEffects.quaternion(mQuatInt1, rotateCen);
+      mCenterEffects.quaternion(mQuatInt2, rotateCen);
 
-      mCenterQueues.move( new Static3D( (width -factorCen*centerSize-mFactorObj*mObjWidth )/2 ,
+      mCenterEffects.move( new Static3D( (width -factorCen*centerSize-mFactorObj*mObjWidth )/2 ,
                                   (height-factorCen*centerSize-mFactorObj*mObjHeight)/2 , mFactorObj*mObjDepth/2+10) );
-      mCenterQueues.move(mCenterInter);
-      mCenterQueues.scale(factorCen);
+      mCenterEffects.move(mCenterInter);
+      mCenterEffects.scale(factorCen);
 
-      mRegionQueues.quaternion(mQuatInt1, rotateCen);
-      mRegionQueues.quaternion(mQuatInt2, rotateCen);
+      mRegionEffects.quaternion(mQuatInt1, rotateCen);
+      mRegionEffects.quaternion(mQuatInt2, rotateCen);
 
-      mRegionQueues.move( new Static3D( (width -mFactorObj*mObjWidth )/2 ,
+      mRegionEffects.move( new Static3D( (width -mFactorObj*mObjWidth )/2 ,
                                   (height-mFactorObj*mObjHeight)/2 , mFactorObj*mObjDepth/2+12) );
-      mRegionQueues.move(mCenterInter);
-      mRegionQueues.move(mRegionInter);
-      mRegionQueues.scale(mRegionScaleInter);
-      mRegionQueues.move( new Static3D( -regionSize/2 , -regionSize/2 , 0) );
+      mRegionEffects.move(mCenterInter);
+      mRegionEffects.move(mRegionInter);
+      mRegionEffects.scale(mRegionScaleInter);
+      mRegionEffects.move( new Static3D( -regionSize/2 , -regionSize/2 , 0) );
 
       int backgroundSize = mBackgroundTexture.getWidth();
       float factorBackX = ((float)width)/backgroundSize;
       float factorBackY = ((float)height)/backgroundSize;
 
-      mBackgroundQueues.move(new Static3D( -width/2, -height/2,-mFactorObj*(mObjWidth+mObjHeight)/2) );
-      mBackgroundQueues.scale(new Static3D(2*factorBackX, 2*factorBackY, 1.0f) );
+      mBackgroundEffects.move(new Static3D( -width/2, -height/2,-mFactorObj*(mObjWidth+mObjHeight)/2) );
+      mBackgroundEffects.scale(new Static3D(2*factorBackX, 2*factorBackY, 1.0f) );
 
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
index a014f48..c8af2b2 100644
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
@@ -27,6 +27,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedObjectTree;
 import org.distorted.library.Distorted;
 import org.distorted.library.GridCubes;
@@ -49,17 +50,18 @@ import android.opengl.GLSurfaceView;
 class FBORenderer implements GLSurfaceView.Renderer 
 {
    private GLSurfaceView mView;
-   private DistortedEffectQueues mQueues;
-   private int lisaHeight, lisaWidth;
-    
+   private DistortedEffectQueues mEffects;
+   private DistortedFramebuffer mScreen;
    private DistortedObjectTree mRoot;
-    
+   private int lisaHeight, lisaWidth;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    FBORenderer(GLSurfaceView v)
       {
-      mView = v;
-      mQueues = new DistortedEffectQueues();
+      mView   = v;
+      mEffects= new DistortedEffectQueues();
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -67,33 +69,33 @@ class FBORenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mRoot.draw(System.currentTimeMillis());
+      mRoot.draw(System.currentTimeMillis(),mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
          
       if( (float)lisaHeight/lisaWidth > (float)height/width )
         {
         int w = (height*lisaWidth)/lisaHeight;
         float factor = (float)height/lisaHeight;
 
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*lisaHeight)/lisaWidth;
         float factor = (float)width/lisaWidth;
 
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
       
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -133,9 +135,9 @@ class FBORenderer implements GLSurfaceView.Renderer
       text.setTexture(bitmap2);
       DistortedEffectQueues textQueues = new DistortedEffectQueues();
 
-      mQueues.abortAllEffects();
+      mEffects.abortAllEffects();
 
-      mRoot = new DistortedObjectTree(lisa,mQueues,new GridFlat(1,1));
+      mRoot = new DistortedObjectTree(lisa, mEffects,new GridFlat(1,1));
       mRoot.attach(text,textQueues,new GridCubes(20,5,false));
 
       float factor = lisaWidth/(2.0f*textWidth);
@@ -160,7 +162,7 @@ class FBORenderer implements GLSurfaceView.Renderer
       chromaDyn.add(new Static1D(0.0f));
       chromaDyn.add(new Static1D(1.0f));
 
-      mQueues.chroma(chromaDyn, new Static3D(0,0,1) );
+      mEffects.chroma(chromaDyn, new Static3D(0,0,1) );
       
       try
         {
diff --git a/src/main/java/org/distorted/examples/flag/FlagRenderer.java b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
index a4766e3..2f7f747 100644
--- a/src/main/java/org/distorted/examples/flag/FlagRenderer.java
+++ b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
@@ -26,6 +26,7 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridCubes;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.DistortedTexture;
@@ -48,13 +49,14 @@ import javax.microedition.khronos.opengles.GL10;
 class FlagRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
     private DistortedTexture mTexture;
+    private DistortedFramebuffer mScreen;
     private GridCubes mGrid;
-    private int mObjWidth, mObjHeight;
     private DynamicQuat mQuatInt1, mQuatInt2;
     private Dynamic5D mWaveDyn;
     private Static5D mWaveSta1, mWaveSta2;
+    private int mObjWidth, mObjHeight;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -65,7 +67,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mQueues  = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
       mGrid    = new GridCubes(50,30,false);
       mTexture = new DistortedTexture(500,300);
 
@@ -92,7 +94,9 @@ class FlagRenderer implements GLSurfaceView.Renderer
       Static3D waveCenter = new Static3D(mObjWidth, mObjHeight/2, 0);  // middle of the right edge
       Static4D waveRegion = new Static4D(0,0,mObjWidth,mObjWidth);
 
-      mQueues.wave(mWaveDyn, waveCenter, waveRegion);
+      mEffects.wave(mWaveDyn, waveCenter, waveRegion);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -139,7 +143,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture, mGrid, mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -148,7 +152,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
       {
       mScreenMin = width<height ? width:height;
     	
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
       float factor;
 
       if( width*mObjHeight > height*mObjWidth ) // screen is more 'horizontal' than the Object
@@ -160,14 +164,14 @@ class FlagRenderer implements GLSurfaceView.Renderer
         factor = (0.8f*width)/mObjWidth;
         }
 
-      mQueues.move( new Static3D( (width-factor*mObjWidth)/2 , (height-factor*mObjHeight)/2 , 0) );
-      mQueues.scale(factor);
+      mEffects.move( new Static3D( (width-factor*mObjWidth)/2 , (height-factor*mObjHeight)/2 , 0) );
+      mEffects.scale(factor);
       Static3D center = new Static3D(mObjWidth/2,mObjHeight/2, 0);
 
-      mQueues.quaternion(mQuatInt1, center);
-      mQueues.quaternion(mQuatInt2, center);
+      mEffects.quaternion(mQuatInt1, center);
+      mEffects.quaternion(mQuatInt2, center);
        
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index 55fc581..a2ace98 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -49,7 +50,8 @@ class GirlRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
+    private DistortedFramebuffer mScreen;
     private GridFlat mGrid;
     private Static3D v0,v1,v2,v3;
     private Static1D dBegin, dMiddle, dEnd, s0;
@@ -109,15 +111,17 @@ class GirlRenderer implements GLSurfaceView.Renderer
       diHips.add(dMiddle);
       diHips.add(dBegin);
 
-      mQueues = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
 
-      mQueues.sink( diSink, pLeft, sinkRegion );
-      mQueues.sink( diSink, pRight,sinkRegion );
+      mEffects.sink( diSink, pLeft, sinkRegion );
+      mEffects.sink( diSink, pRight,sinkRegion );
 
-      mQueues.distort(diL, pLeft , Region);
-      mQueues.distort(diR, pRight, Region);
+      mEffects.distort(diL, pLeft , Region);
+      mEffects.distort(diR, pRight, Region);
 
-      mQueues.swirl(diHips, pHips, HipsRegion );
+      mEffects.swirl(diHips, pHips, HipsRegion );
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -150,33 +154,33 @@ class GirlRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(),mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(),mTexture,mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
       
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
 
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
 
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
       
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index 5fbeb26..29e13d8 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -29,6 +29,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -53,7 +54,8 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
 
    private GLSurfaceView mView;
    private DistortedTexture mTexture;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
+   private DistortedFramebuffer mScreen;
    private GridFlat mGrid;
    private int bmpHeight, bmpWidth;
    private Random mRnd;
@@ -64,8 +66,9 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
       {
       Distorted.setMaxVertex(NUM_BUBBLES);   
       mView = v;
-      mQueues = new DistortedEffectQueues();
-      mQueues.registerForMessages(this);
+      mEffects = new DistortedEffectQueues();
+      mEffects.registerForMessages(this);
+      mScreen = new DistortedFramebuffer(0);
       mRnd = new Random(0);
       }
 
@@ -83,7 +86,7 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
       dDistort.add(new Static3D(0,0,     0));
       dDistort.add(new Static3D(0,0,height));
 
-      return mQueues.distort(dDistort, new Static3D(pointx,pointy,0), new Static4D(0,0,radius,radius));
+      return mEffects.distort(dDistort, new Static3D(pointx,pointy,0), new Static4D(0,0,radius,radius));
       }
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -103,33 +106,33 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
          
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
 
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
 
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
       
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
index 982a51e..147c0d0 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
@@ -24,9 +24,9 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.library.Distorted;
 import org.distorted.library.DistortedEffectQueues;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridObject;
 import org.distorted.library.DistortedTexture;
-import org.distorted.library.EffectTypes;
 
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
@@ -37,7 +37,8 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
+    private DistortedFramebuffer mScreen;
     private GridObject mGrid;
 
     private int mWidth, mHeight;
@@ -50,9 +51,10 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
 
       Matrix3DActivity act = (Matrix3DActivity)v.getContext();
 
-      mQueues = act.getQueues();
+      mEffects = act.getQueues();
       mTexture= act.getTexture();
       mGrid   = act.getGrid();
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -60,7 +62,7 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused)
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(),mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(),mTexture,mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -84,7 +86,7 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
       mWidth = width;
       mHeight= height;
 
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index 911de4a..2afed71 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -27,6 +27,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridFlat;
@@ -46,7 +47,8 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
-    private DistortedEffectQueues mQueues;
+    private DistortedEffectQueues mEffects;
+    private DistortedFramebuffer mScreen;
     private GridFlat mGrid;
     private int bmpHeight, bmpWidth;
 
@@ -68,9 +70,11 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       dRight.add( new Static3D(  0,  0,0) );
       dRight.add( new Static3D( 20,-10,0) );
 
-      mQueues = new DistortedEffectQueues();
-      mQueues.distort( dLeft, pLeft , rLeft );
-      mQueues.distort(dRight, pRight, rRight);
+      mEffects = new DistortedEffectQueues();
+      mEffects.distort( dLeft, pLeft , rLeft );
+      mEffects.distort(dRight, pRight, rRight);
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -78,31 +82,31 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(),mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(),mTexture,mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      mQueues.abortEffects(EffectTypes.MATRIX);
+      mEffects.abortEffects(EffectTypes.MATRIX);
 
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
-        mQueues.move( new Static3D((width-w)/2,0,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
-        mQueues.move( new Static3D(0,(height-h)/2,0) );
-        mQueues.scale(factor);
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
         }
 
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
index 38282b4..2f26204 100644
--- a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
@@ -29,6 +29,7 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.GridFlat;
@@ -45,8 +46,9 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
    private int texW, texH;
 
    private GridFlat mGrid;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
    private DistortedTexture mTexture;
+   private DistortedFramebuffer mScreen;
    private boolean mRefresh;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -57,11 +59,11 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
      mPaint.setAntiAlias(true);
      mPaint.setFakeBoldText(true);
      mPaint.setStyle(Style.FILL);
-      
-     mView = v;
 
-     mQueues = new DistortedEffectQueues();
-     mRefresh = true;
+     mView   = v;
+     mEffects= new DistortedEffectQueues();
+     mScreen = new DistortedFramebuffer(0);
+     mRefresh= true;
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -93,7 +95,7 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
 
    DistortedEffectQueues getQueues()
      {
-     return mQueues;
+     return mEffects;
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -129,7 +131,7 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
      mBitmap  = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
      mCanvas  = new Canvas(mBitmap);
 
-     Distorted.onSurfaceChanged(texW, texH);
+     mScreen.resize(texW, texH);
      mView.onSurfaceChanged(texW,texH);
 
      mRefresh = true;
@@ -151,7 +153,7 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
        mRefresh = false;
        }
       
-     mQueues.draw(time,mTexture,mGrid);
+     mEffects.draw(time,mTexture,mGrid,mScreen);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
index a0c292a..1b791a2 100644
--- a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
+++ b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
@@ -27,6 +27,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.DistortedObjectTree;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
@@ -51,9 +52,9 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
    private static final int NUM_LEAVES  = 8;
    
    private GLSurfaceView mView;
-   private DistortedObjectTree mScreen;
+   private DistortedObjectTree mRoot;
    private DistortedTexture mLeaf;
-
+   private DistortedFramebuffer mScreen;
    private int mScreenW, mScreenH;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -64,11 +65,11 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
 
       mLeaf = new DistortedTexture(LEAF_SIZE,LEAF_SIZE);
       GridFlat grid = new GridFlat(1,1);
-      DistortedEffectQueues queue = new DistortedEffectQueues();
+      DistortedEffectQueues effects = new DistortedEffectQueues();
 
       mScreenW = 9*LEAF_SIZE;
       mScreenH = 9*LEAF_SIZE;
-      mScreen = new DistortedObjectTree(new DistortedTexture(mScreenW,mScreenH), queue, grid);
+      mRoot = new DistortedObjectTree(new DistortedTexture(mScreenW,mScreenH), effects, grid);
      
       Dynamic1D rot = new Dynamic1D(5000,0.0f);
       rot.setMode(Dynamic1D.MODE_JUMP);
@@ -88,15 +89,15 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
         {
         if( i<=1 )
           {
-          queue = new DistortedEffectQueues();
-          mCircleNode[i] = new DistortedObjectTree(new DistortedTexture(3*LEAF_SIZE,3*LEAF_SIZE), queue, grid);
+          effects = new DistortedEffectQueues();
+          mCircleNode[i] = new DistortedObjectTree(new DistortedTexture(3*LEAF_SIZE,3*LEAF_SIZE), effects, grid);
         
           for(int j=0; j<NUM_LEAVES-i; j++)
             {
-            queue = new DistortedEffectQueues();
-            mCircleNode[i].attach(mLeaf, queue, grid);
-            queue.rotate( new Static1D(j*(360/NUM_LEAVES)), axis, center );
-            queue.move(moveVector);
+            effects = new DistortedEffectQueues();
+            mCircleNode[i].attach(mLeaf, effects, grid);
+            effects.rotate( new Static1D(j*(360/NUM_LEAVES)), axis, center );
+            effects.move(moveVector);
             }
           }
         else
@@ -104,12 +105,14 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
           mCircleNode[i] = new DistortedObjectTree(mCircleNode[0], Distorted.CLONE_BITMAP|Distorted.CLONE_CHILDREN);
           }
 
-        mScreen.attach(mCircleNode[i]);
-        queue = mCircleNode[i].getQueues();
-        queue.move( new Static3D(positions[2*i], positions[2*i+1], 0) );
-        queue.rotate( rot, axis, center );
-        queue.chroma( new Static1D(0.5f), new Static3D(colors[3*i],colors[3*i+1], colors[3*i+2]) );
+        mRoot.attach(mCircleNode[i]);
+        effects = mCircleNode[i].getQueues();
+        effects.move( new Static3D(positions[2*i], positions[2*i+1], 0) );
+        effects.rotate( rot, axis, center );
+        effects.chroma( new Static1D(0.5f), new Static3D(colors[3*i],colors[3*i+1], colors[3*i+2]) );
         }
+
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -117,35 +120,35 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mScreen.draw(System.currentTimeMillis());
+      mRoot.draw(System.currentTimeMillis(),mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      DistortedEffectQueues queues = mScreen.getQueues();
+      DistortedEffectQueues effects = mRoot.getQueues();
 
-      queues.abortEffects(EffectTypes.MATRIX);
+      effects.abortEffects(EffectTypes.MATRIX);
       
       if( (float)mScreenH/mScreenW > (float)height/width )
         {
         int w = (height*mScreenW)/mScreenH;
         float factor = (float)height/mScreenH;
 
-        queues.move( new Static3D((width-w)/2 ,0, 0) );
-        queues.scale( factor );
+        effects.move( new Static3D((width-w)/2 ,0, 0) );
+        effects.scale( factor );
         }
       else
         {
         int h = (width*mScreenH)/mScreenW;
         float factor = (float)width/mScreenW;
 
-        queues.move( new Static3D(0,(height-h)/2,0) );
-        queues.scale( factor );
+        effects.move( new Static3D(0,(height-h)/2,0) );
+        effects.scale( factor );
         }
       
-      Distorted.onSurfaceChanged(width, height); 
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
index b455c85..1327f6e 100644
--- a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
+++ b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
@@ -31,6 +31,7 @@ import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -62,7 +63,8 @@ class RenderThread extends Thread
   private EGLSurface eglSurface;
 
   private DistortedTexture mTexture;
-  private DistortedEffectQueues mQueues;
+  private DistortedEffectQueues mEffects;
+  private DistortedFramebuffer mScreen;
   private GridFlat mGrid;
   private int bmpHeight, bmpWidth;
   private SurfaceView mView;
@@ -89,9 +91,11 @@ class RenderThread extends Thread
     dRight.add( new Static3D(  0,  0,0) );
     dRight.add( new Static3D( 20,-10,0) );
 
-    mQueues = new DistortedEffectQueues();
-    mQueues.distort( dLeft, pLeft , rLeft );
-    mQueues.distort(dRight, pRight, rRight);
+    mEffects = new DistortedEffectQueues();
+    mEffects.distort( dLeft, pLeft , rLeft );
+    mEffects.distort(dRight, pRight, rRight);
+
+    mScreen = new DistortedFramebuffer(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -228,26 +232,26 @@ class RenderThread extends Thread
     {
     Log.d(TAG, "surfaceChanged " + width + "x" + height);
 
-    mQueues.abortEffects(EffectTypes.MATRIX);
+    mEffects.abortEffects(EffectTypes.MATRIX);
 
     if( (float)bmpHeight/bmpWidth > (float)height/width )
       {
       int w = (height*bmpWidth)/bmpHeight;
       float factor = (float)height/bmpHeight;
 
-      mQueues.move( new Static3D((width-w)/2,0,0) );
-      mQueues.scale( factor );
+      mEffects.move( new Static3D((width-w)/2,0,0) );
+      mEffects.scale( factor );
       }
     else
       {
       int h = (width*bmpHeight)/bmpWidth;
       float factor = (float)width/bmpWidth;
 
-      mQueues.move( new Static3D(0,(height-h)/2,0) );
-      mQueues.scale( factor );
+      mEffects.move( new Static3D(0,(height-h)/2,0) );
+      mEffects.scale( factor );
       }
 
-    Distorted.onSurfaceChanged(width, height);
+    mScreen.resize(width, height);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -263,7 +267,7 @@ class RenderThread extends Thread
     eglCore.makeCurrent(eglSurface);
 
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+    mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
 
     eglCore.swapBuffers(eglSurface);
     }
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionActivity.java b/src/main/java/org/distorted/examples/projection/ProjectionActivity.java
index 736376a..a47419e 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionActivity.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionActivity.java
@@ -96,16 +96,18 @@ public class ProjectionActivity extends Activity implements OnSeekBarChangeListe
     public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
       {
       int ret;
+      ProjectionSurfaceView view = (ProjectionSurfaceView)findViewById(R.id.surfaceViewProjection);
+      ProjectionRenderer renderer = view.getRenderer();
 
       switch (bar.getId()) 
         {
-        case R.id.projectionSeekFOV: ret = ProjectionRenderer.setFOV(progress);
+        case R.id.projectionSeekFOV: ret = renderer.setFOV(progress);
                                      textF.setText("FOV: "+ret);
                                      break;
-        case R.id.projectionSeekX  : ret = ProjectionRenderer.setX(progress);
+        case R.id.projectionSeekX  : ret = renderer.setX(progress);
                                      textX.setText("X: "+ret);
                                      break;
-        case R.id.projectionSeekY  : ret = ProjectionRenderer.setY(progress);
+        case R.id.projectionSeekY  : ret = renderer.setY(progress);
                                      textY.setText("Y: "+ret);
                                      break;
         }
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
index 702c4df..847f170 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
@@ -23,6 +23,7 @@ import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -42,44 +43,46 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
    private DistortedTexture mTexture;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
+   private DistortedFramebuffer mScreen;
    private GridFlat mGrid;
 
-   private static float mF, mX, mY;
-   private static int mWidth, mHeight;
+   private float mF, mX, mY;
+   private int mWidth, mHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    ProjectionRenderer(GLSurfaceView view)
       { 
-      mView = view;
-      mQueues = new DistortedEffectQueues();
+      mView   = view;
+      mEffects= new DistortedEffectQueues();
+      mScreen = new DistortedFramebuffer(0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   static int setFOV(int f)
+   int setFOV(int f)
       {
       mF = f;
-      Distorted.setProjection(mF,mX,mY);
+      mScreen.setProjection(mF,mX,mY);
       return (int)mF;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   static int setX(int x)
+   int setX(int x)
       {
       mX = (x-50)*0.02f*mWidth;
-      Distorted.setProjection(mF,mX,mY);
+      mScreen.setProjection(mF,mX,mY);
       return (int)mX;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   static int setY(int y)
+   int setY(int y)
       {
       mY = (y-50)*0.02f*mHeight;
-      Distorted.setProjection(mF,mX,mY);
+      mScreen.setProjection(mF,mX,mY);
       return (int)mY;
       }
 
@@ -88,7 +91,7 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+      mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -98,8 +101,8 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
       mWidth = width;
       mHeight= height;
 
-      Distorted.setProjection(mF,mX,mY);
-      mQueues.abortAllEffects();
+      mScreen.setProjection(mF,mX,mY);
+      mEffects.abortAllEffects();
 
       Paint paint = new Paint();
       mTexture    = new DistortedTexture(width,height);
@@ -127,12 +130,12 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
       Static3D vector = new Static3D(0,0,min/5);
       Static4D region = new Static4D(0,0,min/5,min/5);
 
-      mQueues.distort(vector, new Static3D(  width/4,   height/4, 0), region);
-      mQueues.distort(vector, new Static3D(3*width/4,   height/4, 0), region);
-      mQueues.distort(vector, new Static3D(  width/4, 3*height/4, 0), region);
-      mQueues.distort(vector, new Static3D(3*width/4, 3*height/4, 0), region);
+      mEffects.distort(vector, new Static3D(  width/4,   height/4, 0), region);
+      mEffects.distort(vector, new Static3D(3*width/4,   height/4, 0), region);
+      mEffects.distort(vector, new Static3D(  width/4, 3*height/4, 0), region);
+      mEffects.distort(vector, new Static3D(3*width/4, 3*height/4, 0), region);
 
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionSurfaceView.java b/src/main/java/org/distorted/examples/projection/ProjectionSurfaceView.java
index e5fd3b1..5526b91 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionSurfaceView.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionSurfaceView.java
@@ -27,6 +27,8 @@ import android.util.AttributeSet;
 
 class ProjectionSurfaceView extends GLSurfaceView
 {
+    private ProjectionRenderer mRenderer;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
     public ProjectionSurfaceView(Context c, AttributeSet attrs)
@@ -36,8 +38,16 @@ class ProjectionSurfaceView extends GLSurfaceView
       if(!isInEditMode())
         {
         setEGLContextClientVersion(2);
-        setRenderer(new ProjectionRenderer(this));
+        mRenderer = new ProjectionRenderer(this);
+        setRenderer(mRenderer);
         }
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    ProjectionRenderer getRenderer()
+      {
+      return mRenderer;
+      }
 }
 
diff --git a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
index 6e079b3..5614887 100644
--- a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
+++ b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.DynamicQuat;
@@ -51,7 +52,8 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
 
   private GLSurfaceView mView;
   private DistortedTexture mTexture;
-  private DistortedEffectQueues mQueues;
+  private DistortedEffectQueues mEffects;
+  private DistortedFramebuffer mScreen;
   private GridCubes mGrid;
   private DynamicQuat mRot;
     
@@ -62,7 +64,7 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
     mView    = v;
     mGrid    = new GridCubes(1,1,false);
     mTexture = new DistortedTexture(1,1);
-    mQueues  = new DistortedEffectQueues();
+    mEffects = new DistortedEffectQueues();
     mRot     = new DynamicQuat();
 
     Random rnd = new Random(System.currentTimeMillis());
@@ -83,6 +85,8 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
     mRot.setCount(0);
     mRot.setDuration(8000);
     mRot.setMode(Dynamic.MODE_LOOP);
+
+    mScreen = new DistortedFramebuffer(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -90,7 +94,7 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
   public void onDrawFrame(GL10 glUnused) 
     {
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+    mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -99,12 +103,12 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
     {
     float scaleFactor = width>height ? height/3:width/3;
 
-    mQueues.abortEffects(EffectTypes.MATRIX);
-    mQueues.move( new Static3D( (width-scaleFactor)/2 , (height-scaleFactor)/2 , 0) );
-    mQueues.scale(scaleFactor);
-    mQueues.quaternion( mRot, new Static3D(0.5f,0.5f,0) );
+    mEffects.abortEffects(EffectTypes.MATRIX);
+    mEffects.move( new Static3D( (width-scaleFactor)/2 , (height-scaleFactor)/2 , 0) );
+    mEffects.scale(scaleFactor);
+    mEffects.quaternion( mRot, new Static3D(0.5f,0.5f,0) );
        
-    Distorted.onSurfaceChanged(width, height); 
+    mScreen.resize(width, height);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/save/SaveRenderer.java b/src/main/java/org/distorted/examples/save/SaveRenderer.java
index b0b9a56..0deee39 100644
--- a/src/main/java/org/distorted/examples/save/SaveRenderer.java
+++ b/src/main/java/org/distorted/examples/save/SaveRenderer.java
@@ -54,9 +54,9 @@ class SaveRenderer implements GLSurfaceView.Renderer
   {
   private GLSurfaceView mView;
   private DistortedTexture mGirl;
-  private DistortedEffectQueues mQueues;
+  private DistortedEffectQueues mEffects;
   private GridFlat mGrid;
-  private DistortedFramebuffer mOffscreen;
+  private DistortedFramebuffer mScreen, mOffscreen;
   private Static1D s0;
   private Dynamic3D mScaleDyn;
   private Static3D mScaleFactor;
@@ -91,9 +91,11 @@ class SaveRenderer implements GLSurfaceView.Renderer
     mScaleFactor = new Static3D(mScale,mScale,1.0f);
     mScaleDyn.add(mScaleFactor);
 
-    mQueues = new DistortedEffectQueues();
-    mQueues.sink( diSink, pLeft , sinkRegion);
-    mQueues.sink( diSink, pRight, sinkRegion);
+    mEffects = new DistortedEffectQueues();
+    mEffects.sink( diSink, pLeft , sinkRegion);
+    mEffects.sink( diSink, pRight, sinkRegion);
+
+    mScreen = new DistortedFramebuffer(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -152,9 +154,9 @@ class SaveRenderer implements GLSurfaceView.Renderer
 
     if( isSaving )  // render to an offscreen buffer and read pixels
       {
-      mQueues.abortEffects(EffectTypes.MATRIX);
-      mQueues.scale(mScaleFactor);
-      mQueues.draw(time, mGirl, mGrid, mOffscreen);
+      mEffects.abortEffects(EffectTypes.MATRIX);
+      mEffects.scale(mScaleFactor);
+      mEffects.draw(time, mGirl, mGrid, mOffscreen);
       applyMatrixEffects(scrWidth,scrHeight);
 
       int fW =(int)(mScale*bmpWidth);
@@ -178,33 +180,33 @@ class SaveRenderer implements GLSurfaceView.Renderer
       isSaving = false;
       }
 
-    mQueues.draw(time, mGirl, mGrid);
+    mEffects.draw(time, mGirl, mGrid, mScreen);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void applyMatrixEffects(int width, int height)
     {
-    mQueues.abortEffects(EffectTypes.MATRIX);
+    mEffects.abortEffects(EffectTypes.MATRIX);
 
     if( (float)bmpHeight/bmpWidth > (float)height/width )
       {
       int w = (height*bmpWidth)/bmpHeight;
       float factor = (float)height/bmpHeight;
 
-      mQueues.move( new Static3D((width-w)/2,0,0) );
-      mQueues.scale(factor);
+      mEffects.move( new Static3D((width-w)/2,0,0) );
+      mEffects.scale(factor);
       }
     else
       {
       int h = (width*bmpHeight)/bmpWidth;
       float factor = (float)width/bmpWidth;
 
-      mQueues.move( new Static3D(0,(height-h)/2,0) );
-      mQueues.scale(factor);
+      mEffects.move( new Static3D(0,(height-h)/2,0) );
+      mEffects.scale(factor);
       }
 
-    mQueues.scale(mScaleDyn);
+    mEffects.scale(mScaleDyn);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -214,7 +216,7 @@ class SaveRenderer implements GLSurfaceView.Renderer
     scrWidth = width;
     scrHeight= height;
     applyMatrixEffects(width, height);
-    Distorted.onSurfaceChanged(width, height);
+    mScreen.resize(width, height);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 7a9d5c7..c232dea 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.DistortedEffectQueues;
@@ -48,7 +49,8 @@ class SinkRenderer implements GLSurfaceView.Renderer
   {
   private GLSurfaceView mView;
   private DistortedTexture mTexture;
-  private DistortedEffectQueues mQueues;
+  private DistortedEffectQueues mEffects;
+  private DistortedFramebuffer mScreen;
   private GridFlat mGrid;
   private int bmpHeight, bmpWidth;
     
@@ -66,9 +68,11 @@ class SinkRenderer implements GLSurfaceView.Renderer
     dSink.add(new Static1D( 1));
     dSink.add(new Static1D(10));
 
-    mQueues = new DistortedEffectQueues();
-    mQueues.sink( dSink, pLeft, Region);
-    mQueues.sink( dSink, pRight,Region);
+    mEffects = new DistortedEffectQueues();
+    mEffects.sink( dSink, pLeft, Region);
+    mEffects.sink( dSink, pRight,Region);
+
+    mScreen = new DistortedFramebuffer(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -76,33 +80,33 @@ class SinkRenderer implements GLSurfaceView.Renderer
   public void onDrawFrame(GL10 glUnused) 
     {
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    mQueues.draw(System.currentTimeMillis(), mTexture,mGrid);
+    mEffects.draw(System.currentTimeMillis(), mTexture,mGrid,mScreen);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
   public void onSurfaceChanged(GL10 glUnused, int width, int height) 
     { 
-    mQueues.abortEffects(EffectTypes.MATRIX);
+    mEffects.abortEffects(EffectTypes.MATRIX);
          
     if( (float)bmpHeight/bmpWidth > (float)height/width )
       {
       int w = (height*bmpWidth)/bmpHeight;
       float factor = (float)height/bmpHeight;
 
-      mQueues.move( new Static3D((width-w)/2,0,0) );
-      mQueues.scale( factor );
+      mEffects.move( new Static3D((width-w)/2,0,0) );
+      mEffects.scale( factor );
       }
     else
       {
       int h = (width*bmpHeight)/bmpWidth;
       float factor = (float)width/bmpWidth;
 
-      mQueues.move( new Static3D(0,(height-h)/2,0) );
-      mQueues.scale( factor );
+      mEffects.move( new Static3D(0,(height-h)/2,0) );
+      mEffects.scale( factor );
       }
       
-    Distorted.onSurfaceChanged(width, height); 
+    mScreen.resize(width, height);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index 92efdf2..d97b1b0 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridFlat;
 import org.distorted.library.EffectNames;
 import org.distorted.library.type.Dynamic1D;
@@ -103,13 +104,14 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
    
   private GLSurfaceView mView;
   private DistortedTexture mScreenTexture, mGFFATexture, mLogoTexture, mCrawlTexture, mCrawlBackgroundTexture, mStarTexture;
-  private DistortedEffectQueues mScreenQueue, mGFFAQueue, mLogoQueue, mCrawlQueue, mCrawlBackgroundQueue;
+  private DistortedEffectQueues mScreenEffects, mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
   private DistortedEffectQueues[] mStarQueue;
-  private long gffaID, logoID, crawlID;
-    
-  private Random mRnd = new Random(0);
   private DistortedObjectTree mRoot, mBackground;
+  private DistortedFramebuffer mScreen;
   private GridFlat mQuad;
+
+  private long gffaID, logoID, crawlID;
+  private Random mRnd = new Random(0);
   private int mWidth, mHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -120,18 +122,19 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
 
     mQuad = new GridFlat(1,1);
 
-    mScreenQueue          = new DistortedEffectQueues();
-    mGFFAQueue            = new DistortedEffectQueues();
-    mLogoQueue            = new DistortedEffectQueues();
-    mCrawlQueue           = new DistortedEffectQueues();
-    mCrawlBackgroundQueue = new DistortedEffectQueues();
+    mScreenEffects          = new DistortedEffectQueues();
+    mGFFAEffects            = new DistortedEffectQueues();
+    mLogoEffects            = new DistortedEffectQueues();
+    mCrawlEffects           = new DistortedEffectQueues();
+    mCrawlBackgroundEffects = new DistortedEffectQueues();
 
     mStarQueue = new DistortedEffectQueues[NUM_STARS];
     mStarQueue[0] = new DistortedEffectQueues();
 
     for(int i=1; i<NUM_STARS; i++) mStarQueue[i] = new DistortedEffectQueues(mStarQueue[0],Distorted.CLONE_VERTEX);
 
-    Distorted.setProjection(60.0f, 0.0f, 0.0f);
+    mScreen = new DistortedFramebuffer(0);
+    mScreen.setProjection(60.0f, 0.0f, 0.0f);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -147,7 +150,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
   public void onDrawFrame(GL10 glUnused) 
     {
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    mRoot.draw(System.currentTimeMillis());
+    mRoot.draw(System.currentTimeMillis(),mScreen);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -159,17 +162,17 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       mWidth = width;
       mHeight= height;
 
-      mScreenQueue.abortAllEffects();
-      mGFFAQueue.abortAllEffects();
-      mLogoQueue.abortAllEffects();
-      mCrawlQueue.abortAllEffects();
-      mCrawlBackgroundQueue.abortAllEffects();
+      mScreenEffects.abortAllEffects();
+      mGFFAEffects.abortAllEffects();
+      mLogoEffects.abortAllEffects();
+      mCrawlEffects.abortAllEffects();
+      mCrawlBackgroundEffects.abortAllEffects();
 
       for(int i=0; i<NUM_STARS; i++) mStarQueue[i].abortAllEffects();
 
       setupScreen(width,height);
 
-      Distorted.onSurfaceChanged(width, height);
+      mScreen.resize(width, height);
       }
     }
 
@@ -196,7 +199,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
   private void setupScreen(int w, int h)
     {
     mScreenTexture = new DistortedTexture(w,h);
-    mRoot = new DistortedObjectTree(mScreenTexture,mScreenQueue,mQuad);
+    mRoot = new DistortedObjectTree(mScreenTexture, mScreenEffects,mQuad);
       
     mCrawlBackgroundTexture = new DistortedTexture(w,(int)(Math.sqrt(3.0)*h));
        
@@ -238,12 +241,12 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     di.add(new Static1D(1.0f));
     di.add(new Static1D(0.0f));
     
-    mGFFAQueue.move( new Static3D(w/5,h/3,0) );
-    mGFFAQueue.scale( new Static3D(scale,scale,scale) );
-    mGFFAQueue.alpha(di);
+    mGFFAEffects.move( new Static3D(w/5,h/3,0) );
+    mGFFAEffects.scale( new Static3D(scale,scale,scale) );
+    mGFFAEffects.alpha(di);
       
-    mRoot.attach(mGFFATexture, mGFFAQueue, mQuad);
-    mGFFAQueue.registerForMessages(this);
+    mRoot.attach(mGFFATexture, mGFFAEffects, mQuad);
+    mGFFAEffects.registerForMessages(this);
     }
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -314,9 +317,9 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mStarTexture = new DistortedTexture(bitmapStar.getWidth(),bitmapStar.getHeight());
     mStarTexture.setTexture(bitmapStar);
 
-    gffaID = mGFFAQueue.getID();
-    logoID = mLogoQueue.getID();
-    crawlID= mCrawlQueue.getID();
+    gffaID = mGFFAEffects.getID();
+    logoID = mLogoEffects.getID();
+    crawlID= mCrawlEffects.getID();
     }
  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -370,8 +373,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       {
       if( objectID == gffaID )
         {
-        mRoot.detach(mGFFAQueue);
-        mGFFAQueue.abortAllEffects();
+        mRoot.detach(mGFFAEffects);
+        mGFFAEffects.abortAllEffects();
         mGFFATexture.markForDeletion();
 
         int screenW=mScreenTexture.getWidth();
@@ -387,17 +390,17 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         di.add(new Static3D(initSize,initSize,1));
         di.add(new Static3D(finaSize,finaSize,1));
 
-        mLogoQueue.move( new Static3D(screenW/2,screenH/2,0) );
-        mLogoQueue.scale(di);
-        mLogoQueue.move( new Static3D(-logoW/2,-logoH/2,0) );
+        mLogoEffects.move( new Static3D(screenW/2,screenH/2,0) );
+        mLogoEffects.scale(di);
+        mLogoEffects.move( new Static3D(-logoW/2,-logoH/2,0) );
       
-        mRoot.attach(mLogoTexture,mLogoQueue,mQuad);
-        mLogoQueue.registerForMessages(this);
+        mRoot.attach(mLogoTexture, mLogoEffects,mQuad);
+        mLogoEffects.registerForMessages(this);
         }
       else if( objectID==logoID )
         {
-        mRoot.detach(mLogoQueue);
-        mLogoQueue.abortAllEffects();
+        mRoot.detach(mLogoEffects);
+        mLogoEffects.abortAllEffects();
         mLogoTexture.markForDeletion();
         
         int crawlW = mCrawlTexture.getWidth();
@@ -411,28 +414,28 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         di.add(new Static3D(screenW/2,+backH       , 0));
         di.add(new Static3D(screenW/2,-scale*crawlH, 0));
         
-        mCrawlBackgroundQueue.move( new Static3D(0,screenH-backH,0) );
-        mCrawlBackgroundQueue.rotate( new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,backH,0) );
+        mCrawlBackgroundEffects.move( new Static3D(0,screenH-backH,0) );
+        mCrawlBackgroundEffects.rotate( new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,backH,0) );
         
         final int transpDist = 5;
         Static4D region = new Static4D(screenW/2,(1-transpDist)*backH,transpDist*backH,transpDist*backH);
-        mCrawlBackgroundQueue.alpha(new Static1D(1-transpDist/2), region, true);
+        mCrawlBackgroundEffects.alpha(new Static1D(1-transpDist/2), region, true);
         
-        mCrawlQueue.move(di);
-        mCrawlQueue.scale( new Static3D(scale,scale,scale) );
-        mCrawlQueue.move( new Static3D(-crawlW/2,0,0) );
+        mCrawlEffects.move(di);
+        mCrawlEffects.scale( new Static3D(scale,scale,scale) );
+        mCrawlEffects.move( new Static3D(-crawlW/2,0,0) );
         
-        mBackground = mRoot.attach(mCrawlBackgroundTexture,mCrawlBackgroundQueue,mQuad);
-        mBackground.attach(mCrawlTexture,mCrawlQueue,mQuad);
-        mCrawlQueue.registerForMessages(this);
+        mBackground = mRoot.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects,mQuad);
+        mBackground.attach(mCrawlTexture, mCrawlEffects,mQuad);
+        mCrawlEffects.registerForMessages(this);
         }
       else if( objectID==crawlID )
         {
         mRoot.detach(mBackground);
-        mBackground.detach(mCrawlQueue);
-        mCrawlQueue.abortAllEffects();
+        mBackground.detach(mCrawlEffects);
+        mCrawlEffects.abortAllEffects();
         mCrawlTexture.markForDeletion();
-        mCrawlBackgroundQueue.abortAllEffects();
+        mCrawlBackgroundEffects.abortAllEffects();
         mCrawlBackgroundTexture.markForDeletion();
         }
       }
diff --git a/src/main/java/org/distorted/examples/wind/WindRenderer.java b/src/main/java/org/distorted/examples/wind/WindRenderer.java
index 4b45050..5f7a565 100644
--- a/src/main/java/org/distorted/examples/wind/WindRenderer.java
+++ b/src/main/java/org/distorted/examples/wind/WindRenderer.java
@@ -26,6 +26,7 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.GridCubes;
 import org.distorted.library.DistortedEffectQueues;
 import org.distorted.library.DistortedTexture;
@@ -43,10 +44,11 @@ import javax.microedition.khronos.opengles.GL10;
 class WindRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
-   private DistortedEffectQueues mQueues;
+   private DistortedEffectQueues mEffects;
    private DistortedTexture mTexture;
+   private DistortedFramebuffer mScreen;
    private GridCubes mGrid;
-   private WindEffectsManager mEffects;
+   private WindEffectsManager mManager;
    private int mObjWidth, mObjHeight;
    private int mWind;
 
@@ -57,9 +59,10 @@ class WindRenderer implements GLSurfaceView.Renderer
       mView = view;
 
       mGrid    = new GridCubes(50,30,false);
-      mQueues  = new DistortedEffectQueues();
+      mEffects = new DistortedEffectQueues();
       mTexture = new DistortedTexture(50,30);
-      mEffects = new WindEffectsManager(mTexture);
+      mManager = new WindEffectsManager(mTexture);
+      mScreen  = new DistortedFramebuffer(0);
 
       mObjWidth = mTexture.getWidth();
       mObjHeight= mTexture.getHeight();
@@ -70,7 +73,7 @@ class WindRenderer implements GLSurfaceView.Renderer
    void setWind(int wind)
       {
       mWind = wind;
-      mEffects.setWind(mWind);
+      mManager.setWind(mWind);
       }
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -78,29 +81,27 @@ class WindRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mQueues.draw(System.currentTimeMillis(),mTexture, mGrid);
+      mEffects.draw(System.currentTimeMillis(),mTexture, mGrid,mScreen);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      mQueues.abortAllEffects();
+      mEffects.abortAllEffects();
 
       float factor = ( (float)(width<height? width:height) )/(mObjHeight + 1.4f*mObjWidth);
 
-      mQueues.move( new Static3D( factor*mObjHeight*0.58f , factor*mObjHeight*0.08f , 0) );
-      mQueues.scale(factor);
+      mEffects.move( new Static3D( factor*mObjHeight*0.58f , factor*mObjHeight*0.08f , 0) );
+      mEffects.scale(factor);
 
       Static1D angle = new Static1D(-45);
       Static3D axis  = new Static3D(0,0,1);
       Static3D center= new Static3D(0,mObjHeight/2,0);
 
-      mQueues.rotate(angle, axis, center);
-
-      mEffects.apply(mQueues,mWind);
-
-      Distorted.onSurfaceChanged(width, height);
+      mEffects.rotate(angle, axis, center);
+      mManager.apply(mEffects,mWind);
+      mScreen.resize(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
