Lighting Being Applied to Node without Lighting

My scenegraph is set up as follows


RootNode
|
|
---LitNode-UnlitNode----
|
|
----Ship
Bullet

The LitNode has an Enabled LightState which I do with the following code


        // Set up a basic, default directional light.
        DirectionalLight light = new DirectionalLight();
        light.setDirection(new Vector3f(0,-1,0));
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        light.setAmbient(new ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f));
        light.setEnabled(true);

        // Attach the light to a lightState and the lightState to rootNode.
        lightState = display.getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.attach(light);
        sceneLightedNode.setRenderState(lightState);



The unlitNode has no lightState attached. When I attach a bullet to the unlitNode the bullet still gets lit in the same red ambient light. Is this supposed to happen?? I've checked to make sure the bullet is in fact getting attached to unlitNode and that unlitNode is attached to rootNode.

I've also tried adding a disable lightState to unlitNode to no avail. I wrote a small demo program to try to reproduce the problem but was unsucessful in getting the problem to occur.

Finally, I printed out the renderstates of the unlitNode just in case but there are no unexpected renderStates.

Another odd thing which might help in figuring out the problem is that if I toggle wireframe mode on the lighting on the bullets turns off. Then when I turn wireframe off the lighting stays off. Also, if I toggle the lights off for the litNode then turn the lights back on for the litNode the bullets remain unlit like they should.

Does anyone have any ideas as to what might be going on? My program is too large at this point to post as code. Thank you for any help.

It’s hard to say what is going wrong in your scene. The code your post doesn’t show any apparent issues. You say the test program doesn’t exhibit the problem, so it’s not a jME bug?



One thing you can do is insure that it ignores any light state that it might get assigned:


bullet.setLightCombineMode(LightState.OFF);



That doesn't really answer why the bullet is getting a lightstate assigned but will keep it from getting lit.

When I print out the RenderStateList for the bullet it comes up as empty. Ditto for the rootNode and the unlitNode that the bullet is attached to. If a lightState is being assigned should it show up in one of those lists?



Doing the LightState.OFF thing makes the bullet disappear entirely! 8-O



I’ll keep looking through the code to try and figure out what might be the problem.



Oh … is there anyway to dump a “layout” of your scenegraph? So something like rootNode.print() and it shows you all the children and the childrens children and how they are laid out?



I think I code that up myself but just wanted to see if there was an easy way to do it already.

Doing the LightState.OFF thing makes the bullet disappear entirely! Shocked


Hmmm something certainly is strange then.

It's hard to think of what the problem could be without a test case. I'll play with stuff a little bit this evening and see if anything causes a lightbulb to go off.

Okay … I have a theory. I think it might have something to do with zBuffer stuff. I think maybe the bullet is getting “covered” by my space background because when I create the bullet I can’t see it. But when I fly my ship over where the bullet is (the bullet is just a stationary sphere at the moment) I can now see the bullet.



In other words, I can see the bullet when my ship is sitting on top of it. I’m not familiar enough with the zBuffer stuff to know for sure if that could cause this type of problem.





How should I set the ZBufferState for a node that I want to always be rendered in the back (i.e., everything else should be on top of it)?

Sounds similar to how you’d want to set up a skybox (your space background is always the background).


      ZBufferState zbs= display.getRenderer().createZBufferState();
      zbs.setWritable(false);
      zbs.setEnabled(true);
      zbs.setFunction(ZBufferState.CF_LEQUAL);
      background.setRenderState(zbs);



would set zbuffer to never allow the space background to overwrite a pixel in the depthbuffer (i.e. anything drawn in that pixel will overwrite the space background no matter what.

shoot … that wasn’t the problem. This is so crazy. When I create the bullets and attach them to the nonLit node I can’t see them at all. When I toggle the lights for the litNode on then off all of a sudden they appear.





sigh I think this is gonna take a while to figure out. I hate getting stuck on stuff like this. Oh well hehe. It’s a good thing spring break is coming up.

Well, we’ll help in any way we can. As you think you have it down to a few bits of code, feel free to post them and ask.

I just noticed my rootNode has the following zBufferState


        ZBufferState buf = display.getRenderer().createZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.CF_LEQUAL);
        rootNode.setRenderState(buf);



From the code snippet you provided before this doesn't make sense does it? If you have ZBufferState.CF_LEQUAL that means nothing in rootNode can ever overwrite a pixel in the depthbuffer?? Is that something you want set at the rootNode level? I think that code was from some demo that I was using as a starting point and I just left it in cause I didn't understand it at the time.

Thanks for all your help so far mojo.

--Edit

Taking that out made everything disappear heh. I definitely don't understand this zbuffer stuff. Time to do some reading :)

---Edit
Okay well I read my handy openGL book and the depth buffer stuff makes sense now. Obviously I need to set CF_LEQUAL so that any fragment which is closer to the near clipping plane overrides anything that is further.

Problem solved I think :smiley:



Right after I attach the bullet to the unlitNode I needed to call unlitNode.updateRenderState();



I’m not quite sure why I have to do this though. Anyone know why?

Ahh, simply forgot the basic stuff. updateRenderState initializes the nodes renderstates (only needs to be called when the node is added to the tree). This is done to create the final renderstates for a node as the propogate and in the case of lighting and textures merge down the tree.

ahh … So you need to call updateRenderState even if you didn’t explicitly set any render states? Sorry to bug you so much on something that ended up being so basic. It’s almost always something like that haha.



Thank again for your help Mojo.

Heh, while reading down through this thread I was screaming updateRenderState… XD



setting a render state on a spatial is a bit like setting a local translation. We actually translate to a spatial’s world translate before rendering, the local translate is used to calculate that though. The same is true for setting a render state… those you set on a spatial are considered “local” but an updateRenderState is needed to calculate the “world” states (ie. those inherited from further up in the tree, or default states if nothing is inherited.)



I’ve thought before about forcing the update, but you’d need to do so once all scenegraph elements above the spatial are set. I’ll keep that in mind as jME .9 unfolds.

ahhh … thank you for the clarification Renase. Makes a lot of sense now.