Skip to content

Commit 81c26e1

Browse files
authored
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.
1 parent 116ee9e commit 81c26e1

File tree

1 file changed

+40
-8
lines changed

1 file changed

+40
-8
lines changed

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

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,14 @@
5858
import java.nio.FloatBuffer;
5959
import java.util.ArrayList;
6060
import java.util.Arrays;
61+
import java.util.function.BiFunction;
6162

6263
public class InstancedGeometry extends Geometry {
6364

6465
private static final int INSTANCE_SIZE = 16;
6566

67+
private static BiFunction<Camera, Geometry, Boolean> instanceCullingFunction = new DefaultInstanceCullingFunction();
68+
6669
private VertexBuffer[] globalInstanceData;
6770
private VertexBuffer transformInstanceData;
6871
private Geometry[] geometries = new Geometry[1];
@@ -95,6 +98,22 @@ public InstancedGeometry(String name) {
9598
setMaxNumInstances(1);
9699
}
97100

101+
/**
102+
* Set the function used for culling instances from being rendered.
103+
* Default is {@link DefaultInstanceCullingFunction}.
104+
*/
105+
public static void setInstanceCullingFunction(BiFunction<Camera, Geometry, Boolean> instanceCullingFunction) {
106+
InstancedGeometry.instanceCullingFunction = instanceCullingFunction;
107+
}
108+
109+
/**
110+
* @return The instance culling function or null if there isn't any.
111+
* Default is {@link DefaultInstanceCullingFunction}.
112+
*/
113+
public static BiFunction<Camera, Geometry, Boolean> getInstanceCullingFunction() {
114+
return instanceCullingFunction;
115+
}
116+
98117
/**
99118
* Global user specified per-instance data.
100119
*
@@ -284,14 +303,9 @@ public void updateInstances() {
284303
}
285304
}
286305

287-
if (cam != null) {
288-
BoundingVolume bv = geom.getWorldBound();
289-
int save = cam.getPlaneState();
290-
cam.setPlaneState(0);
291-
FrustumIntersect intersect = cam.contains(bv);
292-
cam.setPlaneState(save);
293-
294-
if (intersect == FrustumIntersect.Outside) {
306+
if (cam != null && instanceCullingFunction != null) {
307+
boolean culled = instanceCullingFunction.apply(cam, geom);
308+
if (culled) {
295309
numCulledGeometries++;
296310
continue;
297311
}
@@ -458,4 +472,22 @@ protected void cleanup() {
458472
allInstanceData = null;
459473
geometries = null;
460474
}
475+
476+
/**
477+
* By default, it checks if geometry is in camera frustum and culls it
478+
* if it is outside camera view.
479+
*/
480+
public static class DefaultInstanceCullingFunction implements BiFunction<Camera, Geometry, Boolean> {
481+
482+
@Override
483+
public Boolean apply(Camera cam, Geometry geom) {
484+
BoundingVolume bv = geom.getWorldBound();
485+
int save = cam.getPlaneState();
486+
cam.setPlaneState(0);
487+
FrustumIntersect intersect = cam.contains(bv);
488+
cam.setPlaneState(save);
489+
490+
return intersect == FrustumIntersect.Outside;
491+
}
492+
}
461493
}

0 commit comments

Comments
 (0)