Shader lightning problem

Hi everyone!



Currently I had tried to make the more simplest shader: a gouraud per-pixel illumination



I have a simple problem: the light is always in front of my camera; when I turn around my object, light turn with me…



Here my code:



public static void main(String[] args) throws Exception {
      final StandardGame game = new StandardGame("Test Planete");
      
      if (GameSettingsPanel.prompt(game.getSettings())) {
         game.start();
               
         game.executeInGL(new Callable<Integer>() {
            public Integer call() {
               
               DebugGameState state = new DebugGameState();

               //Enable mouse input:
               MouseInput.get().setCursorVisible(true);

               Sphere s = new Sphere("sphere", Vector3f.ZERO, 16, 16, 10);
               
               CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
               
               cs.setEnabled(true);
               cs.setCullMode(CullState.CS_BACK);
               
               GLSLShaderObjectsState glsl = DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState();
               
               glsl.load(getClass().getResource("test.vert.glsl"),
                     getClass().getResource("test.frag.glsll"));
               glsl.setEnabled(true);
               
               s.setRenderState(glsl);
               s.setRenderState(cs);
               s.updateRenderState();
               
               DirectionalLight dl = new DirectionalLight();
               dl.setEnabled(true);
               dl.setDirection(new Vector3f(1500 , 1500, 2500));
               
               state.getLightState().attach( dl );
               
               s.setLocalTranslation(0, 0, -100);

               //Disable mouse input:
               MouseInput.get().setCursorVisible(false);

               state.getRootNode().attachChild(s);

               // Add it to the manager
               GameStateManager.getInstance().attachChild(state);

               // Activate the game state
               state.setActive(true);
               
               return 0;
            }
         });
      }
      
   }




And here my shaders code:

Vertex program...


varying vec3 normal;
varying vec3 lightDirection;

void main() {
   gl_Position = ftransform();
      
   normal = gl_NormalMatrix * gl_Normal;   
   
   lightDirection = gl_LightSource[0].position.xyz;   
}



...and fragment

varying vec3 normal;
varying vec3 lightDirection;

void main() { 
   gl_FragColor = vec4(dot(normalize(normal), normalize(lightDirection)));
}



I want to fix this for more complicated shaders based on light position, and I've make this sample application just for fix this :o/

Thanks to you ;)

I think gl_NormalMatrix automatically converts the normal to window space, you might want to multiply only by the modelview matrix.

unfortunely the modelviewMatrix is a 4x4 matrix, and when I make a vec4 from gl_Normal (x, y, z, 0), this do the same thing than gl_NormalMatrix… :confused:

the DebugGameState has a pointlight attached by default, so you are not referencing your directional light in your shader(and thus, position is not a direction)…

MrCoder said:

the DebugGameState has a pointlight attached by default, so you are not referencing your directional light in your shader(and thus, position is not a direction)...

But how does that explain this problem?
anykeyh said:

I have a simple problem: the light is always in front of my camera; when I turn around my object, light turn with me...

I have the same result on my machine with anykeyh's code.



gl_FragColor = vec4(normal.x, normal.y, normal.z, 1.0);


illustrates the problem even better. The normals change when rotating the camera, gives a nice psychedelic effect on a terrain :D

I have resolve them! (after one day and one night xD)



In fact i've tried to multiply the light position by gl_ModelViewMatrix but it's don't work perfectly:

If I apply any transformations on my mesh, the light position take the same transformation and rotate with object…



So I've tried to make an uniform, a vector to light position, but the position in the camera orthocenter axis:



//Compute it before each frame:

                //World light position
                Vector3f lightPosition = new Vector3f(0 , 0,  25000);
      
      //We transform world camera position to camera's axis position.
                Vector3f lightPositionInModelView = new Vector3f();
      
      lightPositionInModelView.set(
            -lightPosition.dot(r.getCamera().getLeft()),
            lightPosition.dot(r.getCamera().getUp()),
            -lightPosition.dot(r.getCamera().getDirection())
      );
//And use it in shader:
                glsl.setUniform("fvLightPosition", lightPositionInModelView);





In vertex program:


uniform vec3 fvLightPosition;

varying vec3 normal;
varying vec3 lightDirection;

void main() {
   gl_Position = ftransform();
      
   normal = gl_NormalMatrix * gl_Normal;   

        vec3 vertex = (gl_ModelViewMatrix * gl_Vertex).xyz;   

   lightDirection = fvLightPosition  - vertex;   
}



Thanks for your patience  :D

if you just add in a state.getRootNode().updateRenderState(); in the end of your code you can keep your old shaders, cause they were working…(but since you have a pointlight in there the lightdir will always be 100,100,100)…it didnt get the settings, but i've never used that standardgame stuff so i have no clue why, better ask darkfrog or start using simplegame instead