Skip to content

Commit 5f2828f

Browse files
committed
fix cloning and improve baker performances
1 parent 9eb6817 commit 5f2828f

5 files changed

Lines changed: 158 additions & 40 deletions

File tree

jme3-core/src/main/java/com/jme3/environment/EnvironmentProbeControl.java

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ public class EnvironmentProbeControl extends LightProbe implements Control {
8787
private boolean enabled = true;
8888
private IBLGLEnvBakerLight.SphericalHarmonicsMode sphericalHarmonicsMode =
8989
IBLGLEnvBakerLight.SphericalHarmonicsMode.AUTO;
90-
9190
private Predicate<Geometry> filter = (s) -> {
9291
return s.getUserData("tags.env") != null || s.getUserData("tags.env.env" + uuid) != null;
9392
};
93+
private transient IBLGLEnvBakerLight baker;
9494

9595
protected EnvironmentProbeControl() {
9696
super();
@@ -187,20 +187,38 @@ public static void untagGlobal(Spatial s) {
187187

188188
@Override
189189
public Control cloneForSpatial(Spatial spatial) {
190-
EnvironmentProbeControl control = new EnvironmentProbeControl();
191-
control.setAssetManager(assetManager);
190+
EnvironmentProbeControl control = new EnvironmentProbeControl(assetManager, envMapSize);
192191
control.setFrustumFar(frustumFar);
193192
control.setFrustumNear(frustumNear);
194193
control.setRequiredSavableResults(requiredSavableResults);
195194
control.setEnabled(enabled);
196195
control.setSphericalHarmonicsMode(sphericalHarmonicsMode);
197-
control.envMapSize = envMapSize;
198-
control.uuid = uuid;
199-
control.filter = filter;
200-
control.spatial = spatial;
196+
control.setColor(getColor());
197+
control.setName(getName());
198+
control.setFrustumCheckNeeded(isFrustumCheckNeeded());
199+
control.setAreaType(getAreaType());
200+
control.getArea().setRadius(getArea().getRadius());
201+
control.setPosition(getPosition());
202+
control.retagForClone(spatial, uuid);
203+
control.setSpatial(spatial);
201204
return control;
202205
}
203206

207+
private void retagForClone(Spatial spatial, String sourceUuid) {
208+
if (spatial instanceof Node) {
209+
Node n = (Node) spatial;
210+
for (Spatial sx : n.getChildren()) {
211+
retagForClone(sx, sourceUuid);
212+
}
213+
} else if (spatial instanceof Geometry) {
214+
String sourceTag = "tags.env.env" + sourceUuid;
215+
if (spatial.getUserData(sourceTag) != null) {
216+
spatial.setUserData("tags.env.env" + uuid, true);
217+
spatial.setUserData(sourceTag, null);
218+
}
219+
}
220+
}
221+
204222
/**
205223
* Requests savable results from the baking process. This will make the
206224
* baking process slower and more memory intensive but will allow to
@@ -259,6 +277,10 @@ public void setSpatial(Spatial spatial) {
259277
if (this.spatial != null && spatial != null && spatial != this.spatial) {
260278
throw new IllegalStateException("This control has already been added to a Spatial");
261279
}
280+
if (spatial == null && baker != null) {
281+
baker.clean();
282+
baker = null;
283+
}
262284
this.spatial = spatial;
263285
if (spatial != null) spatial.addLight(this);
264286
}
@@ -273,7 +295,12 @@ public void render(RenderManager rm, ViewPort vp) {
273295
if (!isEnabled()) return;
274296
if (bakeNeeded) {
275297
bakeNeeded = false;
276-
rebakeNow(rm);
298+
try {
299+
rebakeNow(rm);
300+
} finally {
301+
rm.getRenderer().setFrameBuffer(vp.getOutputFrameBuffer());
302+
rm.setCamera(vp.getCamera(), false);
303+
}
277304
}
278305
}
279306

@@ -327,11 +354,22 @@ public float getFrustumFar() {
327354
*/
328355
public void setAssetManager(AssetManager assetManager) {
329356
this.assetManager = assetManager;
357+
if (baker != null) {
358+
baker.clean();
359+
baker = null;
360+
}
361+
}
362+
363+
private IBLGLEnvBakerLight getBaker(RenderManager renderManager) {
364+
if (baker == null) {
365+
baker = new IBLGLEnvBakerLight(renderManager, assetManager, null,
366+
null, envMapSize, envMapSize);
367+
}
368+
return baker;
330369
}
331370

332371
void rebakeNow(RenderManager renderManager) {
333-
IBLGLEnvBakerLight baker = new IBLGLEnvBakerLight(renderManager, assetManager, null,
334-
null, envMapSize, envMapSize);
372+
IBLGLEnvBakerLight baker = getBaker(renderManager);
335373
baker.setSphericalHarmonicsMode(sphericalHarmonicsMode);
336374

337375
baker.setTexturePulling(isRequiredSavableResults());
@@ -347,8 +385,6 @@ void rebakeNow(RenderManager renderManager) {
347385
setShCoeffs(baker.getSphericalHarmonicsCoefficients());
348386
setPosition(Vector3f.ZERO);
349387
setReady(true);
350-
351-
baker.clean();
352388
}
353389

354390
public void setEnabled(boolean enabled) {

jme3-core/src/main/java/com/jme3/environment/baker/GenericEnvBaker.java

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public abstract class GenericEnvBaker implements EnvBaker {
105105
protected final Camera cam;
106106
protected boolean texturePulling = false;
107107
protected List<ByteArrayOutputStream> bos = new ArrayList<>();
108+
private FrameBuffer[] envBakers;
108109

109110
protected GenericEnvBaker(RenderManager rm, AssetManager am, Format colorFormat, Format depthFormat, int env_size) {
110111
this.depthFormat = depthFormat;
@@ -178,18 +179,35 @@ protected Camera updateAndGetInternalCamera(int faceId, int w, int h, Vector3f p
178179

179180
@Override
180181
public void clean() {
182+
if (envBakers != null) {
183+
for (FrameBuffer envBaker : envBakers) {
184+
if (envBaker != null) {
185+
envBaker.dispose();
186+
}
187+
}
188+
envBakers = null;
189+
}
181190

182191
}
183192

184-
@Override
185-
public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear, float frustumFar, Predicate<Geometry> filter) {
186-
FrameBuffer envbakers[] = new FrameBuffer[6];
193+
private FrameBuffer[] getEnvBakers() {
194+
if (envBakers != null) {
195+
return envBakers;
196+
}
197+
198+
envBakers = new FrameBuffer[6];
187199
for (int i = 0; i < 6; i++) {
188-
envbakers[i] = new FrameBuffer(envMap.getImage().getWidth(), envMap.getImage().getHeight(), 1);
189-
envbakers[i].setDepthTarget(FrameBufferTarget.newTarget(getDepthFormat()));
190-
envbakers[i].setSrgb(false);
191-
envbakers[i].addColorTarget(FrameBufferTarget.newTarget(envMap).face(TextureCubeMap.Face.values()[i]));
200+
envBakers[i] = new FrameBuffer(envMap.getImage().getWidth(), envMap.getImage().getHeight(), 1);
201+
envBakers[i].setDepthTarget(FrameBufferTarget.newTarget(getDepthFormat()));
202+
envBakers[i].setSrgb(false);
203+
envBakers[i].addColorTarget(FrameBufferTarget.newTarget(envMap).face(TextureCubeMap.Face.values()[i]));
192204
}
205+
return envBakers;
206+
}
207+
208+
@Override
209+
public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear, float frustumFar, Predicate<Geometry> filter) {
210+
FrameBuffer envbakers[] = getEnvBakers();
193211

194212
if (isTexturePulling()) {
195213
startPulling();
@@ -212,8 +230,11 @@ public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear,
212230
Predicate<Geometry> ofilter = renderManager.getRenderFilter();
213231

214232
renderManager.setRenderFilter(filter);
215-
renderManager.renderViewPort(viewPort, 0.16f);
216-
renderManager.setRenderFilter(ofilter);
233+
try {
234+
renderManager.renderViewPort(viewPort, 0.16f);
235+
} finally {
236+
renderManager.setRenderFilter(ofilter);
237+
}
217238

218239
if (isTexturePulling()) {
219240
pull(envbaker, envMap, i);
@@ -226,10 +247,6 @@ public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear,
226247
}
227248

228249
envMap.getImage().clearUpdateNeeded();
229-
230-
for (int i = 0; i < 6; i++) {
231-
envbakers[i].dispose();
232-
}
233250
}
234251

235252
/**

jme3-core/src/main/java/com/jme3/environment/baker/IBLGLEnvBakerLight.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public enum SphericalHarmonicsMode {
8989

9090
private SphericalHarmonicsMode sphericalHarmonicsMode = SphericalHarmonicsMode.AUTO;
9191
private int sphericalHarmonicsFastPathSampleCount = DEFAULT_FAST_SH_SAMPLE_COUNT;
92+
private Texture2D shCoefTexture;
93+
private FrameBuffer shBaker;
9294

9395
/**
9496
* Create a new IBL env baker
@@ -158,6 +160,35 @@ public int getSphericalHarmonicsFastPathSampleCount() {
158160
return sphericalHarmonicsFastPathSampleCount;
159161
}
160162

163+
@Override
164+
public void clean() {
165+
super.clean();
166+
if (shBaker != null) {
167+
shBaker.dispose();
168+
shBaker = null;
169+
}
170+
shCoefTexture = null;
171+
}
172+
173+
private Texture2D getShCoefTexture(Format format) {
174+
if (shCoefTexture == null || shCoefTexture.getImage().getFormat() != format) {
175+
if (shBaker != null) {
176+
shBaker.dispose();
177+
shBaker = null;
178+
}
179+
shCoefTexture = new Texture2D(NUM_SH_COEFFICIENT, 1, 1, format);
180+
}
181+
return shCoefTexture;
182+
}
183+
184+
private FrameBuffer getShBaker(Texture2D shCoefTexture) {
185+
if (shBaker == null) {
186+
shBaker = new FrameBuffer(NUM_SH_COEFFICIENT, 1, 1);
187+
shBaker.setSrgb(false);
188+
shBaker.addColorTarget(FrameBufferTarget.newTarget(shCoefTexture));
189+
}
190+
return shBaker;
191+
}
161192

162193
@Override
163194
public void bakeSphericalHarmonicsCoefficients() {
@@ -202,11 +233,8 @@ public void bakeSphericalHarmonicsCoefficients() {
202233
mat.clearParam("RemapMaxValue");
203234
}
204235

205-
Texture2D shCoefTx = new Texture2D(NUM_SH_COEFFICIENT, 1, 1, format);
206-
207-
FrameBuffer shbaker = new FrameBuffer(NUM_SH_COEFFICIENT, 1, 1);
208-
shbaker.setSrgb(false);
209-
shbaker.addColorTarget(FrameBufferTarget.newTarget(shCoefTx));
236+
Texture2D shCoefTx = getShCoefTexture(format);
237+
FrameBuffer shbaker = getShBaker(shCoefTx);
210238

211239
screen.updateLogicalState(0);
212240
screen.updateGeometricState();
@@ -244,7 +272,6 @@ else if (weightAccum != c.a) {
244272
}
245273
EnvMapUtils.prepareShCoefs(shCoef);
246274
img.dispose();
247-
shbaker.dispose();
248275

249276
}
250277
}

jme3-core/src/main/java/com/jme3/environment/baker/IBLHybridEnvBakerLight.java

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBak
6464
private static final Logger LOGGER = Logger.getLogger(IBLHybridEnvBakerLight.class.getName());
6565
protected TextureCubeMap specular;
6666
protected Vector3f[] shCoef;
67+
private FrameBuffer[][] specularBakers;
6768

6869
/**
6970
* Create a new IBL env baker
@@ -104,6 +105,24 @@ public IBLHybridEnvBakerLight(RenderManager rm, AssetManager am, Format format,
104105

105106
}
106107

108+
@Override
109+
public void clean() {
110+
super.clean();
111+
if (specularBakers != null) {
112+
for (FrameBuffer[] mipBakers : specularBakers) {
113+
if (mipBakers == null) {
114+
continue;
115+
}
116+
for (FrameBuffer specularBaker : mipBakers) {
117+
if (specularBaker != null) {
118+
specularBaker.dispose();
119+
}
120+
}
121+
}
122+
specularBakers = null;
123+
}
124+
}
125+
107126
@Override
108127
public boolean isTexturePulling() { // always pull textures from gpu
109128
return true;
@@ -123,19 +142,36 @@ private float roughnessFromMip(int mip) {
123142
return mipNorm * mipNorm;
124143
}
125144

126-
private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
127-
mat.setFloat("Roughness", roughness);
145+
private FrameBuffer[] getSpecularBakers(int mip, int mipWidth, int mipHeight) {
146+
if (specularBakers == null) {
147+
specularBakers = new FrameBuffer[specular.getImage().getMipMapSizes().length][];
148+
}
128149

129-
int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
130-
int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
150+
FrameBuffer[] specularbakers = specularBakers[mip];
151+
if (specularbakers != null
152+
&& specularbakers[0].getWidth() == mipWidth
153+
&& specularbakers[0].getHeight() == mipHeight) {
154+
return specularbakers;
155+
}
131156

132-
FrameBuffer specularbakers[] = new FrameBuffer[6];
157+
specularbakers = new FrameBuffer[6];
133158
for (int i = 0; i < 6; i++) {
134159
specularbakers[i] = new FrameBuffer(mipWidth, mipHeight, 1);
135160
specularbakers[i].setSrgb(false);
136161
specularbakers[i].addColorTarget(FrameBufferTarget.newTarget(specular).level(mip).face(i));
137162
specularbakers[i].setMipMapsGenerationHint(false);
138163
}
164+
specularBakers[mip] = specularbakers;
165+
return specularbakers;
166+
}
167+
168+
private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
169+
mat.setFloat("Roughness", roughness);
170+
171+
int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
172+
int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
173+
174+
FrameBuffer specularbakers[] = getSpecularBakers(mip, mipWidth, mipHeight);
139175

140176
for (int i = 0; i < 6; i++) {
141177
FrameBuffer specularbaker = specularbakers[i];
@@ -153,9 +189,6 @@ private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry sc
153189
}
154190

155191
}
156-
for (int i = 0; i < 6; i++) {
157-
specularbakers[i].dispose();
158-
}
159192
}
160193

161194
@Override

jme3-examples/src/main/java/jme3test/light/pbr/TestPBRSimple.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class TestPBRSimple extends SimpleApplication {
5555
private static final String INCREASE_METALLIC = "IncreaseMetallic";
5656
private static final String DECREASE_METALLIC = "DecreaseMetallic";
5757
private static final String TOGGLE_SH_FAST_PATH = "ToggleShFastPath";
58+
private static final String TOGGLE_SH_REALTIME = "ToggleShRealtime";
5859

5960
private Material pbrMat;
6061
private EnvironmentProbeControl envProbe;
@@ -99,7 +100,8 @@ public void simpleInitApp() {
99100
inputManager.addMapping(INCREASE_METALLIC, new KeyTrigger(KeyInput.KEY_N));
100101
inputManager.addMapping(DECREASE_METALLIC, new KeyTrigger(KeyInput.KEY_P));
101102
inputManager.addMapping(TOGGLE_SH_FAST_PATH, new KeyTrigger(KeyInput.KEY_F));
102-
inputManager.addListener(materialListener, INCREASE_METALLIC, DECREASE_METALLIC, TOGGLE_SH_FAST_PATH);
103+
inputManager.addMapping(TOGGLE_SH_REALTIME, new KeyTrigger(KeyInput.KEY_R));
104+
inputManager.addListener(materialListener, TOGGLE_SH_REALTIME, INCREASE_METALLIC, DECREASE_METALLIC, TOGGLE_SH_FAST_PATH);
103105

104106
updateMaterial();
105107

@@ -136,6 +138,9 @@ public void simpleUpdate(float tpf) {
136138
envProbe.rebake();
137139
System.out.println("Spherical harmonics mode -> "
138140
+ envProbe.getSphericalHarmonicsMode() + "; rebaking probe");
141+
} else if (TOGGLE_SH_REALTIME.equals(name)) {
142+
REALTIME_BAKING = !REALTIME_BAKING;
143+
System.out.println("Real-time baking -> " + REALTIME_BAKING);
139144
}
140145

141146
updateMaterial();

0 commit comments

Comments
 (0)