commit 1b80a6e2f12bdf454981645e30f6d2c3d0af2a3e
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Oct 7 15:23:23 2021 +0200

    New postprocess effect 'Border' (not working yet) and adding it to the testing app 'Triblur'.

diff --git a/src/main/java/org/distorted/examples/triblur/TriblurActivity.java b/src/main/java/org/distorted/examples/triblur/TriblurActivity.java
index bf0db8f..f9ccc65 100644
--- a/src/main/java/org/distorted/examples/triblur/TriblurActivity.java
+++ b/src/main/java/org/distorted/examples/triblur/TriblurActivity.java
@@ -36,16 +36,6 @@ import org.distorted.library.main.DistortedLibrary;
 
 public class TriblurActivity extends Activity implements SeekBar.OnSeekBarChangeListener, AdapterView.OnItemSelectedListener
 {
-    private static final int NONE0 = 0;
-    private static final int NONE1 = 1;
-    private static final int NONE2 = 2;
-    private static final int BLUR0 = 3;
-    private static final int BLUR1 = 4;
-    private static final int BLUR2 = 5;
-    private static final int GLOW0 = 6;
-    private static final int GLOW1 = 7;
-    private static final int GLOW2 = 8;
-
     private int mQuality;
     private int mBackground;
 
@@ -74,28 +64,29 @@ public class TriblurActivity extends Activity implements SeekBar.OnSeekBarChange
 
         privateQuality(1);
         privateBackgroundColor(1);
-        privateEffect(BLUR0);
-        privateEffect(BLUR1);
-        privateEffect(BLUR2);
         }
 
-      Spinner typeSpinner  = findViewById(R.id.triblur_spinnerQuality);
-      typeSpinner.setOnItemSelectedListener(this);
-
       String[] objectType = new String[] {"Quality Highest", "Quality High", "Quality Medium", "Quality Low"};
+      setUpSpinner(R.id.triblur_spinnerQuality, objectType);
+      String[] renderType = new String[] {"Render: Normal", "Render: OIT" };
+      setUpSpinner(R.id.triblur_spinnerMode, renderType);
+
+      String[] effects = new String[] {"NONE", "BLUR", "GLOW", "BORDER" };
+      setUpSpinner(R.id.triblur_effect0, effects);
+      setUpSpinner(R.id.triblur_effect1, effects);
+      setUpSpinner(R.id.triblur_effect2, effects);
+      }
 
-      ArrayAdapter<String> adapterType = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, objectType);
-      adapterType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-      typeSpinner.setAdapter(adapterType);
-
-      Spinner bitmapSpinner  = findViewById(R.id.triblur_spinnerMode);
-      bitmapSpinner.setOnItemSelectedListener(this);
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      String[] objectBitmap = new String[] { "Render: Normal", "Render: OIT" };
+    private void setUpSpinner(int spinnerID, String[] options)
+      {
+      Spinner typeSpinner  = findViewById(spinnerID);
+      typeSpinner.setOnItemSelectedListener(this);
 
-      ArrayAdapter<String> adapterBitmap = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, objectBitmap);
-      adapterBitmap.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-      bitmapSpinner.setAdapter(adapterBitmap);
+      ArrayAdapter<String> adapterType = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, options);
+      adapterType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+      typeSpinner.setAdapter(adapterType);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -110,6 +101,12 @@ public class TriblurActivity extends Activity implements SeekBar.OnSeekBarChange
                                           TriblurRenderer renderer = v.getRenderer();
                                           renderer.setRenderModeToOIT(pos==1);
                                           break;
+        case R.id.triblur_effect0       : privateEffect(0,pos);
+                                          break;
+        case R.id.triblur_effect1       : privateEffect(1,pos);
+                                          break;
+        case R.id.triblur_effect2       : privateEffect(2,pos);
+                                          break;
         }
       }
 
@@ -211,49 +208,20 @@ public class TriblurActivity extends Activity implements SeekBar.OnSeekBarChange
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void onStartTrackingTouch(SeekBar bar) { }
+  public void onStartTrackingTouch(SeekBar bar) { }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void onStopTrackingTouch(SeekBar bar)  { }
+  public void onStopTrackingTouch(SeekBar bar)  { }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void effect(View v)
-    {
-    switch(v.getId())
-      {
-      case R.id.triblurRadioNone0: privateEffect(NONE0); break;
-      case R.id.triblurRadioNone1: privateEffect(NONE1); break;
-      case R.id.triblurRadioNone2: privateEffect(NONE2); break;
-      case R.id.triblurRadioBlur0: privateEffect(BLUR0); break;
-      case R.id.triblurRadioBlur1: privateEffect(BLUR1); break;
-      case R.id.triblurRadioBlur2: privateEffect(BLUR2); break;
-      case R.id.triblurRadioGlow0: privateEffect(GLOW0); break;
-      case R.id.triblurRadioGlow1: privateEffect(GLOW1); break;
-      case R.id.triblurRadioGlow2: privateEffect(GLOW2); break;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void privateEffect(int index)
+  private void privateEffect(int object, int effect)
     {
     TriblurSurfaceView view = findViewById(R.id.triblurSurfaceView);
     TriblurRenderer renderer = view.getRenderer();
 
-    switch(index)
-      {
-      case NONE0: renderer.setEffects(0,0); break;
-      case NONE1: renderer.setEffects(1,0); break;
-      case NONE2: renderer.setEffects(2,0); break;
-      case BLUR0: renderer.setEffects(0,1); break;
-      case BLUR1: renderer.setEffects(1,1); break;
-      case BLUR2: renderer.setEffects(2,1); break;
-      case GLOW0: renderer.setEffects(0,2); break;
-      case GLOW1: renderer.setEffects(1,2); break;
-      case GLOW2: renderer.setEffects(2,2); break;
-      }
+    renderer.setEffects(object,effect);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
index 1e629bd..c5353ae 100644
--- a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
+++ b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
@@ -31,6 +31,7 @@ import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.effect.PostprocessEffectBlur;
+import org.distorted.library.effect.PostprocessEffectBorder;
 import org.distorted.library.effect.PostprocessEffectGlow;
 import org.distorted.library.effect.VertexEffectScale;
 import org.distorted.library.main.DistortedLibrary;
@@ -66,15 +67,17 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     private static final int NUM_OBJECTS = OBJECTS.length/NUM;
     private static final int OBJ_SIZE    = 100;
 
-    private GLSurfaceView mView;
-    private DistortedTexture mTex;
-    private DistortedNode[] mNode;
-    private Static2D[] mEffectHaloRadius;
-    private DistortedScreen mScreen;
-    private PostprocessEffectBlur[] mBlur;
-    private PostprocessEffectGlow[] mGlow;
-    private int[] mEffectStatus;
-    private Static3D mScale1, mScale2;
+    private final GLSurfaceView mView;
+    private final DistortedTexture mTex;
+    private final DistortedNode[] mNode;
+    private final Static2D[] mEffectHaloRadius;
+    private final Static1D[] mEffectHalo;
+    private final DistortedScreen mScreen;
+    private final PostprocessEffectBlur[] mBlur;
+    private final PostprocessEffectGlow[] mGlow;
+    private final PostprocessEffectBorder[] mBord;
+    private final int[] mEffectStatus;
+    private final Static3D mScale1, mScale2;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -97,9 +100,11 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
 
       mEffectStatus    = new int[NUM_OBJECTS];
       mEffectHaloRadius= new Static2D[NUM_OBJECTS];
+      mEffectHalo      = new Static1D[NUM_OBJECTS];
       mNode            = new DistortedNode[NUM_OBJECTS];
       mBlur            = new PostprocessEffectBlur[NUM_OBJECTS];
       mGlow            = new PostprocessEffectGlow[NUM_OBJECTS];
+      mBord            = new PostprocessEffectBorder[NUM_OBJECTS];
 
       FragmentEffectChroma[] chroma= new FragmentEffectChroma[NUM_OBJECTS];
       Static3D[] chromaVector      = new Static3D[NUM_OBJECTS];
@@ -122,11 +127,12 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
         moveVector[i]       = new Static3D(OBJECTS[NUM*i  ], OBJECTS[NUM*i+1], OBJECTS[NUM*i+2]);
         chromaVector[i]     = new Static3D(OBJECTS[NUM*i+3], OBJECTS[NUM*i+4], OBJECTS[NUM*i+5]);
         mEffectHaloRadius[i]= new Static2D(10,10);
+        mEffectHalo[i]      = new Static1D(10);
         mBlur[i]            = new PostprocessEffectBlur(mEffectHaloRadius[i] );
         mGlow[i]            = new PostprocessEffectGlow(mEffectHaloRadius[i], new Static4D(1.0f,1.0f,1.0f,0.5f) );
+        mBord[i]            = new PostprocessEffectBorder(mEffectHalo[i], new Static4D(0.0f,0.0f,0.0f,0.5f) );
         chroma[i]           = new FragmentEffectChroma( new Static1D(0.3f), chromaVector[i]);
         effects[i]          = new DistortedEffects();
-        effects[i].apply(mBlur[i]);
         effects[i].apply(chroma[i]);
         effects[i].apply(scaleEffectV);
         effects[i].apply(new MatrixEffectMove(moveVector[i]));
@@ -134,7 +140,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
         effects[i].apply(quatEffect1);
         effects[i].apply( (i==0||i==NUM_OBJECTS-1) ? scaleEffect1 : scaleEffect2 );
 
-        mEffectStatus[i] = 1;
+        mEffectStatus[i] = 0;
         mNode[i] = new DistortedNode(mTex, effects[i], mesh );
         mScreen.attach(mNode[i]);
         }
@@ -228,6 +234,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       if( object>=0 && object<NUM_OBJECTS )
         {
         mEffectHaloRadius[object].set(range*0.5f,range*0.5f);
+        mEffectHalo[object].set(range*0.5f);
         }
       }
 
@@ -251,6 +258,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
 
           if( effect==1 ) mNode[object].getEffects().apply(mBlur[object]);
           if( effect==2 ) mNode[object].getEffects().apply(mGlow[object]);
+          if( effect==3 ) mNode[object].getEffects().apply(mBord[object]);
           }
         }
       else
diff --git a/src/main/res/layout/triblurlayout.xml b/src/main/res/layout/triblurlayout.xml
index ca36c85..72d3bcc 100644
--- a/src/main/res/layout/triblurlayout.xml
+++ b/src/main/res/layout/triblurlayout.xml
@@ -40,48 +40,16 @@
         android:orientation="horizontal"
         android:paddingTop="5dp">
 
-        <RadioGroup
-            android:id="@+id/triblurRadio0"
+        <Spinner
             android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="0.6"
-            android:orientation="horizontal">
-
-            <RadioButton
-                android:id="@+id/triblurRadioNone0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/none"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioBlur0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:checked="true"
-                android:onClick="effect"
-                android:text="@string/blur"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioGlow0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/glow"
-                android:textSize="14sp" />
-
-        </RadioGroup>
-
+            android:layout_height="50dp"
+            android:layout_weight="0.5"
+            android:id="@+id/triblur_effect0" />
         <SeekBar
             android:id="@+id/triblurSeek0"
             android:layout_width="wrap_content"
             android:layout_height="fill_parent"
-            android:layout_weight="0.4"
+            android:layout_weight="0.5"
             android:paddingLeft="5dp"
             android:paddingRight="5dp" />
     </LinearLayout>
@@ -93,48 +61,16 @@
         android:orientation="horizontal"
         android:paddingTop="5dp">
 
-        <RadioGroup
-            android:id="@+id/triblurRadio1"
+        <Spinner
             android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="0.6"
-            android:orientation="horizontal">
-
-            <RadioButton
-                android:id="@+id/triblurRadioNone1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/none"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioBlur1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:checked="true"
-                android:onClick="effect"
-                android:text="@string/blur"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioGlow1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/glow"
-                android:textSize="14sp" />
-
-        </RadioGroup>
-
+            android:layout_height="50dp"
+            android:layout_weight="0.5"
+            android:id="@+id/triblur_effect1" />
         <SeekBar
             android:id="@+id/triblurSeek1"
             android:layout_width="wrap_content"
             android:layout_height="fill_parent"
-            android:layout_weight="0.4"
+            android:layout_weight="0.5"
             android:paddingLeft="5dp"
             android:paddingRight="5dp" />
     </LinearLayout>
@@ -146,48 +82,16 @@
         android:orientation="horizontal"
         android:paddingTop="5dp">
 
-        <RadioGroup
-            android:id="@+id/triblurRadio2"
+        <Spinner
             android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="0.6"
-            android:orientation="horizontal">
-
-            <RadioButton
-                android:id="@+id/triblurRadioNone2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/none"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioBlur2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:checked="true"
-                android:onClick="effect"
-                android:text="@string/blur"
-                android:textSize="14sp" />
-
-            <RadioButton
-                android:id="@+id/triblurRadioGlow2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:onClick="effect"
-                android:text="@string/glow"
-                android:textSize="14sp" />
-
-        </RadioGroup>
-
+            android:layout_height="50dp"
+            android:layout_weight="0.5"
+            android:id="@+id/triblur_effect2" />
         <SeekBar
             android:id="@+id/triblurSeek2"
             android:layout_width="wrap_content"
             android:layout_height="fill_parent"
-            android:layout_weight="0.4"
+            android:layout_weight="0.5"
             android:paddingLeft="5dp"
             android:paddingRight="5dp" />
     </LinearLayout>
