commit b24e4719a81c2144a9aeb52331bb946ee0a3f445
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Jan 2 15:57:54 2019 +0000

    Make the Fragment effects truly 3D: change their 4D 'region' into a 3D 'center' (a point in 3D) and 3D 'region' (which is now a set of 3 radii defining an ellipsoid around the center)
    
    Also corresponding changes to the applications.

diff --git a/src/main/java/org/distorted/library/effect/Effect.java b/src/main/java/org/distorted/library/effect/Effect.java
index 1e08a70..e6b7276 100644
--- a/src/main/java/org/distorted/library/effect/Effect.java
+++ b/src/main/java/org/distorted/library/effect/Effect.java
@@ -32,8 +32,8 @@ public abstract class Effect
   private final EffectType mType;
   private final EffectName mName;
   private final int mDimension;
-  private final boolean mSupportsR;
-  private final boolean mSupportsC;
+  private final int mRegionDim;
+  private final int mCenterDim;
 
   private static long mNextID = 0;
 
@@ -53,9 +53,9 @@ public abstract class Effect
     {
     mName      = name;
     mType      = name.getType();
-    mDimension = name.getDimension();
-    mSupportsC = name.supportsCenter();
-    mSupportsR = name.supportsRegion();
+    mDimension = name.getEffectDimension();
+    mCenterDim = name.getCenterDimension();
+    mRegionDim = name.getRegionDimension();
 
     int n = name.ordinal();
     float[] u = name.getUnity();
@@ -167,27 +167,27 @@ public abstract class Effect
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Does this effect have a Center?
+ * Return the dimension of the Center supported by this effect (0- no center supported at all).
  */
-  public boolean supportsCenter()
+  public int getCenterDimension()
     {
-    return mSupportsC;
+    return mCenterDim;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Does this effect support being masked by a Region?
+ * Return the dimension of the Region supported by this effect (0- no region supported at all).
  */
-  public boolean supportsRegion()
+  public int getRegionDimension()
     {
-    return mSupportsR;
+    return mRegionDim;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Return the number of Uniforms needed to describe this effect.
  */
-  public int getDimension()
+  public int getEffectDimension()
     {
     return mDimension;
     }
diff --git a/src/main/java/org/distorted/library/effect/EffectName.java b/src/main/java/org/distorted/library/effect/EffectName.java
index b90a4e1..5754793 100644
--- a/src/main/java/org/distorted/library/effect/EffectName.java
+++ b/src/main/java/org/distorted/library/effect/EffectName.java
@@ -43,32 +43,32 @@ package org.distorted.library.effect;
 public enum EffectName
   {
   // EFFECT NAME /////// EFFECT TYPE ////////// EFFECT UNITY //////////// DIM REGION CENTER // CLASS
-  ROTATE           ( EffectType.MATRIX  ,   new float[] {0.0f}           , 4, false, true  , MatrixEffectRotate.class       ),
-  QUATERNION       ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 4, false, true  , MatrixEffectQuaternion.class   ),
-  MOVE             ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 3, false, false , MatrixEffectMove.class         ),
-  SCALE            ( EffectType.MATRIX  ,   new float[] {1.0f,1.0f,1.0f} , 3, false, false , MatrixEffectScale.class        ),
-  SHEAR            ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 3, false, true  , MatrixEffectShear.class        ),
-
-  DISTORT          ( EffectType.VERTEX  ,   new float[] {0.0f,0.0f,0.0f} , 3, true , true  , VertexEffectDistort.class      ),
-  DEFORM           ( EffectType.VERTEX  ,   new float[] {0.0f,0.0f,0.0f} , 3, true , true  , VertexEffectDeform.class       ),
-  SINK             ( EffectType.VERTEX  ,   new float[] {1.0f}           , 1, true , true  , VertexEffectSink.class         ),
-  PINCH            ( EffectType.VERTEX  ,   new float[] {1.0f}           , 2, true , true  , VertexEffectPinch.class        ),
-  SWIRL            ( EffectType.VERTEX  ,   new float[] {0.0f}           , 1, true , true  , VertexEffectSwirl.class        ),
-  WAVE             ( EffectType.VERTEX  ,   new float[] {0.0f}           , 5, true , true  , VertexEffectWave.class         ),
-
-  ALPHA            ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectAlpha.class      ),
-  SMOOTH_ALPHA     ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectAlpha.class      ),
-  CHROMA           ( EffectType.FRAGMENT,   new float[] {0.0f}           , 4, true , false , FragmentEffectChroma.class     ),
-  SMOOTH_CHROMA    ( EffectType.FRAGMENT,   new float[] {0.0f}           , 4, true , false , FragmentEffectChroma.class     ),
-  BRIGHTNESS       ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectBrightness.class ),
-  SMOOTH_BRIGHTNESS( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectBrightness.class ),
-  SATURATION       ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectSaturation.class ),
-  SMOOTH_SATURATION( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectSaturation.class ),
-  CONTRAST         ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectContrast.class   ),
-  SMOOTH_CONTRAST  ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, true , false , FragmentEffectContrast.class   ),
-
-  BLUR             ( EffectType.POSTPROCESS,new float[] {0.0f}           , 1, false, false , PostprocessEffectBlur.class    ),
-  GLOW             ( EffectType.POSTPROCESS,new float[] {0.0f}           , 5, false, false , PostprocessEffectGlow.class    );
+  ROTATE           ( EffectType.MATRIX  ,   new float[] {0.0f}           , 4, 0,     3    , MatrixEffectRotate.class       ),
+  QUATERNION       ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 4, 0,     3    , MatrixEffectQuaternion.class   ),
+  MOVE             ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 3, 0,     0    , MatrixEffectMove.class         ),
+  SCALE            ( EffectType.MATRIX  ,   new float[] {1.0f,1.0f,1.0f} , 3, 0,     0    , MatrixEffectScale.class        ),
+  SHEAR            ( EffectType.MATRIX  ,   new float[] {0.0f,0.0f,0.0f} , 3, 0,     3    , MatrixEffectShear.class        ),
+
+  DISTORT          ( EffectType.VERTEX  ,   new float[] {0.0f,0.0f,0.0f} , 3, 4 ,    3    , VertexEffectDistort.class      ),
+  DEFORM           ( EffectType.VERTEX  ,   new float[] {0.0f,0.0f,0.0f} , 3, 4 ,    3    , VertexEffectDeform.class       ),
+  SINK             ( EffectType.VERTEX  ,   new float[] {1.0f}           , 1, 4 ,    3    , VertexEffectSink.class         ),
+  PINCH            ( EffectType.VERTEX  ,   new float[] {1.0f}           , 2, 4 ,    3    , VertexEffectPinch.class        ),
+  SWIRL            ( EffectType.VERTEX  ,   new float[] {0.0f}           , 1, 4 ,    3    , VertexEffectSwirl.class        ),
+  WAVE             ( EffectType.VERTEX  ,   new float[] {0.0f}           , 5, 4 ,    3    , VertexEffectWave.class         ),
+
+  ALPHA            ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectAlpha.class      ),
+  SMOOTH_ALPHA     ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectAlpha.class      ),
+  CHROMA           ( EffectType.FRAGMENT,   new float[] {0.0f}           , 4, 3 ,    3    , FragmentEffectChroma.class     ),
+  SMOOTH_CHROMA    ( EffectType.FRAGMENT,   new float[] {0.0f}           , 4, 3 ,    3    , FragmentEffectChroma.class     ),
+  BRIGHTNESS       ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectBrightness.class ),
+  SMOOTH_BRIGHTNESS( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectBrightness.class ),
+  SATURATION       ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectSaturation.class ),
+  SMOOTH_SATURATION( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectSaturation.class ),
+  CONTRAST         ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectContrast.class   ),
+  SMOOTH_CONTRAST  ( EffectType.FRAGMENT,   new float[] {1.0f}           , 1, 3 ,    3    , FragmentEffectContrast.class   ),
+
+  BLUR             ( EffectType.POSTPROCESS,new float[] {0.0f}           , 1, 0,     0    , PostprocessEffectBlur.class    ),
+  GLOW             ( EffectType.POSTPROCESS,new float[] {0.0f}           , 5, 0,     0    , PostprocessEffectGlow.class    );
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -77,13 +77,13 @@ public enum EffectName
   private final EffectType type;
   private final float[] unity;
   private final int dimension;
-  private final boolean supportsR;
-  private final boolean supportsC;
+  private final int regionDim;
+  private final int centerDim;
   private final Class<? extends Effect> effectClass;
 
   private static final int[] dimensions;
-  private static final boolean[] supportsRegion;
-  private static final boolean[] supportsCenter;
+  private static final int[] regionDimension;
+  private static final int[] centerDimension;
   private static final EffectName[] names;  // copy the values() to a local variable so that we
                                             // don't have to keep recreating the array every time
   static
@@ -91,15 +91,15 @@ public enum EffectName
     int i=0;
 
     dimensions      = new int[LENGTH];
-    supportsRegion  = new boolean[LENGTH];
-    supportsCenter  = new boolean[LENGTH];
+    regionDimension = new int[LENGTH];
+    centerDimension = new int[LENGTH];
     names           = new EffectName[LENGTH];
 
     for(EffectName name: EffectName.values())
       {
       dimensions[i]      = name.dimension;
-      supportsRegion[i]  = name.supportsR;
-      supportsCenter[i]  = name.supportsC;
+      regionDimension[i] = name.regionDim;
+      centerDimension[i] = name.centerDim;
       names[i]           = name;
 
       i++;
@@ -115,14 +115,14 @@ public enum EffectName
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  EffectName(EffectType type, float[] unity, int dimension, boolean supportsR,
-             boolean supportsC, Class<? extends Effect> effectClass )
+  EffectName(EffectType type, float[] unity, int dimension, int regionDim,
+             int centerDim, Class<? extends Effect> effectClass )
     {
     this.type        = type;
     this.unity       = unity;
     this.dimension   = dimension;
-    this.supportsR   = supportsR;
-    this.supportsC   = supportsC;
+    this.regionDim   = regionDim;
+    this.centerDim   = centerDim;
     this.effectClass = effectClass;
     }
 
@@ -166,20 +166,20 @@ public enum EffectName
  * Returns the dimension of an Effect (in other words, the number of interpolated values).
  * @return dimension of the Effect.
  */
-  public int getDimension() { return dimensions[ordinal()]; }
+  public int getEffectDimension() { return dimensions[ordinal()]; }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Do we support being masked by a Region?
- * @return true if the Effect supports being masked with a Region.
+ * What is the dimension of the Region supported by this effect?
+ * @return Dimension of the Region supported (0-region not supported at all).
  */
-  public boolean supportsRegion() { return supportsRegion[ordinal()]; }
+  public int getRegionDimension() { return regionDimension[ordinal()]; }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Does this Effect have a center?
- * @return true if the Effect has a center.
+ * What is the dimension of the Center supported by this effect?
+ * @return Dimension of the Center supported (0-center not supported at all).
  */
-  public boolean supportsCenter() { return supportsCenter[ordinal()]; }
+  public int getCenterDimension() { return centerDimension[ordinal()]; }
   }
 
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffect.java b/src/main/java/org/distorted/library/effect/FragmentEffect.java
index 0c4eab8..88d2a61 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffect.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffect.java
@@ -26,9 +26,12 @@ package org.distorted.library.effect;
 public abstract class FragmentEffect extends Effect
   {
 /**
- * 8: 4-per effect interpolated values, 4 dimensional Region.
+ * 12: 4-per effect interpolated values, 3 dimensional Center (+padding), 3 dimensional Region (+padding).
  */
-  public static final int NUM_UNIFORMS = 8;
+  public static final int NUM_UNIFORMS = 12;
+  static final int VALUES_OFFSET = 0;
+  static final int CENTER_OFFSET = 5;
+  static final int REGION_OFFSET = 8;
   private static String mGLSL = "";
   private static int mNumEnabled = 0;
 
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffectAlpha.java b/src/main/java/org/distorted/library/effect/FragmentEffectAlpha.java
index 73c574b..8c8a69f 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffectAlpha.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffectAlpha.java
@@ -20,8 +20,8 @@
 package org.distorted.library.effect;
 
 import org.distorted.library.type.Data1D;
-import org.distorted.library.type.Data4D;
-import org.distorted.library.type.Static4D;
+import org.distorted.library.type.Data3D;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -30,7 +30,8 @@ import org.distorted.library.type.Static4D;
 public class FragmentEffectAlpha extends FragmentEffect
   {
   private Data1D mAlpha;
-  private Data4D mRegion;
+  private Data3D mCenter;
+  private Data3D mRegion;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -40,7 +41,8 @@ public class FragmentEffectAlpha extends FragmentEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mRegion.get(uniforms, index+4, currentDuration, step);
+    mCenter.get(uniforms, index+CENTER_OFFSET, currentDuration, step);
+    mRegion.get(uniforms, index+REGION_OFFSET, currentDuration, step);
     return mAlpha.get(uniforms,index, currentDuration, step);
     }
 
@@ -52,14 +54,16 @@ public class FragmentEffectAlpha extends FragmentEffect
  *
  * @param alpha  level of transparency we want to have at any given moment: pixel.a *= alpha.
  *               Valid range: <0,1>
- * @param region Region this Effect is limited to.
+ * @param center center of the Effect (point in 3D).
+ * @param region Region this Effect is limited to (3 radii defining an ellipsoid).
  * @param smooth If true, the level of 'alpha' will smoothly fade out towards the edges of the region.
  */
-  public FragmentEffectAlpha(Data1D alpha, Data4D region, boolean smooth)
+  public FragmentEffectAlpha(Data1D alpha, Data3D center, Data3D region, boolean smooth)
     {
     super(smooth? EffectName.SMOOTH_ALPHA:EffectName.ALPHA);
-    mAlpha = alpha;
-    mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
+    mAlpha  = alpha;
+    mCenter = center;
+    mRegion = (region==null ? new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE) : region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -72,8 +76,9 @@ public class FragmentEffectAlpha extends FragmentEffect
   public FragmentEffectAlpha(Data1D alpha)
     {
     super(EffectName.ALPHA);
-    mAlpha = alpha;
-    mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
+    mAlpha  = alpha;
+    mCenter = new Static3D(0,0,0);
+    mRegion = new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffectBrightness.java b/src/main/java/org/distorted/library/effect/FragmentEffectBrightness.java
index d0ec2e2..a37ba8a 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffectBrightness.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffectBrightness.java
@@ -20,8 +20,8 @@
 package org.distorted.library.effect;
 
 import org.distorted.library.type.Data1D;
-import org.distorted.library.type.Data4D;
-import org.distorted.library.type.Static4D;
+import org.distorted.library.type.Data3D;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -30,8 +30,8 @@ import org.distorted.library.type.Static4D;
 public class FragmentEffectBrightness extends FragmentEffect
   {
   private Data1D mBrightness;
-  private Data4D mRegion;
-
+  private Data3D mCenter;
+  private Data3D mRegion;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -41,7 +41,8 @@ public class FragmentEffectBrightness extends FragmentEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mRegion.get(uniforms,index+4,currentDuration,step);
+    mCenter.get(uniforms, index+CENTER_OFFSET, currentDuration, step);
+    mRegion.get(uniforms, index+REGION_OFFSET, currentDuration, step);
     return mBrightness.get(uniforms,index,currentDuration,step);
     }
 
@@ -52,14 +53,16 @@ public class FragmentEffectBrightness extends FragmentEffect
  * Makes a certain sub-region of the Object smoothly change its brightness level.
  *
  * @param brightness level of brightness we want to have at any given moment. Valid range: <0,infinity)
- * @param region     Region this Effect is limited to.
+ * @param center center of the Effect (point in 3D).
+ * @param region Region this Effect is limited to (3 radii defining an ellipsoid).
  * @param smooth     If true, the level of 'brightness' will smoothly fade out towards the edges of the region.
  */
-  public FragmentEffectBrightness(Data1D brightness, Data4D region, boolean smooth)
+  public FragmentEffectBrightness(Data1D brightness, Data3D center, Data3D region, boolean smooth)
     {
     super(smooth?EffectName.SMOOTH_BRIGHTNESS:EffectName.BRIGHTNESS);
     mBrightness = brightness;
-    mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
+    mCenter = center;
+    mRegion = (region==null ? new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE) : region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -72,7 +75,8 @@ public class FragmentEffectBrightness extends FragmentEffect
     {
     super(EffectName.BRIGHTNESS);
     mBrightness = brightness;
-    mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
+    mCenter = new Static3D(0,0,0);
+    mRegion = new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffectChroma.java b/src/main/java/org/distorted/library/effect/FragmentEffectChroma.java
index 207cd26..903261c 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffectChroma.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffectChroma.java
@@ -21,8 +21,7 @@ package org.distorted.library.effect;
 
 import org.distorted.library.type.Data1D;
 import org.distorted.library.type.Data3D;
-import org.distorted.library.type.Data4D;
-import org.distorted.library.type.Static4D;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -32,7 +31,8 @@ public class FragmentEffectChroma extends FragmentEffect
   {
   private Data1D mBlend;
   private Data3D mColor;
-  private Data4D mRegion;
+  private Data3D mCenter;
+  private Data3D mRegion;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -42,8 +42,9 @@ public class FragmentEffectChroma extends FragmentEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mRegion.get(uniforms,index+4,currentDuration,step);
     mColor.get(uniforms,index+1,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     return mBlend.get(uniforms,index,currentDuration,step);
     }
 
@@ -57,15 +58,17 @@ public class FragmentEffectChroma extends FragmentEffect
  *               pixel = (1-level)*pixel + level*color.
  *               Valid range: <0,1>
  * @param color  Color to mix. (1,0,0) is RED.
- * @param region Region this Effect is limited to.
+ * @param center center of the Effect (point in 3D).
+ * @param region Region this Effect is limited to (3 radii defining an ellipsoid).
  * @param smooth If true, the level of 'blend' will smoothly fade out towards the edges of the region.
  */
-  public FragmentEffectChroma(Data1D blend, Data3D color, Data4D region, boolean smooth)
+  public FragmentEffectChroma(Data1D blend, Data3D color, Data3D center, Data3D region, boolean smooth)
     {
     super(smooth?EffectName.SMOOTH_CHROMA:EffectName.CHROMA);
-    mBlend = blend;
-    mColor = color;
-    mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
+    mBlend  = blend;
+    mColor  = color;
+    mCenter = center;
+    mRegion = (region==null ? new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE) : region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -82,7 +85,8 @@ public class FragmentEffectChroma extends FragmentEffect
     super(EffectName.CHROMA);
     mBlend = blend;
     mColor = color;
-    mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
+    mCenter = new Static3D(0,0,0);
+    mRegion = new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffectContrast.java b/src/main/java/org/distorted/library/effect/FragmentEffectContrast.java
index 9b6eddb..88b943b 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffectContrast.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffectContrast.java
@@ -20,8 +20,8 @@
 package org.distorted.library.effect;
 
 import org.distorted.library.type.Data1D;
-import org.distorted.library.type.Data4D;
-import org.distorted.library.type.Static4D;
+import org.distorted.library.type.Data3D;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -30,7 +30,8 @@ import org.distorted.library.type.Static4D;
 public class FragmentEffectContrast extends FragmentEffect
   {
   private Data1D mContrast;
-  private Data4D mRegion;
+  private Data3D mCenter;
+  private Data3D mRegion;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -40,7 +41,8 @@ public class FragmentEffectContrast extends FragmentEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mRegion.get(uniforms,index+4,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     return mContrast.get(uniforms,index,currentDuration,step);
     }
 
@@ -51,14 +53,16 @@ public class FragmentEffectContrast extends FragmentEffect
  * Makes a certain sub-region of the Object smoothly change its contrast level.
  *
  * @param contrast level of contrast we want to have at any given moment. Valid range: <0,infinity)
- * @param region   Region this Effect is limited to.
+ * @param center center of the Effect (point in 3D).
+ * @param region Region this Effect is limited to (3 radii defining an ellipsoid).
  * @param smooth   If true, the level of 'contrast' will smoothly fade out towards the edges of the region.
  */
-  public FragmentEffectContrast(Data1D contrast, Data4D region, boolean smooth)
+  public FragmentEffectContrast(Data1D contrast, Data3D center, Data3D region, boolean smooth)
     {
     super(smooth?EffectName.SMOOTH_CONTRAST:EffectName.CONTRAST);
     mContrast = contrast;
-    mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
+    mCenter = center;
+    mRegion = (region==null ? new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE) : region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -71,7 +75,8 @@ public class FragmentEffectContrast extends FragmentEffect
     {
     super(EffectName.CONTRAST);
     mContrast = contrast;
-    mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
+    mCenter = new Static3D(0,0,0);
+    mRegion = new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/FragmentEffectSaturation.java b/src/main/java/org/distorted/library/effect/FragmentEffectSaturation.java
index d1897cf..e2a753a 100644
--- a/src/main/java/org/distorted/library/effect/FragmentEffectSaturation.java
+++ b/src/main/java/org/distorted/library/effect/FragmentEffectSaturation.java
@@ -20,8 +20,8 @@
 package org.distorted.library.effect;
 
 import org.distorted.library.type.Data1D;
-import org.distorted.library.type.Data4D;
-import org.distorted.library.type.Static4D;
+import org.distorted.library.type.Data3D;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -30,7 +30,8 @@ import org.distorted.library.type.Static4D;
 public class FragmentEffectSaturation extends FragmentEffect
   {
   private Data1D mSaturation;
-  private Data4D mRegion;
+  private Data3D mCenter;
+  private Data3D mRegion;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -40,7 +41,8 @@ public class FragmentEffectSaturation extends FragmentEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mRegion.get(uniforms,index+4,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     return mSaturation.get(uniforms,index,currentDuration,step);
     }
 
@@ -51,15 +53,17 @@ public class FragmentEffectSaturation extends FragmentEffect
  * Makes a certain sub-region of the Object smoothly change its saturation level.
  *
  * @param saturation level of saturation we want to have at any given moment. Valid range: <0,infinity)
- * @param region     Region this Effect is limited to.
+ * @param center center of the Effect (point in 3D).
+ * @param region Region this Effect is limited to (3 radii defining an ellipsoid).
  * @param smooth     If true, the level of 'saturation' will smoothly fade out towards the edges of the region.
  */
-  public FragmentEffectSaturation(Data1D saturation, Data4D region, boolean smooth)
+  public FragmentEffectSaturation(Data1D saturation, Data3D center, Data3D region, boolean smooth)
     {
     super(smooth?EffectName.SMOOTH_SATURATION:EffectName.SATURATION);
 
     mSaturation = saturation;
-    mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
+    mCenter = center;
+    mRegion = (region==null ? new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE) : region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -73,7 +77,8 @@ public class FragmentEffectSaturation extends FragmentEffect
     super(EffectName.SATURATION);
 
     mSaturation = saturation;
-    mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
+    mCenter = new Static3D(0,0,0);
+    mRegion = new Static3D(Float.MAX_VALUE,Float.MAX_VALUE, Float.MAX_VALUE);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/effect/VertexEffect.java b/src/main/java/org/distorted/library/effect/VertexEffect.java
index c8bb053..7c07faa 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffect.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffect.java
@@ -29,6 +29,9 @@ public abstract class VertexEffect extends Effect
  * 12: 5 per-effect interpolated values, 3-dimensional center, 4-dimensional Region
  */
   public static final int NUM_UNIFORMS = 12;
+  static final int VALUES_OFFSET = 0;
+  static final int CENTER_OFFSET = 5;
+  static final int REGION_OFFSET = 8;
   private static String mGLSL = "";
   private static int mNumEnabled = 0;
 
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectDeform.java b/src/main/java/org/distorted/library/effect/VertexEffectDeform.java
index c5d83e7..534fc24 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectDeform.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectDeform.java
@@ -40,11 +40,11 @@ public class VertexEffectDeform extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mVector.get(uniforms,index,currentDuration,step);
 
-    uniforms[index+9] =-uniforms[index+9];
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectDistort.java b/src/main/java/org/distorted/library/effect/VertexEffectDistort.java
index dcc3a3d..ed8e8ee 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectDistort.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectDistort.java
@@ -40,12 +40,12 @@ public class VertexEffectDistort extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mVector.get(uniforms,index,currentDuration,step);
 
     uniforms[index+1] =-uniforms[index+1];
-    uniforms[index+9] =-uniforms[index+9];
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectPinch.java b/src/main/java/org/distorted/library/effect/VertexEffectPinch.java
index 0e77689..5ceb87f 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectPinch.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectPinch.java
@@ -43,12 +43,12 @@ public class VertexEffectPinch extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mPinch.get(uniforms,index,currentDuration,step);
 
     uniforms[index+1] = (float)(Math.PI*uniforms[index+1]/180);
-    uniforms[index+9] =-uniforms[index+9];
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectSink.java b/src/main/java/org/distorted/library/effect/VertexEffectSink.java
index 3c79da0..338c28a 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectSink.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectSink.java
@@ -43,11 +43,11 @@ public class VertexEffectSink extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mSink.get(uniforms,index,currentDuration,step);
 
-    uniforms[index+9] =-uniforms[index+9];
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectSwirl.java b/src/main/java/org/distorted/library/effect/VertexEffectSwirl.java
index 788641f..f9b172d 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectSwirl.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectSwirl.java
@@ -42,12 +42,12 @@ public class VertexEffectSwirl extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mSwirl.get(uniforms,index,currentDuration,step);
 
     uniforms[index  ] = (float)(Math.PI*uniforms[index]/180);
-    uniforms[index+9] =-uniforms[index+9];
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/effect/VertexEffectWave.java b/src/main/java/org/distorted/library/effect/VertexEffectWave.java
index 85c7cf7..fd8fcd5 100644
--- a/src/main/java/org/distorted/library/effect/VertexEffectWave.java
+++ b/src/main/java/org/distorted/library/effect/VertexEffectWave.java
@@ -42,14 +42,15 @@ public class VertexEffectWave extends VertexEffect
  */
   public boolean compute(float[] uniforms, int index, long currentDuration, long step )
     {
-    mCenter.get(uniforms,index+5,currentDuration,step);
-    mRegion.get(uniforms,index+8,currentDuration,step);
+    mCenter.get(uniforms,index+CENTER_OFFSET,currentDuration,step);
+    mRegion.get(uniforms,index+REGION_OFFSET,currentDuration,step);
     boolean ret = mWave.get(uniforms,index,currentDuration,step);
 
     uniforms[index+2] = (float)(Math.PI*uniforms[index+2]/180);
     uniforms[index+3] = (float)(Math.PI*uniforms[index+3]/180);
     uniforms[index+4] = (float)(Math.PI*uniforms[index+4]/180);
-    uniforms[index+9] =-uniforms[index+9];
+
+    uniforms[index+REGION_OFFSET+1] =-uniforms[index+REGION_OFFSET+1];  // region's y
 
     return ret;
     }
diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index d6bef07..f66454c 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -467,7 +467,7 @@ public class DistortedEffects
 
     mM.compute(currTime);
     mV.compute(currTime,halfW,halfH,halfZ);
-    mF.compute(currTime,halfW,halfH);
+    mF.compute(currTime,halfW,halfH,halfZ);
     mP.compute(currTime);
 
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
@@ -505,7 +505,7 @@ public class DistortedEffects
 
     mM.compute(currTime);
     mV.compute(currTime,halfW,halfH,halfZ);
-    mF.compute(currTime,halfW,halfH);
+    mF.compute(currTime,halfW,halfH,halfZ);
     mP.compute(currTime);
 
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
diff --git a/src/main/java/org/distorted/library/main/EffectQueueFragment.java b/src/main/java/org/distorted/library/main/EffectQueueFragment.java
index f77eed5..96bc0e6 100644
--- a/src/main/java/org/distorted/library/main/EffectQueueFragment.java
+++ b/src/main/java/org/distorted/library/main/EffectQueueFragment.java
@@ -55,7 +55,7 @@ class EffectQueueFragment extends EffectQueue
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  void compute(long currTime,float halfX, float halfY)
+  void compute(long currTime,float halfX, float halfY, float halfZ)
     { 
     if( currTime==mTime ) return;
     if( mTime==0 ) mTime = currTime;
@@ -78,8 +78,9 @@ class EffectQueueFragment extends EffectQueue
           }
         }
 
-      mUniforms[NUM_UNIFORMS*i+4] = mUniforms[NUM_UNIFORMS*i+4]-halfX;
-      mUniforms[NUM_UNIFORMS*i+5] =-mUniforms[NUM_UNIFORMS*i+5]+halfY;
+      mUniforms[NUM_UNIFORMS*i+5] = mUniforms[NUM_UNIFORMS*i+5]-halfX;
+      mUniforms[NUM_UNIFORMS*i+6] =-mUniforms[NUM_UNIFORMS*i+6]+halfY;
+      mUniforms[NUM_UNIFORMS*i+7] =-mUniforms[NUM_UNIFORMS*i+7]+halfZ;
       }
 
     mTime = currTime;  
diff --git a/src/main/res/raw/main_fragment_shader.glsl b/src/main/res/raw/main_fragment_shader.glsl
index 91c480c..4809b6e 100644
--- a/src/main/res/raw/main_fragment_shader.glsl
+++ b/src/main/res/raw/main_fragment_shader.glsl
@@ -47,8 +47,9 @@ layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints
 #if NUM_FRAGMENT>0
 uniform int fNumEffects;                // total number of fragment effects
 uniform int fName[NUM_FRAGMENT];        // their namess.
-uniform vec4 fUniforms[2*NUM_FRAGMENT]; // i-th effect is 2 consecutive vec4's: [2*i], [2*i+1]. First vec4 is the Interpolated values,
-                                        // next describes the Region, i.e. area over which the effect is active.
+uniform vec4 fUniforms[3*NUM_FRAGMENT]; // i-th effect is 3 consecutive vec4's: [3*i], [3*i+1], [3*i+2].
+                                        // The first vec4 is the Interpolated values,
+                                        // second vec4: first float - cache, next 3: Center, the third - the Region.
 #endif    // NUM_FRAGMENT>0
 
 #ifdef OIT
@@ -110,18 +111,18 @@ void main()
   vec4 color = texture(u_Texture,v_TexCoordinate);
 
 #if NUM_FRAGMENT>0
-  vec2 diff;
+  vec3 diff;
   float degree;
   int effect=0;
 
   for(int i=0; i<fNumEffects; i++)
     {
-    diff   = (v_Position.xy - fUniforms[effect+1].xy)/fUniforms[effect+1].zw;
+    diff   = (v_Position - fUniforms[effect+1].yzw)/fUniforms[effect+2].xyz;
     degree = max(0.0,1.0-dot(diff,diff));
 
     // ENABLED EFFECTS WILL BE INSERTED HERE
 
-    effect+=2;
+    effect+=3;
     }
 #endif
 
