commit 5a68329579404cb6da7c9f3011172a638b68623e
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Mar 2 23:12:06 2020 +0000

    Size of the FBO internal to Nodes is now NO MORE taken from the Mesh's stretch values.
    Instead, the size is copied from child's FBO size (if there is one) or if the child is a leaf with texture in it (which is sizeless) then we get the default 100x100 ( which means we probably have to explicitly call Node.resizeFBO() )

diff --git a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
index ea0f26d..afbc962 100644
--- a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
+++ b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
@@ -62,7 +62,6 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer,EffectListener
    private DistortedScreen mScreen;
    private DistortedEffects[] mLeafEffects = new DistortedEffects[NUM_LEAVES];
    private PostprocessEffectGlow[] mGlow = new PostprocessEffectGlow[NUM_LEAVES];
-   private int mRootW, mRootH;
    private int mGlowing;
    private Static3D mScale;
 
@@ -72,48 +71,41 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer,EffectListener
       {     
       mView = v;
 
-      mRootW = 5*LEAF_SIZE;
-      mRootH = 5*LEAF_SIZE;
-
+      MeshQuad mesh = new MeshQuad();
+      mScale= new Static3D(1,1,1);
       mLeaf = new DistortedTexture();
       DistortedTexture surface = new DistortedTexture();
 
-      MeshQuad rootMesh = new MeshQuad();
-      rootMesh.setStretch(mRootW,mRootH,0);
-      MeshQuad leafMesh = new MeshQuad();
-      leafMesh.setStretch(LEAF_SIZE,LEAF_SIZE,0);
-
-      DistortedEffects rootEffects = new DistortedEffects();
-      DistortedNode root = new DistortedNode(surface, rootEffects, rootMesh);
-
       Static3D moveVector = new Static3D(-1.45f*LEAF_SIZE, 0, 0);
       Static1D chromaLevel= new Static1D(0.5f);
       Static3D center     = new Static3D(0,0,0);
       Static3D axis       = new Static3D(0,0,1);
 
+      Dynamic1D rot = new Dynamic1D(5000,0.0f);
+      rot.setMode(Dynamic1D.MODE_JUMP);
+      rot.add(new Static1D(  0));
+      rot.add(new Static1D(360));
+
+      DistortedEffects rootEffects = new DistortedEffects();
+      rootEffects.apply(new MatrixEffectRotate(rot, axis, center) );
+      rootEffects.apply(new MatrixEffectScale(mScale));
+
+      DistortedNode root = new DistortedNode(surface, rootEffects, mesh);
+      root.resizeFBO(5*LEAF_SIZE,5*LEAF_SIZE);
+
       MatrixEffectMove leafMove = new MatrixEffectMove(moveVector);
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
         mLeafEffects[j] = new DistortedEffects();
+        mLeafEffects[j].apply( new MatrixEffectScale(LEAF_SIZE) );
         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])) );
-        DistortedNode node = new DistortedNode( mLeaf, mLeafEffects[j], leafMesh);
+        DistortedNode node = new DistortedNode( mLeaf, mLeafEffects[j], mesh);
         root.attach(node);
         }
 
-      mScale= new Static3D(1,1,1);
-
-      Dynamic1D rot = new Dynamic1D(5000,0.0f);
-      rot.setMode(Dynamic1D.MODE_JUMP);
-      rot.add(new Static1D(  0));
-      rot.add(new Static1D(360));
-
-      DistortedEffects effects = root.getEffects();
-      effects.apply(new MatrixEffectRotate(rot, axis, center) );
-      effects.apply(new MatrixEffectScale(mScale));
-
       Dynamic1D radiusDyn = new Dynamic1D(FLASH_TIME,1.0f);
       radiusDyn.add(new Static1D( 0));
       radiusDyn.add(new Static1D(50));
@@ -167,8 +159,8 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer,EffectListener
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
      {
-     float qw = (float)width /mRootW;
-     float qh = (float)height/mRootH;
+     float qw = (float)width ;
+     float qh = (float)height;
      float factor = 0.9f* (qw<qh ? qw:qh);
 
      mScale.set( factor,factor,factor );
diff --git a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
index e299c32..6865fd4 100644
--- a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
@@ -37,7 +37,7 @@ import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.mesh.MeshCubes;
-import org.distorted.library.mesh.MeshRectangles;
+import org.distorted.library.mesh.MeshQuad;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.Dynamic1D;
@@ -55,15 +55,18 @@ import android.opengl.GLSurfaceView;
 
 class ObjectTreeRenderer implements GLSurfaceView.Renderer
 {
+   private static final int NODE_FBO_SIZE = 300;
+
    private GLSurfaceView mView;
-   private DistortedEffects mEffects;
+   private DistortedEffects mEffectsNode, mEffectsGrid;
    private DistortedTexture mLisaTexture, mGridTexture;
    private DistortedScreen mScreen;
    private DistortedNode mRoot;
-   private MeshRectangles mMeshRectangles;
+   private MeshQuad mMeshQuad;
    private MeshCubes mMeshCubes;
    private boolean mDepth;
    private Static3D mScale;
+   private float mLisaAspectRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -76,9 +79,28 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer
       chromaDyn.add(new Static1D(0.0f));
       chromaDyn.add(new Static1D(0.8f));
 
-      mEffects= new DistortedEffects();
-      mEffects.apply(new MatrixEffectScale(mScale));
-      mEffects.apply(new FragmentEffectChroma(chromaDyn, new Static3D(0,0,1)));
+      mEffectsNode= new DistortedEffects();
+      mEffectsNode.apply(new MatrixEffectScale(mScale));
+      mEffectsNode.apply(new FragmentEffectChroma(chromaDyn, new Static3D(0,0,1)));
+
+      mEffectsGrid = new DistortedEffects();
+
+      float factor = NODE_FBO_SIZE/2;
+      MatrixEffectScale scale = new MatrixEffectScale( new Static3D(factor,factor,factor/10) );
+      mEffectsGrid.apply(scale);
+
+      Dynamic1D rotDyn = new Dynamic1D(12000,0.0f);
+      rotDyn.add(new Static1D(  0));
+      rotDyn.add(new Static1D(360));
+      rotDyn.setMode(Dynamic.MODE_JUMP);
+      MatrixEffectRotate rotate = new MatrixEffectRotate(rotDyn, new Static3D(1,0,0), new Static3D(0,0,0));
+      mEffectsGrid.apply(rotate);
+
+      Dynamic1D sinkDyn = new Dynamic1D(3000,0.0f);
+      sinkDyn.add(new Static1D(1.0f));
+      sinkDyn.add(new Static1D(0.3f));
+      VertexEffectSink sink = new VertexEffectSink(sinkDyn, new Static3D(0,0,0) );
+      mEffectsGrid.apply(sink);
 
       mScreen = new DistortedScreen();
       }
@@ -116,9 +138,9 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
-      float horiRatio = (float)width / mMeshRectangles.getStretchX();
-      float vertRatio = (float)height/ mMeshRectangles.getStretchY();
-      float factor    = horiRatio > vertRatio ? vertRatio : horiRatio;
+      float hor   = width /mLisaAspectRatio;
+      float ver   = height;
+      float factor= hor>ver ? ver : hor;
 
       mScale.set( factor,factor,factor );
       mScreen.resize(width, height);
@@ -128,90 +150,52 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer
     
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
-      // TODO
-      // This appears to be needed in case we create the app anew with NO DEPTH
-      // (i.e. we set 'no depth' and then rotate screen). Investigate.
-      GLES31.glEnable(GLES31.GL_CULL_FACE);
-      GLES31.glCullFace(GLES31.GL_BACK);
-      GLES31.glFrontFace(GLES31.GL_CW);
-
       Resources res = mView.getContext().getResources();
 
-      InputStream is1 = res.openRawResource(R.raw.monalisa);
-      InputStream is2 = res.openRawResource(R.raw.grid);
+      InputStream isLisa = res.openRawResource(R.raw.monalisa);
+      InputStream isGrid = res.openRawResource(R.raw.grid);
       
-      Bitmap bitmap1, bitmap2;
+      Bitmap bitmapLisa, bitmapGrid;
        
       try 
         {
-        bitmap1 = BitmapFactory.decodeStream(is1);
-        bitmap2 = BitmapFactory.decodeStream(is2);
+        bitmapLisa = BitmapFactory.decodeStream(isLisa);
+        bitmapGrid = BitmapFactory.decodeStream(isGrid);
         } 
       finally 
         {
         try 
           {
-          is1.close();
-          is2.close();
+          isLisa.close();
+          isGrid.close();
           } 
         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);
-
-      int lisaWidth = bitmap1.getWidth();
-      int lisaHeight= bitmap1.getHeight();
-      int gridWidth = bitmap2.getWidth();
-      int gridHeight= bitmap2.getHeight();
-      int gridDepth = gridWidth/GRID;
+      mLisaAspectRatio = ((float)bitmapLisa.getWidth())/bitmapLisa.getHeight();
 
       if( mLisaTexture==null ) mLisaTexture = new DistortedTexture();
       if( mGridTexture==null ) mGridTexture = new DistortedTexture();
-      mLisaTexture.setTexture(bitmap1);
-      mGridTexture.setTexture(bitmap2);
-
-      DistortedEffects gridEffects = new DistortedEffects();
+      mLisaTexture.setTexture(bitmapLisa);
+      mGridTexture.setTexture(bitmapGrid);
 
-      if( mMeshRectangles ==null )
-        {
-        mMeshRectangles = new MeshRectangles(1,1);
-        mMeshRectangles.setStretch(lisaWidth,lisaHeight,0);
-        }
+      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);
 
-      if( mMeshCubes==null)
-        {
-        mMeshCubes= new MeshCubes(GRID,GRID,1, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
-        mMeshCubes.setStretch(gridWidth,gridHeight,gridDepth);
-        }
+      if( mMeshQuad ==null ) mMeshQuad = new MeshQuad();
+      if( mMeshCubes==null ) mMeshCubes= new MeshCubes(GRID,GRID,1, mapFB, mapFB, mapLR, mapLR, mapTB, mapTB);
 
-      mRoot = new DistortedNode(mLisaTexture, mEffects, mMeshRectangles);
-      mRoot.attach(mGridTexture,gridEffects,mMeshCubes);
+      mRoot = new DistortedNode(mLisaTexture, mEffectsNode, mMeshQuad);
+      mRoot.resizeFBO(NODE_FBO_SIZE,NODE_FBO_SIZE);
+      mRoot.attach(mGridTexture, mEffectsGrid, mMeshCubes);
 
       setDepthPriv();
 
       mScreen.detachAll();
       mScreen.attach(mRoot);
 
-      float factor = lisaWidth/(2.0f*gridWidth);
-      MatrixEffectScale scale = new MatrixEffectScale( new Static3D(factor,factor,factor) );
-      gridEffects.apply(scale);
-
-      Dynamic1D rotDyn = new Dynamic1D(12000,0.0f);
-      rotDyn.add(new Static1D(  0));
-      rotDyn.add(new Static1D(360));
-      rotDyn.setMode(Dynamic.MODE_JUMP);
-      MatrixEffectRotate rotate = new MatrixEffectRotate(rotDyn, new Static3D(1,0,0), new Static3D(0,0,0));
-      gridEffects.apply(rotate);
-
-      Dynamic1D sinkDyn = new Dynamic1D(3000,0.0f);
-      sinkDyn.add(new Static1D(1.0f));
-      sinkDyn.add(new Static1D(0.3f));
-      VertexEffectSink sink = new VertexEffectSink(sinkDyn, new Static3D(0,0,0) );
-      gridEffects.apply(sink);
-
       VertexEffectSink.enable();
       FragmentEffectChroma.enable();
 
diff --git a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
index 2672274..c0236d0 100644
--- a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
+++ b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
@@ -58,7 +58,6 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
    private DistortedTexture mLeaf;
    private DistortedScreen mScreen;
    private MeshQuad mLeafMesh;
-   private int mScreenW, mScreenH;
    private int mPrevRendered, mCurrRendered;
    private Static3D mScale;
 
@@ -93,26 +92,20 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
       mPrevRendered = -1;
       mCurrRendered = -1;
 
-      mScreenW = 9*LEAF_SIZE;
-      mScreenH = 9*LEAF_SIZE;
-
       mLeaf = new DistortedTexture();
       DistortedTexture surface = new DistortedTexture();
 
       mLeafMesh = new MeshQuad();
-      mLeafMesh.setStretch(LEAF_SIZE,LEAF_SIZE,0);
-      MeshQuad circleMesh = new MeshQuad();
-      circleMesh.setStretch(3*LEAF_SIZE,3*LEAF_SIZE,0);
-      MeshQuad rootMesh = new MeshQuad();
-      rootMesh.setStretch(mScreenW,mScreenH,0);
+      MeshQuad quad = new MeshQuad();
 
       mScale= new Static3D(1,1,1);
 
       DistortedEffects rootEffects = new DistortedEffects();
       rootEffects.apply(new MatrixEffectScale(mScale));
 
-      mRoot = new DistortedNode(new DistortedTexture(), rootEffects, rootMesh);
-     
+      mRoot = new DistortedNode(new DistortedTexture(), rootEffects, quad);
+      mRoot.resizeFBO(9*LEAF_SIZE,9*LEAF_SIZE);
+
       Dynamic1D rot = new Dynamic1D(5000,0.0f);
       rot.setMode(Dynamic1D.MODE_JUMP);
       rot.add(new Static1D(  0));
@@ -132,18 +125,21 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
       for(int j=0; j<NUM_LEAVES; j++)
         {
         mEffects[j] = new DistortedEffects();
-        mEffects[j].apply(new MatrixEffectMove(moveVector));
+        mEffects[j].apply( new MatrixEffectScale(LEAF_SIZE) );
+        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++)
         {
         DistortedEffects effects = new DistortedEffects();
+        effects.apply( new MatrixEffectScale(3*LEAF_SIZE) );
         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])) );
 
-        mCircleNode[i] = new DistortedNode( surface, effects, circleMesh);
+        mCircleNode[i] = new DistortedNode( surface, effects, quad);
+        mCircleNode[i].resizeFBO(3*LEAF_SIZE, 3*LEAF_SIZE);
         mRoot.attach(mCircleNode[i]);
 
         for(int j=0; j<NUM_LEAVES; j++) mCircleNode[i].attach(mLeaf, mEffects[j], mLeafMesh);
@@ -179,8 +175,8 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
      {
-     float horiRatio = (float)width / mScreenW;
-     float vertRatio = (float)height/ mScreenH;
+     float horiRatio = (float)width ;
+     float vertRatio = (float)height;
      float factor    = horiRatio > vertRatio ? vertRatio : horiRatio;
 
      mScale.set(factor,factor,factor);
diff --git a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
index 6dc4106..f559660 100644
--- a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
@@ -55,7 +55,6 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
    private GLSurfaceView mView;
    private DistortedTexture mLeaf;
    private DistortedScreen mScreen;
-   private int mScreenW, mScreenH;
    private Static3D mScale;
    private Static1D mRadius;
 
@@ -68,31 +67,22 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
       final int OUTER = 9;
       final int INNER = 4;
 
-      mScreenW = OUTER*LEAF_SIZE;
-      mScreenH = OUTER*LEAF_SIZE;
-
       mRadius = new Static1D(5);
       Dynamic1D radiusDyn = new Dynamic1D();
       radiusDyn.add(mRadius);
       PostprocessEffectBlur blurEffect = new PostprocessEffectBlur(radiusDyn);
 
       mLeaf = new DistortedTexture();
-
-      MeshQuad rootMesh  = new MeshQuad();
-      rootMesh.setStretch(mScreenW,mScreenH,0);
-      MeshQuad innerMesh = new MeshQuad();
-      innerMesh.setStretch(INNER*LEAF_SIZE,INNER*LEAF_SIZE,0);
-      MeshQuad leafMesh  = new MeshQuad();
-      leafMesh.setStretch(LEAF_SIZE,LEAF_SIZE,0);
-
       mScale= new Static3D(1,1,1);
+      MeshQuad mesh = new MeshQuad();
 
       DistortedEffects rootEffects  = new DistortedEffects();
       DistortedEffects innerEffects = new DistortedEffects();
       DistortedEffects[] innerLeafEffects= new DistortedEffects[NUM_LEAVES];
       DistortedEffects[] outerLeafEffects= new DistortedEffects[NUM_LEAVES];
 
-      DistortedNode root = new DistortedNode(new DistortedTexture(), rootEffects, rootMesh);
+      DistortedNode root = new DistortedNode(new DistortedTexture(), rootEffects, mesh);
+      root.resizeFBO(OUTER*LEAF_SIZE,OUTER*LEAF_SIZE);
 
       rootEffects.apply(new MatrixEffectScale(mScale));
       rootEffects.apply(blurEffect);
@@ -110,26 +100,30 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
       for(int j=0; j<NUM_LEAVES; j++)
         {
         outerLeafEffects[j] = new DistortedEffects();
-        outerLeafEffects[j].apply(new MatrixEffectMove(outerMoveVector));
+        outerLeafEffects[j].apply( new MatrixEffectScale(LEAF_SIZE) );
+        outerLeafEffects[j].apply( new MatrixEffectMove(outerMoveVector));
         outerLeafEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, center) );
 
-        root.attach(mLeaf, outerLeafEffects[j], leafMesh);
+        root.attach(mLeaf, outerLeafEffects[j], mesh);
         }
 
+      innerEffects.apply( new MatrixEffectScale(INNER*LEAF_SIZE) );
       innerEffects.apply( new MatrixEffectRotate(rotate, axis, center) );
       innerEffects.apply( new FragmentEffectChroma(new Static1D(0.5f), new Static3D(1,0,0) ) );
       innerEffects.apply(blurEffect);
 
-      DistortedNode innerNode = new DistortedNode( new DistortedTexture(), innerEffects, innerMesh);
+      DistortedNode innerNode = new DistortedNode( new DistortedTexture(), innerEffects, mesh);
+      innerNode.resizeFBO(INNER*LEAF_SIZE,INNER*LEAF_SIZE);
       root.attach(innerNode);
 
       for(int j=0; j<NUM_LEAVES; j++)
         {
         innerLeafEffects[j] = new DistortedEffects();
+        innerLeafEffects[j].apply( new MatrixEffectScale(LEAF_SIZE) );
         innerLeafEffects[j].apply(new MatrixEffectMove(innerMoveVector));
         innerLeafEffects[j].apply( new MatrixEffectRotate(new Static1D(j*(360/NUM_LEAVES)), axis, center) );
 
-        innerNode.attach( mLeaf, innerLeafEffects[j], leafMesh );
+        innerNode.attach( mLeaf, innerLeafEffects[j], mesh );
         }
 
       mScreen = new DistortedScreen();
@@ -156,8 +150,8 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
      {
-     float horiRatio = (float)width / mScreenW;
-     float vertRatio = (float)height/ mScreenH;
+     float horiRatio = (float)width ;
+     float vertRatio = (float)height;
      float factor    = horiRatio > vertRatio ? vertRatio : horiRatio;
 
      mScale.set(factor,factor,factor);
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index fae53c6..d51e53e 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -110,11 +110,13 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
   private DistortedEffects[] mStarEffects;
   private DistortedNode mBackground;
   private DistortedScreen mScreen;
-  private MeshQuad mGFFAQuad, mCrawlQuad, mCrawlBackgroundQuad, mLogoQuad, mStarQuad;
+  private MeshQuad mQuad;
 
   private long alphaEffectID, scaleEffectID, moveEffectID;
   private Random mRnd = new Random(0);
   private int mWidth, mHeight;
+  private float mLogoRatio;
+  private int mCrawlBackgroundW, mCrawlBackgroundH;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -122,14 +124,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     {
     mView = v;
 
-    mGFFAQuad            = new MeshQuad();
-    mStarQuad            = new MeshQuad();
-    mCrawlQuad           = new MeshQuad();
-    mCrawlBackgroundQuad = new MeshQuad();
-    mLogoQuad            = new MeshQuad();
-
-    mGFFAQuad.setStretch(GFFA_WIDTH,GFFA_HEIGHT,0);
-    mCrawlQuad.setStretch(CRAWL_WIDTH,CRAWL_HEIGHT,0);
+    mQuad = new MeshQuad();
 
     mGFFAEffects            = new DistortedEffects();
     mLogoEffects            = new DistortedEffects();
@@ -214,7 +209,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
     mCrawlBackgroundTexture = new DistortedTexture();
 
-    mCrawlBackgroundQuad.setStretch(scrW,(int)(scrH*Math.sin(angleA)/Math.sin(angleB)),0);
+    mCrawlBackgroundW = scrW;
+    mCrawlBackgroundH = (int)(scrH*Math.sin(angleA)/Math.sin(angleB));
 
     int randomA, randomX, randomY, randomTime;
     float randomS, randomAlpha1, randomAlpha2;
@@ -227,7 +223,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       {
       randomX = mRnd.nextInt(scrW) - scrW/2;
       randomY = mRnd.nextInt(scrH) - scrH/2;
-      randomS = 0.2f+ 0.8f*mRnd.nextFloat();
+      randomS = (0.2f+ 0.8f*mRnd.nextFloat())*20;
       randomA = (int)(180*mRnd.nextFloat());
       randomAlpha1 = 0.2f + 0.8f*mRnd.nextFloat();
       randomAlpha2 = 0.8f + 0.2f*mRnd.nextFloat();
@@ -244,11 +240,9 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       
       mStarEffects[i].apply( new FragmentEffectAlpha(di) );
       
-      mScreen.attach(mStarTexture, mStarEffects[i], mStarQuad);
+      mScreen.attach(mStarTexture, mStarEffects[i], mQuad);
       }
-      
-    float scale = (0.5f*scrW/mGFFAQuad.getStretchX());
-    
+
     Dynamic1D di = new Dynamic1D(6000,0.5f);
     di.add(new Static1D(1.0f));
     di.add(new Static1D(1.0f));
@@ -258,11 +252,13 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     alpha.notifyWhenFinished(this);
     alphaEffectID = alpha.getID();
 
+    Static3D scale = new Static3D(0.5f*scrW, 0.5f*scrW * GFFA_HEIGHT / GFFA_WIDTH, 1);
+
     mGFFAEffects.apply( new MatrixEffectScale(scale) );
-    mGFFAEffects.apply( new MatrixEffectMove(new Static3D(-scrW/3 + mGFFAQuad.getStretchX()/2 ,scrH/6,0)) );
+    mGFFAEffects.apply( new MatrixEffectMove(new Static3D(-scrW/3 + GFFA_WIDTH/2 ,scrH/6,0)) );
     mGFFAEffects.apply( alpha );
       
-    mScreen.attach(mGFFATexture, mGFFAEffects, mGFFAQuad);
+    mScreen.attach(mGFFATexture, mGFFAEffects, mQuad);
     }
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -312,9 +308,9 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mGFFATexture.setTexture(bitmapGFFA);
       
     ///// create Logo ///////////////////
-    mLogoQuad.setStretch(bitmapLogo.getWidth(),bitmapLogo.getHeight(),0);
-    if( mLogoTexture==null ) mLogoTexture  = new DistortedTexture();
+    if( mLogoTexture==null ) mLogoTexture = new DistortedTexture();
     mLogoTexture.setTexture(bitmapLogo);
+    mLogoRatio = (float)bitmapLogo.getWidth()/bitmapLogo.getHeight();
 
     ///// create CRAWL //////////////////
     if( mCrawlTexture==null ) mCrawlTexture = new DistortedTexture();
@@ -331,7 +327,6 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mCrawlTexture.setTexture(bitmapText);
       
     ///// create Stars ///////////////////
-    mStarQuad.setStretch(bitmapStar.getWidth(),bitmapStar.getHeight(),0);
     if( mStarTexture==null ) mStarTexture = new DistortedTexture();
     mStarTexture.setTexture(bitmapStar);
     }
@@ -388,52 +383,47 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       mGFFATexture.markForDeletion();
 
       int screenW = mScreen.getWidth();
-      float logoW = mLogoQuad.getStretchX();
-      int initSize= (int)(3.0f*screenW/logoW);
-      int finaSize= (int)(0.1f*screenW/logoW);
+      int initSize= (int)(3.00f*screenW);
+      int finaSize= (int)(0.01f*screenW);
       
       Dynamic3D di = new Dynamic3D(10000,0.5f);
-      di.add(new Static3D(initSize,initSize,1));
-      di.add(new Static3D(finaSize,finaSize,1));
+      di.add(new Static3D(initSize,initSize/mLogoRatio,1));
+      di.add(new Static3D(finaSize,finaSize/mLogoRatio,1));
       MatrixEffectScale scale = new MatrixEffectScale(di);
       scale.notifyWhenFinished(this);
       scaleEffectID = scale.getID();
       mLogoEffects.apply( scale );
-      mScreen.attach(mLogoTexture, mLogoEffects, mLogoQuad);
+      mScreen.attach(mLogoTexture, mLogoEffects, mQuad);
       }
     else if( effectID == scaleEffectID )
       {
       mScreen.detach(mLogoEffects);
       mLogoTexture.markForDeletion();
-        
-      float crawlW = mCrawlQuad.getStretchX();
-      float crawlH = mCrawlQuad.getStretchY();
-      float screenW= mScreen.getWidth();
-      float screenH= mScreen.getHeight();
-      float backW  = mCrawlBackgroundQuad.getStretchX();
-      float backH  = mCrawlBackgroundQuad.getStretchY();
-      float scale  = backW/crawlW;
-
-      mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(0,-backH/2,0)) );
-      mCrawlBackgroundEffects.apply( new MatrixEffectMove(new Static3D( 0, (backH-screenH)/2, 0)) );
-
-      final int transpDist = 5;
-      Static3D center = new Static3D( 0, (transpDist-0.5f)*backH , 0 );
-      Static3D region = new Static3D( transpDist*backH , transpDist*backH , transpDist*backH );
+
+      float scale = mCrawlBackgroundW/CRAWL_WIDTH;
+
+      mCrawlBackgroundEffects.apply( new MatrixEffectScale( new Static3D(mCrawlBackgroundW, mCrawlBackgroundH, 1) ) );
+      mCrawlBackgroundEffects.apply( new MatrixEffectRotate(new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(0,-mCrawlBackgroundH/2,0)) );
+      mCrawlBackgroundEffects.apply( new MatrixEffectMove(new Static3D( 0, (mCrawlBackgroundH-mHeight)/2, 0)) );
+
+      final float transpDist = 5;
+      Static3D center = new Static3D( 0, transpDist-0.5f, 0 );
+      Static3D region = new Static3D( transpDist, transpDist, transpDist );
       mCrawlBackgroundEffects.apply( new FragmentEffectAlpha(new Static1D(1-transpDist*0.6f), center, region, true) );
 
       Dynamic3D di = new Dynamic3D(70000,0.5f);
-      di.add(new Static3D(0, -(scale*crawlH+backH)/2, 0));
-      di.add(new Static3D(0, +(scale*crawlH+backH)/2, 0));
+      di.add(new Static3D(0, -(scale*CRAWL_HEIGHT+mCrawlBackgroundH)/2, 0));
+      di.add(new Static3D(0, +(scale*CRAWL_HEIGHT+mCrawlBackgroundH)/2, 0));
       MatrixEffectMove move = new MatrixEffectMove(di);
       move.notifyWhenFinished(this);
       moveEffectID = move.getID();
 
-      mCrawlEffects.apply( new MatrixEffectScale(new Static3D(scale,scale,scale)) );
+      mCrawlEffects.apply( new MatrixEffectScale(new Static3D(scale*CRAWL_WIDTH,scale*CRAWL_HEIGHT,1)) );
       mCrawlEffects.apply( move );
 
-      mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects, mCrawlBackgroundQuad);
-      mBackground.attach(mCrawlTexture, mCrawlEffects, mCrawlQuad);
+      mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects, mQuad);
+      mBackground.resizeFBO(mCrawlBackgroundW,mCrawlBackgroundH);
+      mBackground.attach(mCrawlTexture, mCrawlEffects, mQuad);
       mBackground.glDisable(GLES31.GL_DEPTH_TEST);
       mBackground.glDepthMask(false);
       }
diff --git a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
index 6b46333..69aeea7 100644
--- a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
+++ b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
@@ -201,7 +201,7 @@ class StencilRenderer implements GLSurfaceView.Renderer
       mScale.set(scale,scale,scale);
       mFBOScale.set((float)width/bw, (float)height/bh, 1.0f );
 
-      mFBONode.resize(width,height);
+      mFBONode.resizeFBO(width,height);
       mScreen.resize( width,height);
       }
 
