How to load scene with lightprobe?

Hi I have made a scene using the sdk with terrain, skybox, ambientlight, lightprobe, how to correctly use/activate the lightprobe in the scene?

        Node level = (Node) assetManager.loadModel("scenes/level1.j3o");

        LightList lightList = level.getLocalLightList();
        LightProbe lightProbe = (LightProbe) lightList.get(1);
        // do something with lightProbe?


doing it all programmatically works fine:

        final LightProbe probe = LightProbeFactory.makeProbe(simpleApplication.getStateManager().getState(EnvironmentCamera.class), scene, new JobProgressAdapter<LightProbe>() {

            public void done(LightProbe result) {
                System.out.println("Done rendering env maps");
                lightProbeDone = true;
                tex = EnvMapUtils.getCubeMapCrossDebugViewWithMipMaps(result.getPrefilteredEnvMap(), simpleApplication.getAssetManager());

        ((SphereProbeArea) probe.getArea()).setRadius(100);
        probe.setPosition(new Vector3f(0,20,0));

This will then take some time, isn’t it an advantage to add the lightprobe to the scene since
we don’t need to wait for rendering the env map?

You need to add the lighProbe to the rootNode.
This is regular jme methodology: A light affects every node below the node it’s added to.

Ah it makes sense, it now works thanks!

Actually this way works to, which is funny, since I am just creating a new Node called stageNode, and just pick every element out from the scene and add it to the stageNode, Its like doing double the work.
Shouldn’t it just be enough loading that scene?

        Node levelRoot = (Node) assetManager.loadModel("scenes/level1.j3o");

        Spatial sky = (Spatial) levelRoot.getChild("Sky");
        Node terrain = (Node) levelRoot.getChild("terrain-level1");

        LightList lightList = levelRoot.getLocalLightList();

        AmbientLight ambientLight = (AmbientLight) lightList.get(0);
        LightProbe lightProbe = (LightProbe) lightList.get(1);


I tried this instead to test further

        Node levelRoot = (Node) assetManager.loadModel("scenes/level1.j3o");

        LightList lightList = levelRoot.getLocalLightList();

        LightProbe lightProbe = (LightProbe) lightList.get(1).clone();


and it works, so I suspect that the lightprobe doesn’t get loaded properly, since the ambientlight actually works fine in the scene.

I don’t understand your problem correctly, but if you have the following Nodes:
A => B => C

You load something, attach it as C to B, then only the children would be lit.
If you add it to A, everything is lit.

This is like here creating B and adding C etc.
If you only load the scene, then you have to add it to the rootNode, but then you have to see where the light probe is, it has to be in “stageNode” (so it should work).

We need the exact node/light hiearchies to see what is going wrong.

Its like you got a Car, but it have wheels objects and chaisis object, etc objects and all of this is under one Car Node(parent) that is “container” for all of this objects. if you add light to Car Node, everything will be affected by light, if you add only to some sub-node, for example wheel, then only wheel will be affected by light. (lightprobe also work same way)

Also some general info: Spatial can be anything, Geometry, Node, or even something else.
While only Node is “container” that you want use. In java you trully can just cast and see if(spatial instanceof Geometry) etc. so you know what it is.

here is wiki:

also not sure if this will help you somehow, but there is video:

Generally Light Probe need Envmap to generate “map”. Nothing special, but it take some time to generate, so usually people “pre-generate” them in SDK or via code and save as j3o file.

1 Like

Thank you guys I understand :slight_smile:

Okay what I`m trying to say just by observation

Node a = loadModel("somescenewithlights");
Node b = new Node("copyNode");


// so a and b are identical having the same children and lights

//rootNode.AttachChild(a); // ambient light works and lightprobe not showing
//rootNode.AttachChild(b); // ambient light works and lightprobe works

So just by sheer observation that they don’t do the same,
which I don’t understand since they hold the same

hmm, i dont really understand what you mean, but i think i will show you example i see myself, so you might understand it better:

Spatial PBRModel = loadModel("some PBR model"); //Spatial - it means it can be Geometry or Node, whatever - if this is all Scene, it will be Node.

Spatial NonPBRModel = loadModel("some NoN-PBR model"); //same it will be spatial so can be anything
// Some simple Scene graph structure
Node generalLitNode = new Node("generalLitNode");
Node pbrObjectsNode = new Node("PBR Node")
generalLitNode.attachChild(pbrObjectsNode); // we make pbrNode to be inside generalLitNode
generalLitNode .addLight(ambientLight);
generalLitNode .addLight(directionalLight);

generalLitNode.attachChild(NonPBRModel); // general(main) node that have lights here.
pbrObjectsNode.attachChild(PBRModel); // we have pbrNode where for example you will want all PBR objects. this PBR node is also in generalLitNode that have lights. But it also have LightProbe.

lightProbe = LightProbeFactory.makeProbe(environmentCamera, generalLitNode, new JobProgressAdapter<LightProbe>() {
....... (there is more code to generate it)

So in this example you have

generalLitNode(general lights) → pbrObjectsNode(+light probe) + NonPBRModel.
Where in pbrObjectsNode → PBRModel

NonPBRModel is only in generalLitNode so it will be affected by general lights, even if it would be PBR Model, it will not be affected by LightProbe, because its not in this Node.

PBRModel is in pbrObjectsNode so it is affected by both generalLitNode(that have general lights) and pbrObjectsNode(that have lightProbe with generated envMap)

Also please focus on some sample i provided:

lightProbe = LightProbeFactory.makeProbe(environmentCamera, generalLitNode, new JobProgressAdapter<LightProbe>() {
....... (there is more code to generate it)

What i mean here is that it generate probe envmap based on generalLitNode (that can be non-pbr scene, anything here) while lightProbe is put only to pbrObjectsNode to affect only PBR Models you put there.

You can create ANY sceneGraph you want, i just provided you some example to make you understand how it work :slight_smile:

1 Like

What does this mean? How did you “copy” them?

        for (var childSpatial: a.getChildren()) {
        for (var light : a.getLocalLightList()) {

like this :slight_smile:

Ah thanks for the example :smiley:

i dont say it will not work(copy idea).

but imo if you already have a Scene with lights, why not just attach it to rootNode?(or some ScenesNode)

What is this Scene exactly?

I’m doing as guys says attaching to the rootNode or parentNode higher in the hiearchy, as this is the right way. I was just fooling around, and try to copy some node to see difference in behaviors, that’s all. Many thanks for the help. :smiley:

the “right way” depends on many things :wink:

but right, this seems fine.

Just lights like directionalLight or AmbientLight IMO should not be in “this scenes”. but in some rootNode or some lightNode “higher in the hiearchy” like you said :slight_smile:

LightProbe, SpotLight, AreaLight etc. can be in “this scenes” IMO.

Why? because if you will have DL Light in “this scenes”, you might have situation that this light will be “doubled” for example when scene will have DLLight and “parentNode higher in the hiearchy” will also have one. (but it also depends, there might be situations where you would want 2 Directional Lights). but it depends on game too. if you will have Scenes where you will “dont want DL Light”(or want different colors/intensity each scene), then this way(having DL light in scenes) is proper too.

1 Like

You could try looking at the resulting graph as your approach definitely kills the deeper structure.

Or lightProbe doesnt survive cloning, we could Test that rather easy