commit 687263cc0c5b65b47ada4d6c4e0e15724272e02f
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Feb 26 15:52:02 2020 +0000

    Move the 'pre-multiply mesh before applying any effects' thing from [(Xsize of texture, Ysize of texture) x Mesh's zFactor] to Effects.setStretch(sx,sy,sz)

diff --git a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
index a06e7ca..efd4157 100644
--- a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
+++ b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
@@ -68,7 +68,7 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
 
       mView = view;
       mManager = new AroundTheWorldEffectsManager();
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
       mEffects.apply(new MatrixEffectScale(mScale));
       mEffects.apply(new MatrixEffectMove(mMove));
 
@@ -136,7 +136,9 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
       mObjWidth = bitmap.getWidth();
       mObjHeight= bitmap.getHeight();
 
-      if( mTexture==null ) mTexture = new DistortedTexture(mObjWidth,mObjHeight);
+      mEffects.setStretch(mObjWidth,mObjHeight,0);
+
+      if( mTexture==null ) mTexture = new DistortedTexture();
       mTexture.setTexture(bitmap);
 
       if( mMesh==null ) mMesh = new MeshRectangles(30,30*mObjHeight/mObjWidth);
diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index 6b77219..38a9ec8 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -88,7 +88,7 @@ class BeanRenderer implements GLSurfaceView.Renderer
       mMove = new Static3D(0,0,0);
       mScale= new Static3D(1,1,1);
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
       mEffects.apply( new VertexEffectDistort(dynLeft , pointLeft , regionLeft) );
       mEffects.apply( new VertexEffectDistort(dynRight, pointRight, regionRight));
       mEffects.apply( new MatrixEffectScale(mScale) );
@@ -148,8 +148,10 @@ class BeanRenderer implements GLSurfaceView.Renderer
       
      mObjHeight = bitmap.getHeight();
      mObjWidth  = bitmap.getWidth();
-      
-     if( mTexture==null ) mTexture = new DistortedTexture(mObjWidth,mObjHeight);
+
+     mEffects.setStretch(mObjWidth,mObjHeight,0);
+
+     if( mTexture==null ) mTexture = new DistortedTexture();
      mTexture.setTexture(bitmap);
      if( mMesh==null ) mMesh = new MeshRectangles(25,25*mObjHeight/mObjWidth);
 
diff --git a/src/main/java/org/distorted/examples/blur/BlurRenderer.java b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
index cda7cfe..8004958 100644
--- a/src/main/java/org/distorted/examples/blur/BlurRenderer.java
+++ b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
@@ -78,11 +78,11 @@ class BlurRenderer implements GLSurfaceView.Renderer
       mBufferMove = new Static3D(0,0,0);
       mBufferScale= new Static3D(1,1,1);
 
-      mBufferEffects = new DistortedEffects();
+      mBufferEffects = new DistortedEffects(1);
       mBufferEffects.apply(new MatrixEffectScale(mBufferScale));
       mBufferEffects.apply(new MatrixEffectMove(mBufferMove));
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
       mEffects.apply( new PostprocessEffectBlur(radiusDyn) );
       mEffects.apply(new MatrixEffectScale(mScale));
       mEffects.apply(new MatrixEffectMove(mMove));
@@ -155,7 +155,10 @@ class BlurRenderer implements GLSurfaceView.Renderer
      mObjHeight = bitmap.getHeight();
      mObjWidth  = bitmap.getWidth();
 
-     if( mTexture==null ) mTexture = new DistortedTexture(mObjWidth,mObjHeight);
+     mEffects.setStretch(mObjWidth,mObjHeight,0);
+     mBufferEffects.setStretch(SIZE,SIZE,0);
+
+     if( mTexture==null ) mTexture = new DistortedTexture();
      mTexture.setTexture(bitmap);
 
      mScreen.detachAll();
diff --git a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
index 2c17811..ec99405 100644
--- a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
+++ b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
@@ -92,7 +92,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       diRotate.add(new Static1D(  0));
       diRotate.add(new Static1D(360));
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
 
       mEffects.apply( new MatrixEffectRotate( diRotate, new Static3D(0,0,1), mRotate) );
       mEffects.apply( new MatrixEffectScale(diScale));
@@ -142,7 +142,9 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       mObjWidth  = bitmap.getWidth();
       mRotate.set(mObjWidth/2,mObjHeight/2,0);
 
-      if( mTexture==null ) mTexture = new DistortedTexture(mObjWidth,mObjHeight);
+      mEffects.setStretch(mObjWidth,mObjHeight,0);
+
+      if( mTexture==null ) mTexture = new DistortedTexture();
       mTexture.setTexture(bitmap);
 
       mScreen.detachAll();
diff --git a/src/main/java/org/distorted/examples/check/CheckRenderer.java b/src/main/java/org/distorted/examples/check/CheckRenderer.java
index 247ef98..f727e8e 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -92,7 +92,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
       mScale  = new Static3D(1,1,1);
       mCenter = new Static3D(0,0,0);
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
       mEffects.apply(new MatrixEffectScale(mScale));
       mEffects.apply(new MatrixEffectMove(mMove));
 
@@ -181,7 +181,9 @@ class CheckRenderer implements GLSurfaceView.Renderer
       mObjHeight = bitmap.getHeight();
       mObjWidth  = bitmap.getWidth();
 
-      if( mTexture==null ) mTexture = new DistortedTexture(mObjWidth,mObjHeight);
+      mEffects.setStretch(mObjWidth,mObjHeight,0);
+
+      if( mTexture==null ) mTexture = new DistortedTexture();
       mTexture.setTexture(bitmap);
 
       if( mMesh==null ) mMesh = new MeshRectangles(30,30*mObjHeight/mObjWidth);
diff --git a/src/main/java/org/distorted/examples/deform/DeformRenderer.java b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
index f2b08e9..1311c06 100644
--- a/src/main/java/org/distorted/examples/deform/DeformRenderer.java
+++ b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
@@ -81,7 +81,7 @@ class DeformRenderer implements GLSurfaceView.Renderer , EffectListener
       { 
       mView = view;
 
-      mEffects    = new DistortedEffects();
+      mEffects    = new DistortedEffects(1);
       mRegion     = new Static4D(0,0,0,0);
       mMove       = new Static3D(0,0,0);
       mTouchPoint = new Static3D(0,0,0);
@@ -209,7 +209,9 @@ class DeformRenderer implements GLSurfaceView.Renderer , EffectListener
        stretchCanvas.drawRect(              0, h*i/NUM_LINES-1, w              , h*i/NUM_LINES+1, paint);
        }
 
-     if( mTexture==null ) mTexture = new DistortedTexture(w,h);
+     mEffects.setStretch(w,h,0);
+
+     if( mTexture==null ) mTexture = new DistortedTexture();
      mTexture.setTexture(stretchBitmap);
 
      mMove.set(scrWidth/4,scrHeight/4,0);
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index ec726d5..cd50484 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -72,7 +72,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       Static3D mPoint = new Static3D(305, 220, 0);
 
       mEffects = new DistortedEffects[NUM];
-      mEffects[0] = new DistortedEffects();
+      mEffects[0] = new DistortedEffects(1);
       for(int i=1; i<NUM; i++)
         mEffects[i] = new DistortedEffects(mEffects[0], DistortedLibrary.CLONE_VERTEX| DistortedLibrary.CLONE_FRAGMENT);
 
@@ -174,12 +174,14 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
      bmpHeight = bitmap0.getHeight();
      bmpWidth  = bitmap0.getWidth();
 
+     mEffects[0].setStretch(bmpWidth,bmpHeight,0);
+
      if( mTexture==null )
        {
        mTexture = new DistortedTexture[NUM];
 
        for(int i=0; i<NUM; i++)
-         mTexture[i] = new DistortedTexture(bmpWidth,bmpHeight);
+         mTexture[i] = new DistortedTexture();
        }
 
      mTexture[0].setTexture(bitmap0);
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index f041ced..117b383 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -83,7 +83,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
 
       mEffects = new DistortedEffects[NUM];
 
-      for(int i=0; i<NUM; i++) mEffects[i] = new DistortedEffects();
+      for(int i=0; i<NUM; i++) mEffects[i] = new DistortedEffects(1);
 
       Dynamic1D sink = new Dynamic1D(2000,0.0f);
       sink.add(new Static1D( 1));
@@ -173,8 +173,13 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
      bmpHeight = bitmap.getHeight();
      bmpWidth  = bitmap.getWidth();
 
+      for(int i=0; i<NUM; i++)
+        {
+        mEffects[i].setStretch(bmpWidth, bmpHeight, 0);
+        }
+
      if( mMesh==null ) mMesh = new MeshRectangles(30,30*bmpHeight/bmpWidth);
-     if( mTexture==null ) mTexture  = new DistortedTexture(bmpWidth,bmpHeight);
+     if( mTexture==null ) mTexture  = new DistortedTexture();
      mTexture.setTexture(bitmap);
 
      mScreen.detachAll();
diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
index 9943207..2d60945 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
@@ -61,7 +61,6 @@ class DynamicRenderer implements GLSurfaceView.Renderer
       
      mView    = v;
      mMesh    = new MeshRectangles(1,1);
-     mEffects = new DistortedEffects();
      mScreen  = new DistortedScreen();
      }
 
@@ -90,7 +89,8 @@ class DynamicRenderer implements GLSurfaceView.Renderer
      DynamicSurfaceView.setHalfWidth(texW/2);
 
      if( mTexture!=null ) mTexture.markForDeletion();
-     mTexture= new DistortedTexture(texW,texH);
+     mTexture= new DistortedTexture();
+     mEffects = new DistortedEffects(texW, texH, 0);
      mBitmap = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
      mCanvas = new Canvas(mBitmap);
 
diff --git a/src/main/java/org/distorted/examples/earth/EarthRenderer.java b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
index 823f287..3d74046 100644
--- a/src/main/java/org/distorted/examples/earth/EarthRenderer.java
+++ b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
@@ -116,11 +116,9 @@ class EarthRenderer implements GLSurfaceView.Renderer
       scale.add(mScaleFactor);
 
       mMesh     = new MeshSphere(LEVEL);
-      mTexture  = new DistortedTexture(SIZE,SIZE);
+      mTexture  = new DistortedTexture();
 
-      mObjWidth = mTexture.getWidth();
-      mObjHeight= mTexture.getHeight();
-      mObjDepth = mTexture.getDepth(mMesh);
+      mObjWidth = mObjHeight = mObjDepth = SIZE;
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
@@ -131,7 +129,7 @@ class EarthRenderer implements GLSurfaceView.Renderer
       quatInt1.add(mQuat1);
       quatInt2.add(mQuat2);
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(SIZE,SIZE,SIZE);
       mEffects.apply( new MatrixEffectQuaternion(quatInt2, mCenter) );
       mEffects.apply( new MatrixEffectQuaternion(quatInt1, mCenter) );
       mEffects.apply( new MatrixEffectScale(scale));
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
index 24e7e4d..73debf9 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
@@ -78,8 +78,8 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
     MatrixEffectScale scaleEffect = new MatrixEffectScale(mScale);
 
     mMesh = new MeshRectangles(MESH_QUALITY,MESH_QUALITY*texHeight/texWidth);
-    mTexture = new DistortedTexture(texWidth,texHeight);
-    mEffects = new DistortedEffects();
+    mTexture = new DistortedTexture();
+    mEffects = new DistortedEffects(texWidth,texHeight,0);
     mEffects.apply(scaleEffect);
 
     mScreen = new DistortedScreen();
diff --git a/src/main/java/org/distorted/examples/flag/FlagRenderer.java b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
index 503232f..f93edc2 100644
--- a/src/main/java/org/distorted/examples/flag/FlagRenderer.java
+++ b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
@@ -66,10 +66,19 @@ class FlagRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mTexture = new DistortedTexture(500,300);
+      final int GRIDX = 50;
+      final int GRIDY = 30;
+
+      final Static4D mapFB = new Static4D(0.0f,0.0f,1.0f      ,1.0f      );
+      final Static4D mapLR = new Static4D(0.0f,0.0f,1.0f/GRIDX,1.0f      );
+      final Static4D mapTB = new Static4D(0.0f,0.0f,1.0f      ,1.0f/GRIDY);
+
+      MeshCubes mesh = new MeshCubes(GRIDX,GRIDY,1, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
 
-      mObjWidth = mTexture.getWidth();
-      mObjHeight= mTexture.getHeight();
+      mTexture = new DistortedTexture();
+
+      mObjWidth = 500;
+      mObjHeight= 300;
 
       mWaveDyn = new Dynamic5D(1000,0.0f);
       mWaveSta1= new Static5D(0,0,-180,0,0);  // all other values besides the
@@ -85,7 +94,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
       Static3D waveCenter = new Static3D(mObjWidth, mObjHeight/2, 0);  // middle of the right edge
       Static4D waveRegion = new Static4D(0,0,0,mObjWidth);
 
-      DistortedEffects effects = new DistortedEffects();
+      DistortedEffects effects = new DistortedEffects(mObjWidth,mObjHeight,1);
       effects.apply( new VertexEffectWave(mWaveDyn, waveCenter, waveRegion) );
 
       mMove  = new Static3D(0,0,0);
@@ -97,15 +106,9 @@ class FlagRenderer implements GLSurfaceView.Renderer
       effects.apply( new MatrixEffectScale(mScale));
       effects.apply( new MatrixEffectMove(mMove));
 
-      final int GRIDX = 50;
-      final int GRIDY = 30;
-
-      final Static4D mapFB = new Static4D(0.0f,0.0f,1.0f      ,1.0f      );
-      final Static4D mapLR = new Static4D(0.0f,0.0f,1.0f/GRIDX,1.0f      );
-      final Static4D mapTB = new Static4D(0.0f,0.0f,1.0f      ,1.0f/GRIDY);
 
       mScreen = new DistortedScreen();
-      mScreen.attach(mTexture, effects, new MeshCubes(GRIDX,GRIDY,1, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB) );
+      mScreen.attach(mTexture, effects, mesh );
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/generic/GenericActivity2.java b/src/main/java/org/distorted/examples/generic/GenericActivity2.java
index 047bdfb..4a0aa16 100644
--- a/src/main/java/org/distorted/examples/generic/GenericActivity2.java
+++ b/src/main/java/org/distorted/examples/generic/GenericActivity2.java
@@ -80,6 +80,8 @@ public class GenericActivity2 extends AppCompatActivity
     mShowNormal = false;
     mUseOIT     = false;
 
+    mEffects= new DistortedEffects(1);
+
     int maxsize = numCols > numRows ? (numCols>numSlic ? numCols:numSlic) : (numRows>numSlic ? numRows:numSlic) ;
 
     createBitmap(maxsize, bitmapID);
@@ -98,18 +100,20 @@ public class GenericActivity2 extends AppCompatActivity
 
                 mMesh = new MeshCubes(numCols, str, numSlic, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
                 }
+              mEffects.setStretch(numCols,numRows,numSlic);
               break;
       case 1: mMesh = new MeshRectangles(numCols,numRows);
+              mEffects.setStretch(numCols,numRows,0);
               break;
       case 2: mMesh = new MeshSphere(numRows);
+              mEffects.setStretch(numRows,numRows,numRows);
               break;
       case 3: mMesh = new MeshQuad();
               break;
       }
 
     mMesh.setShowNormals(mShowNormal);
-    mTexture= new DistortedTexture(numCols,numRows);
-    mEffects= new DistortedEffects();
+    mTexture= new DistortedTexture();
 
     final View view = getLayoutInflater().inflate(R.layout.genericlayout, null);
 
@@ -204,21 +208,21 @@ public class GenericActivity2 extends AppCompatActivity
 
   public int getWidth()
     {
-    return mTexture==null ? 0: mTexture.getWidth();
+    return mEffects==null ? 0: mEffects.getStartchX();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getHeight()
     {
-    return mTexture==null ? 0: mTexture.getHeight();
+    return mEffects==null ? 0: mEffects.getStartchY();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getDepth()
     {
-    return mTexture==null ? 0: mTexture.getDepth(mMesh);
+    return mEffects==null ? 0: mEffects.getStartchZ();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/generic/GenericEffect.java b/src/main/java/org/distorted/examples/generic/GenericEffect.java
index db05766..8ded9be 100644
--- a/src/main/java/org/distorted/examples/generic/GenericEffect.java
+++ b/src/main/java/org/distorted/examples/generic/GenericEffect.java
@@ -107,7 +107,7 @@ class GenericEffect implements SeekBar.OnSeekBarChangeListener
 
     switch(mName)
       {
-      case ROTATE           : effect = new MatrixEffectRotate      (mDyn1, mDyn3, mCenterDyn); break;
+      case ROTATE           : effect = new MatrixEffectRotate      (mDyn1, mDyn3, mCenterDyn); android.util.Log.e("eff", "adding rotate with center "+mCenterSta.get0());break;
       case QUATERNION       : effect = new MatrixEffectQuaternion  (mDyn4, mCenterDyn); break;
       case MOVE             : effect = new MatrixEffectMove        (mDyn3)            ; break;
       case SCALE            : effect = new MatrixEffectScale       (mDyn3)            ; break;
diff --git a/src/main/java/org/distorted/examples/generic/GenericRenderer.java b/src/main/java/org/distorted/examples/generic/GenericRenderer.java
index e68fbe9..335f643 100644
--- a/src/main/java/org/distorted/examples/generic/GenericRenderer.java
+++ b/src/main/java/org/distorted/examples/generic/GenericRenderer.java
@@ -55,6 +55,7 @@ class GenericRenderer implements GLSurfaceView.Renderer
 
     private GLSurfaceView mView;
     private DistortedTexture mObjectTexture, mBackgroundTexture, mCenterTexture, mRegionTexture;
+    private DistortedEffects mObjectEffects,mBackgroundEffects,mCenterEffects,mRegionEffects;
     private DistortedScreen mScreen;
     private DistortedNode mCenterNode, mRegionNode;
     private int mObjWidth, mObjHeight, mObjDepth;
@@ -87,25 +88,25 @@ class GenericRenderer implements GLSurfaceView.Renderer
       mScaleBackground= new Static3D(1,1,1);
 
       mObjectTexture     = act.getTexture();
-      mBackgroundTexture = new DistortedTexture(100,100);
-      mCenterTexture     = new DistortedTexture(100,100);
-      mRegionTexture     = new DistortedTexture(100,100);
+      mBackgroundTexture = new DistortedTexture();
+      mCenterTexture     = new DistortedTexture();
+      mRegionTexture     = new DistortedTexture();
 
       mFactorObj = 1.0f;
 
-      DistortedEffects objectEffects     = act.getEffects();
-      DistortedEffects backgroundEffects = new DistortedEffects();
-      DistortedEffects centerEffects     = new DistortedEffects();
-      DistortedEffects regionEffects     = new DistortedEffects();
+      mObjectEffects     = act.getEffects();
+      mBackgroundEffects = new DistortedEffects(1);
+      mCenterEffects     = new DistortedEffects(1);
+      mRegionEffects     = new DistortedEffects(1);
 
-      MeshBase mesh    = act.getMesh();
-      MeshRectangles quad    = new MeshRectangles(1,1);
+      MeshBase mesh        = act.getMesh();
+      MeshRectangles quad  = new MeshRectangles(1,1);
 
       mFactor = mesh instanceof MeshSphere ? 1.0f : 0.7f;
 
-      mObjWidth = mObjectTexture.getWidth();
-      mObjHeight= mObjectTexture.getHeight();
-      mObjDepth = mObjectTexture.getDepth(mesh);
+      mObjWidth = act.getWidth();
+      mObjHeight= act.getHeight();
+      mObjDepth = act.getDepth();
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
@@ -114,57 +115,55 @@ class GenericRenderer implements GLSurfaceView.Renderer
       mRegionPoint= new Static3D(0,0,0);
       mRegionScalePoint = new Static3D(0,0,0);
 
-      mCenterNode = new DistortedNode(mCenterTexture, centerEffects, quad);
-      mRegionNode = new DistortedNode(mRegionTexture, regionEffects, quad);
+      mCenterNode = new DistortedNode(mCenterTexture, mCenterEffects, quad);
+      mRegionNode = new DistortedNode(mRegionTexture, mRegionEffects, quad);
 
       mScreen = new DistortedScreen();
       mScreen.setProjection(FOV, NEAR);
-      mScreen.attach(mBackgroundTexture, backgroundEffects, quad );
-      mScreen.attach(mObjectTexture    , objectEffects    , mesh );
+      mScreen.attach(mBackgroundTexture, mBackgroundEffects, quad );
+      mScreen.attach(mObjectTexture    , mObjectEffects    , mesh );
 
-      int regionSize = mRegionTexture.getWidth();
+      int regionSize = mRegionEffects.getStartchX();
       mRotateCen = new Static3D(0 ,0, 0);
 
       MatrixEffectQuaternion quat1cen = new MatrixEffectQuaternion(mQuat1, mRotateCen);
       MatrixEffectQuaternion quat2cen = new MatrixEffectQuaternion(mQuat2, mRotateCen);
       MatrixEffectMove centerMove = new MatrixEffectMove(mCenterPoint);
 
-      centerEffects.apply( new MatrixEffectScale(mScaleCenter) );
-      centerEffects.apply( centerMove );
-      centerEffects.apply( new MatrixEffectMove(mMoveCenter) );
-      centerEffects.apply(quat2cen);
-      centerEffects.apply(quat1cen);
+      mCenterEffects.apply( new MatrixEffectScale(mScaleCenter) );
+      mCenterEffects.apply( centerMove );
+      mCenterEffects.apply( new MatrixEffectMove(mMoveCenter) );
+      mCenterEffects.apply(quat2cen);
+      mCenterEffects.apply(quat1cen);
 
-      regionEffects.apply( new MatrixEffectMove(new Static3D( -regionSize*0.5f , -regionSize*0.5f , 0)) );
-      regionEffects.apply( new MatrixEffectScale(mRegionScalePoint) );
-      regionEffects.apply( new MatrixEffectMove(mRegionPoint) );
-      regionEffects.apply( centerMove );
-      regionEffects.apply( new MatrixEffectMove(mMoveRegion) );
-      regionEffects.apply(quat2cen);
-      regionEffects.apply(quat1cen);
+      mRegionEffects.apply( new MatrixEffectMove(new Static3D( -regionSize*0.5f , -regionSize*0.5f , 0)) );
+      mRegionEffects.apply( new MatrixEffectScale(mRegionScalePoint) );
+      mRegionEffects.apply( new MatrixEffectMove(mRegionPoint) );
+      mRegionEffects.apply( centerMove );
+      mRegionEffects.apply( new MatrixEffectMove(mMoveRegion) );
+      mRegionEffects.apply(quat2cen);
+      mRegionEffects.apply(quat1cen);
 
       resetMatrixEffects();
 
       // quite tricky: move the background exactly to the FAR plane! (see InternalOutputSurface.setProjection() )
-      backgroundEffects.apply(new MatrixEffectScale(mScaleBackground) );
-      backgroundEffects.apply(new MatrixEffectMove(mMoveBackground) );
+      mBackgroundEffects.apply(new MatrixEffectScale(mScaleBackground) );
+      mBackgroundEffects.apply(new MatrixEffectMove(mMoveBackground) );
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     void resetMatrixEffects()
       {
-      GenericActivity2 act = (GenericActivity2)mView.getContext();
-      DistortedEffects objectEffects= act.getEffects();
       Static3D rotateObj = new Static3D( (float)mObjWidth/2, (float)mObjHeight/2, (float)mObjDepth/2 );
 
       MatrixEffectQuaternion quat1obj = new MatrixEffectQuaternion(mQuat1,  rotateObj);
       MatrixEffectQuaternion quat2obj = new MatrixEffectQuaternion(mQuat2,  rotateObj);
 
-      objectEffects.apply(quat2obj);
-      objectEffects.apply(quat1obj);
-      objectEffects.apply( new MatrixEffectScale(mScaleObject) );
-      objectEffects.apply( new MatrixEffectMove(mMoveObject));
+      mObjectEffects.apply(quat2obj);
+      mObjectEffects.apply(quat1obj);
+      mObjectEffects.apply( new MatrixEffectScale(mScaleObject) );
+      mObjectEffects.apply( new MatrixEffectMove(mMoveObject));
 
       mQuat1.set(0,0,0,1);
       mQuat2.set(0,0,0,1);
@@ -217,7 +216,7 @@ class GenericRenderer implements GLSurfaceView.Renderer
 
     void setRegion(float x, float y, float z, float r)
       {
-      float factorReg = 2*mFactorObj*r/mRegionTexture.getWidth();
+      float factorReg = 2*mFactorObj*r/mRegionEffects.getStartchX();
       mRegionPoint.set(mFactorObj*x,mFactorObj*y, mFactorObj*z);
       mRegionScalePoint.set(factorReg,factorReg,factorReg);
       }
@@ -244,7 +243,7 @@ class GenericRenderer implements GLSurfaceView.Renderer
       mScreenMin = width<height ? width:height;
 
       float factorCen;
-      int centerSize = mCenterTexture.getWidth();
+      int centerSize = mCenterEffects.getStartchX();
 
       if( width*mObjHeight > height*mObjWidth ) // screen is more 'horizontal' than the Object
         {
@@ -268,7 +267,7 @@ class GenericRenderer implements GLSurfaceView.Renderer
       mScaleCenter.set(factorCen,factorCen,factorCen);
       mMoveRegion.set( (width -mFactorObj*mObjWidth )/2 ,(height-mFactorObj*mObjHeight)/2 , 12 );
 
-      int backgroundSize = mBackgroundTexture.getWidth();
+      int backgroundSize = mBackgroundEffects.getStartchX();
       float factorBackX = ((float)width)/backgroundSize;
       float factorBackY = ((float)height)/backgroundSize;
 
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index 4764d71..85c0093 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -115,7 +115,7 @@ class GirlRenderer implements GLSurfaceView.Renderer
       diHips.add(dMiddle);
       diHips.add(dBegin);
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
 
       mEffects.apply( new VertexEffectSink   ( diSink, pLeft , sinkRegion) );
       mEffects.apply( new VertexEffectSink   ( diSink, pRight, sinkRegion) );
@@ -210,7 +210,9 @@ class GirlRenderer implements GLSurfaceView.Renderer
      bmpHeight = bitmap.getHeight();
      bmpWidth  = bitmap.getWidth();
 
-     if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+     mEffects.setStretch(bmpWidth,bmpHeight,0);
+
+     if( mTexture==null ) mTexture = new DistortedTexture();
      mTexture.setTexture(bitmap);
 
      if( mMesh==null ) mMesh = new MeshRectangles(30,30*bmpHeight/bmpWidth);
diff --git a/src/main/java/org/distorted/examples/glow/GlowRenderer.java b/src/main/java/org/distorted/examples/glow/GlowRenderer.java
index 8239345..7656038 100644
--- a/src/main/java/org/distorted/examples/glow/GlowRenderer.java
+++ b/src/main/java/org/distorted/examples/glow/GlowRenderer.java
@@ -66,7 +66,7 @@ class GlowRenderer implements GLSurfaceView.Renderer
 
       mRootW = LEAF_SIZE;
       mRootH = LEAF_SIZE;
-      mLeaf  = new DistortedTexture(mRootW,mRootH);
+      mLeaf  = new DistortedTexture();
       mMove  = new Static3D(0,0,0);
       mScale = new Static3D(1,1,1);
       mRadius= new Static1D(25);
@@ -74,7 +74,7 @@ class GlowRenderer implements GLSurfaceView.Renderer
 
       mGlow  = new PostprocessEffectGlow(mRadius,mColor);
 
-      DistortedEffects effects = new DistortedEffects();
+      DistortedEffects effects = new DistortedEffects(mRootW,mRootH,0);
       effects.apply(new MatrixEffectScale(mScale));
       effects.apply(new MatrixEffectMove(mMove));
       effects.apply(mGlow);
diff --git a/src/main/java/org/distorted/examples/inflate/InflateActivity2.java b/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
index 517902c..543d295 100644
--- a/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
+++ b/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
@@ -54,6 +54,7 @@ public class InflateActivity2 extends Activity implements SeekBar.OnSeekBarChang
     private TextView mTextLevel;
     private DistortedTexture mTexture;
     private MeshBase mMesh;
+    private int mNumCols, mNumRows, mNumSlic;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
@@ -98,12 +99,12 @@ public class InflateActivity2 extends Activity implements SeekBar.OnSeekBarChang
 
       String str     = b.getString("string");
       int objectType = b.getInt("type");
-      int numCols    = b.getInt("cols");
-      int numRows    = b.getInt("rows");
-      int numSlic    = b.getInt("slices");
       int bitmapID   = b.getInt("bitmap");
+      mNumCols       = b.getInt("cols");
+      mNumRows       = b.getInt("rows");
+      mNumSlic       = b.getInt("slices");
 
-      int maxsize = numCols > numRows ? (numCols>numSlic ? numCols:numSlic) : (numRows>numSlic ? numRows:numSlic) ;
+      int maxsize = mNumCols > mNumRows ? (mNumCols>mNumSlic ? mNumCols:mNumSlic) : (mNumRows>mNumSlic ? mNumRows:mNumSlic) ;
 
       createBitmap(maxsize,bitmapID);
 
@@ -111,26 +112,26 @@ public class InflateActivity2 extends Activity implements SeekBar.OnSeekBarChang
         {
         case 0: if( bitmapID!=-1 )
                   {
-                  mMesh = new MeshCubes(numCols, str, numSlic);
+                  mMesh = new MeshCubes(mNumCols, str, mNumSlic);
                   }
                 else
                   {
-                  Static4D mapFB = new Static4D(0.0f,0.0f, (float)numCols/maxsize, (float)numRows/maxsize);
-                  Static4D mapLR = new Static4D(0.0f,0.0f, (float)numSlic/maxsize, (float)numRows/maxsize);
-                  Static4D mapTB = new Static4D(0.0f,0.0f, (float)numCols/maxsize, (float)numSlic/maxsize);
+                  Static4D mapFB = new Static4D(0.0f,0.0f, (float)mNumCols/maxsize, (float)mNumRows/maxsize);
+                  Static4D mapLR = new Static4D(0.0f,0.0f, (float)mNumSlic/maxsize, (float)mNumRows/maxsize);
+                  Static4D mapTB = new Static4D(0.0f,0.0f, (float)mNumCols/maxsize, (float)mNumSlic/maxsize);
 
-                  mMesh = new MeshCubes(numCols, str, numSlic, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
+                  mMesh = new MeshCubes(mNumCols, str, mNumSlic, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
                   }
                 break;
-        case 1: mMesh = new MeshRectangles(numCols,numRows);
+        case 1: mMesh = new MeshRectangles(mNumCols,mNumRows);
                 break;
-        case 2: mMesh = new MeshSphere(numRows);
+        case 2: mMesh = new MeshSphere(mNumRows);
                 break;
         case 3: mMesh = new MeshQuad();
                 break;
         }
 
-      mTexture = new DistortedTexture(numCols,numRows);
+      mTexture = new DistortedTexture();
 
       setContentView(R.layout.inflatelayout);
 
@@ -263,4 +264,25 @@ public class InflateActivity2 extends Activity implements SeekBar.OnSeekBarChang
       {
       return mMesh;
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getNumCols()
+      {
+      return mNumCols;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getNumRows()
+      {
+      return mNumRows;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getNumSlic()
+      {
+      return mNumSlic;
+      }
 }
diff --git a/src/main/java/org/distorted/examples/inflate/InflateRenderer.java b/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
index 0173692..5b1eeba 100644
--- a/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
+++ b/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
@@ -72,11 +72,11 @@ class InflateRenderer implements GLSurfaceView.Renderer
       InflateActivity2 act = (InflateActivity2)v.getContext();
 
       mTexture = act.getTexture();
-      mMesh = act.getMesh();
+      mMesh    = act.getMesh();
 
-      mObjWidth = mTexture.getWidth();
-      mObjHeight= mTexture.getHeight();
-      mObjDepth = mTexture.getDepth(mMesh);
+      mObjWidth = act.getNumCols();
+      mObjHeight= act.getNumRows();
+      mObjDepth = act.getNumSlic();
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
@@ -87,7 +87,7 @@ class InflateRenderer implements GLSurfaceView.Renderer
       quatInt1.add(mQuat1);
       quatInt2.add(mQuat2);
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(mObjWidth,mObjHeight,mObjDepth);
       mEffects.apply( new MatrixEffectQuaternion(quatInt2, mCenter) );
       mEffects.apply( new MatrixEffectQuaternion(quatInt1, mCenter) );
       mEffects.apply( new MatrixEffectScale(mScale));
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index 103595d..c033e37 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -66,14 +66,12 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
    ListenerRenderer(GLSurfaceView v)
       {
       mView = v;
-      mEffects = new DistortedEffects();
+
       mScreen = new DistortedScreen();
       mRnd = new Random(0);
 
       mMove = new Static3D(0,0,0);
       mScale= new Static3D(1,1,1);
-      mEffects.apply(new MatrixEffectScale(mScale));
-      mEffects.apply(new MatrixEffectMove(mMove));
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -162,11 +160,18 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
      bmpHeight = bitmap.getHeight();
      bmpWidth  = bitmap.getWidth();
 
-     if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+     if( mTexture==null ) mTexture = new DistortedTexture();
      mTexture.setTexture(bitmap);
 
      if( mMesh==null ) mMesh = new MeshRectangles(50,50*bmpHeight/bmpWidth);
 
+     if( mEffects==null )
+       {
+       mEffects = new DistortedEffects(bmpWidth,bmpHeight,0);
+       mEffects.apply(new MatrixEffectScale(mScale));
+       mEffects.apply(new MatrixEffectMove(mMove));
+       }
+
      mScreen.detachAll();
      mScreen.attach(mTexture,mEffects,mMesh);
 
diff --git a/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java b/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
index 5c553d2..0c4afce 100644
--- a/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
+++ b/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
@@ -55,7 +55,7 @@ class MirrorRenderer implements GLSurfaceView.Renderer
    private static final float MIRROR_MOVE_V    =0.22f;  // Move the mirror up
 
    private GLSurfaceView mView;
-   private DistortedEffects mEffectsMirror, mEffectsHead, mEffectsNull;
+   private DistortedEffects mEffectsMirror, mEffectsHead, mEffectsScreen;
    private DistortedEffects mEffectsOffscreen1, mEffectsOffscreen2;
    private DistortedTexture mTextureMirror, mTextureHead;
    private DistortedFramebuffer mOffScreen1, mOffScreen2;
@@ -75,11 +75,11 @@ class MirrorRenderer implements GLSurfaceView.Renderer
       mQuad    = new MeshRectangles(1,1);
       mScreen  = new DistortedScreen();
 
-      mEffectsMirror    = new DistortedEffects();
-      mEffectsHead      = new DistortedEffects();
-      mEffectsOffscreen1= new DistortedEffects();
-      mEffectsOffscreen2= new DistortedEffects();
-      mEffectsNull      = new DistortedEffects();
+      mEffectsMirror    = new DistortedEffects(1);
+      mEffectsHead      = new DistortedEffects(1);
+      mEffectsOffscreen1= new DistortedEffects(1);
+      mEffectsOffscreen2= new DistortedEffects(1);
+      mEffectsScreen    = new DistortedEffects(1);
 
       mX = MirrorActivity.INIT_POSITION;
 
@@ -138,8 +138,17 @@ class MirrorRenderer implements GLSurfaceView.Renderer
         if( mOffScreen1!=null ) mOffScreen1.markForDeletion();
         if( mOffScreen2!=null ) mOffScreen2.markForDeletion();
 
-        mOffScreen1 = new DistortedFramebuffer(                     mScreenW,                     mScreenH, 1, DistortedFramebuffer.NO_DEPTH_NO_STENCIL );
-        mOffScreen2 = new DistortedFramebuffer( (int)(MIRROR_SCALE*mScreenW), (int)(MIRROR_SCALE*mScreenH), 1, DistortedFramebuffer.NO_DEPTH_NO_STENCIL );
+        int offscreen1W = mScreenW;
+        int offscreen1H = mScreenH;
+        int offscreen2W = (int)(MIRROR_SCALE*mScreenW);
+        int offscreen2H = (int)(MIRROR_SCALE*mScreenH);
+
+        mEffectsOffscreen1.setStretch(offscreen1W, offscreen1H, 0);
+        mEffectsOffscreen2.setStretch(offscreen2W, offscreen2H, 0);
+        mEffectsScreen.setStretch(offscreen1W, offscreen1H, 0);
+
+        mOffScreen1 = new DistortedFramebuffer( offscreen1W, offscreen1H, 1, DistortedFramebuffer.NO_DEPTH_NO_STENCIL );
+        mOffScreen2 = new DistortedFramebuffer( offscreen2W, offscreen2H, 1, DistortedFramebuffer.NO_DEPTH_NO_STENCIL );
 
         mScaleMirror.set( (float)mScreenW/mMirrorW, (float)mScreenH/mMirrorH, 1.0f);
         mMoveOffscreen2.set( MIRROR_MOVE_H*mScreenW, MIRROR_MOVE_V*mScreenH*mMirrorW/mMirrorH, 0);
@@ -155,7 +164,7 @@ class MirrorRenderer implements GLSurfaceView.Renderer
         mOffScreen2.attach( mOffScreen1   , mEffectsOffscreen1, mQuad );
 
         mScreen.detachAll();
-        mScreen.attach    ( mOffScreen1   , mEffectsNull      , mQuad );
+        mScreen.attach    ( mOffScreen1   , mEffectsScreen    , mQuad );
         mScreen.resize(mScreenW,mScreenH);
         }
       }
@@ -189,8 +198,11 @@ class MirrorRenderer implements GLSurfaceView.Renderer
       mHeadW   = bitmapH.getWidth();
       mHeadH   = bitmapH.getHeight();
 
-      if( mTextureMirror==null ) mTextureMirror = new DistortedTexture(mMirrorW,mMirrorH);
-      if( mTextureHead  ==null ) mTextureHead   = new DistortedTexture(mHeadW, mHeadH);
+      mEffectsMirror.setStretch(mMirrorW,mMirrorH,0);
+      mEffectsHead.setStretch(mHeadW, mHeadH,0);
+
+      if( mTextureMirror==null ) mTextureMirror = new DistortedTexture();
+      if( mTextureHead  ==null ) mTextureHead   = new DistortedTexture();
 
       mTextureMirror.setTexture(bitmapM);
       mTextureHead.setTexture(bitmapH);
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index 26e94b1..3a8241c 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -84,7 +84,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       dRight.add( new Static3D(  0,  0, 0) );
       dRight.add( new Static3D( 20, 10, 0) );
 
-      mEffects = new DistortedEffects();
+      mEffects = new DistortedEffects(1);
       mEffects.apply( new VertexEffectDistort(dLeft , pLeft , rLeft ) );
       mEffects.apply( new VertexEffectDistort(dRight, pRight, rRight) );
 
@@ -150,10 +150,20 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
 
+      // This will make the Mesh stretched by bmpWidth x bmpHeight even before any effects
+      // are applied to it (the Mesh - MeshRectangles - is flat, so the third parameter does not
+      // not matter). bmpWight x bmpHeight is the size of the Bitmap, thus this means that we can
+      // conveniently work with Effects thinking in Bitmap's native size in pixels. The origin is
+      // in Bitmap's lower-left corner, thus e.g. a rotation which is meant to rotate the bitmap
+      // around its center has to be centered at (bmpWidth/2, bmpHeight/2, 0).
+      // Without this call, the default size of the Mesh is 1x1x0 ( or 1x1x1 in case of not-flat
+      // Meshes) so we would need to be rotating around (0.5,0.5,0.0).
+      mEffects.setStretch(bmpWidth,bmpHeight,0);
+
       // We could have gotten here after the activity went to the background
       // for a brief amount of time; in this case mTexture is already created.
       // Do not leak memory by creating it the second time around.
-      if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+      if( mTexture==null ) mTexture = new DistortedTexture();
 
       // likewise the Mesh
       if( mMesh==null ) mMesh = new MeshRectangles(9,9*bmpHeight/bmpWidth);
diff --git a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
index ccbb365..caaaf4a 100644
--- a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
@@ -65,7 +65,7 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
      mPaint.setStyle(Style.FILL);
 
      mView   = v;
-     mEffects= new DistortedEffects();
+     mEffects= new DistortedEffects(1);
      mScreen = new DistortedScreen();
      mRefresh= true;
      }
@@ -137,10 +137,12 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
      texH = height;
 
      if( mTexture!=null ) mTexture.markForDeletion();
-     mTexture = new DistortedTexture(texW,texH);
+     mTexture = new DistortedTexture();
      mBitmap  = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
      mCanvas  = new Canvas(mBitmap);
 
+     mEffects.setStretch(texW,texH,0);
+
      if( mMesh!=null ) mMesh.markForDeletion();
      mMesh = new MeshRectangles(80,80*texH/texW);
 
diff --git a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
index 0748427..ccabca9 100644
--- a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
+++ b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
@@ -76,11 +76,11 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer,EffectListener
       mRootW = 5*LEAF_SIZE;
       mRootH = 5*LEAF_SIZE;
 
-      mLeaf = new DistortedTexture(LEAF_SIZE,LEAF_SIZE);
-      DistortedTexture surface = new DistortedTexture(mRootW,mRootH);
+      mLeaf = new DistortedTexture();
+      DistortedTexture surface = new DistortedTexture();
       MeshBase mesh = new MeshRectangles(1,1);
 
-      DistortedNode root = new DistortedNode(surface, new DistortedEffects(), mesh);
+      DistortedNode root = new DistortedNode(surface, new DistortedEffects(mRootW,mRootH,0), mesh);
      
       Static3D moveVector = new Static3D(0.55f*LEAF_SIZE, (mRootH-LEAF_SIZE)/2, 0);
       Static1D chromaLevel= new Static1D(0.5f);
@@ -91,7 +91,7 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer,EffectListener
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
-        mLeafEffects[j] = new DistortedEffects();
+        mLeafEffects[j] = new DistortedEffects(LEAF_SIZE,LEAF_SIZE,0);
         mLeafEffects[j].apply(leafMove);
         mLeafEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, center) );
         mLeafEffects[j].apply( new FragmentEffectChroma(chromaLevel, new Static3D(colors[3*j],colors[3*j+1], colors[3*j+2])) );
diff --git a/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java b/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
index affcb39..51dbaab 100644
--- a/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
+++ b/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
@@ -94,7 +94,7 @@ class MultiblurRenderer implements GLSurfaceView.Renderer
       for(int i=0; i<NUM_OBJECTS; i++)
         {
         mMoveVector[i] = new Static3D(0,0,0);
-        effects[i]     = new DistortedEffects();
+        effects[i]     = new DistortedEffects(OBJ_SIZE,OBJ_SIZE,OBJ_SIZE);
         mBlurStatus[i] = false;
         }
 
@@ -102,8 +102,8 @@ class MultiblurRenderer implements GLSurfaceView.Renderer
 
       MeshCubes mesh = new MeshCubes(1,1,1);
 
-      mTex1 = new DistortedTexture(OBJ_SIZE,OBJ_SIZE);
-      mTex2 = new DistortedTexture(OBJ_SIZE,OBJ_SIZE);
+      mTex1 = new DistortedTexture();
+      mTex2 = new DistortedTexture();
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
diff --git a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
index 5bd622f..c0146ed 100644
--- a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
@@ -78,7 +78,7 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer
       chromaDyn.add(new Static1D(0.0f));
       chromaDyn.add(new Static1D(0.8f));
 
-      mEffects= new DistortedEffects();
+      mEffects= new DistortedEffects(1);
       mEffects.apply(new MatrixEffectScale(mScale));
       mEffects.apply(new MatrixEffectMove(mMove));
       mEffects.apply(new FragmentEffectChroma(chromaDyn, new Static3D(0,0,1)));
@@ -169,28 +169,30 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer
           } 
         catch(IOException e) { }
         }  
-      
+
+      final int GRID = 20;
+      final Static4D mapFB = new Static4D(0.0f,0.0f,1.0f     ,1.0f     );
+      final Static4D mapLR = new Static4D(0.0f,0.0f,1.0f/GRID,1.0f     );
+      final Static4D mapTB = new Static4D(0.0f,0.0f,1.0f     ,1.0f/GRID);
+
       lisaWidth     = bitmap1.getWidth();
       lisaHeight    = bitmap1.getHeight();
       int gridWidth = bitmap2.getWidth();
       int gridHeight= bitmap2.getHeight();
+      int gridDepth = gridWidth/GRID;
 
-      if( mLisaTexture==null ) mLisaTexture = new DistortedTexture(lisaWidth,lisaHeight);
-      if( mGridTexture==null ) mGridTexture = new DistortedTexture(gridWidth,gridHeight);
+      mEffects.setStretch(lisaWidth,lisaHeight,0);
+
+      if( mLisaTexture==null ) mLisaTexture = new DistortedTexture();
+      if( mGridTexture==null ) mGridTexture = new DistortedTexture();
       mLisaTexture.setTexture(bitmap1);
       mGridTexture.setTexture(bitmap2);
-      DistortedEffects gridEffects = new DistortedEffects();
 
-      final int GRID = 20;
-      final Static4D mapFB = new Static4D(0.0f,0.0f,1.0f     ,1.0f     );
-      final Static4D mapLR = new Static4D(0.0f,0.0f,1.0f/GRID,1.0f     );
-      final Static4D mapTB = new Static4D(0.0f,0.0f,1.0f     ,1.0f/GRID);
+      DistortedEffects gridEffects = new DistortedEffects(gridWidth,gridHeight,gridDepth);
 
       if( mMeshRectangles ==null ) mMeshRectangles = new MeshRectangles(1,1);
       if( mMeshCubes==null) mMeshCubes= new MeshCubes(GRID,GRID,1, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
 
-      int gridDepth = mGridTexture.getDepth(mMeshCubes);
-
       mRoot = new DistortedNode(mLisaTexture, mEffects, mMeshRectangles);
       mRoot.attach(mGridTexture,gridEffects,mMeshCubes);
 
diff --git a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
index bf8fb7b..6675f14 100644
--- a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
+++ b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
@@ -93,19 +93,20 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
       mPrevRendered = -1;
       mCurrRendered = -1;
 
-      mLeaf = new DistortedTexture(LEAF_SIZE,LEAF_SIZE);
-      DistortedTexture surface = new DistortedTexture(3*LEAF_SIZE,3*LEAF_SIZE);
+      mScreenW = 9*LEAF_SIZE;
+      mScreenH = 9*LEAF_SIZE;
+
+      mLeaf = new DistortedTexture();
+      DistortedTexture surface = new DistortedTexture();
       mMesh = new MeshRectangles(1,1);
       mMove = new Static3D(0,0,0);
       mScale= new Static3D(1,1,1);
 
-      DistortedEffects effects = new DistortedEffects();
-      effects.apply(new MatrixEffectScale(mScale));
-      effects.apply(new MatrixEffectMove(mMove));
+      DistortedEffects rootEffects = new DistortedEffects(mScreenW,mScreenH,0);
+      rootEffects.apply(new MatrixEffectScale(mScale));
+      rootEffects.apply(new MatrixEffectMove(mMove));
 
-      mScreenW = 9*LEAF_SIZE;
-      mScreenH = 9*LEAF_SIZE;
-      mRoot = new DistortedNode(new DistortedTexture(mScreenW,mScreenH), effects, mMesh);
+      mRoot = new DistortedNode(new DistortedTexture(), rootEffects, mMesh);
      
       Dynamic1D rot = new Dynamic1D(5000,0.0f);
       rot.setMode(Dynamic1D.MODE_JUMP);
@@ -121,14 +122,14 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
-        mEffects[j] = new DistortedEffects();
+        mEffects[j] = new DistortedEffects(LEAF_SIZE,LEAF_SIZE,0);
         mEffects[j].apply(new MatrixEffectMove(moveVector));
         mEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, center) );
         }
 
       for(int i=0; i<NUM_CIRCLES; i++)
         {
-        effects = new DistortedEffects();
+        DistortedEffects effects = new DistortedEffects(3*LEAF_SIZE,3*LEAF_SIZE,0);
         effects.apply( new MatrixEffectRotate(rot, axis, center) );
         effects.apply( new MatrixEffectMove(new Static3D(positions[2*i], positions[2*i+1], 0)) );
         effects.apply( new FragmentEffectChroma(new Static1D(0.5f), new Static3D(colors[3*i],colors[3*i+1], colors[3*i+2])) );
diff --git a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
index cee2a99..d7e35dc 100644
--- a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
+++ b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
@@ -95,7 +95,7 @@ class RenderThread extends Thread
     dRight.add( new Static3D(  0,  0, 0) );
     dRight.add( new Static3D( 20, 10, 0) );
 
-    mEffects = new DistortedEffects();
+    mEffects = new DistortedEffects(1);
     mEffects.apply( new VertexEffectDistort(dLeft , pLeft , rLeft ) );
     mEffects.apply( new VertexEffectDistort(dRight, pRight, rRight) );
 
@@ -262,7 +262,9 @@ class RenderThread extends Thread
     bmpHeight = bmp.getHeight();
     bmpWidth  = bmp.getWidth();
 
-    if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+    mEffects.setStretch(bmpWidth,bmpHeight,0);
+
+    if( mTexture==null ) mTexture = new DistortedTexture();
     mTexture.setTexture(bmp);
 
     if( mMesh==null ) mMesh = new MeshRectangles(9,9*bmpHeight/bmpWidth);
diff --git a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
index aea5d9b..061dca4 100644
--- a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
@@ -76,18 +76,18 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
       radiusDyn.add(mRadius);
       PostprocessEffectBlur blurEffect = new PostprocessEffectBlur(radiusDyn);
 
-      mLeaf = new DistortedTexture(LEAF_SIZE,LEAF_SIZE);
+      mLeaf = new DistortedTexture();
 
       MeshRectangles mesh = new MeshRectangles(1,1);
       mMove = new Static3D(0,0,0);
       mScale= new Static3D(1,1,1);
 
-      DistortedEffects rootEffects  = new DistortedEffects();
-      DistortedEffects innerEffects = new DistortedEffects();
+      DistortedEffects rootEffects  = new DistortedEffects(mScreenW,mScreenH,0);
+      DistortedEffects innerEffects = new DistortedEffects(INNER*LEAF_SIZE,INNER*LEAF_SIZE,0);
       DistortedEffects[] innerLeafEffects= new DistortedEffects[NUM_LEAVES];
       DistortedEffects[] outerLeafEffects= new DistortedEffects[NUM_LEAVES];
 
-      DistortedNode root = new DistortedNode(new DistortedTexture(mScreenW,mScreenH), rootEffects, mesh);
+      DistortedNode root = new DistortedNode(new DistortedTexture(), rootEffects, mesh);
 
       rootEffects.apply(new MatrixEffectScale(mScale));
       rootEffects.apply(new MatrixEffectMove(mMove));
@@ -107,7 +107,7 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
-        outerLeafEffects[j] = new DistortedEffects();
+        outerLeafEffects[j] = new DistortedEffects(LEAF_SIZE,LEAF_SIZE,0);
         outerLeafEffects[j].apply(new MatrixEffectMove(outerMoveVector));
         outerLeafEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, outerCenter) );
 
@@ -119,12 +119,12 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
       innerEffects.apply( new FragmentEffectChroma(new Static1D(0.5f), new Static3D(1,0,0) ) );
       innerEffects.apply(blurEffect);
 
-      DistortedNode innerNode = new DistortedNode( new DistortedTexture(INNER*LEAF_SIZE,INNER*LEAF_SIZE), innerEffects, mesh);
+      DistortedNode innerNode = new DistortedNode( new DistortedTexture(), innerEffects, mesh);
       root.attach(innerNode);
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
-        innerLeafEffects[j] = new DistortedEffects();
+        innerLeafEffects[j] = new DistortedEffects(LEAF_SIZE,LEAF_SIZE,0);
         innerLeafEffects[j].apply(new MatrixEffectMove(innerMoveVector));
         innerLeafEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, innerCenter) );
 
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
index b49c9dc..c11d72d 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
@@ -56,7 +56,7 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
    ProjectionRenderer(GLSurfaceView view)
       { 
       mView   = view;
-      mEffects= new DistortedEffects();
+      mEffects= new DistortedEffects(1);
       mScreen = new DistortedScreen();
 
       mVector = new Static3D(0,0,0);
@@ -130,11 +130,13 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
       mPoint3.set(  width/4, 3*height/4, 0);
       mPoint4.set(3*width/4, 3*height/4, 0);
 
+      mEffects.setStretch(width,height,0);
+
       // Avoid memory leaks: delete old texture if it exists (it might if we
       // got here after a brief amount of time spent in the background)
       if( mTexture!=null ) mTexture.markForDeletion();
 
-      mTexture= new DistortedTexture(width,height);
+      mTexture= new DistortedTexture();
       mTexture.setTexture(bmp);
 
       // likewise with the Mesh
diff --git a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
index da7733e..0c94f0e 100644
--- a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
+++ b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
@@ -35,7 +35,6 @@ import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
-import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshCubes;
 import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.DynamicQuat;
@@ -54,7 +53,6 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
 
   private GLSurfaceView mView;
   private DistortedTexture mTexture;
-  private MeshBase mMesh;
   private DistortedScreen mScreen;
   private Static3D mMove, mScale, mCenter;
 
@@ -63,10 +61,9 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
   QuaternionRenderer(GLSurfaceView v)
     {
     mView    = v;
-    mTexture = new DistortedTexture(1,1);
-    mMesh    = new MeshCubes(1,1,1);
+    mTexture = new DistortedTexture();
 
-    DistortedEffects effects = new DistortedEffects();
+    DistortedEffects effects = new DistortedEffects(1);
     DynamicQuat rot = new DynamicQuat();
 
     Random rnd = new Random(System.currentTimeMillis());
@@ -97,7 +94,7 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
     effects.apply( new MatrixEffectMove(mMove));
 
     mScreen = new DistortedScreen();
-    mScreen.attach(mTexture,effects,mMesh);
+    mScreen.attach(mTexture,effects,new MeshCubes(1,1,1));
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -111,14 +108,10 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
     
   public void onSurfaceChanged(GL10 glUnused, int width, int height) 
     {
-    float w = mTexture.getWidth();
-    float h = mTexture.getHeight();
-    float d = mTexture.getDepth(mMesh);
+    float factor = 0.5f*(width>height ? height:width);
 
-    float factor = 0.5f*(width>height ? height/h:width/w);
-
-    mCenter.set(w/2,h/2,d/2);
-    mMove.set( (width-factor*w)/2 , (height-factor*h)/2 , -factor*d/2 );
+    mCenter.set(0.5f,0.5f,0.5f);
+    mMove.set( (width-factor)/2 , (height-factor)/2 , -factor/2 );
     mScale.set(factor,factor,factor);
 
     mScreen.resize(width, height);
diff --git a/src/main/java/org/distorted/examples/rubik/RubikCube.java b/src/main/java/org/distorted/examples/rubik/RubikCube.java
index 3355af2..26de816 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikCube.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikCube.java
@@ -50,7 +50,7 @@ class RubikCube
     private static final int VECTZ = 2;
 
     private static final int ROTATION_MILLISEC = 1500;
-    private static final int TEXTURE_SIZE = 100;
+    private static final int STRETCH_SIZE = 100;
 
     private static final Static3D VectX = new Static3D(1,0,0);
     private static final Static3D VectY = new Static3D(0,1,0);
@@ -73,7 +73,7 @@ class RubikCube
       {
       mSize = size;
 
-      mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
+      mTexture = new DistortedTexture();
 
       mNodes          = new DistortedNode[mSize][mSize][mSize];
       mCubes          = new MeshCubes[mSize][mSize][mSize];
@@ -84,8 +84,8 @@ class RubikCube
 
       Static3D[][][] cubeVectors = new Static3D[mSize][mSize][mSize];
 
-      Static3D center = new Static3D(TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f);
-      Static4D region = new Static4D(0,0,0, TEXTURE_SIZE*0.72f);
+      Static3D center = new Static3D(STRETCH_SIZE*0.5f, STRETCH_SIZE*0.5f, STRETCH_SIZE*0.5f);
+      Static4D region = new Static4D(0,0,0, STRETCH_SIZE*0.72f);
 
       VertexEffectSink        sinkEffect = new VertexEffectSink( new Static1D(getSinkStrength()), center, region );
       MatrixEffectMove        moveEffect = new MatrixEffectMove(move);
@@ -130,7 +130,7 @@ class RubikCube
               tmpBottom= (y==       0 ? mapBottom:mapBlack);
 
               mCubes[x][y][z]           = new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
-              cubeVectors[x][y][z]      = new Static3D( TEXTURE_SIZE*(x-nc), TEXTURE_SIZE*(y-nc), TEXTURE_SIZE*(z-nc) );
+              cubeVectors[x][y][z]      = new Static3D( STRETCH_SIZE*(x-nc), STRETCH_SIZE*(y-nc), STRETCH_SIZE*(z-nc) );
               mRotationAngle[x][y][z]   = new Dynamic1D();
               mRotationAxis[x][y][z]    = new Static3D(1,0,0);
 
@@ -138,7 +138,7 @@ class RubikCube
               mRotationAngle[x][y][z].add(new Static1D(0.0f));
               mRotate[x][y][z] = new MatrixEffectRotate( mRotationAngle[x][y][z], mRotationAxis[x][y][z], center);
 
-              mEffects[x][y][z] = new DistortedEffects();
+              mEffects[x][y][z] = new DistortedEffects(STRETCH_SIZE,STRETCH_SIZE,STRETCH_SIZE);
               mEffects[x][y][z].apply( new MatrixEffectMove(cubeVectors[x][y][z]) );
               mEffects[x][y][z].apply( mRotate[x][y][z] );
               mEffects[x][y][z].apply(quatEffect);
@@ -308,9 +308,9 @@ class RubikCube
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   float getTextureSize()
+   float getStretchSize()
      {
-     return TEXTURE_SIZE;
+     return STRETCH_SIZE;
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
index 81f10a0..50181a4 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
@@ -155,7 +155,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
    private void recomputeScaleFactor(int screenWidth, int screenHeight)
      {
      float cubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
-     float texSize = mCube.getTextureSize();
+     float texSize = mCube.getStretchSize();
      float scaleFactor = cubeSizeInScreenSpace/(texSize*mCube.getSize());
 
      mMove.set( (screenWidth-scaleFactor*texSize)/2 , (screenHeight-scaleFactor*texSize)/2 , -scaleFactor*texSize/2 );
diff --git a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
index bd0db97..452c36a 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
@@ -31,18 +31,12 @@ import java.lang.ref.WeakReference;
 
 class RubikSurfaceView extends GLSurfaceView
 {
-    private WeakReference<RubikActivity> mWeakAct;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
     public RubikSurfaceView(Context context, AttributeSet attrs)
       {
       super(context,attrs);
 
       if(!isInEditMode())
         {
-        mWeakAct = new WeakReference<>( (RubikActivity)context);
-
         final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
         setEGLContextClientVersion( (configurationInfo.reqGlEsVersion>>16) >= 3 ? 3:2 );
@@ -54,7 +48,7 @@ class RubikSurfaceView extends GLSurfaceView
 
     RubikActivity getRubikActivity()
       {
-      return mWeakAct.get();
+      return (RubikActivity)getContext();
       }
 }
 
diff --git a/src/main/java/org/distorted/examples/save/SaveRenderer.java b/src/main/java/org/distorted/examples/save/SaveRenderer.java
index 62c3234..3022176 100644
--- a/src/main/java/org/distorted/examples/save/SaveRenderer.java
+++ b/src/main/java/org/distorted/examples/save/SaveRenderer.java
@@ -93,7 +93,7 @@ class SaveRenderer implements GLSurfaceView.Renderer
     mMove = new Static3D(0,0,0);
     mScaleMain = new Static3D(1,1,1);
 
-    mEffects = new DistortedEffects();
+    mEffects = new DistortedEffects(1);
     mEffects.apply( new VertexEffectSink(diSink, pLeft , sinkRegion) );
     mEffects.apply( new VertexEffectSink(diSink, pRight, sinkRegion) );
     mEffects.apply( new MatrixEffectScale(mScaleMain));
@@ -245,8 +245,10 @@ class SaveRenderer implements GLSurfaceView.Renderer
     bmpHeight = bitmap.getHeight();
     bmpWidth  = bitmap.getWidth();
 
+    mEffects.setStretch(bmpWidth,bmpHeight,0);
+
     if( mMesh==null ) mMesh = new MeshRectangles(30,30*bmpHeight/bmpWidth);
-    if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+    if( mTexture==null ) mTexture = new DistortedTexture();
     mTexture.setTexture(bitmap);
 
     if( mOffscreen==null ) mOffscreen = new DistortedFramebuffer( (int)(mScale*bmpWidth) , (int)(mScale*bmpHeight),
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 2084b51..3ea1c3e 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -65,7 +65,7 @@ class SinkRenderer implements GLSurfaceView.Renderer
     sink.add(new Static1D(1.0f));
     sink.add(new Static1D(0.2f));
 
-    mEffects = new DistortedEffects();
+    mEffects = new DistortedEffects(1);
     VertexEffectSink sinkEffect = new VertexEffectSink(sink, new Static3D(297, 280, 0), null);
     mEffects.apply(sinkEffect);
 
@@ -129,7 +129,9 @@ class SinkRenderer implements GLSurfaceView.Renderer
     bmpHeight = bitmap.getHeight();
     bmpWidth  = bitmap.getWidth();
 
-    if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
+    mEffects.setStretch(bmpWidth,bmpHeight,0);
+
+    if( mTexture==null ) mTexture = new DistortedTexture();
     mTexture.setTexture(bitmap);
     if( mMesh==null ) mMesh = new MeshRectangles(30,30*bmpHeight/bmpWidth);
 
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index 9e24c87..e4bb8fb 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -124,15 +124,15 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
 
     mQuad = new MeshRectangles(1,1);
 
-    mGFFAEffects            = new DistortedEffects();
-    mLogoEffects            = new DistortedEffects();
-    mCrawlEffects           = new DistortedEffects();
-    mCrawlBackgroundEffects = new DistortedEffects();
+    mGFFAEffects            = new DistortedEffects(1);
+    mLogoEffects            = new DistortedEffects(1);
+    mCrawlEffects           = new DistortedEffects(1);
+    mCrawlBackgroundEffects = new DistortedEffects(1);
 
     if( NUM_STARS>0 )
       {
       mStarEffects = new DistortedEffects[NUM_STARS];
-      mStarEffects[0] = new DistortedEffects();
+      mStarEffects[0] = new DistortedEffects(1);
 
       for (int i = 1; i < NUM_STARS; i++)
         mStarEffects[i] = new DistortedEffects(mStarEffects[0], DistortedLibrary.CLONE_VERTEX);
@@ -205,8 +205,10 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     double angleB = (90.0f - FOV_ANGLE/2 +CRAWL_ANGLE)*Math.PI/180;
 
     if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
-    mCrawlBackgroundTexture = new DistortedTexture(w,(int)(h*Math.sin(angleA)/Math.sin(angleB)));
-       
+    mCrawlBackgroundTexture = new DistortedTexture();
+
+    mCrawlBackgroundEffects.setStretch(w,(int)(h*Math.sin(angleA)/Math.sin(angleB)),0);
+
     int randomA, randomX, randomY, randomTime;
     float randomS, randomAlpha1, randomAlpha2;
        
@@ -238,7 +240,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       mScreen.attach(mStarTexture, mStarEffects[i], mQuad);
       }
       
-    float scale = (0.5f*w/mGFFATexture.getWidth());
+    float scale = (0.5f*w/mGFFAEffects.getStartchX());
     
     Dynamic1D di = new Dynamic1D(6000,0.5f);
     di.add(new Static1D(1.0f));
@@ -290,7 +292,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     paint.setTypeface(tf);     
  
     ///// create GFFA ///////////////////
-    if( mGFFATexture==null ) mGFFATexture  = new DistortedTexture(GFFA_WIDTH,GFFA_HEIGHT);
+    mGFFAEffects.setStretch(GFFA_WIDTH,GFFA_HEIGHT,0);
+    if( mGFFATexture==null ) mGFFATexture  = new DistortedTexture();
     bitmapGFFA = Bitmap.createBitmap(GFFA_WIDTH,GFFA_HEIGHT,Bitmap.Config.ARGB_8888);
     bitmapGFFA.eraseColor(0x00000000);
     Canvas gffaCanvas = new Canvas(bitmapGFFA);
@@ -303,11 +306,13 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mGFFATexture.setTexture(bitmapGFFA);
       
     ///// create Logo ///////////////////
-    if( mLogoTexture==null ) mLogoTexture  = new DistortedTexture(bitmapLogo.getWidth(),bitmapLogo.getHeight());
+    mLogoEffects.setStretch(bitmapLogo.getWidth(),bitmapLogo.getHeight(),0);
+    if( mLogoTexture==null ) mLogoTexture  = new DistortedTexture();
     mLogoTexture.setTexture(bitmapLogo);
 
     ///// create CRAWL //////////////////
-    if( mCrawlTexture==null ) mCrawlTexture = new DistortedTexture(CRAWL_WIDTH,CRAWL_HEIGHT);
+    mCrawlEffects.setStretch(CRAWL_WIDTH,CRAWL_HEIGHT,0);
+    if( mCrawlTexture==null ) mCrawlTexture = new DistortedTexture();
     bitmapText = Bitmap.createBitmap(CRAWL_WIDTH,CRAWL_HEIGHT,Bitmap.Config.ARGB_8888);
     bitmapText.eraseColor(0x00000000);
     Canvas textCanvas = new Canvas(bitmapText);
@@ -321,7 +326,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mCrawlTexture.setTexture(bitmapText);
       
     ///// create Stars ///////////////////
-    if( mStarTexture==null ) mStarTexture = new DistortedTexture(bitmapStar.getWidth(),bitmapStar.getHeight());
+    mStarEffects[0].setStretch(bitmapStar.getWidth(),bitmapStar.getHeight(),0);
+    if( mStarTexture==null ) mStarTexture = new DistortedTexture();
     mStarTexture.setTexture(bitmapStar);
     }
  
@@ -379,8 +385,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       int screenW=mScreen.getWidth();
       int screenH=mScreen.getHeight();
         
-      int logoW = mLogoTexture.getWidth();
-      int logoH = mLogoTexture.getHeight();
+      int logoW = mLogoEffects.getStartchX();
+      int logoH = mLogoEffects.getStartchY();
       
       int initSize= (int)(3.0f*screenW/logoW);
       int finaSize= (int)(0.1f*screenW/logoW);
@@ -403,10 +409,10 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       mScreen.detach(mLogoEffects);
       mLogoTexture.markForDeletion();
         
-      int crawlW = mCrawlTexture.getWidth();
-      int crawlH = mCrawlTexture.getHeight();
+      int crawlW = mCrawlEffects.getStartchX();
+      int crawlH = mCrawlEffects.getStartchY();
       int screenW= mScreen.getWidth();
-      int backH  = mCrawlBackgroundTexture.getHeight();
+      int backH  = mCrawlBackgroundEffects.getStartchY();
       float scale= (float)screenW/crawlW;
 
       mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,0,0)) );
diff --git a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
index 75cef07..4ac7e66 100644
--- a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
+++ b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
@@ -36,7 +36,6 @@ import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshCubes;
-import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshQuad;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Static1D;
@@ -86,22 +85,24 @@ class StencilRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      MeshBase cube = new MeshCubes(1,1,1);
-      MeshBase quad = new MeshQuad();
+      MeshCubes cube = new MeshCubes(1,1,1);
+      MeshQuad  quad = new MeshQuad();
 
       mMove       = new Static3D(0,0,0);
       mScale      = new Static3D(1,1,1);
       mRotCenter  = new Static3D(0,0,0);
       mFBOScale   = new Static3D(1,1,1);
 
-      mCubeTex   = new DistortedTexture(1,1);
-      mFloorTex  = new DistortedTexture(2,2);
-      mFBOTex    = new DistortedTexture(1,1);
+      mCubeTex   = new DistortedTexture();
+      mFloorTex  = new DistortedTexture();
+      mFBOTex    = new DistortedTexture();
 
-      DistortedEffects cube1Effects = new DistortedEffects();
-      DistortedEffects cube2Effects = new DistortedEffects();
-      DistortedEffects floorEffects = new DistortedEffects();
-      DistortedEffects FBOEffects   = new DistortedEffects();
+      DistortedEffects cube1Effects = new DistortedEffects(1);
+      DistortedEffects cube2Effects = new DistortedEffects(1);
+      DistortedEffects floorEffects = new DistortedEffects(1);
+      DistortedEffects FBOEffects   = new DistortedEffects(1);
+
+      floorEffects.setStretch(2,2,0);
 
       mCube1Node = new DistortedNode(mCubeTex , cube1Effects, cube );
       mCube2Node = new DistortedNode(mCubeTex , cube2Effects, cube );
@@ -136,11 +137,11 @@ class StencilRenderer implements GLSurfaceView.Renderer
 
       setScreen(true);
 
-      float cw = mCubeTex.getWidth();
-      float ch = mCubeTex.getHeight();
+      float cw = cube1Effects.getStartchX();
+      float ch = cube1Effects.getStartchY();
 
-      float fw = mFloorTex.getWidth();
-      float fh = mFloorTex.getHeight();
+      float fw = floorEffects.getStartchX();
+      float fh = floorEffects.getStartchY();
 
       Static3D axisX = new Static3D(1,0,0);
       Static3D axisZ = new Static3D(0,0,1);
@@ -199,14 +200,14 @@ class StencilRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      float cw = mCubeTex.getWidth();
-      float ch = mCubeTex.getHeight();
+      float cw = mCube1Node.getEffects().getStartchX();
+      float ch = mCube1Node.getEffects().getStartchY();
 
-      float fw = mFloorTex.getWidth();
-      float fh = mFloorTex.getHeight();
+      float fw = mFloorNode.getEffects().getStartchX();
+      float fh = mFloorNode.getEffects().getStartchY();
 
-      float bw = mFBOTex.getWidth();
-      float bh = mFBOTex.getHeight();
+      float bw = mFBONode.getEffects().getStartchX();
+      float bh = mFBONode.getEffects().getStartchY();
 
       float scale = 0.4f*(width>height ? height/ch:width/cw);
 
diff --git a/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java b/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
index 6424112..07d38f1 100644
--- a/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
+++ b/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
@@ -101,16 +101,15 @@ class TransparencyRenderer implements GLSurfaceView.Renderer
       MatrixEffectQuaternion quatEffect1 = new MatrixEffectQuaternion(mQuat1, mCenter);
       MatrixEffectQuaternion quatEffect2 = new MatrixEffectQuaternion(mQuat2, mCenter);
 
-
       for(int i=0; i<NUM_OBJECTS; i++)
         {
-        mTex[i]          = new DistortedTexture(OBJ_SIZE,OBJ_SIZE);
+        mTex[i]          = new DistortedTexture();
         mMoveVector[i]   = new Static3D(0,0,0);
         mAlphaVector[i]  = new Static1D(0.5f);
         mBlur[i]         = new PostprocessEffectBlur(new Static1D(0));
         mBlurApplied[i]  = true;
         alpha[i]         = new FragmentEffectAlpha(mAlphaVector[i]);
-        mEffects[i]      = new DistortedEffects();
+        mEffects[i]      = new DistortedEffects(OBJ_SIZE,OBJ_SIZE,0);
 
         mEffects[i].apply(mBlur[i]);
         mEffects[i].apply(alpha[i]);
@@ -125,7 +124,6 @@ class TransparencyRenderer implements GLSurfaceView.Renderer
         }
       }
 
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     void setPostprocess(int object, boolean doIt)
diff --git a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
index 557eb4f..83bcbd6 100644
--- a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
+++ b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
@@ -85,7 +85,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer
 
       MeshCubes mesh = new MeshCubes(1,1,1);
 
-      mTex = new DistortedTexture(OBJ_SIZE,OBJ_SIZE);
+      mTex = new DistortedTexture();
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
@@ -126,7 +126,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer
         mBlur[i]         = new PostprocessEffectBlur(mEffectVector[i]);
         mGlow[i]         = new PostprocessEffectGlow(mEffectVector[i], new Static4D(1.0f,1.0f,1.0f,0.5f) );
         chroma[i]        = new FragmentEffectChroma( new Static1D(0.3f), chromaVector[i]);
-        effects[i]       = new DistortedEffects();
+        effects[i]       = new DistortedEffects(OBJ_SIZE,OBJ_SIZE,OBJ_SIZE);
 
         effects[i].apply(mBlur[i]);
         effects[i].apply(chroma[i]);
diff --git a/src/main/java/org/distorted/examples/wind/WindEffectsManager.java b/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
index d230f6f..1cd3764 100644
--- a/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
+++ b/src/main/java/org/distorted/examples/wind/WindEffectsManager.java
@@ -57,12 +57,12 @@ class WindEffectsManager
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  WindEffectsManager(DistortedTexture texture)
+  WindEffectsManager(int width, int height)
     {
     lastTime = 0;
 
-    mHeight = texture.getHeight();
-    mWidth  = texture.getWidth();
+    mWidth = width;
+    mHeight= height;
 
     shearFactor = new Static3D(0,0,0);
     scaleFactor = new Static3D(1,1,1);
diff --git a/src/main/java/org/distorted/examples/wind/WindRenderer.java b/src/main/java/org/distorted/examples/wind/WindRenderer.java
index 31c367c..f5e2551 100644
--- a/src/main/java/org/distorted/examples/wind/WindRenderer.java
+++ b/src/main/java/org/distorted/examples/wind/WindRenderer.java
@@ -61,17 +61,18 @@ class WindRenderer implements GLSurfaceView.Renderer
       { 
       mView = view;
 
-      mTexture = new DistortedTexture(50,30);
-      mManager = new WindEffectsManager(mTexture);
+      MeshCubes cubes = new MeshCubes(50,30,1);
+      DistortedEffects effects = new DistortedEffects(50,30,1);
+
+      mTexture = new DistortedTexture();
+      mManager = new WindEffectsManager(50,30);
       mGust    = new WindGust();
       mScreen  = new DistortedScreen();
 
-      DistortedEffects effects = new DistortedEffects();
-
-      mScreen.attach(mTexture,effects,new MeshCubes(50,30,1));
+      mScreen.attach(mTexture,effects,cubes);
 
-      mObjWidth = mTexture.getWidth();
-      mObjHeight= mTexture.getHeight();
+      mObjWidth = effects.getStartchX();
+      mObjHeight= effects.getStartchY();
 
       mManager.apply(effects);
 
@@ -113,7 +114,7 @@ class WindRenderer implements GLSurfaceView.Renderer
       int min = width<height? width:height;
 
       float factor = ((float)min)/(mObjHeight + 1.4f*mObjWidth);
-      mMove.set( factor*mObjHeight*0.58f +(width-min)/2, height - factor*mObjHeight*1.08f -(height-min)/2, 0 );
+      mMove.set( factor*mObjHeight*0.58f +(width-min)*0.5f, height - factor*mObjHeight*1.08f -(height-min)*0.5f, 0 );
       mScale.set(factor,factor,factor);
       mScreen.resize(width, height);
       }
