Any ideas on how to make a global ambient light?

reflecting this thread full of confused folks, I’m having trouble figuring out the global ambient lighting options of the engine.  To be clear, I’m looking to have all sides of an object receive lighting without that dark side of the moon effect…



Thanks :slight_smile:

Curiosity got the better of me yet again, so I took a look into this - and believe its broken!

I wrote a test to play with :-


package jmetest.renderer;

import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Capsule;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;

public class TestAmbient extends SimpleGame {


    public static void main(String[] args) {
   TestAmbient app = new TestAmbient();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }

    protected void simpleInitGame() {
        display.setTitle("Ambient test");

        // Set a value for global ambient coloring.
        lightState.setGlobalAmbient(new ColorRGBA(1f,0,0,0));

        Capsule capsule = new Capsule("capsule", 20, 20, 20, 5, 15);
        capsule.setLocalTranslation(new Vector3f(0, 0, -80));
        rootNode.attachChild(capsule);

        Box box = new Box("BOX", new Vector3f(-20,0,-80), 5f, 5f, 5f);
        TextureState ts = display.getRenderer().createTextureState();
        Texture t0 = TextureManager.loadTexture(
           TestEnvMap.class.getClassLoader().getResource("jmetest/data/images/Monkey.jpg"),
           Texture.MinificationFilter.Trilinear,
           Texture.MagnificationFilter.Bilinear);
        t0.setWrap(Texture.WrapMode.Repeat);
        ts.setTexture(t0);
        box.setRenderState(ts);
        rootNode.attachChild(box);
        box.updateRenderState();

        Sphere sphere = new Sphere("BALL", new Vector3f(20,0,-80), 10, 10, 5f);
        sphere.setRandomColors();
        rootNode.attachChild(sphere);

        rootNode.updateRenderState();
    }
}



The key part of this code being

lightState.setGlobalAmbient(new ColorRGBA(1f,0,0,0));



which I expected to add a red ambience to the scene. It didnt. So I went about looking why and think I found it.
In LWJGLLightState.java there is a method copyLightState - which doesnt copy the globalAmbient colour (patch below).
When I added it, everything seemed to work fine - but I would like a second opinion from someone better in the know :)

Index: LWJGLLightState.java
===================================================================
--- LWJGLLightState.java   (revision 4512)
+++ LWJGLLightState.java   (working copy)
@@ -556,6 +559,7 @@
         lightState.setLocalViewer(pkLState.getLocalViewer());
         lightState.setSeparateSpecular(pkLState.getSeparateSpecular());
         lightState.setEnabled(pkLState.isEnabled());
+        lightState.setGlobalAmbient(pkLState.getGlobalAmbient());
         for (int i = 0, maxL = pkLState.getLightList().size(); i < maxL; i++) {
             Light pkLight = pkLState.get(i);
             if (pkLight != null) {




Note that after applying the patch, I found I had to use values above 1.0 to get a reasonable value - e.g.

lightState.setGlobalAmbient(new ColorRGBA(1f,1f,1f,0));


was kinda grey, but

lightState.setGlobalAmbient(new ColorRGBA(5f,5f,5f,0));


was bright white

that's weird that you have to go above 1, as it should clamp down to 1 anyway…  Even Eberly's book makes note of that.  I'm going to try out the patch now, thanks!

:smiley:

Well that's why with JME I'm always looking for a second opinion :slight_smile:

Im fairly good at finding fixes to problems, but don't always fully understand why or how it fixes anything.

OpenGL, and consequently jME, use the equation materialAmbient * lightAmbient to compute the ambient lighting factor for a lit pixel. Because of that, you need to set both the light ambient and material ambient to ColorRGBA(1,1,1,1) to get perfect white ambient:



LightState lightState = ...
MaterialState matState = ...
matState.setAmbient(new ColorRGBA(1,1,1,1));
lightState.setGlobalAmbient(new ColorRGBA(1,1,1,1));

Thank you for that gem of information :slight_smile:



Unfortunately, now im confused again (always happens!).



The default value for MaterialState is .2, .2, .2, 1 (RGBA)  and the default for LightState is 0, 0, 0, 1 (RGBA).

If the formula is materialAmbient*lightAmbient , then with the LightState defaulting to 0, you shouldn't get anything. If I force the LightState to 0 tho, I still get ambient from the MaterialState. If I set the MaterialState to 0, then black it is?  Is this correct?



Also - Is my fix in LWJGLLightState needed or not. It feels like this is a value that should be inherited (due to the "global" in the name) but maybe im wrong here too?



Just looking to get all the details right here as I want to not only contribute the fix (if its needed), but also to attempt to document this info in the javadocs at least.

The fix seems to be correct and works for me on some objects (namely the primitives created via jME).  I think the majority of the problem for me lies in the OBJ's we're using as some surfaces take the lighting and others don't… direction seems to be less of an issue :expressionless:

Much appreciated, dhdd and JOC!  I always give up trying to fine tune my world atmospheric environment because of this issue (and similar issues with specularity).

JOC, yes the fix is correct, please commit asap.



EDIT: please also commit for JOGLLightState:



Index: src/com/jme/scene/state/jogl/JOGLLightState.java
===================================================================
--- src/com/jme/scene/state/jogl/JOGLLightState.java   (revision 4722)
+++ src/com/jme/scene/state/jogl/JOGLLightState.java   (working copy)
@@ -606,6 +606,7 @@
         lightState.setLocalViewer(pkLState.getLocalViewer());
         lightState.setSeparateSpecular(pkLState.getSeparateSpecular());
         lightState.setEnabled(pkLState.isEnabled());
+        lightState.setGlobalAmbient(pkLState.getGlobalAmbient());
         for (int i = 0, maxL = pkLState.getLightList().size(); i < maxL; i++) {
             Light pkLight = pkLState.get(i);
             if (pkLight != null) {
Index: src/com/jme/scene/state/lwjgl/LWJGLLightState.java
===================================================================
--- src/com/jme/scene/state/lwjgl/LWJGLLightState.java   (revision 4722)
+++ src/com/jme/scene/state/lwjgl/LWJGLLightState.java   (working copy)
@@ -556,6 +556,7 @@
         lightState.setLocalViewer(pkLState.getLocalViewer());
         lightState.setSeparateSpecular(pkLState.getSeparateSpecular());
         lightState.setEnabled(pkLState.isEnabled());
+        lightState.setGlobalAmbient(pkLState.getGlobalAmbient());
         for (int i = 0, maxL = pkLState.getLightList().size(); i < maxL; i++) {
             Light pkLight = pkLState.get(i);
             if (pkLight != null) {

I Committed it for you. Please modify the first posts subject to suggest that  :wink: