Преглед изворни кода

Add instance culling function in InstancedGeometry (#1865)

* Added a workaround to prevent shadow disappearing on instanced geometries away from camera by introducing an instance culling function on InstancedGeometry. There also is a default implementation provided.

* Removed the bound-scale hack for shadow disappearing issue from DefaultInstanceCullingFunction. The “right” solution is to have it pay attention to the frustums of whatever shadow-casting lights are around… but anyway developers now can implement their own frustum culling however they like or even "unset" it to disable instance culling which should also resolve the shadow issue.

* Remove unused imports.
Ali-RS пре 2 година
родитељ
комит
81c26e1414

+ 40 - 8
jme3-core/src/main/java/com/jme3/scene/instancing/InstancedGeometry.java

@@ -58,11 +58,14 @@ import java.io.IOException;
 import java.nio.FloatBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.function.BiFunction;
 
 public class InstancedGeometry extends Geometry {
 
     private static final int INSTANCE_SIZE = 16;
 
+    private static BiFunction<Camera, Geometry, Boolean> instanceCullingFunction = new DefaultInstanceCullingFunction();
+
     private VertexBuffer[] globalInstanceData;
     private VertexBuffer transformInstanceData;
     private Geometry[] geometries = new Geometry[1];
@@ -95,6 +98,22 @@ public class InstancedGeometry extends Geometry {
         setMaxNumInstances(1);
     }
 
+    /**
+     * Set the function used for culling instances from being rendered.
+     * Default is {@link DefaultInstanceCullingFunction}.
+     */
+    public static void setInstanceCullingFunction(BiFunction<Camera, Geometry, Boolean> instanceCullingFunction) {
+        InstancedGeometry.instanceCullingFunction = instanceCullingFunction;
+    }
+
+    /**
+     * @return The instance culling function or null if there isn't any.
+     * Default is {@link DefaultInstanceCullingFunction}.
+     */
+    public static BiFunction<Camera, Geometry, Boolean> getInstanceCullingFunction() {
+        return instanceCullingFunction;
+    }
+
     /**
      * Global user specified per-instance data.
      *
@@ -284,14 +303,9 @@ public class InstancedGeometry extends Geometry {
                     }
                 }
 
-                if (cam != null) {
-                    BoundingVolume bv = geom.getWorldBound();
-                    int save = cam.getPlaneState();
-                    cam.setPlaneState(0);
-                    FrustumIntersect intersect = cam.contains(bv);
-                    cam.setPlaneState(save);
-
-                    if (intersect == FrustumIntersect.Outside) {
+                if (cam != null && instanceCullingFunction != null) {
+                    boolean culled = instanceCullingFunction.apply(cam, geom);
+                    if (culled) {
                         numCulledGeometries++;
                         continue;
                     }
@@ -458,4 +472,22 @@ public class InstancedGeometry extends Geometry {
         allInstanceData = null;
         geometries = null;
     }
+
+    /**
+     * By default, it checks if geometry is in camera frustum and culls it
+     * if it is outside camera view.
+     */
+    public static class DefaultInstanceCullingFunction implements BiFunction<Camera, Geometry, Boolean> {
+
+        @Override
+        public Boolean apply(Camera cam, Geometry geom) {
+            BoundingVolume bv = geom.getWorldBound();
+            int save = cam.getPlaneState();
+            cam.setPlaneState(0);
+            FrustumIntersect intersect = cam.contains(bv);
+            cam.setPlaneState(save);
+
+            return intersect == FrustumIntersect.Outside;
+        }
+    }
 }