Skip to content

Refactor: PointLightShadowRenderer reduce object allocations #2514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -51,33 +51,39 @@
import java.io.IOException;

/**
* PointLightShadowRenderer renders shadows for a point light
* Renders shadows for a {@link PointLight}. This renderer uses six cameras,
* one for each face of a cube map, to capture shadows from the point light's
* perspective.
*
* @author Rémy Bouquet aka Nehon
* @author Nehon
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the author change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original author's alias 'Nehon' is already the standard signature for most of their contributions, consistent with their GitHub nickname. To maintain uniformity with the other 500 classes in the jme3-core module and to align with this established practice, I've adjusted the signatures in these four Shadow classes. My intention is never to remove an original author's alias from any jME class, only to ensure consistency where a clear alias already exists and is widely used. This change also implicitly supports privacy by standardizing the alias used.

*/
public class PointLightShadowRenderer extends AbstractShadowRenderer {

/**
* The fixed number of cameras used for rendering point light shadows (6 for a cube map).
*/
public static final int CAM_NUMBER = 6;

protected PointLight light;
protected Camera[] shadowCams;
private Geometry[] frustums = null;
protected Geometry[] frustums = null;
protected final Vector3f X_NEG = Vector3f.UNIT_X.mult(-1f);
protected final Vector3f Y_NEG = Vector3f.UNIT_Y.mult(-1f);
protected final Vector3f Z_NEG = Vector3f.UNIT_Z.mult(-1f);

/**
* Used for serialization.
* Use PointLightShadowRenderer#PointLightShadowRenderer(AssetManager
* assetManager, int shadowMapSize)
* instead.
* For serialization only. Do not use.
*/
protected PointLightShadowRenderer() {
super();
}

/**
* Creates a PointLightShadowRenderer
* Creates a new {@code PointLightShadowRenderer} instance.
*
* @param assetManager the application asset manager
* @param shadowMapSize the size of the rendered shadowmaps (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 PointLightShadowRenderer(AssetManager assetManager, int shadowMapSize) {
super(assetManager, shadowMapSize, CAM_NUMBER);
Expand All @@ -86,7 +92,7 @@ public PointLightShadowRenderer(AssetManager assetManager, int shadowMapSize) {

private void init(int shadowMapSize) {
shadowCams = new Camera[CAM_NUMBER];
for (int i = 0; i < CAM_NUMBER; i++) {
for (int i = 0; i < shadowCams.length; i++) {
shadowCams[i] = new Camera(shadowMapSize, shadowMapSize);
}
}
Expand All @@ -95,9 +101,9 @@ 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());
}


@Override
protected void updateShadowCams(Camera viewCam) {
Expand All @@ -107,31 +113,21 @@ protected void updateShadowCams(Camera viewCam) {
return;
}

//bottom
shadowCams[0].setAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Z.mult(-1f), Vector3f.UNIT_Y.mult(-1f));

//top
shadowCams[1].setAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Z, Vector3f.UNIT_Y);

//forward
shadowCams[2].setAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Y, Vector3f.UNIT_Z.mult(-1f));

//backward
shadowCams[3].setAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z);

//left
shadowCams[4].setAxes(Vector3f.UNIT_Z, Vector3f.UNIT_Y, Vector3f.UNIT_X.mult(-1f));

//right
shadowCams[5].setAxes(Vector3f.UNIT_Z.mult(-1f), Vector3f.UNIT_Y, Vector3f.UNIT_X);

for (int i = 0; i < CAM_NUMBER; i++) {
shadowCams[i].setFrustumPerspective(90f, 1f, 0.1f, light.getRadius());
shadowCams[i].setLocation(light.getPosition());
shadowCams[i].update();
shadowCams[i].updateViewProjection();
// Configure axes for each of the six cube map cameras (positive/negative X, Y, Z)
shadowCams[0].setAxes(X_NEG, Z_NEG, Y_NEG); // -Y (bottom)
shadowCams[1].setAxes(X_NEG, Vector3f.UNIT_Z, Vector3f.UNIT_Y); // +Y (top)
shadowCams[2].setAxes(X_NEG, Vector3f.UNIT_Y, Z_NEG); // +Z (forward)
shadowCams[3].setAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z); // -Z (backward)
shadowCams[4].setAxes(Vector3f.UNIT_Z, Vector3f.UNIT_Y, X_NEG); // -X (left)
shadowCams[5].setAxes(Z_NEG, Vector3f.UNIT_Y, Vector3f.UNIT_X); // +X (right)

// Set perspective and location for all shadow cameras
for (Camera shadowCam : shadowCams) {
shadowCam.setFrustumPerspective(90f, 1f, 0.1f, light.getRadius());
shadowCam.setLocation(light.getPosition());
shadowCam.update();
shadowCam.updateViewProjection();
}

}

@Override
Expand Down Expand Up @@ -160,16 +156,17 @@ protected void doDisplayFrustumDebug(int shadowMapIndex) {
if (frustums == null) {
frustums = new Geometry[CAM_NUMBER];
Vector3f[] points = new Vector3f[8];
for (int i = 0; i < 8; i++) {
for (int i = 0; i < points.length; i++) {
points[i] = new Vector3f();
}
for (int i = 0; i < CAM_NUMBER; i++) {
ShadowUtil.updateFrustumPoints2(shadowCams[i], points);
frustums[i] = createFrustum(points, i);
}
}
if (frustums[shadowMapIndex].getParent() == null) {
((Node) viewPort.getScenes().get(0)).attachChild(frustums[shadowMapIndex]);
Geometry geo = frustums[shadowMapIndex];
if (geo.getParent() == null) {
((Node) viewPort.getScenes().get(0)).attachChild(geo);
}
}

Expand Down Expand Up @@ -237,13 +234,13 @@ 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;
}
Expand Down