|
|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2009-2024 jMonkeyEngine
|
|
|
+ * Copyright (c) 2009-2025 jMonkeyEngine
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
@@ -32,7 +32,11 @@
|
|
|
package com.jme3.shadow;
|
|
|
|
|
|
import com.jme3.asset.AssetManager;
|
|
|
-import com.jme3.export.*;
|
|
|
+import com.jme3.export.InputCapsule;
|
|
|
+import com.jme3.export.JmeExporter;
|
|
|
+import com.jme3.export.JmeImporter;
|
|
|
+import com.jme3.export.OutputCapsule;
|
|
|
+import com.jme3.export.Savable;
|
|
|
import com.jme3.light.LightFilter;
|
|
|
import com.jme3.light.NullLightFilter;
|
|
|
import com.jme3.material.Material;
|
|
|
@@ -55,12 +59,12 @@ import com.jme3.scene.Geometry;
|
|
|
import com.jme3.scene.Spatial;
|
|
|
import com.jme3.scene.debug.WireFrustum;
|
|
|
import com.jme3.texture.FrameBuffer;
|
|
|
+import com.jme3.texture.FrameBuffer.FrameBufferTarget;
|
|
|
import com.jme3.texture.Image.Format;
|
|
|
import com.jme3.texture.Texture.MagFilter;
|
|
|
import com.jme3.texture.Texture.MinFilter;
|
|
|
import com.jme3.texture.Texture.ShadowCompareMode;
|
|
|
import com.jme3.texture.Texture2D;
|
|
|
-import com.jme3.texture.FrameBuffer.FrameBufferTarget;
|
|
|
import com.jme3.ui.Picture;
|
|
|
import com.jme3.util.clone.Cloner;
|
|
|
import com.jme3.util.clone.JmeCloneable;
|
|
|
@@ -71,83 +75,101 @@ import java.util.List;
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
/**
|
|
|
- * abstract shadow renderer that holds commons feature to have for a shadow
|
|
|
- * renderer
|
|
|
+ * An abstract shadow renderer that provides common features for shadow rendering.
|
|
|
*
|
|
|
* @author Rémy Bouquet aka Nehon
|
|
|
*/
|
|
|
-public abstract class AbstractShadowRenderer implements SceneProcessor, Savable, JmeCloneable, Cloneable {
|
|
|
+public abstract class AbstractShadowRenderer implements SceneProcessor, Savable, JmeCloneable {
|
|
|
|
|
|
protected static final Logger logger = Logger.getLogger(AbstractShadowRenderer.class.getName());
|
|
|
private static final LightFilter NULL_LIGHT_FILTER = new NullLightFilter();
|
|
|
+
|
|
|
+ // The number of shadow maps to render.
|
|
|
protected int nbShadowMaps = 1;
|
|
|
+ // The resolution (width and height) of each shadow map.
|
|
|
protected float shadowMapSize;
|
|
|
+ // The intensity of the shadows, ranging from 0.0 (fully transparent) to 1.0 (fully opaque).
|
|
|
protected float shadowIntensity = 0.7f;
|
|
|
+ // The RenderManager instance used for rendering operations.
|
|
|
protected RenderManager renderManager;
|
|
|
+ // The ViewPort associated with this shadow renderer.
|
|
|
protected ViewPort viewPort;
|
|
|
+ // Array of frame buffers used for rendering shadow maps.
|
|
|
protected FrameBuffer[] shadowFB;
|
|
|
+ // Array of 2D textures representing the generated shadow maps.
|
|
|
protected Texture2D[] shadowMaps;
|
|
|
+ // A dummy texture used to prevent read-buffer crashes on certain platforms (e.g., OSX).
|
|
|
protected Texture2D dummyTex;
|
|
|
+ // Material used for the pre-shadow pass (rendering occluders into the shadow map).
|
|
|
protected Material preshadowMat;
|
|
|
+ // Material used for the post-shadow pass (applying shadows to the scene).
|
|
|
protected Material postshadowMat;
|
|
|
+ // Array of light view projection matrices for each shadow map.
|
|
|
protected Matrix4f[] lightViewProjectionsMatrices;
|
|
|
+ // The AssetManager instance used to load assets.
|
|
|
protected AssetManager assetManager;
|
|
|
+ // Flag indicating whether debug visualizations (e.g., shadow maps) should be displayed.
|
|
|
protected boolean debug = false;
|
|
|
+ // The thickness of shadow edges, influencing PCF (Percentage-Closer Filtering). Value is in tenths of a pixel.
|
|
|
protected float edgesThickness = 1.0f;
|
|
|
+ // The filtering mode applied to shadow edges.
|
|
|
protected EdgeFilteringMode edgeFilteringMode = EdgeFilteringMode.Bilinear;
|
|
|
+ // The shadow comparison mode (hardware or software).
|
|
|
protected CompareMode shadowCompareMode = CompareMode.Hardware;
|
|
|
+ // Array of Picture objects used for debugging to display shadow maps.
|
|
|
protected Picture[] dispPic;
|
|
|
+ // Forced RenderState used during the pre-shadow pass to render occluders.
|
|
|
protected RenderState forcedRenderState = new RenderState();
|
|
|
+ // Flag indicating whether back faces should cast shadows.
|
|
|
protected boolean renderBackFacesShadows = true;
|
|
|
+ // The application profiler for performance monitoring.
|
|
|
protected AppProfiler prof;
|
|
|
-
|
|
|
- /**
|
|
|
- * true if the fallback material should be used, otherwise false
|
|
|
- */
|
|
|
+ // Flag indicating whether shadow frustums should be displayed for debugging.
|
|
|
+ protected boolean debugfrustums = false;
|
|
|
+ // True if a fallback material should be used for post-shadow rendering, otherwise false.
|
|
|
+ // This occurs if some scene materials do not support the post-shadow technique.
|
|
|
protected boolean needsfallBackMaterial = false;
|
|
|
- /**
|
|
|
- * name of the post material technique
|
|
|
- */
|
|
|
+ // The name of the technique to use for the post-shadow material.
|
|
|
protected String postTechniqueName = "PostShadow";
|
|
|
- /**
|
|
|
- * list of materials for post shadow queue geometries
|
|
|
- */
|
|
|
+ // A cache of materials found on geometries in the post-shadow queue.
|
|
|
protected List<Material> matCache = new ArrayList<>();
|
|
|
+ // List of geometries that receive shadows.
|
|
|
protected GeometryList lightReceivers = new GeometryList(new OpaqueComparator());
|
|
|
+ // List of geometries that cast shadows (occluders).
|
|
|
protected GeometryList shadowMapOccluders = new GeometryList(new OpaqueComparator());
|
|
|
+ // Internal cache for shadow map uniform names (e.g., "ShadowMap0", "ShadowMap1").
|
|
|
private String[] shadowMapStringCache;
|
|
|
+ // nternal cache for light view projection matrix uniform names (e.g., "LightViewProjectionMatrix0").
|
|
|
private String[] lightViewStringCache;
|
|
|
- /**
|
|
|
- * fade shadows at distance
|
|
|
- */
|
|
|
+ // The distance at which shadows start to fade out. A value of 0 means no override.
|
|
|
protected float zFarOverride = 0;
|
|
|
+ // Vector containing information about shadow fading (start distance, inverse fade length).
|
|
|
protected Vector2f fadeInfo;
|
|
|
+ // The length over which shadows fade out.
|
|
|
protected float fadeLength;
|
|
|
+ // A camera used to define the frustum for shadow rendering, especially when `zFarOverride` is used.
|
|
|
protected Camera frustumCam;
|
|
|
- /**
|
|
|
- * true to skip the post pass when there are no shadow casters
|
|
|
- */
|
|
|
+ // True to skip the post pass when there are no shadow casters.
|
|
|
protected boolean skipPostPass;
|
|
|
|
|
|
/**
|
|
|
- * used for serialization
|
|
|
+ * For serialization only. Do not use.
|
|
|
*/
|
|
|
protected AbstractShadowRenderer() {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Create an abstract shadow renderer. Subclasses invoke this constructor.
|
|
|
+ * Creates an AbstractShadowRenderer. Subclasses invoke this constructor.
|
|
|
*
|
|
|
- * @param assetManager the application asset manager
|
|
|
- * @param shadowMapSize the size of the rendered shadow maps (512,1024,2048,
|
|
|
- * etc...)
|
|
|
- * @param nbShadowMaps the number of shadow maps rendered (the more shadow
|
|
|
- * maps the more quality, the fewer fps).
|
|
|
+ * @param assetManager The application's asset manager.
|
|
|
+ * @param shadowMapSize The size of the rendered shadow maps (e.g., 512, 1024, 2048).
|
|
|
+ * @param nbShadowMaps The number of shadow maps to render (1 to 4). More maps
|
|
|
+ * improve quality but can reduce performance.
|
|
|
*/
|
|
|
protected AbstractShadowRenderer(AssetManager assetManager, int shadowMapSize, int nbShadowMaps) {
|
|
|
this.assetManager = assetManager;
|
|
|
- this.nbShadowMaps = nbShadowMaps;
|
|
|
this.shadowMapSize = shadowMapSize;
|
|
|
+ this.nbShadowMaps = nbShadowMaps;
|
|
|
init(assetManager, nbShadowMaps, shadowMapSize);
|
|
|
}
|
|
|
|
|
|
@@ -200,9 +222,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * set the post shadow material for this renderer
|
|
|
+ * Sets the post-shadow material for this renderer. This material is used to apply
|
|
|
+ * the shadows to the main scene.
|
|
|
*
|
|
|
- * @param postShadowMat the desired Material (alias created)
|
|
|
+ * @param postShadowMat The desired Material instance to use (alias created).
|
|
|
*/
|
|
|
protected final void setPostShadowMaterial(Material postShadowMat) {
|
|
|
this.postshadowMat = postShadowMat;
|
|
|
@@ -216,10 +239,11 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Sets the filtering mode for shadow edges. See {@link EdgeFilteringMode}
|
|
|
- * for more info.
|
|
|
+ * Sets the filtering mode for shadow edges. This affects the smoothness of
|
|
|
+ * shadow boundaries.
|
|
|
*
|
|
|
- * @param filterMode the desired filtering mode (not null)
|
|
|
+ * @param filterMode The desired filtering mode (cannot be null). See {@link EdgeFilteringMode}
|
|
|
+ * for available options.
|
|
|
*/
|
|
|
final public void setEdgeFilteringMode(EdgeFilteringMode filterMode) {
|
|
|
if (filterMode == null) {
|
|
|
@@ -243,19 +267,21 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * returns the edge filtering mode
|
|
|
+ * Returns the currently edge filtering mode for shadows.
|
|
|
*
|
|
|
+ * @return The current {@link EdgeFilteringMode} enum value.
|
|
|
* @see EdgeFilteringMode
|
|
|
- * @return the enum value
|
|
|
*/
|
|
|
public EdgeFilteringMode getEdgeFilteringMode() {
|
|
|
return edgeFilteringMode;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Sets the shadow compare mode. See {@link CompareMode} for more info.
|
|
|
+ * Sets the shadow comparison mode. This determines how shadow map values are
|
|
|
+ * compared to generate shadows.
|
|
|
*
|
|
|
- * @param compareMode the desired compare mode (not null)
|
|
|
+ * @param compareMode The desired compare mode (cannot be null). See {@link CompareMode}
|
|
|
+ * for available options.
|
|
|
*/
|
|
|
final public void setShadowCompareMode(CompareMode compareMode) {
|
|
|
if (compareMode == null) {
|
|
|
@@ -283,50 +309,52 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * returns the shadow compare mode
|
|
|
+ * Returns the currently shadow comparison mode.
|
|
|
*
|
|
|
+ * @return The current {@link CompareMode} enum value.
|
|
|
* @see CompareMode
|
|
|
- * @return the shadowCompareMode
|
|
|
*/
|
|
|
public CompareMode getShadowCompareMode() {
|
|
|
return shadowCompareMode;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * debug function to create a visible frustum
|
|
|
+ * Debug function to create a visible wireframe frustum. This is useful for
|
|
|
+ * visualizing the shadow camera's view.
|
|
|
*
|
|
|
- * @param pts optional storage for vertex positions (may be null)
|
|
|
- * @param i the index of the desired wire color (default=White)
|
|
|
- * @return a new Geometry
|
|
|
+ * @param pts Optional storage for vertex positions. If null, a new array will be created.
|
|
|
+ * @param i The index, used to assign a color to the frustum for differentiation (e.g., for multiple shadow maps).
|
|
|
+ * @return A new {@link Geometry} representing the wireframe frustum.
|
|
|
*/
|
|
|
protected Geometry createFrustum(Vector3f[] pts, int i) {
|
|
|
WireFrustum frustum = new WireFrustum(pts);
|
|
|
- Geometry frustumMdl = new Geometry("f", frustum);
|
|
|
- frustumMdl.setCullHint(Spatial.CullHint.Never);
|
|
|
- frustumMdl.setShadowMode(ShadowMode.Off);
|
|
|
+ Geometry geo = new Geometry("WireFrustum" + i, frustum);
|
|
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
mat.getAdditionalRenderState().setWireframe(true);
|
|
|
- frustumMdl.setMaterial(mat);
|
|
|
+ geo.setMaterial(mat);
|
|
|
+ geo.setCullHint(Spatial.CullHint.Never);
|
|
|
+ geo.setShadowMode(ShadowMode.Off);
|
|
|
+
|
|
|
switch (i) {
|
|
|
case 0:
|
|
|
- frustumMdl.getMaterial().setColor("Color", ColorRGBA.Pink);
|
|
|
+ mat.setColor("Color", ColorRGBA.Pink);
|
|
|
break;
|
|
|
case 1:
|
|
|
- frustumMdl.getMaterial().setColor("Color", ColorRGBA.Red);
|
|
|
+ mat.setColor("Color", ColorRGBA.Red);
|
|
|
break;
|
|
|
case 2:
|
|
|
- frustumMdl.getMaterial().setColor("Color", ColorRGBA.Green);
|
|
|
+ mat.setColor("Color", ColorRGBA.Green);
|
|
|
break;
|
|
|
case 3:
|
|
|
- frustumMdl.getMaterial().setColor("Color", ColorRGBA.Blue);
|
|
|
+ mat.setColor("Color", ColorRGBA.Blue);
|
|
|
break;
|
|
|
default:
|
|
|
- frustumMdl.getMaterial().setColor("Color", ColorRGBA.White);
|
|
|
+ mat.setColor("Color", ColorRGBA.White);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- frustumMdl.updateGeometricState();
|
|
|
- return frustumMdl;
|
|
|
+ geo.updateGeometricState();
|
|
|
+ return geo;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -340,13 +368,14 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
renderManager = rm;
|
|
|
viewPort = vp;
|
|
|
postTechniqueName = "PostShadow";
|
|
|
- if(zFarOverride>0 && frustumCam == null){
|
|
|
+ if (zFarOverride > 0 && frustumCam == null) {
|
|
|
initFrustumCam();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * delegates the initialization of the frustum cam to child renderers
|
|
|
+ * Delegates the initialization of the frustum camera to child renderers.
|
|
|
+ * This camera defines the view for calculating shadow frustums.
|
|
|
*/
|
|
|
protected abstract void initFrustumCam();
|
|
|
|
|
|
@@ -361,42 +390,43 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Invoked once per frame to update the shadow cams according to the light
|
|
|
- * view.
|
|
|
+ * Invoked once per frame to update the shadow cameras according to the light view.
|
|
|
+ * Subclasses must implement this method to define how shadow cameras are positioned
|
|
|
+ * and oriented.
|
|
|
*
|
|
|
- * @param viewCam the scene cam
|
|
|
+ * @param viewCam The main scene camera.
|
|
|
*/
|
|
|
protected abstract void updateShadowCams(Camera viewCam);
|
|
|
|
|
|
/**
|
|
|
- * Returns a subclass-specific geometryList containing the occluders to be
|
|
|
- * rendered in the shadow map
|
|
|
+ * Returns a subclass-specific {@link GeometryList} containing the occluders
|
|
|
+ * that should be rendered into the shadow map.
|
|
|
*
|
|
|
- * @param shadowMapIndex the index of the shadow map being rendered
|
|
|
- * @param shadowMapOccluders the list of occluders
|
|
|
- * @return the geometryList
|
|
|
+ * @param shadowMapIndex The index of the shadow map being rendered.
|
|
|
+ * @param shadowMapOccluders An existing {@link GeometryList} that can be reused or populated.
|
|
|
+ * @return A {@link GeometryList} containing the geometries that cast shadows for the given map.
|
|
|
*/
|
|
|
protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList shadowMapOccluders);
|
|
|
|
|
|
/**
|
|
|
- * return the shadow camera to use for rendering the shadow map according
|
|
|
- * the given index
|
|
|
+ * Returns the shadow camera to use for rendering the shadow map according to the given index.
|
|
|
+ * Subclasses must implement this to provide the correct camera for each shadow map.
|
|
|
*
|
|
|
- * @param shadowMapIndex the index of the shadow map being rendered
|
|
|
- * @return the shadowCam
|
|
|
+ * @param shadowMapIndex The index of the shadow map being rendered.
|
|
|
+ * @return The {@link Camera} instance representing the shadow's viewpoint.
|
|
|
*/
|
|
|
protected abstract Camera getShadowCam(int shadowMapIndex);
|
|
|
|
|
|
/**
|
|
|
- * responsible for displaying the frustum of the shadow cam for debug
|
|
|
- * purpose
|
|
|
+ * Responsible for displaying the frustum of the shadow camera for debugging purposes.
|
|
|
+ * Subclasses can override this method to provide specific debug visualizations.
|
|
|
*
|
|
|
- * @param shadowMapIndex the index of the shadow map
|
|
|
+ * @param shadowMapIndex The index of the shadow map for which to display the frustum.
|
|
|
*/
|
|
|
protected void doDisplayFrustumDebug(int shadowMapIndex) {
|
|
|
+ // Default implementation does nothing.
|
|
|
}
|
|
|
|
|
|
- @SuppressWarnings("fallthrough")
|
|
|
@Override
|
|
|
public void postQueue(RenderQueue rq) {
|
|
|
lightReceivers.clear();
|
|
|
@@ -413,13 +443,11 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
renderManager.setForcedTechnique("PreShadow");
|
|
|
|
|
|
for (int shadowMapIndex = 0; shadowMapIndex < nbShadowMaps; shadowMapIndex++) {
|
|
|
-
|
|
|
- if (debugfrustums) {
|
|
|
- doDisplayFrustumDebug(shadowMapIndex);
|
|
|
- }
|
|
|
- renderShadowMap(shadowMapIndex);
|
|
|
-
|
|
|
+ if (debugfrustums) {
|
|
|
+ doDisplayFrustumDebug(shadowMapIndex);
|
|
|
}
|
|
|
+ renderShadowMap(shadowMapIndex);
|
|
|
+ }
|
|
|
|
|
|
debugfrustums = false;
|
|
|
|
|
|
@@ -442,7 +470,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
renderManager.getRenderer().clearBuffers(true, true, true);
|
|
|
renderManager.setForcedRenderState(forcedRenderState);
|
|
|
|
|
|
- // render shadow casters to shadow map and disables the lightfilter
|
|
|
+ // render shadow casters to shadow map and disables the light filter
|
|
|
LightFilter tmpLightFilter = renderManager.getLightFilter();
|
|
|
renderManager.setLightFilter(NULL_LIGHT_FILTER);
|
|
|
viewPort.getQueue().renderShadowQueue(shadowMapOccluders, renderManager, shadowCam, true);
|
|
|
@@ -450,16 +478,18 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
renderManager.setForcedRenderState(null);
|
|
|
}
|
|
|
|
|
|
- boolean debugfrustums = false;
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Enables debugging of shadow frustums, making them visible in the scene.
|
|
|
+ * Call this before {@link #postQueue(RenderQueue)} to see the frustums.
|
|
|
+ */
|
|
|
public void displayFrustum() {
|
|
|
debugfrustums = true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * For debugging purposes, display depth shadow maps.
|
|
|
+ * For debugging purposes, displays the depth shadow maps on screen as Picture quads.
|
|
|
*
|
|
|
- * @param r ignored
|
|
|
+ * @param r The current {@link Renderer} (ignored).
|
|
|
*/
|
|
|
protected void displayShadowMap(Renderer r) {
|
|
|
Camera cam = viewPort.getCamera();
|
|
|
@@ -476,12 +506,19 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * For debugging purposes, "snapshot" the current frustum to the scene.
|
|
|
+ * For debugging purposes, "snapshots" the current state of the shadow maps
|
|
|
+ * and displays them on screen.
|
|
|
*/
|
|
|
public void displayDebug() {
|
|
|
debug = true;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Populates the provided {@link GeometryList} with geometries that are considered
|
|
|
+ * shadow receivers. Subclasses must implement this method.
|
|
|
+ *
|
|
|
+ * @param lightReceivers The {@link GeometryList} to populate with shadow-receiving geometries.
|
|
|
+ */
|
|
|
protected abstract void getReceivers(GeometryList lightReceivers);
|
|
|
|
|
|
@Override
|
|
|
@@ -523,13 +560,19 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
|
|
|
/**
|
|
|
* This method is called once per frame and is responsible for clearing any
|
|
|
- * material parameters that subclasses may need to clear on the post material.
|
|
|
+ * material parameters that subclasses may have set on the post-shadow material.
|
|
|
+ * This ensures that parameters from previous frames or other renderers do not
|
|
|
+ * interfere.
|
|
|
*
|
|
|
- * @param material the material that was used for the post shadow pass
|
|
|
+ * @param material The material that was used for the post-shadow pass.
|
|
|
*/
|
|
|
protected abstract void clearMaterialParameters(Material material);
|
|
|
|
|
|
- private void clearMatParams(){
|
|
|
+ /**
|
|
|
+ * Clears common material parameters set by this renderer on materials in the cache.
|
|
|
+ * This is done to avoid interference with other shadow renderers or subsequent frames.
|
|
|
+ */
|
|
|
+ private void clearMatParams() {
|
|
|
for (Material mat : matCache) {
|
|
|
|
|
|
//clearing only necessary params, the others may be set by other
|
|
|
@@ -556,14 +599,19 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
*/
|
|
|
protected abstract void setMaterialParameters(Material material);
|
|
|
|
|
|
- private void setMatParams(GeometryList l) {
|
|
|
+ /**
|
|
|
+ * Iterates through the given {@link GeometryList} to gather unique materials
|
|
|
+ * and sets common shadow-related parameters on them.
|
|
|
+ *
|
|
|
+ * @param list The {@link GeometryList} containing geometries whose materials need parameters set.
|
|
|
+ */
|
|
|
+ private void setMatParams(GeometryList list) {
|
|
|
//iterate through all the geometries of the list to gather the materials
|
|
|
|
|
|
- buildMatCache(l);
|
|
|
+ buildMatCache(list);
|
|
|
|
|
|
//iterating through the mat cache and setting the parameters
|
|
|
for (Material mat : matCache) {
|
|
|
-
|
|
|
mat.setFloat("ShadowMapSize", shadowMapSize);
|
|
|
|
|
|
for (int j = 0; j < nbShadowMaps; j++) {
|
|
|
@@ -581,7 +629,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
mat.setBoolean("BackfaceShadows", renderBackFacesShadows);
|
|
|
|
|
|
if (fadeInfo != null) {
|
|
|
- mat.setVector2("FadeInfo", fadeInfo);
|
|
|
+ mat.setVector2("FadeInfo", fadeInfo);
|
|
|
}
|
|
|
|
|
|
setMaterialParameters(mat);
|
|
|
@@ -592,13 +640,19 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
if (needsfallBackMaterial) {
|
|
|
setPostShadowParams();
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- private void buildMatCache(GeometryList l) {
|
|
|
+ /**
|
|
|
+ * Builds a cache of unique materials from the provided {@link GeometryList}
|
|
|
+ * that support the post-shadow technique. If any material does not support
|
|
|
+ * it, the `needsfallBackMaterial` flag is set.
|
|
|
+ *
|
|
|
+ * @param list The {@link GeometryList} to extract materials from.
|
|
|
+ */
|
|
|
+ private void buildMatCache(GeometryList list) {
|
|
|
matCache.clear();
|
|
|
- for (int i = 0; i < l.size(); i++) {
|
|
|
- Material mat = l.get(i).getMaterial();
|
|
|
+ for (int i = 0; i < list.size(); i++) {
|
|
|
+ Material mat = list.get(i).getMaterial();
|
|
|
//checking if the material has the post technique and adding it to the material cache
|
|
|
if (mat.getMaterialDef().getTechniqueDefs(postTechniqueName) != null) {
|
|
|
if (!matCache.contains(mat)) {
|
|
|
@@ -611,7 +665,8 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * for internal use only
|
|
|
+ * For internal use only. Sets the common shadow parameters on the internal
|
|
|
+ * post-shadow material. This is used when a fallback material is needed.
|
|
|
*/
|
|
|
protected void setPostShadowParams() {
|
|
|
setMaterialParameters(postshadowMat);
|
|
|
@@ -626,43 +681,45 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * How far the shadows are rendered in the view
|
|
|
+ * Returns the maximum distance from the eye where shadows are rendered.
|
|
|
+ * A value of 0 indicates that the distance is dynamically computed based on scene bounds.
|
|
|
*
|
|
|
+ * @return The shadow Z-extend distance in world units.
|
|
|
* @see #setShadowZExtend(float zFar)
|
|
|
- * @return shadowZExtend
|
|
|
*/
|
|
|
public float getShadowZExtend() {
|
|
|
return zFarOverride;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Set the distance from the eye where the shadows will be rendered default
|
|
|
- * value is dynamically computed to the shadow casters/receivers union bound
|
|
|
- * zFar, capped to view frustum far value.
|
|
|
+ * Sets the distance from the camera where shadows will be rendered.
|
|
|
+ * By default (0), this value is dynamically computed based on the union bound
|
|
|
+ * of shadow casters and receivers, capped by the view frustum's far value.
|
|
|
+ * Setting a positive value overrides this dynamic computation.
|
|
|
*
|
|
|
- * @param zFar the zFar values that override the computed one
|
|
|
+ * @param zFar The zFar value that overrides the computed one. Set to 0 to use dynamic computation.
|
|
|
*/
|
|
|
public void setShadowZExtend(float zFar) {
|
|
|
this.zFarOverride = zFar;
|
|
|
- if(zFarOverride == 0){
|
|
|
+ if (zFarOverride == 0) {
|
|
|
fadeInfo = null;
|
|
|
frustumCam = null;
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
if (fadeInfo != null) {
|
|
|
fadeInfo.set(zFarOverride - fadeLength, 1f / fadeLength);
|
|
|
}
|
|
|
- if(frustumCam == null && viewPort != null){
|
|
|
+ if (frustumCam == null && viewPort != null) {
|
|
|
initFrustumCam();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Define the length over which the shadow will fade out when using a
|
|
|
- * shadowZextend This is useful to make dynamic shadows fade into baked
|
|
|
- * shadows in the distance.
|
|
|
+ * Defines the length over which the shadow will fade out when using a
|
|
|
+ * custom `shadowZextend`. This is useful for smoothly transitioning
|
|
|
+ * dynamic shadows into baked shadows or for preventing abrupt shadow cut-offs.
|
|
|
*
|
|
|
- * @param length the fade length in world units
|
|
|
+ * @param length The fade length in world units. Set to 0 to disable fading.
|
|
|
*/
|
|
|
public void setShadowZFadeLength(float length) {
|
|
|
if (length == 0) {
|
|
|
@@ -681,10 +738,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * get the length over which the shadow will fade out when using a
|
|
|
- * shadowZextend
|
|
|
+ * Returns the length over which the shadow will fade out when using a
|
|
|
+ * custom `shadowZextend`.
|
|
|
*
|
|
|
- * @return the fade length in world units
|
|
|
+ * @return The fade length in world units. Returns 0 if no fading is applied.
|
|
|
*/
|
|
|
public float getShadowZFadeLength() {
|
|
|
if (fadeInfo != null) {
|
|
|
@@ -694,39 +751,45 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @param viewCam a Camera to define the view frustum
|
|
|
- * @return true if the light source bounding box is in the view frustum
|
|
|
+ * Abstract method to check if the light source's bounding box is within the view frustum
|
|
|
+ * of the given camera. This is used for culling to avoid unnecessary shadow computations.
|
|
|
+ *
|
|
|
+ * @param viewCam A {@link Camera} to define the view frustum against which to check.
|
|
|
+ * @return True if the light source's bounding box is in the view frustum, otherwise false.
|
|
|
*/
|
|
|
protected abstract boolean checkCulling(Camera viewCam);
|
|
|
|
|
|
@Override
|
|
|
public void preFrame(float tpf) {
|
|
|
+ // no-op
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void cleanup() {
|
|
|
+ // no-op
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void reshape(ViewPort vp, int w, int h) {
|
|
|
+ // no-op
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Returns the shadow intensity.
|
|
|
+ * Returns the current shadow intensity.
|
|
|
*
|
|
|
+ * @return The shadow intensity value, ranging from 0.0 to 1.0.
|
|
|
* @see #setShadowIntensity(float shadowIntensity)
|
|
|
- * @return shadowIntensity
|
|
|
*/
|
|
|
public float getShadowIntensity() {
|
|
|
return shadowIntensity;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Set the shadowIntensity. The value should be between 0 and 1. A 0 value
|
|
|
- * gives a bright and invisible shadow, a 1 value gives a pitch black
|
|
|
- * shadow. The default is 0.7
|
|
|
+ * Sets the shadow intensity. This value controls the darkness of the shadows.
|
|
|
+ * A value of 0.0 results in bright, almost invisible shadows, while 1.0 creates
|
|
|
+ * pitch-black shadows. The default value is 0.7.
|
|
|
*
|
|
|
- * @param shadowIntensity the darkness of the shadow
|
|
|
+ * @param shadowIntensity The desired darkness of the shadow, a float between 0.0 and 1.0.
|
|
|
*/
|
|
|
final public void setShadowIntensity(float shadowIntensity) {
|
|
|
this.shadowIntensity = shadowIntensity;
|
|
|
@@ -734,38 +797,41 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * returns the edges thickness
|
|
|
+ * Returns the configured shadow edges thickness. The value is returned
|
|
|
+ * as an integer representing tenths of a pixel (e.g., 10 for 1.0 pixel).
|
|
|
*
|
|
|
+ * @return The edges thickness in tenths of a pixel.
|
|
|
* @see #setEdgesThickness(int edgesThickness)
|
|
|
- * @return edgesThickness
|
|
|
*/
|
|
|
public int getEdgesThickness() {
|
|
|
return (int) (edgesThickness * 10);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Read the number of shadow maps rendered by this renderer.
|
|
|
+ * Returns the number of shadow maps currently rendered by this processor.
|
|
|
*
|
|
|
- * @return count
|
|
|
+ * @return The count of shadow maps.
|
|
|
*/
|
|
|
public int getNumShadowMaps() {
|
|
|
return nbShadowMaps;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Read the size of each shadow map rendered by this renderer.
|
|
|
+ * Returns the size (width and height) of each shadow map rendered by this processor.
|
|
|
*
|
|
|
- * @return a map's height (which is also its width, in pixels)
|
|
|
+ * @return The resolution of a single shadow map in pixels.
|
|
|
*/
|
|
|
public int getShadowMapSize() {
|
|
|
return (int) shadowMapSize;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Sets the shadow edges thickness. Default is 10. Setting it to lower values
|
|
|
- * can help reduce the jagged effect of shadow edges.
|
|
|
+ * Sets the shadow edges thickness. This parameter influences the
|
|
|
+ * smoothness of shadow edges, particularly with PCF (Percentage-Closer Filtering).
|
|
|
+ * Setting lower values can help reduce jagged artifacts.
|
|
|
*
|
|
|
- * @param edgesThickness the desired thickness (in tenths of a pixel, default=10)
|
|
|
+ * @param edgesThickness The desired thickness in tenths of a pixel (e.g., 10 for 1.0 pixel).
|
|
|
+ * The value is clamped between 1 and 10. Default is 10.
|
|
|
*/
|
|
|
public void setEdgesThickness(int edgesThickness) {
|
|
|
this.edgesThickness = Math.max(1, Math.min(edgesThickness, 10));
|
|
|
@@ -779,29 +845,39 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
* @return false
|
|
|
*/
|
|
|
@Deprecated
|
|
|
- public boolean isFlushQueues() { return false; }
|
|
|
+ public boolean isFlushQueues() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
- * returns the pre shadows pass render state.
|
|
|
- * use it to adjust the RenderState parameters of the pre shadow pass.
|
|
|
- * Note that this will be overridden if the preShadow technique in the material has a ForcedRenderState
|
|
|
- * @return the pre shadow render state.
|
|
|
+ * Returns the {@link RenderState} that is forced during the pre-shadow pass.
|
|
|
+ * You can use this to adjust the rendering parameters for geometries that cast shadows.
|
|
|
+ * Note that this will be overridden if the "PreShadow" technique in the material definition
|
|
|
+ * has its own `ForcedRenderState`.
|
|
|
+ *
|
|
|
+ * @return The {@link RenderState} applied to the pre-shadow pass.
|
|
|
*/
|
|
|
public RenderState getPreShadowForcedRenderState() {
|
|
|
return forcedRenderState;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Set to true if you want back faces shadows on geometries.
|
|
|
- * Note that back faces shadows will be blended over dark lighten areas and may produce overly dark lighting.
|
|
|
+ * Sets whether back faces of geometries should cast shadows.
|
|
|
+ * When enabled, shadows cast by the back side of an object can appear.
|
|
|
+ * Be aware that back face shadows can sometimes lead to overly dark lighting
|
|
|
+ * when blended with existing dark areas.
|
|
|
*
|
|
|
- * Also note that setting this parameter will override this parameter for ALL materials in the scene.
|
|
|
- * You can alternatively change this parameter on a single material using {@link Material#setBoolean(String, boolean)}
|
|
|
+ * <p>Setting this parameter will globally override this setting for ALL materials
|
|
|
+ * in the scene for the shadow pass. Alternatively, you can control this on
|
|
|
+ * individual materials using {@link Material#setBoolean(String, boolean)}
|
|
|
+ * with the "BackfaceShadows" parameter.
|
|
|
*
|
|
|
- * This also will automatically adjust the faceCullMode and the PolyOffset of the pre shadow pass.
|
|
|
- * You can modify them by using {@link #getPreShadowForcedRenderState()}
|
|
|
+ * <p>This method also automatically adjusts the {@link RenderState.FaceCullMode}
|
|
|
+ * and {@link RenderState#setPolyOffset(float, float)} of the pre-shadow pass
|
|
|
+ * to accommodate back face rendering. You can further modify these
|
|
|
+ * using {@link #getPreShadowForcedRenderState()}.
|
|
|
*
|
|
|
- * @param renderBackFacesShadows true or false.
|
|
|
+ * @param renderBackFacesShadows True to enable back face shadows, false to disable.
|
|
|
*/
|
|
|
public void setRenderBackFacesShadows(boolean renderBackFacesShadows) {
|
|
|
this.renderBackFacesShadows = renderBackFacesShadows;
|
|
|
@@ -815,9 +891,9 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * if this processor renders back faces shadows
|
|
|
+ * Checks if this shadow processor is configured to render shadows from back faces.
|
|
|
*
|
|
|
- * @return true if this processor renders back faces shadows
|
|
|
+ * @return True if back face shadows are enabled, false otherwise.
|
|
|
*/
|
|
|
public boolean isRenderBackFacesShadows() {
|
|
|
return renderBackFacesShadows;
|