commit 8a6898dc481ddb697af580c1318a2f115ea0b84f
Author: leszek <leszek@koltunski.pl>
Date:   Wed Dec 18 22:14:51 2024 +0100

    Make it possible to apply Postprocessing effects to only an arbitrary subset of components.

diff --git a/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
index d70df8c..05c4d6e 100644
--- a/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
@@ -133,6 +133,7 @@ public class EffectQueuePostprocess extends EffectQueue
     mainVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
     if( MeshBase.getUseCenters() )      mainVertHeader += "#define COMP_CENTERS\n";
     if( DistortedLibrary.isUBOBuggy() ) mainVertHeader += "#define BUGGY_UBOS\n";
+    mainVertHeader += "#define POSTPROCESS\n";
 
     String enabledEffectV= VertexEffect.getGLSL();
 
diff --git a/src/main/java/org/distorted/library/mesh/DeferredJobs.java b/src/main/java/org/distorted/library/mesh/DeferredJobs.java
index ce8e5a3..5d4e65a 100644
--- a/src/main/java/org/distorted/library/mesh/DeferredJobs.java
+++ b/src/main/java/org/distorted/library/mesh/DeferredJobs.java
@@ -46,6 +46,7 @@ public class DeferredJobs
   private static final int JOB_TYPE_ASSOC        = 7;
   private static final int JOB_TYPE_CENTER       = 8;
   private static final int JOB_TYPE_ADD_EMPTY_TEX= 9;
+  private static final int JOB_TYPE_NOT_AFFECTED = 10;
 
   private static final ArrayList<JobNode> mJobs = new ArrayList<>();
 
@@ -60,11 +61,12 @@ public class DeferredJobs
     private final Static4D[] mMaps;
     private final int mComp, mAndAssoc, mEquAssoc;
     private final float mX,mY,mZ;
+    private final int[] mComps;
 
     private EffectQueueVertex mVertexEffects;
 
     Job(int type, MeshBase target, MeshBase[] source, VertexEffect vEff, MatrixEffect mEff,
-        Static4D[] maps, int comp, int and, int equ, float x, float y, float z)
+        Static4D[] maps, int comp, int and, int equ, float x, float y, float z, int[] comps)
       {
       mType     = type;
       mTarget   = target;
@@ -76,6 +78,7 @@ public class DeferredJobs
       mX        = x;
       mY        = y;
       mZ        = z;
+      mComps    = comps;
 
       if( vEff!=null )
         {
@@ -115,6 +118,7 @@ public class DeferredJobs
                                      break;
         case JOB_TYPE_ADD_EMPTY_TEX: mTarget.addEmptyTexComponentNow();
                                      break;
+        case JOB_TYPE_NOT_AFFECTED:  mTarget.setNotAffectedComponentsNow(mComps);
         }
       }
 
@@ -137,6 +141,7 @@ public class DeferredJobs
         case JOB_TYPE_ASSOC        : return "ASSOC";
         case JOB_TYPE_CENTER       : return "CENTER";
         case JOB_TYPE_ADD_EMPTY_TEX: return "ADD_EMPTY_TEX";
+        case JOB_TYPE_NOT_AFFECTED : return "POSTPROC COMPS";
         }
 
       return null;
@@ -243,7 +248,7 @@ public class DeferredJobs
 
     if( jn==null )
       {
-      Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0);
+      Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null);
       JobNode node = new JobNode(job);
       mJobs.add(node);
       return node;
@@ -257,7 +262,7 @@ public class DeferredJobs
         }
       else
         {
-        Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0);
+        Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null);
         JobNode node = new JobNode(job);
         node.mPrevJobs.add(jn);
         jn.mNextJobs.add(node);
@@ -272,7 +277,7 @@ public class DeferredJobs
   static JobNode matrix(MeshBase target, MatrixEffect effect, int andAssoc, int ecuAssoc)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_MATRIX,target,null,null,effect,null,0,andAssoc,ecuAssoc,0,0,0);
+    Job job = new Job(JOB_TYPE_MATRIX,target,null,null,effect,null,0,andAssoc,ecuAssoc,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -285,7 +290,7 @@ public class DeferredJobs
   static JobNode mergeTex(MeshBase target)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_MERGE_TEX,target,null,null,null,null,0,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_MERGE_TEX,target,null,null,null,null,0,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -298,7 +303,7 @@ public class DeferredJobs
   static JobNode addEmptyTex(MeshBase target)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_ADD_EMPTY_TEX,target,null,null,null,null,0,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_ADD_EMPTY_TEX,target,null,null,null,null,0,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -311,7 +316,7 @@ public class DeferredJobs
   static JobNode mergeEff(MeshBase target)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_MERGE_EFF,target,null,null,null,null,0,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_MERGE_EFF,target,null,null,null,null,0,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -325,7 +330,7 @@ public class DeferredJobs
     {
     JobNode jn;
 
-    Job job = new Job(JOB_TYPE_JOIN,target,meshes,null,null,null,0,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_JOIN,target,meshes,null,null,null,0,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
 
     for (MeshBase mesh : meshes)
@@ -350,7 +355,7 @@ public class DeferredJobs
     JobNode jn = mesh.mJobNode[0];
     MeshBase[] meshes = new MeshBase[1];
     meshes[0] = mesh;
-    Job job = new Job(JOB_TYPE_COPY,target,meshes,null,null,null,0,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_COPY,target,meshes,null,null,null,0,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -363,7 +368,7 @@ public class DeferredJobs
   static JobNode textureMap(MeshBase target, Static4D[] maps, int comp)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_TEXTURE,target,null,null,null,maps,comp,0,0,0,0,0);
+    Job job = new Job(JOB_TYPE_TEXTURE,target,null,null,null,maps,comp,0,0,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -376,7 +381,7 @@ public class DeferredJobs
   static JobNode effectAssoc(MeshBase target, int comp, int andAssoc, int equAssoc)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_ASSOC,target,null,null,null,null,comp,andAssoc,equAssoc,0,0,0);
+    Job job = new Job(JOB_TYPE_ASSOC,target,null,null,null,null,comp,andAssoc,equAssoc,0,0,0,null);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
@@ -389,7 +394,20 @@ public class DeferredJobs
   static JobNode componentCenter(MeshBase target, int comp, float x, float y, float z)
     {
     JobNode jn = target.mJobNode[0];
-    Job job = new Job(JOB_TYPE_CENTER,target,null,null,null,null,comp,0,0,x,y,z);
+    Job job = new Job(JOB_TYPE_CENTER,target,null,null,null,null,comp,0,0,x,y,z,null);
+    JobNode node = new JobNode(job);
+    node.mPrevJobs.add(jn);
+    jn.mNextJobs.add(node);
+    mJobs.add(node);
+    return node;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static JobNode setNotAffected(MeshBase target, int[] comps)
+    {
+    JobNode jn = target.mJobNode[0];
+    Job job = new Job(JOB_TYPE_NOT_AFFECTED,target,null,null,null,null,0,0,0,0,0,0,comps);
     JobNode node = new JobNode(job);
     node.mPrevJobs.add(jn);
     jn.mNextJobs.add(node);
diff --git a/src/main/java/org/distorted/library/mesh/MeshBase.java b/src/main/java/org/distorted/library/mesh/MeshBase.java
index 8e8a74f..28355ae 100644
--- a/src/main/java/org/distorted/library/mesh/MeshBase.java
+++ b/src/main/java/org/distorted/library/mesh/MeshBase.java
@@ -328,6 +328,13 @@ public abstract class MeshBase
      mUBA.setEffectAssociationNow(component, andAssociation, equAssociation);
      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   void setNotAffectedComponentsNow(int[] components)
+     {
+     mUBA.setNotAffectedComponentsNow(components);
+     }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    void setComponentCenterNow(int component, float x, float y, float z)
@@ -1334,11 +1341,16 @@ public abstract class MeshBase
  * (see main_vertex_shader)
  * The point: this way we can configure the system so that each Vertex Effect acts only on a certain
  * subset of a Mesh, thus potentially significantly reducing the number of render calls.
+ * <p>
+ * Only the bottom 31 bits of the 'andAssociation' are possible, the top one is taken by Postprocessing
+ * Association [i.e. marking which components are disabled when we postprocess]
  */
    public void setEffectAssociation(int component, int andAssociation, int equAssociation)
      {
      if( component>=0 && component<mMaxComponents )
        {
+       andAssociation &= 0x7fff;
+
        if( mJobNode[0]==null )
          {
          setEffectAssociationNow(component, andAssociation, equAssociation);
@@ -1350,6 +1362,26 @@ public abstract class MeshBase
        }
      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Set certain components to be not affected by any subsequent postprocessing.
+ * Calling this the second time resets the list. Calling this with null makes all components
+ * affected again.
+ *
+ * @param components list of components which will not be not affected by any Postprocessing.
+ */
+  public void setComponentsNotAffectedByPostprocessing(int[] components)
+    {
+    if( mJobNode[0]==null )
+      {
+      setNotAffectedComponentsNow(components);
+      }
+    else
+      {
+      mJobNode[0] = DeferredJobs.setNotAffected(this,components);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Set center of a Component.
diff --git a/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java b/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
index 55df663..25a7ff8 100644
--- a/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
+++ b/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
@@ -112,6 +112,20 @@ public class UniformBlockAssociation
     mUBO.invalidate();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setNotAffectedComponentsNow(int[] components)
+    {
+    for(int c=0; c<mMax; c++) mAssociations[mStride*c+LOC_AND] &= 0x7fff;
+
+    if( components!=null )
+      {
+      for(int c : components) mAssociations[mStride*c+LOC_AND] |= 0x8000;
+      }
+
+    mUBO.invalidate();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getIndex()
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 030fa58..bc97986 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -130,12 +130,21 @@ void main()
   vec3 v = a_Position + u_Inflate*a_Position;
 #endif
 
+#ifdef POSTPROCESS
+  if( (vComAssoc[component].x & 0x8000) != 0 )
+    {
+    v = vec3(0.0, 0.0, 0.0);
+    }
+#endif
+
 #if NUM_VERTEX>0
   int effect=0;
+  int andC = vComAssoc[component].x & 0x7fff;
+  int equC = vComAssoc[component].y;
 
   for(int i=0; i<vNumEffects; i++)
     {
-    if( ((vComAssoc[component].x & vProperties[i].y) != 0) || (vComAssoc[component].y == vProperties[i].w) )
+    if( ((andC & vProperties[i].y) != 0) || (equC == vProperties[i].w) )
       {
       // ENABLED EFFECTS WILL BE INSERTED HERE
 
