Browse Source

Implemented proper frustum culling for the shadow post pass.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9979 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 13 years ago
parent
commit
78d1754df1

+ 21 - 10
engine/src/core/com/jme3/shadow/AbstractShadowRenderer.java

@@ -43,6 +43,7 @@ import com.jme3.renderer.RenderManager;
 import com.jme3.renderer.Renderer;
 import com.jme3.renderer.Renderer;
 import com.jme3.renderer.ViewPort;
 import com.jme3.renderer.ViewPort;
 import com.jme3.renderer.queue.GeometryList;
 import com.jme3.renderer.queue.GeometryList;
+import com.jme3.renderer.queue.OpaqueComparator;
 import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Geometry;
@@ -75,8 +76,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
     protected Texture2D dummyTex;
     protected Texture2D dummyTex;
     protected Material preshadowMat;
     protected Material preshadowMat;
     protected Material postshadowMat;
     protected Material postshadowMat;
-    protected Matrix4f[] lightViewProjectionsMatrices;
-    protected boolean noOccluders = false;
+    protected Matrix4f[] lightViewProjectionsMatrices;    
     protected AssetManager assetManager;
     protected AssetManager assetManager;
     protected boolean debug = false;
     protected boolean debug = false;
     protected float edgesThickness = 1.0f;
     protected float edgesThickness = 1.0f;
@@ -91,6 +91,9 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
     //flags to know when to change params in the materials
     //flags to know when to change params in the materials
     //a list of material of the post shadow queue geometries.
     //a list of material of the post shadow queue geometries.
     protected List<Material> matCache = new ArrayList<Material>();
     protected List<Material> matCache = new ArrayList<Material>();
+    protected GeometryList sceneReceivers;
+    protected GeometryList lightReceivers = new GeometryList(new OpaqueComparator());
+    protected GeometryList shadowMapOccluders = new GeometryList(new OpaqueComparator());
 
 
     /**
     /**
      * Create an abstract shadow renderer, this is to be called in extending classes
      * Create an abstract shadow renderer, this is to be called in extending classes
@@ -300,7 +303,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
      * @param sceneReceivers the recievers of the whole scene
      * @param sceneReceivers the recievers of the whole scene
      * @return 
      * @return 
      */
      */
-    protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers);
+    protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers,GeometryList shadowMapOccluders);
 
 
     /**
     /**
      * return the shadow camera to use for rendering the shadow map according the given index
      * return the shadow camera to use for rendering the shadow map according the given index
@@ -319,8 +322,8 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
     @SuppressWarnings("fallthrough")
     @SuppressWarnings("fallthrough")
     public void postQueue(RenderQueue rq) {
     public void postQueue(RenderQueue rq) {
         GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
         GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
-        GeometryList receivers = rq.getShadowQueueContent(ShadowMode.Receive);
-        if (receivers.size() == 0 || occluders.size() == 0) {
+        sceneReceivers = rq.getShadowQueueContent(ShadowMode.Receive);
+        if (sceneReceivers.size() == 0 || occluders.size() == 0) {
             return;
             return;
         }
         }
 
 
@@ -335,7 +338,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
             if (debugfrustums) {
             if (debugfrustums) {
                 doDisplayFrustumDebug(shadowMapIndex);
                 doDisplayFrustumDebug(shadowMapIndex);
             }
             }
-            renderShadowMap(shadowMapIndex, occluders, receivers);
+            renderShadowMap(shadowMapIndex, occluders, sceneReceivers);
 
 
         }
         }
 
 
@@ -352,7 +355,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
     }
     }
 
 
     protected void renderShadowMap(int shadowMapIndex, GeometryList occluders, GeometryList receivers) {
     protected void renderShadowMap(int shadowMapIndex, GeometryList occluders, GeometryList receivers) {
-        GeometryList mapOccluders = getOccludersToRender(shadowMapIndex, occluders, receivers);
+        shadowMapOccluders = getOccludersToRender(shadowMapIndex, occluders, receivers,shadowMapOccluders);
         Camera shadowCam = getShadowCam(shadowMapIndex);
         Camera shadowCam = getShadowCam(shadowMapIndex);
 
 
         //saving light view projection matrix for this split            
         //saving light view projection matrix for this split            
@@ -363,7 +366,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
         renderManager.getRenderer().clearBuffers(false, true, false);
         renderManager.getRenderer().clearBuffers(false, true, false);
 
 
         // render shadow casters to shadow map
         // render shadow casters to shadow map
-        viewPort.getQueue().renderShadowQueue(mapOccluders, renderManager, shadowCam, true);
+        viewPort.getQueue().renderShadowQueue(shadowMapOccluders, renderManager, shadowCam, true);
     }
     }
     boolean debugfrustums = false;
     boolean debugfrustums = false;
 
 
@@ -393,13 +396,18 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
     public void displayDebug() {
     public void displayDebug() {
         debug = true;
         debug = true;
     }
     }
+    
+    abstract GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers);
 
 
     public void postFrame(FrameBuffer out) {
     public void postFrame(FrameBuffer out) {
 
 
         if (debug) {
         if (debug) {
             displayShadowMap(renderManager.getRenderer());
             displayShadowMap(renderManager.getRenderer());
         }
         }
-        if (!noOccluders) {
+        
+        lightReceivers = getReceivers(sceneReceivers, lightReceivers);
+        
+        if (lightReceivers.size()!=0) {
             //setting params to recieving geometry list
             //setting params to recieving geometry list
             setMatParams();
             setMatParams();
 
 
@@ -413,7 +421,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
             renderManager.setForcedTechnique(postTechniqueName);
             renderManager.setForcedTechnique(postTechniqueName);
 
 
             //rendering the post shadow pass
             //rendering the post shadow pass
-            viewPort.getQueue().renderShadowQueue(ShadowMode.Receive, renderManager, cam, flushQueues);
+            viewPort.getQueue().renderShadowQueue(lightReceivers, renderManager, cam, true);
+            if(flushQueues){
+                sceneReceivers.clear();
+            }
 
 
             //resetting renderManager settings
             //resetting renderManager settings
             renderManager.setForcedTechnique(null);
             renderManager.setForcedTechnique(null);

+ 9 - 5
engine/src/core/com/jme3/shadow/DirectionalLightShadowRenderer.java

@@ -58,8 +58,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
     protected float lambda = 0.65f;
     protected float lambda = 0.65f;
     protected float zFarOverride = 0;
     protected float zFarOverride = 0;
     protected Camera shadowCam;
     protected Camera shadowCam;
-    protected ColorRGBA splits;    
-    protected GeometryList splitOccluders = new GeometryList(new OpaqueComparator());
+    protected ColorRGBA splits;  
     protected float[] splitsArray;
     protected float[] splitsArray;
     protected DirectionalLight light;
     protected DirectionalLight light;
     protected Vector3f[] points = new Vector3f[8];
     protected Vector3f[] points = new Vector3f[8];
@@ -145,15 +144,20 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
     }
     }
 
 
     @Override
     @Override
-    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers) {
+    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers, GeometryList shadowMapOccluders) {
 
 
         // update frustum points based on current camera and split
         // update frustum points based on current camera and split
         ShadowUtil.updateFrustumPoints(viewPort.getCamera(), splitsArray[shadowMapIndex], splitsArray[shadowMapIndex + 1], 1.0f, points);
         ShadowUtil.updateFrustumPoints(viewPort.getCamera(), splitsArray[shadowMapIndex], splitsArray[shadowMapIndex + 1], 1.0f, points);
 
 
         //Updating shadow cam with curent split frustra
         //Updating shadow cam with curent split frustra
-        ShadowUtil.updateShadowCamera(sceneOccluders, sceneReceivers, shadowCam, points, splitOccluders);
+        ShadowUtil.updateShadowCamera(sceneOccluders, sceneReceivers, shadowCam, points, shadowMapOccluders);
 
 
-        return splitOccluders;
+        return shadowMapOccluders;
+    }
+        
+    @Override
+    GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers) {
+        return sceneReceivers;
     }
     }
 
 
     @Override
     @Override

+ 8 - 3
engine/src/core/com/jme3/shadow/PointLightShadowRenderer.java

@@ -51,7 +51,6 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer {
     public static final int CAM_NUMBER = 6;
     public static final int CAM_NUMBER = 6;
     protected PointLight light;
     protected PointLight light;
     protected Camera[] shadowCams;
     protected Camera[] shadowCams;
-    protected GeometryList shadowMapOccluders = new GeometryList(new OpaqueComparator());
     private Geometry[] frustums = null;
     private Geometry[] frustums = null;
 
 
     /**
     /**
@@ -104,11 +103,17 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer {
     }
     }
 
 
     @Override
     @Override
-    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers) {
-        ShadowUtil.getOccludersInCamFrustum(sceneOccluders, shadowCams[shadowMapIndex], shadowMapOccluders);
+    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers, GeometryList shadowMapOccluders) {
+        ShadowUtil.getGeometriesInCamFrustum(sceneOccluders, shadowCams[shadowMapIndex], shadowMapOccluders);
         return shadowMapOccluders;
         return shadowMapOccluders;
     }
     }
 
 
+    @Override
+    GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers) {
+        ShadowUtil.getGeometriesInLightRadius(sceneReceivers, shadowCams, lightReceivers);
+        return lightReceivers;
+    }
+
     @Override
     @Override
     protected Camera getShadowCam(int shadowMapIndex) {
     protected Camera getShadowCam(int shadowMapIndex) {
         return shadowCams[shadowMapIndex];
         return shadowCams[shadowMapIndex];

+ 130 - 98
engine/src/core/com/jme3/shadow/ShadowUtil.java

@@ -50,29 +50,29 @@ import java.util.List;
 /**
 /**
  * Includes various useful shadow mapping functions.
  * Includes various useful shadow mapping functions.
  *
  *
- * @see
- * <ul>
- * <li><a href="http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/">http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/</a></li>
- * <li><a href="http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html">http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html</a></li>
- * </ul>
- * for more info.
+ * @see <ul> <li><a
+ * href="http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/">http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/</a></li>
+ * <li><a
+ * href="http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html">http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html</a></li>
+ * </ul> for more info.
  */
  */
 public class ShadowUtil {
 public class ShadowUtil {
 
 
     /**
     /**
      * Updates a points arrays with the frustum corners of the provided camera.
      * Updates a points arrays with the frustum corners of the provided camera.
+     *
      * @param viewCam
      * @param viewCam
-     * @param points 
+     * @param points
      */
      */
     public static void updateFrustumPoints2(Camera viewCam, Vector3f[] points) {
     public static void updateFrustumPoints2(Camera viewCam, Vector3f[] points) {
         int w = viewCam.getWidth();
         int w = viewCam.getWidth();
-        int h = viewCam.getHeight();    
-
+        int h = viewCam.getHeight();
+        
         points[0].set(viewCam.getWorldCoordinates(new Vector2f(0, 0), 0));
         points[0].set(viewCam.getWorldCoordinates(new Vector2f(0, 0), 0));
         points[1].set(viewCam.getWorldCoordinates(new Vector2f(0, h), 0));
         points[1].set(viewCam.getWorldCoordinates(new Vector2f(0, h), 0));
         points[2].set(viewCam.getWorldCoordinates(new Vector2f(w, h), 0));
         points[2].set(viewCam.getWorldCoordinates(new Vector2f(w, h), 0));
         points[3].set(viewCam.getWorldCoordinates(new Vector2f(w, 0), 0));
         points[3].set(viewCam.getWorldCoordinates(new Vector2f(w, 0), 0));
-
+        
         points[4].set(viewCam.getWorldCoordinates(new Vector2f(0, 0), 1));
         points[4].set(viewCam.getWorldCoordinates(new Vector2f(0, 0), 1));
         points[5].set(viewCam.getWorldCoordinates(new Vector2f(0, h), 1));
         points[5].set(viewCam.getWorldCoordinates(new Vector2f(0, h), 1));
         points[6].set(viewCam.getWorldCoordinates(new Vector2f(w, h), 1));
         points[6].set(viewCam.getWorldCoordinates(new Vector2f(w, h), 1));
@@ -81,8 +81,8 @@ public class ShadowUtil {
 
 
     /**
     /**
      * Updates the points array to contain the frustum corners of the given
      * Updates the points array to contain the frustum corners of the given
-     * camera. The nearOverride and farOverride variables can be used
-     * to override the camera's near/far values with own values.
+     * camera. The nearOverride and farOverride variables can be used to
+     * override the camera's near/far values with own values.
      *
      *
      * TODO: Reduce creation of new vectors
      * TODO: Reduce creation of new vectors
      *
      *
@@ -95,23 +95,23 @@ public class ShadowUtil {
             float farOverride,
             float farOverride,
             float scale,
             float scale,
             Vector3f[] points) {
             Vector3f[] points) {
-
+        
         Vector3f pos = viewCam.getLocation();
         Vector3f pos = viewCam.getLocation();
         Vector3f dir = viewCam.getDirection();
         Vector3f dir = viewCam.getDirection();
         Vector3f up = viewCam.getUp();
         Vector3f up = viewCam.getUp();
-
+        
         float depthHeightRatio = viewCam.getFrustumTop() / viewCam.getFrustumNear();
         float depthHeightRatio = viewCam.getFrustumTop() / viewCam.getFrustumNear();
         float near = nearOverride;
         float near = nearOverride;
         float far = farOverride;
         float far = farOverride;
         float ftop = viewCam.getFrustumTop();
         float ftop = viewCam.getFrustumTop();
         float fright = viewCam.getFrustumRight();
         float fright = viewCam.getFrustumRight();
         float ratio = fright / ftop;
         float ratio = fright / ftop;
-
+        
         float near_height;
         float near_height;
         float near_width;
         float near_width;
         float far_height;
         float far_height;
         float far_width;
         float far_width;
-
+        
         if (viewCam.isParallelProjection()) {
         if (viewCam.isParallelProjection()) {
             near_height = ftop;
             near_height = ftop;
             near_width = near_height * ratio;
             near_width = near_height * ratio;
@@ -123,30 +123,30 @@ public class ShadowUtil {
             far_height = depthHeightRatio * far;
             far_height = depthHeightRatio * far;
             far_width = far_height * ratio;
             far_width = far_height * ratio;
         }
         }
-
+        
         Vector3f right = dir.cross(up).normalizeLocal();
         Vector3f right = dir.cross(up).normalizeLocal();
-
+        
         Vector3f temp = new Vector3f();
         Vector3f temp = new Vector3f();
         temp.set(dir).multLocal(far).addLocal(pos);
         temp.set(dir).multLocal(far).addLocal(pos);
         Vector3f farCenter = temp.clone();
         Vector3f farCenter = temp.clone();
         temp.set(dir).multLocal(near).addLocal(pos);
         temp.set(dir).multLocal(near).addLocal(pos);
         Vector3f nearCenter = temp.clone();
         Vector3f nearCenter = temp.clone();
-
+        
         Vector3f nearUp = temp.set(up).multLocal(near_height).clone();
         Vector3f nearUp = temp.set(up).multLocal(near_height).clone();
         Vector3f farUp = temp.set(up).multLocal(far_height).clone();
         Vector3f farUp = temp.set(up).multLocal(far_height).clone();
         Vector3f nearRight = temp.set(right).multLocal(near_width).clone();
         Vector3f nearRight = temp.set(right).multLocal(near_width).clone();
         Vector3f farRight = temp.set(right).multLocal(far_width).clone();
         Vector3f farRight = temp.set(right).multLocal(far_width).clone();
-
+        
         points[0].set(nearCenter).subtractLocal(nearUp).subtractLocal(nearRight);
         points[0].set(nearCenter).subtractLocal(nearUp).subtractLocal(nearRight);
         points[1].set(nearCenter).addLocal(nearUp).subtractLocal(nearRight);
         points[1].set(nearCenter).addLocal(nearUp).subtractLocal(nearRight);
         points[2].set(nearCenter).addLocal(nearUp).addLocal(nearRight);
         points[2].set(nearCenter).addLocal(nearUp).addLocal(nearRight);
         points[3].set(nearCenter).subtractLocal(nearUp).addLocal(nearRight);
         points[3].set(nearCenter).subtractLocal(nearUp).addLocal(nearRight);
-
+        
         points[4].set(farCenter).subtractLocal(farUp).subtractLocal(farRight);
         points[4].set(farCenter).subtractLocal(farUp).subtractLocal(farRight);
         points[5].set(farCenter).addLocal(farUp).subtractLocal(farRight);
         points[5].set(farCenter).addLocal(farUp).subtractLocal(farRight);
         points[6].set(farCenter).addLocal(farUp).addLocal(farRight);
         points[6].set(farCenter).addLocal(farUp).addLocal(farRight);
         points[7].set(farCenter).subtractLocal(farUp).addLocal(farRight);
         points[7].set(farCenter).subtractLocal(farUp).addLocal(farRight);
-
+        
         if (scale != 1.0f) {
         if (scale != 1.0f) {
             // find center of frustum
             // find center of frustum
             Vector3f center = new Vector3f();
             Vector3f center = new Vector3f();
@@ -154,7 +154,7 @@ public class ShadowUtil {
                 center.addLocal(points[i]);
                 center.addLocal(points[i]);
             }
             }
             center.divideLocal(8f);
             center.divideLocal(8f);
-
+            
             Vector3f cDir = new Vector3f();
             Vector3f cDir = new Vector3f();
             for (int i = 0; i < 8; i++) {
             for (int i = 0; i < 8; i++) {
                 cDir.set(points[i]).subtractLocal(center);
                 cDir.set(points[i]).subtractLocal(center);
@@ -168,7 +168,7 @@ public class ShadowUtil {
      * Compute bounds of a geomList
      * Compute bounds of a geomList
      * @param list
      * @param list
      * @param transform
      * @param transform
-     * @return 
+     * @return
      */
      */
     public static BoundingBox computeUnionBound(GeometryList list, Transform transform) {
     public static BoundingBox computeUnionBound(GeometryList list, Transform transform) {
         BoundingBox bbox = new BoundingBox();
         BoundingBox bbox = new BoundingBox();
@@ -187,7 +187,7 @@ public class ShadowUtil {
      * Compute bounds of a geomList
      * Compute bounds of a geomList
      * @param list
      * @param list
      * @param mat
      * @param mat
-     * @return 
+     * @return
      */
      */
     public static BoundingBox computeUnionBound(GeometryList list, Matrix4f mat) {
     public static BoundingBox computeUnionBound(GeometryList list, Matrix4f mat) {
         BoundingBox bbox = new BoundingBox();
         BoundingBox bbox = new BoundingBox();
@@ -205,8 +205,9 @@ public class ShadowUtil {
 
 
     /**
     /**
      * Computes the bounds of multiple bounding volumes
      * Computes the bounds of multiple bounding volumes
+     *
      * @param bv
      * @param bv
-     * @return 
+     * @return
      */
      */
     public static BoundingBox computeUnionBound(List<BoundingVolume> bv) {
     public static BoundingBox computeUnionBound(List<BoundingVolume> bv) {
         BoundingBox bbox = new BoundingBox();
         BoundingBox bbox = new BoundingBox();
@@ -219,9 +220,10 @@ public class ShadowUtil {
 
 
     /**
     /**
      * Compute bounds from an array of points
      * Compute bounds from an array of points
+     *
      * @param pts
      * @param pts
      * @param transform
      * @param transform
-     * @return 
+     * @return
      */
      */
     public static BoundingBox computeBoundForPoints(Vector3f[] pts, Transform transform) {
     public static BoundingBox computeBoundForPoints(Vector3f[] pts, Transform transform) {
         Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
         Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
@@ -229,7 +231,7 @@ public class ShadowUtil {
         Vector3f temp = new Vector3f();
         Vector3f temp = new Vector3f();
         for (int i = 0; i < pts.length; i++) {
         for (int i = 0; i < pts.length; i++) {
             transform.transformVector(pts[i], temp);
             transform.transformVector(pts[i], temp);
-
+            
             min.minLocal(temp);
             min.minLocal(temp);
             max.maxLocal(temp);
             max.maxLocal(temp);
         }
         }
@@ -242,22 +244,22 @@ public class ShadowUtil {
      * Compute bounds from an array of points
      * Compute bounds from an array of points
      * @param pts
      * @param pts
      * @param mat
      * @param mat
-     * @return 
+     * @return
      */
      */
     public static BoundingBox computeBoundForPoints(Vector3f[] pts, Matrix4f mat) {
     public static BoundingBox computeBoundForPoints(Vector3f[] pts, Matrix4f mat) {
         Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
         Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
         Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
         Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
         TempVars vars = TempVars.get();
         TempVars vars = TempVars.get();
         Vector3f temp = vars.vect1;
         Vector3f temp = vars.vect1;
-
+        
         for (int i = 0; i < pts.length; i++) {
         for (int i = 0; i < pts.length; i++) {
             float w = mat.multProj(pts[i], temp);
             float w = mat.multProj(pts[i], temp);
-
+            
             temp.x /= w;
             temp.x /= w;
             temp.y /= w;
             temp.y /= w;
             // Why was this commented out?
             // Why was this commented out?
             temp.z /= w;
             temp.z /= w;
-
+            
             min.minLocal(temp);
             min.minLocal(temp);
             max.maxLocal(temp);
             max.maxLocal(temp);
         }
         }
@@ -269,8 +271,8 @@ public class ShadowUtil {
     }
     }
 
 
     /**
     /**
-     * Updates the shadow camera to properly contain the given
-     * points (which contain the eye camera frustum corners)
+     * Updates the shadow camera to properly contain the given points (which
+     * contain the eye camera frustum corners)
      *
      *
      * @param shadowCam
      * @param shadowCam
      * @param points
      * @param points
@@ -278,20 +280,20 @@ public class ShadowUtil {
     public static void updateShadowCamera(Camera shadowCam, Vector3f[] points) {
     public static void updateShadowCamera(Camera shadowCam, Vector3f[] points) {
         boolean ortho = shadowCam.isParallelProjection();
         boolean ortho = shadowCam.isParallelProjection();
         shadowCam.setProjectionMatrix(null);
         shadowCam.setProjectionMatrix(null);
-
+        
         if (ortho) {
         if (ortho) {
             shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
             shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
         } else {
         } else {
             shadowCam.setFrustumPerspective(45, 1, 1, 150);
             shadowCam.setFrustumPerspective(45, 1, 1, 150);
         }
         }
-
+        
         Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
         Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
         Matrix4f projMatrix = shadowCam.getProjectionMatrix();
         Matrix4f projMatrix = shadowCam.getProjectionMatrix();
-
+        
         BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
         BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
         
         
         TempVars vars = TempVars.get();
         TempVars vars = TempVars.get();
-
+        
         Vector3f splitMin = splitBB.getMin(vars.vect1);
         Vector3f splitMin = splitBB.getMin(vars.vect1);
         Vector3f splitMax = splitBB.getMax(vars.vect2);
         Vector3f splitMax = splitBB.getMax(vars.vect2);
 
 
@@ -300,33 +302,32 @@ public class ShadowUtil {
         // Create the crop matrix.
         // Create the crop matrix.
         float scaleX, scaleY, scaleZ;
         float scaleX, scaleY, scaleZ;
         float offsetX, offsetY, offsetZ;
         float offsetX, offsetY, offsetZ;
-
+        
         scaleX = 2.0f / (splitMax.x - splitMin.x);
         scaleX = 2.0f / (splitMax.x - splitMin.x);
         scaleY = 2.0f / (splitMax.y - splitMin.y);
         scaleY = 2.0f / (splitMax.y - splitMin.y);
         offsetX = -0.5f * (splitMax.x + splitMin.x) * scaleX;
         offsetX = -0.5f * (splitMax.x + splitMin.x) * scaleX;
         offsetY = -0.5f * (splitMax.y + splitMin.y) * scaleY;
         offsetY = -0.5f * (splitMax.y + splitMin.y) * scaleY;
         scaleZ = 1.0f / (splitMax.z - splitMin.z);
         scaleZ = 1.0f / (splitMax.z - splitMin.z);
         offsetZ = -splitMin.z * scaleZ;
         offsetZ = -splitMin.z * scaleZ;
-
+        
         Matrix4f cropMatrix = vars.tempMat4;
         Matrix4f cropMatrix = vars.tempMat4;
         cropMatrix.set(scaleX, 0f, 0f, offsetX,
         cropMatrix.set(scaleX, 0f, 0f, offsetX,
                 0f, scaleY, 0f, offsetY,
                 0f, scaleY, 0f, offsetY,
                 0f, 0f, scaleZ, offsetZ,
                 0f, 0f, scaleZ, offsetZ,
                 0f, 0f, 0f, 1f);
                 0f, 0f, 0f, 1f);
-
-
+        
+        
         Matrix4f result = new Matrix4f();
         Matrix4f result = new Matrix4f();
         result.set(cropMatrix);
         result.set(cropMatrix);
         result.multLocal(projMatrix);
         result.multLocal(projMatrix);
-
+        
         vars.release();
         vars.release();
         shadowCam.setProjectionMatrix(result);
         shadowCam.setProjectionMatrix(result);
     }
     }
 
 
     /**
     /**
-     * Updates the shadow camera to properly contain the given
-     * points (which contain the eye camera frustum corners) and the
-     * shadow occluder objects.
+     * Updates the shadow camera to properly contain the given points (which
+     * contain the eye camera frustum corners) and the shadow occluder objects.
      *
      *
      * @param occluders
      * @param occluders
      * @param receivers
      * @param receivers
@@ -341,10 +342,9 @@ public class ShadowUtil {
     }
     }
 
 
     /**
     /**
-     * Updates the shadow camera to properly contain the given
-     * points (which contain the eye camera frustum corners) and the
-     * shadow occluder objects.
-     * 
+     * Updates the shadow camera to properly contain the given points (which
+     * contain the eye camera frustum corners) and the shadow occluder objects.
+     *
      * @param occluders
      * @param occluders
      * @param shadowCam
      * @param shadowCam
      * @param points
      * @param points
@@ -354,39 +354,39 @@ public class ShadowUtil {
             Camera shadowCam,
             Camera shadowCam,
             Vector3f[] points,
             Vector3f[] points,
             GeometryList splitOccluders) {
             GeometryList splitOccluders) {
-
+        
         boolean ortho = shadowCam.isParallelProjection();
         boolean ortho = shadowCam.isParallelProjection();
-
+        
         shadowCam.setProjectionMatrix(null);
         shadowCam.setProjectionMatrix(null);
-
+        
         if (ortho) {
         if (ortho) {
             shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
             shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
-        } 
+        }
 
 
         // create transform to rotate points to viewspace        
         // create transform to rotate points to viewspace        
         Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
         Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
-
+        
         BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
         BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
-
+        
         ArrayList<BoundingVolume> visRecvList = new ArrayList<BoundingVolume>();
         ArrayList<BoundingVolume> visRecvList = new ArrayList<BoundingVolume>();
         for (int i = 0; i < receivers.size(); i++) {
         for (int i = 0; i < receivers.size(); i++) {
             // convert bounding box to light's viewproj space
             // convert bounding box to light's viewproj space
             Geometry receiver = receivers.get(i);
             Geometry receiver = receivers.get(i);
             BoundingVolume bv = receiver.getWorldBound();
             BoundingVolume bv = receiver.getWorldBound();
             BoundingVolume recvBox = bv.transform(viewProjMatrix, null);
             BoundingVolume recvBox = bv.transform(viewProjMatrix, null);
-
+            
             if (splitBB.intersects(recvBox)) {
             if (splitBB.intersects(recvBox)) {
                 visRecvList.add(recvBox);
                 visRecvList.add(recvBox);
             }
             }
         }
         }
-
+        
         ArrayList<BoundingVolume> visOccList = new ArrayList<BoundingVolume>();
         ArrayList<BoundingVolume> visOccList = new ArrayList<BoundingVolume>();
         for (int i = 0; i < occluders.size(); i++) {
         for (int i = 0; i < occluders.size(); i++) {
             // convert bounding box to light's viewproj space
             // convert bounding box to light's viewproj space
             Geometry occluder = occluders.get(i);
             Geometry occluder = occluders.get(i);
             BoundingVolume bv = occluder.getWorldBound();
             BoundingVolume bv = occluder.getWorldBound();
             BoundingVolume occBox = bv.transform(viewProjMatrix, null);
             BoundingVolume occBox = bv.transform(viewProjMatrix, null);
-
+            
             boolean intersects = splitBB.intersects(occBox);
             boolean intersects = splitBB.intersects(occBox);
             if (!intersects && occBox instanceof BoundingBox) {
             if (!intersects && occBox instanceof BoundingBox) {
                 BoundingBox occBB = (BoundingBox) occBox;
                 BoundingBox occBB = (BoundingBox) occBox;
@@ -416,7 +416,7 @@ public class ShadowUtil {
                 }
                 }
             }
             }
         }
         }
-
+        
         BoundingBox casterBB = computeUnionBound(visOccList);
         BoundingBox casterBB = computeUnionBound(visOccList);
         BoundingBox receiverBB = computeUnionBound(visRecvList);
         BoundingBox receiverBB = computeUnionBound(visRecvList);
 
 
@@ -426,18 +426,18 @@ public class ShadowUtil {
             casterBB.setYExtent(casterBB.getYExtent() + 2.0f);
             casterBB.setYExtent(casterBB.getYExtent() + 2.0f);
             casterBB.setZExtent(casterBB.getZExtent() + 2.0f);
             casterBB.setZExtent(casterBB.getZExtent() + 2.0f);
         }
         }
-
+        
         TempVars vars = TempVars.get();
         TempVars vars = TempVars.get();
-
+        
         Vector3f casterMin = casterBB.getMin(vars.vect1);
         Vector3f casterMin = casterBB.getMin(vars.vect1);
         Vector3f casterMax = casterBB.getMax(vars.vect2);
         Vector3f casterMax = casterBB.getMax(vars.vect2);
-
+        
         Vector3f receiverMin = receiverBB.getMin(vars.vect3);
         Vector3f receiverMin = receiverBB.getMin(vars.vect3);
         Vector3f receiverMax = receiverBB.getMax(vars.vect4);
         Vector3f receiverMax = receiverBB.getMax(vars.vect4);
-
+        
         Vector3f splitMin = splitBB.getMin(vars.vect5);
         Vector3f splitMin = splitBB.getMin(vars.vect5);
         Vector3f splitMax = splitBB.getMax(vars.vect6);
         Vector3f splitMax = splitBB.getMax(vars.vect6);
-
+        
         splitMin.z = 0;
         splitMin.z = 0;
 
 
 //        if (!ortho) {
 //        if (!ortho) {
@@ -445,17 +445,17 @@ public class ShadowUtil {
 //        }
 //        }
 
 
         Matrix4f projMatrix = shadowCam.getProjectionMatrix();
         Matrix4f projMatrix = shadowCam.getProjectionMatrix();
-
+        
         Vector3f cropMin = vars.vect7;
         Vector3f cropMin = vars.vect7;
         Vector3f cropMax = vars.vect8;
         Vector3f cropMax = vars.vect8;
 
 
         // IMPORTANT: Special handling for Z values
         // IMPORTANT: Special handling for Z values
         cropMin.x = max(max(casterMin.x, receiverMin.x), splitMin.x);
         cropMin.x = max(max(casterMin.x, receiverMin.x), splitMin.x);
         cropMax.x = min(min(casterMax.x, receiverMax.x), splitMax.x);
         cropMax.x = min(min(casterMax.x, receiverMax.x), splitMax.x);
-
+        
         cropMin.y = max(max(casterMin.y, receiverMin.y), splitMin.y);
         cropMin.y = max(max(casterMin.y, receiverMin.y), splitMin.y);
         cropMax.y = min(min(casterMax.y, receiverMax.y), splitMax.y);
         cropMax.y = min(min(casterMax.y, receiverMax.y), splitMax.y);
-
+        
         cropMin.z = min(casterMin.z, splitMin.z);
         cropMin.z = min(casterMin.z, splitMin.z);
         cropMax.z = min(receiverMax.z, splitMax.z);
         cropMax.z = min(receiverMax.z, splitMax.z);
 
 
@@ -463,56 +463,88 @@ public class ShadowUtil {
         // Create the crop matrix.
         // Create the crop matrix.
         float scaleX, scaleY, scaleZ;
         float scaleX, scaleY, scaleZ;
         float offsetX, offsetY, offsetZ;
         float offsetX, offsetY, offsetZ;
-
+        
         scaleX = (2.0f) / (cropMax.x - cropMin.x);
         scaleX = (2.0f) / (cropMax.x - cropMin.x);
         scaleY = (2.0f) / (cropMax.y - cropMin.y);
         scaleY = (2.0f) / (cropMax.y - cropMin.y);
-
+        
         offsetX = -0.5f * (cropMax.x + cropMin.x) * scaleX;
         offsetX = -0.5f * (cropMax.x + cropMin.x) * scaleX;
         offsetY = -0.5f * (cropMax.y + cropMin.y) * scaleY;
         offsetY = -0.5f * (cropMax.y + cropMin.y) * scaleY;
-
+        
         scaleZ = 1.0f / (cropMax.z - cropMin.z);
         scaleZ = 1.0f / (cropMax.z - cropMin.z);
         offsetZ = -cropMin.z * scaleZ;
         offsetZ = -cropMin.z * scaleZ;
-
-
-
-
+        
+        
+        
+        
         Matrix4f cropMatrix = vars.tempMat4;
         Matrix4f cropMatrix = vars.tempMat4;
         cropMatrix.set(scaleX, 0f, 0f, offsetX,
         cropMatrix.set(scaleX, 0f, 0f, offsetX,
                 0f, scaleY, 0f, offsetY,
                 0f, scaleY, 0f, offsetY,
                 0f, 0f, scaleZ, offsetZ,
                 0f, 0f, scaleZ, offsetZ,
                 0f, 0f, 0f, 1f);
                 0f, 0f, 0f, 1f);
-
-
+        
+        
         Matrix4f result = new Matrix4f();
         Matrix4f result = new Matrix4f();
         result.set(cropMatrix);
         result.set(cropMatrix);
         result.multLocal(projMatrix);
         result.multLocal(projMatrix);
         vars.release();
         vars.release();
-
+        
         shadowCam.setProjectionMatrix(result);
         shadowCam.setProjectionMatrix(result);
-
+        
     }
     }
-    
-     /**
-     * Updates the shadow camera to properly contain the given
-     * points (which contain the eye camera frustum corners) and the
-     * shadow occluder objects.
-     * 
-     * @param occluders
-     * @param shadowCam
-     * @param points
+
+    /**
+     * Populates the outputGeometryList with the geometry of the
+     * inputGeomtryList that are in the frustum of the given camera
+     *
+     * @param inputGeometryList The list containing all geometry to check
+     * against the camera frustum
+     * @param camera the camera to check geometries against
+     * @param outputGeometryList the list of all geometries that are in the
+     * camera frustum
      */
      */
-    public static void getOccludersInCamFrustum(GeometryList occluders,
-            Camera shadowCam,
-            GeometryList splitOccluders) {
-        for (int i = 0; i < occluders.size(); i++) {
-            Geometry g = occluders.get(i);
-            int planeState = shadowCam.getPlaneState();
-            shadowCam.setPlaneState(0);
-            if (shadowCam.contains(g.getWorldBound()) != Camera.FrustumIntersect.Outside) {
-                splitOccluders.add(g);
+    public static void getGeometriesInCamFrustum(GeometryList inputGeometryList,
+            Camera camera,
+            GeometryList outputGeometryList) {
+        for (int i = 0; i < inputGeometryList.size(); i++) {
+            Geometry g = inputGeometryList.get(i);
+            int planeState = camera.getPlaneState();
+            camera.setPlaneState(0);
+            if (camera.contains(g.getWorldBound()) != Camera.FrustumIntersect.Outside) {
+                outputGeometryList.add(g);
             }
             }
-            shadowCam.setPlaneState(planeState);
+            camera.setPlaneState(planeState);
         }
         }
+        
+    }
 
 
+    /**
+     * Populates the outputGeometryList with the geometry of the
+     * inputGeomtryList that are in the radius of a light.
+     * The array of camera must be an array of 6 cameara initialized so they represent the light viewspace of a pointlight
+     *
+     * @param inputGeometryList The list containing all geometry to check
+     * against the camera frustum
+     * @param cameras the camera array to check geometries against
+     * @param outputGeometryList the list of all geometries that are in the
+     * camera frustum
+     */
+    public static void getGeometriesInLightRadius(GeometryList inputGeometryList,
+            Camera[] cameras,
+            GeometryList outputGeometryList) {
+        for (int i = 0; i < inputGeometryList.size(); i++) {
+            Geometry g = inputGeometryList.get(i);
+            boolean inFrustum = false;
+            for (int j = 0; j < cameras.length && inFrustum == false; j++) {
+                Camera camera = cameras[j];
+                int planeState = camera.getPlaneState();
+                camera.setPlaneState(0);
+                inFrustum = camera.contains(g.getWorldBound()) != Camera.FrustumIntersect.Outside;
+                camera.setPlaneState(planeState);
+            }
+            if (inFrustum) {
+                outputGeometryList.add(g);
+            }
+        }
+        
     }
     }
 }
 }

+ 10 - 5
engine/src/core/com/jme3/shadow/SpotLightShadowRenderer.java

@@ -59,8 +59,7 @@ import com.jme3.scene.Node;
 public class SpotLightShadowRenderer extends AbstractShadowRenderer {
 public class SpotLightShadowRenderer extends AbstractShadowRenderer {
 
 
     protected float zFarOverride = 0;
     protected float zFarOverride = 0;
-    protected Camera shadowCam;
-    protected GeometryList mapOccluders = new GeometryList(new OpaqueComparator());
+    protected Camera shadowCam;    
     protected SpotLight light;
     protected SpotLight light;
     protected Vector3f[] points = new Vector3f[8];
     protected Vector3f[] points = new Vector3f[8];
     //Holding the info for fading shadows in the far distance 
     //Holding the info for fading shadows in the far distance 
@@ -125,11 +124,17 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer {
     }
     }
 
 
     @Override
     @Override
-    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers) {
-        ShadowUtil.getOccludersInCamFrustum(sceneOccluders, shadowCam, mapOccluders);
-        return mapOccluders;
+    protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers, GeometryList shadowMapOccluders) {
+        ShadowUtil.getGeometriesInCamFrustum(sceneOccluders, shadowCam, shadowMapOccluders);
+        return shadowMapOccluders;
     }
     }
 
 
+    @Override
+    GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers) {
+        ShadowUtil.getGeometriesInCamFrustum(sceneReceivers, shadowCam, lightReceivers);
+        return lightReceivers;
+    }
+    
     @Override
     @Override
     protected Camera getShadowCam(int shadowMapIndex) {
     protected Camera getShadowCam(int shadowMapIndex) {
         return shadowCam;
         return shadowCam;