Bunker lighting


#1

hi, im just curious, what is the best way of doing some bunker lighting?

should i add point light each sector and remove directional light and ambient while player is inside or how? adding a lot point lights sound fps kill for me, but i never tried so idk.

it was funny for me that directional light was working so floor specular was looking bad there.

was also thinking about adding just directional light from above(0,-1,0) with little ambient and add point lights only in some specific areas to increase lighting.

i hope you will advise me.


#2

3 days no respond :frowning:

i tried PointLights, but i had problem with only one PointLight working…
found this topic:

in my code i prepare “parts” and use them via cloning.

Please note im using PBR materials - but one point light work, as i know more should too.

So i started doing some custom LightNode(because LightNode clone dont work too).
(init method is executed on cloned node)
i tried a lot of implementations, dont know why it dont work. here are some:

no point lights working with below:

import com.jme3.light.PointLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.LightNode;
import com.jme3.scene.Node;

/**
 *
 * @author oxplay
 */
public class LampContainer extends Node {
    public float radius;
    public ColorRGBA color;
    public LightNode light;
    
    public LampContainer(float radius, ColorRGBA color) {
        this.radius = radius;
        this.color = color;
    }

    public void init(){
        light = new LightNode("Light", new PointLight(Vector3f.ZERO, color, radius));
        App.getRootNode().attachChild(light);
        updateLightPos();
    }
    
    @Override
    public void setLocalTranslation(float x, float y, float z) {
        super.setLocalTranslation(x, y, z);
        //updateLightPos();
    }

    @Override
    public void setLocalTranslation(Vector3f localTranslation) {
        super.setLocalTranslation(localTranslation);
        //updateLightPos();
    }

    @Override
    protected void updateWorldTransforms() {
        super.updateWorldTransforms();
        //updateLightPos();
    }

    @Override
    protected void setParent(Node parent) {
        if(parent == null){
            App.getRootNode().detachChild(light);
        }
        super.setParent(parent); //To change body of generated methods, choose Tools | Templates.
    }
    
    private void updateLightPos(){
        if(light != null){
            //light.setLocalTranslation(this.getWorldTranslation());
        } 
    }
}

no light with below too:

import com.jme3.light.PointLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

/**
 *
 * @author oxplay
 */
public class LampContainer extends Node {
    public float radius;
    public ColorRGBA color;
    public PointLight light;
    
    public LampContainer(float radius, ColorRGBA color) {
        this.radius = radius;
        this.color = color;
    }

    public void init(){
        light = new PointLight(Vector3f.ZERO, color, radius);
        Inversion.app.getRootNode().addLight(light);
        updateLightPos();
    }
    
    @Override
    public void setLocalTranslation(float x, float y, float z) {
        super.setLocalTranslation(x, y, z);
        updateLightPos();
    }

    @Override
    public void setLocalTranslation(Vector3f localTranslation) {
        super.setLocalTranslation(localTranslation);
        updateLightPos();
    }

    @Override
    protected void updateWorldTransforms() {
        super.updateWorldTransforms();
        updateLightPos();
    }

    @Override
    protected void setParent(Node parent) {
        if(parent == null){
            Inversion.app.getRootNode().removeLight(light);
        }
        super.setParent(parent); //To change body of generated methods, choose Tools | Templates.
    }
    
    private void updateLightPos(){
        if(light != null){
            light.setPosition(this.getWorldTranslation());
        } 
    }
}

to the last one, when i move

    light = new PointLight(Vector3f.ZERO, color, radius);
    Inversion.app.getRootNode().addLight(light);
    updateLightPos();

to constructor method, i see one point light only. this is certain, because its cloned and clone dont work it seems. Anyway im not quite sure, why it dont work when this 3 lines are in init method that is executed on already cloned node…

i will work on it more, but wanted to share that something wrong is with PointLight.(at least with cloning - still)


#3

I’m curious to know the best way to do this as well, in my case for the lighting inside caves and houses


#4

Lights only effect spatials that are below them on the same node. You can easily break each “sector” into it’s own scene via nodes and only add the lights to that sector node, not to the root node. You’ll need to parent anything you want effected by the lights to the scene they are in, which may or may not be easier than loading/unloading scene lights onto the root node.

That said, you shouldn’t extend node, especially not the way you are making your “lamp container”. To add a light to the scene it’s as simple as

Light light = new PointLight(new Vector3f(0,0,0), color, radius);
sceneNode.addLight(light); //could be your rootNode or a scene of just the room

If you later want to move said lights make a LightControl and attach it to the spatial you want the light to follow.

Light light = new PointLight(new Vector3f(0,0,0), color, radius);
rootNode.addLight(light);//use root node to have the light effect everything
LightControl lc = new LightControl(light);
spatial.addControl(lc);//NOT the root node!

#5

Now that I think about it, having the lights on individual scene nodes will look fine in the scene but will “snap” in and out as you change rooms. It might be better to have an appstate that loads light setups based on the player entering/exiting bounding boxes that are larger than the rooms you actually want lit. That way when a player gets close to the next room, it loads in the corresponding lights, you open the door and enter the new room and the old rooms lights are still present until you move far enough away. You might be able to accomplish this via a control as well, I’m not entirely sure.


#6

that is exactly what i want to do(when this issue is solved), enable/disable lights based on rooms/distance. where rooms are generated based on tiles, player will be able build bunker.

But im stuck on problem that lights dont work.

its not about light location, because i tried setting light more above and also no help.

But i will try LightControl like you said and we will see.


#7

Where did you add the light? It seems like it worked when you added it to the root node. I didn’t see the code where you added it to some other node under which geometry exists.

Lights only light the parts of the scene to which they are added (and can be added to multiple).

I also reiterate QSDragon’s advice not to extend node for this. The fact that you have kind of means you don’t understand how lights work, though, so that was a good indicator of where you needed help.


#8

“it worked” is wrong sentence, because there is bug in cloning.

Anyway like said i moved lines this mean i still add it to rootNode.

Lights only light the parts of the scene to which they are added

this is why i add light to RootNode. directly or via LightNode.

I also reiterate QSDragon’s advice not to extend node for this. The fact that you have kind of means you don’t understand how lights work, though, so that was a good indicator of where you needed help.

i think you dont read all posts. since LightNode dont work with clone, i created test semi-custom-LightNode to init light after clone, but had some new issues. also like i said im still looking at this, so just posted if someone might help, if not, then i will fix it myself.

Please do not skip main thread question and read every post.

btw. true help, would be providing “some” fix for a point light cloning trully.

also:

You’ll need to parent anything you want effected by the lights to the scene they are in, which may or may not be easier than loading/unloading scene lights onto the root node.

i did not explained how scene will look exactly, so this advise will not help. i need pointLights in rootNode to affect everything i got. (or later some bunkerNode i will do).

if you really need have explained this(because i think its not related to my issue) so i create bunker from tiles/parts. each some distance(some tiles) will be light(that need to be in bunkerNode - currently rootNode to affect all bunker tiles) where parts for tiles i prepare earlier to just clone. but, when creating LightNode or Light and clone it as tile part, it dont work(only first light exist, and its not about locations - in my first post i even provided topic where other person had this clone issue), thats why i created this test-node-extension that you mention all the time idk why. Please focus on cloning issue and please provide some solution instead.


#9

ok finished my workarround for light clone issue.

To explain to others, i spotted issue when i was doing below(this add part to my part list, where parts are cloned later and used):

    partList.put("TunnelLight", new LightNode("TunnelLight", new PointLight(new Vector3f(0,0,0), ColorRGBA.Blue, 20)));

this was providing only one light for me, found topic about this issue that someone else had it too. please note when i tried clone Light without LightNode, it also got same issue.

for me fix was to create custom LightNode.

    partList.put("TunnelLight", new LampContainer(20, ColorRGBA.Blue));

where i can later just check if its LampContainer and use init() to make new light since clone dont work, or just override clone method to add new Light with params assigned.

@QSDragon
i think LightControl would not help me much here, since i need clone light anyway. and cloning was issue trully.


#10

Ugh… I didn’t even know JME had a LightNode. Blindspot I guess.

That class should be deprecated.


#11

hmm, but PointLight is not deprecated right? as i seen pointLight.clone() have some issue.

Please see Many point light, only one rendered

at least i think so, because when i used .clone() it dont work.
when i create new PointLight(same params) - it work.


#12

Not sure how that can be, though. The clone methods of the Light classes are really straight forward. Doesn’t seem like there is any state leaking, etc…

The other thread is super light on details.

A test case might be nice if someone has the time to put one together.


#13

hmmm… every situation of cloning in TestCase works.

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.LightNode;
import com.jme3.scene.shape.Box;

/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 * @author normenhansen
 */
public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        Box b = new Box(1, 1, 1);
        Geometry geom = new Geometry("Box", b);

        Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        mat.setColor("Diffuse",ColorRGBA.White);
        mat.setColor("Specular",ColorRGBA.White);
        geom.setMaterial(mat);
        geom.setLocalTranslation(-2, -2, -2);
        
//        PointLight lightR = new PointLight(new Vector3f(0, -2, -2), ColorRGBA.Red, 30);
//        rootNode.addLight(lightR);
//        PointLight lightB = new PointLight(new Vector3f(-2, 0, -2), ColorRGBA.Blue, 30);
//        rootNode.addLight(lightB);
//        PointLight lightG = new PointLight(new Vector3f(-2, -2, 0), ColorRGBA.Green, 30);
//        rootNode.addLight(lightG);
        
        
//        PointLight lightR2 = new PointLight(new Vector3f(0, -2, -2), ColorRGBA.Red, 30);
//        rootNode.addLight(lightR2);
//        PointLight lightB2 = lightR2.clone();
//        lightB2.setPosition(new Vector3f(-2, 0, -2));
//        lightB2.setColor(ColorRGBA.Blue);
//        rootNode.addLight(lightB2);
//        PointLight lightG2 = lightR2.clone();
//        lightG2.setPosition(new Vector3f(-2, -2, 0));
//        lightG2.setColor(ColorRGBA.Green);
//        rootNode.addLight(lightG2);
        
        LightNode lnode = new LightNode("test", new PointLight(new Vector3f(0, -2, -2), ColorRGBA.Red, 30));
        rootNode.attachChild(lnode);
        rootNode.addLight(lnode.getLight());
        LightNode lnode2 = (LightNode)lnode.clone();
        lnode2.setLocalTranslation(new Vector3f(-2, 0, -2));
        lnode2.getLight().setColor(ColorRGBA.Blue);
        rootNode.attachChild(lnode2);
        rootNode.addLight(lnode2.getLight());
        LightNode lnode3 = (LightNode)lnode.clone();
        lnode3.setLocalTranslation(new Vector3f(-2, -2, 0));
        lnode3.getLight().setColor(ColorRGBA.Green);
        rootNode.attachChild(lnode3);
        rootNode.addLight(lnode3.getLight());
        
        
        rootNode.attachChild(geom);
    }

    @Override
    public void simpleUpdate(float tpf) {
        //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}

you might be right, its something else, or maybe its PBR related(or maybe because im setting colors), hard to say. i will try find.

edit:

anyway you say LightNode is deprecated, so good to know. I needed some spatial based element to be able to clone and attach like other elements, knew only LightNode.


#14

I think I found an additional way to dim the ambient light and directional light, from within the fragment shader

I notice that you can use the value of the fallOff variable for each light to determine its type, and then omit certain lights in the lighting loop accordinglyt. If the falloff value is 1.0 or 0.0 then the light is a directional or ambient lightt, and any values between means its a point light


#15

It isn’t deprecated. I just think it should be deprecated. It provides no real value over LightControl except confusing people about extending Node.


#16

i really dont know what exactly caused my earlier issue.

Anyway i thought so many lights will kill fps, but its not. JME rules :slight_smile:

lllllllllllllllllllllllliiii

the only problem i had was shadows. it was working but flickering. i found some posts that need rotate node a little or settings.setDepthBits(32); but nothing helped trully. i belive i just have too many lights.

i also noticed point light shadows pass through walls, or something else odd happended. but anyway im happy how it look without shadows.


#17

i already got it working properly using own light control (similar to LightControl)

Anyway wanted to share some odd behaviour about LightNodes i noticed.

i understand i should remove light too, but this made me confused, because i thought lights are in same place(0,0,0) and dont even realize that removed LightNode do not remove its light too.

the only difference is this line:
rootNode.detachAllChildren();

    PointLight light = new PointLight(new Vector3f(0, 0, 0), ColorRGBA.Brown, 30);

    LightNode lnode = new LightNode("test", light);
    lnode.setLocalTranslation(new Vector3f(0, -2, -2));
    lnode.getLight().setColor(ColorRGBA.Red);
    rootNode.attachChild(lnode);
    rootNode.removeLight(lnode.getLight());
    rootNode.addLight(lnode.getLight());
    rootNode.removeLight(lnode.getLight());
    rootNode.addLight(lnode.getLight());

    LightNode lnode2 = (LightNode)lnode.clone();
    lnode2.setLocalTranslation(new Vector3f(-2, 0, -2));
    lnode2.getLight().setColor(ColorRGBA.Blue);
    rootNode.attachChild(lnode2);
    rootNode.removeLight(lnode2.getLight());
    rootNode.addLight(lnode2.getLight());

    rootNode.detachAllChildren();

    
    LightNode lnode3 = (LightNode)lnode.clone();
    lnode3.setLocalTranslation(new Vector3f(-2, -2, 0));
    lnode3.getLight().setColor(ColorRGBA.Green);
    rootNode.attachChild(lnode3);
    rootNode.removeLight(lnode3.getLight());
    rootNode.addLight(lnode3.getLight());
    rootNode.removeLight(lnode3.getLight());
    rootNode.addLight(lnode3.getLight());

mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm

    PointLight light = new PointLight(new Vector3f(0, 0, 0), ColorRGBA.Brown, 30);

    LightNode lnode = new LightNode("test", light);
    lnode.setLocalTranslation(new Vector3f(0, -2, -2));
    lnode.getLight().setColor(ColorRGBA.Red);
    rootNode.attachChild(lnode);
    rootNode.removeLight(lnode.getLight());
    rootNode.addLight(lnode.getLight());
    rootNode.removeLight(lnode.getLight());
    rootNode.addLight(lnode.getLight());

    LightNode lnode2 = (LightNode)lnode.clone();
    lnode2.setLocalTranslation(new Vector3f(-2, 0, -2));
    lnode2.getLight().setColor(ColorRGBA.Blue);
    rootNode.attachChild(lnode2);
    rootNode.removeLight(lnode2.getLight());
    rootNode.addLight(lnode2.getLight());

    LightNode lnode3 = (LightNode)lnode.clone();
    lnode3.setLocalTranslation(new Vector3f(-2, -2, 0));
    lnode3.getLight().setColor(ColorRGBA.Green);
    rootNode.attachChild(lnode3);
    rootNode.removeLight(lnode3.getLight());
    rootNode.addLight(lnode3.getLight());
    rootNode.removeLight(lnode3.getLight());
    rootNode.addLight(lnode3.getLight());


#18

Lights are not part of the scene graph. They ANNOTATE the scene graph.

This is why LightNode is so confusing because all it’s doing is providing a position to a light… which is precisely what the LightControl will do. (This is why I think LightNode should be deprecated.)

So of course removing LightNode will not remove it’s light that has been annotated around the scene graph. a) how could it? b) that’s a totally separate thing from what LightNode is doing: just setting the position of the light.


#19

what i wanted to tell was that removed LightNode should not reset light position to same position, because it is confusing.

this is how its visible for someone who start using multiple lightNodes:

  • he add lightNodes and lights
  • he remove some of lightNodes
  • lights was “removed”(moved trully) from lightNodes positions
  • so he think it is removing light…
  • light in one place is more bright(he wonder why)
  • he investigate that lightNode was not removing light trully, but move it on remove.

this path is very confusing :slight_smile: i hope it will be deprecated and removed quickly or at least changed so position dont change on remove, because it make people dont see it trully dont remove the light.

Next thing what i noticed is that AbstractControl do not have any method related to “spatial remove from render scene node”. Usually controls just control spatial data, but what should i use if i for example want to attach and detach light or physics or anything else related to spatial only via control? Once spatial is removed, then control do not even know it. just update method do not eval anymore. Maybe im just blind but i dont seen method related to spatial remove. (set spatial null is related to control remove only)


#20

The first part of your post describes something that can’t be happening because of the second part of your post.

Every update, the LightNode’s LightControl (because LightNode is pointlessly just a wrapper around a LightControl) sets the position of the light. When it is no longer being updated, the light just stops being updated. No zeroing or anything.

If that’s what you are seeing then you are doing something else that’s causing that.

This is one of the many many hazards of treating spatials like game objects.

It is an unanswerable question. A particular node could be in 100 attached scenes. It has no way of knowing unless update and render are called.

So Spatials make really piss-poor game objects. They make really excellent views, though.