4444import com .jme3 .material .RenderState ;
4545import com .jme3 .material .Technique ;
4646import com .jme3 .material .TechniqueDef ;
47+ import com .jme3 .math .FastMath ;
4748import com .jme3 .math .Matrix4f ;
4849import com .jme3 .post .SceneProcessor ;
4950import com .jme3 .profile .AppProfiler ;
@@ -108,7 +109,7 @@ public class RenderManager {
108109 private LightFilter lightFilter = new DefaultLightFilter ();
109110 private TechniqueDef .LightMode preferredLightMode = TechniqueDef .LightMode .MultiPass ;
110111 private int singlePassLightBatchSize = 1 ;
111- private static final int MAX_SINGLE_PASS_LIGHT_BATCH_SIZE = 16 ;
112+ private int maxSinglePassLightBatchSize = 16 ;
112113 private final MatParamOverride boundDrawBufferId = new MatParamOverride (VarType .Int , "BoundDrawBuffer" , 0 );
113114 private Predicate <Geometry > renderFilter ;
114115
@@ -777,10 +778,10 @@ public void renderGeometry(Geometry geom, LightList lightList) {
777778 }
778779
779780 // Auto-scale singlePassLightBatchSize exponentially (powers of 2) up to
780- // MAX_SINGLE_PASS_LIGHT_BATCH_SIZE to reduce shader recompilations.
781+ // maxSinglePassLightBatchSize to reduce shader recompilations.
781782 int nLights = lightList .size ();
782- if (nLights > singlePassLightBatchSize && singlePassLightBatchSize < MAX_SINGLE_PASS_LIGHT_BATCH_SIZE ) {
783- singlePassLightBatchSize = Math .min (nextPowerOfTwo (nLights ), MAX_SINGLE_PASS_LIGHT_BATCH_SIZE );
783+ if (nLights > singlePassLightBatchSize && singlePassLightBatchSize < maxSinglePassLightBatchSize ) {
784+ singlePassLightBatchSize = Math .min (FastMath . nearestPowerOfTwo (nLights ), maxSinglePassLightBatchSize );
784785 }
785786
786787 this .renderer .pushDebugGroup (geom .getName ());
@@ -1065,7 +1066,7 @@ public TechniqueDef.LightMode getPreferredLightMode() {
10651066 * Returns the number of lights used for each pass when the light mode is single pass.
10661067 *
10671068 * <p>This value is automatically scaled up (in powers of two, up to
1068- * {@value #MAX_SINGLE_PASS_LIGHT_BATCH_SIZE }) during rendering whenever a geometry
1069+ * {@link #getMaxSinglePassLightBatchSize() }) during rendering whenever a geometry
10691070 * has more lights than the current batch size, reducing the number of rendering passes
10701071 * and shader recompilations.
10711072 *
@@ -1076,30 +1077,49 @@ public int getSinglePassLightBatchSize() {
10761077 }
10771078
10781079 /**
1079- * Sets the number of lights to use for each pass when the light mode is single pass.
1080+ * Sets the number of lights to use for each pass when the light mode is single pass,
1081+ * and simultaneously sets the maximum batch size to the same value.
10801082 *
1081- * <p>The value will be automatically scaled up during rendering (in powers of two,
1082- * up to {@value #MAX_SINGLE_PASS_LIGHT_BATCH_SIZE}) when geometries with more lights
1083- * are encountered. Setting this value explicitly will override the current auto-scaled
1084- * value, but it may be increased again by subsequent rendering calls.
1083+ * <p>This effectively pins the batch size and disables the automatic scaling,
1084+ * which is useful when you know in advance how many lights your scene uses and
1085+ * want predictable shader compilation.
10851086 *
1086- * @param singlePassLightBatchSize the number of lights.
1087+ * <p>To set only the upper limit while still allowing automatic scaling,
1088+ * use {@link #setMaxSinglePassLightBatchSize(int)} instead.
1089+ *
1090+ * @param singlePassLightBatchSize the number of lights (minimum 1).
10871091 */
10881092 public void setSinglePassLightBatchSize (int singlePassLightBatchSize ) {
1089- // Ensure the batch size is no less than 1
10901093 this .singlePassLightBatchSize = Math .max (singlePassLightBatchSize , 1 );
1094+ this .maxSinglePassLightBatchSize = this .singlePassLightBatchSize ;
10911095 }
10921096
10931097 /**
1094- * Returns the smallest power of two that is greater than or equal to {@code n}.
1098+ * Returns the maximum number of lights allowed in a single pass batch.
1099+ *
1100+ * <p>The batch size will never be auto-scaled beyond this value.
1101+ * The default is 16.
10951102 *
1096- * @param n the value
1097- * @return the smallest power of two ≥ {@code n}, or 1 if {@code n} ≤ 1
1103+ * @return the maximum single pass light batch size.
10981104 */
1099- private static int nextPowerOfTwo (int n ) {
1100- if (n <= 1 ) return 1 ;
1101- int highest = Integer .highestOneBit (n );
1102- return highest < n ? highest << 1 : highest ;
1105+ public int getMaxSinglePassLightBatchSize () {
1106+ return maxSinglePassLightBatchSize ;
1107+ }
1108+
1109+ /**
1110+ * Sets the maximum number of lights allowed in a single pass batch.
1111+ *
1112+ * <p>If the current {@link #getSinglePassLightBatchSize() batch size} exceeds the
1113+ * new maximum, it is clamped down to the new maximum. Otherwise the current
1114+ * batch size is left unchanged and will continue to auto-scale up to the new limit.
1115+ *
1116+ * @param maxSinglePassLightBatchSize the maximum number of lights (minimum 1).
1117+ */
1118+ public void setMaxSinglePassLightBatchSize (int maxSinglePassLightBatchSize ) {
1119+ this .maxSinglePassLightBatchSize = Math .max (maxSinglePassLightBatchSize , 1 );
1120+ if (singlePassLightBatchSize > this .maxSinglePassLightBatchSize ) {
1121+ singlePassLightBatchSize = this .maxSinglePassLightBatchSize ;
1122+ }
11031123 }
11041124
11051125 /**
0 commit comments