From 2d0de1b188c229a8af017741fddc8f321eec5cd0 Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Mon, 23 Jun 2025 17:10:22 +0200 Subject: [PATCH 1/4] Update SpotLightShadowRenderer.java --- .../jme3/shadow/SpotLightShadowRenderer.java | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java index 448857408b..d9373efef5 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2025 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,38 +60,37 @@ * mapping.
for more information on this read http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html
* - * @author Rémy Bouquet aka Nehon + * @author Nehon */ public class SpotLightShadowRenderer extends AbstractShadowRenderer { - protected Camera shadowCam; + protected Camera shadowCam; protected SpotLight light; + protected Camera[] cameras = new Camera[1]; protected Vector3f[] points = new Vector3f[8]; - //Holding the info for fading shadows in the far distance - + protected Vector3f tempVec = new Vector3f(); /** - * Used for serialization use SpotLightShadowRenderer#SpotLightShadowRenderer(AssetManager assetManager, int shadowMapSize) + * For serialization only. Do not use. */ protected SpotLightShadowRenderer() { super(); } /** - * Create a SpotLightShadowRenderer This use standard shadow mapping + * Creates a SpotLightShadowRenderer. * - * @param assetManager the application asset manager - * @param shadowMapSize the size of the rendered shadowmaps (512,1024,2048, - * etc...) The more quality, the fewer fps. + * @param assetManager the application's asset manager + * @param shadowMapSize the size of the rendered shadow maps (512, 1024, 2048, etc...) */ public SpotLightShadowRenderer(AssetManager assetManager, int shadowMapSize) { super(assetManager, shadowMapSize, 1); init(shadowMapSize); } - private void init(int shadowMapSize) { shadowCam = new Camera(shadowMapSize, shadowMapSize); + cameras[0] = shadowCam; for (int i = 0; i < points.length; i++) { points[i] = new Vector3f(); } @@ -101,7 +100,8 @@ private void init(int shadowMapSize) { protected void initFrustumCam() { Camera viewCam = viewPort.getCamera(); frustumCam = viewCam.clone(); - frustumCam.setFrustum(viewCam.getFrustumNear(), zFarOverride, viewCam.getFrustumLeft(), viewCam.getFrustumRight(), viewCam.getFrustumTop(), viewCam.getFrustumBottom()); + frustumCam.setFrustum(viewCam.getFrustumNear(), zFarOverride, + viewCam.getFrustumLeft(), viewCam.getFrustumRight(), viewCam.getFrustumTop(), viewCam.getFrustumBottom()); } /** @@ -138,10 +138,9 @@ protected void updateShadowCams(Camera viewCam) { //We prevent computing the frustum points and splits with zeroed or negative near clip value float frustumNear = Math.max(viewCam.getFrustumNear(), 0.001f); ShadowUtil.updateFrustumPoints(viewCam, frustumNear, zFar, 1.0f, points); - //shadowCam.setDirection(direction); shadowCam.setFrustumPerspective(light.getSpotOuterAngle() * FastMath.RAD_TO_DEG * 2.0f, 1, 1f, light.getSpotRange()); - shadowCam.getRotation().lookAt(light.getDirection(), shadowCam.getUp()); + shadowCam.getRotation().lookAt(light.getDirection(), shadowCam.getUp(tempVec)); shadowCam.setLocation(light.getPosition()); shadowCam.update(); @@ -159,8 +158,6 @@ protected GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sha @Override protected void getReceivers(GeometryList lightReceivers) { lightReceivers.clear(); - Camera[] cameras = new Camera[1]; - cameras[0] = shadowCam; for (Spatial scene : viewPort.getScenes()) { ShadowUtil.getLitGeometriesInViewPort(scene, viewPort.getCamera(), cameras, RenderQueue.ShadowMode.Receive, lightReceivers); } @@ -174,7 +171,6 @@ protected Camera getShadowCam(int shadowMapIndex) { @Override protected void doDisplayFrustumDebug(int shadowMapIndex) { Vector3f[] points2 = points.clone(); - ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points, shadowMapIndex)); ShadowUtil.updateFrustumPoints2(shadowCam, points2); ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points2, shadowMapIndex)); @@ -208,7 +204,6 @@ public void read(JmeImporter im) throws IOException { fadeInfo = (Vector2f) ic.readSavable("fadeInfo", null); fadeLength = ic.readFloat("fadeLength", 0f); init((int) shadowMapSize); - } @Override @@ -227,18 +222,17 @@ public void write(JmeExporter ex) throws IOException { * @return true if intersects, otherwise false */ @Override - protected boolean checkCulling(Camera viewCam) { + protected boolean checkCulling(Camera viewCam) { Camera cam = viewCam; - if(frustumCam != null){ - cam = frustumCam; + if (frustumCam != null) { + cam = frustumCam; cam.setLocation(viewCam.getLocation()); cam.setRotation(viewCam.getRotation()); } TempVars vars = TempVars.get(); - boolean intersects = light.intersectsFrustum(cam,vars); + boolean intersects = light.intersectsFrustum(cam, vars); vars.release(); return intersects; - } } From 7a5f700f0fa2ab3bc79efe269508a6d924134c9f Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Tue, 24 Jun 2025 14:54:42 +0200 Subject: [PATCH 2/4] SpotLightShadowRenderer: fix javadoc --- .../jme3/shadow/SpotLightShadowRenderer.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java index d9373efef5..6517683da7 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java @@ -52,13 +52,18 @@ import java.io.IOException; /** - * SpotLightShadowRenderer renderer use Parallel Split Shadow Mapping technique - * (pssm)
It splits the view frustum in several parts and compute a shadow - * map for each one.
splits are distributed so that the closer they are from - * the camera, the smaller they are to maximize the resolution used of the - * shadow map.
This results in a better quality shadow than standard shadow - * mapping.
for more information on this read http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html
+ * Implements a shadow renderer specifically for {@link SpotLight SpotLights} + * using the **Parallel Split Shadow Mapping (PSSM)** technique. + * + *

PSSM divides the camera's view frustum into multiple sections, + * generating a separate shadow map for each. These splits are + * intelligently distributed, with smaller, higher-resolution maps for areas + * closer to the camera and larger, lower-resolution maps for distant areas. + * This approach optimizes shadow map usage, leading to superior shadow quality + * compared to standard shadow mapping techniques. + * + *

For a detailed explanation of PSSM, refer to: + * GPU Gems 3, Chapter 10: Parallel-Split Shadow Maps on Programmable GPUs * * @author Nehon */ @@ -66,9 +71,9 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer { protected Camera shadowCam; protected SpotLight light; - protected Camera[] cameras = new Camera[1]; - protected Vector3f[] points = new Vector3f[8]; - protected Vector3f tempVec = new Vector3f(); + protected final Camera[] cameras = new Camera[1]; + protected final Vector3f[] points = new Vector3f[8]; + protected final Vector3f tempVec = new Vector3f(); /** * For serialization only. Do not use. @@ -78,10 +83,11 @@ protected SpotLightShadowRenderer() { } /** - * Creates a SpotLightShadowRenderer. + * Creates a new {@code SpotLightShadowRenderer} instance. * - * @param assetManager the application's asset manager - * @param shadowMapSize the size of the rendered shadow maps (512, 1024, 2048, etc...) + * @param assetManager The application's asset manager. + * @param shadowMapSize The size of the rendered shadow maps (e.g., 512, 1024, 2048). + * Higher values produce better quality shadows but may impact performance. */ public SpotLightShadowRenderer(AssetManager assetManager, int shadowMapSize) { super(assetManager, shadowMapSize, 1); @@ -170,10 +176,9 @@ protected Camera getShadowCam(int shadowMapIndex) { @Override protected void doDisplayFrustumDebug(int shadowMapIndex) { - Vector3f[] points2 = points.clone(); ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points, shadowMapIndex)); - ShadowUtil.updateFrustumPoints2(shadowCam, points2); - ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points2, shadowMapIndex)); + ShadowUtil.updateFrustumPoints2(shadowCam, points); + ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points, shadowMapIndex)); } @Override From d63a2b8a7d7c77bf3ab541bd75d4e892e5939388 Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Tue, 24 Jun 2025 15:09:15 +0200 Subject: [PATCH 3/4] SpotLightShadowRenderer: fix link --- .../src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java index 6517683da7..e05c16be47 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java @@ -63,7 +63,7 @@ * compared to standard shadow mapping techniques. * *

For a detailed explanation of PSSM, refer to: - * GPU Gems 3, Chapter 10: Parallel-Split Shadow Maps on Programmable GPUs + * GPU Gems 3, Chapter 10: Parallel-Split Shadow Maps on Programmable GPUs * * @author Nehon */ From 88788eaa6a65b860109cded27492c8003ef7026b Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Tue, 24 Jun 2025 15:12:58 +0200 Subject: [PATCH 4/4] SpotLightShadowRenderer: revert points cloning --- .../main/java/com/jme3/shadow/SpotLightShadowRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java index e05c16be47..2d5ea1a867 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/SpotLightShadowRenderer.java @@ -176,9 +176,11 @@ protected Camera getShadowCam(int shadowMapIndex) { @Override protected void doDisplayFrustumDebug(int shadowMapIndex) { + Vector3f[] points2 = points.clone(); + ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points, shadowMapIndex)); - ShadowUtil.updateFrustumPoints2(shadowCam, points); - ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points, shadowMapIndex)); + ShadowUtil.updateFrustumPoints2(shadowCam, points2); + ((Node) viewPort.getScenes().get(0)).attachChild(createFrustum(points2, shadowMapIndex)); } @Override