-2

There is a scene with some objects and a terrain. When I try to rotate the object the normals stay the same. Means that the dark side of an object stays the dark side of an object. My specular lightning is working.

Vertex Shader:

uniform vec3 lightPos;
uniform sampler2D Texture;
varying vec2 TexCoord;

varying vec3 position;
varying vec3 vertex;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 normal;
varying vec3 oneNormal;
varying vec3 lightPos2;

void main()
{
        gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;
        position=vec3(gl_ModelViewMatrix*gl_Vertex);
        vMatrix = mat3(gl_ModelViewMatrix);
        lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
        vertex = vec3(gl_Vertex);
        nMat = gl_NormalMatrix;
        normal=gl_NormalMatrix*gl_Normal;
        oneNormal = gl_Normal;
        TexCoord=gl_MultiTexCoord0.xy;
}

Fragment Shader:

varying vec3 position;
varying vec3 normal;

uniform sampler2D Texture;
varying vec2 TexCoord;

uniform vec3 lightPos;
varying vec3 vertex;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
uniform float shininess;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 oneNormal;
varying vec3 lightPos2;


void main()
{
        float dist=length(vertex-lightPos);
        float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
        vec4 TexColor = texture2D(Texture, TexCoord);
        vec3 ambient=TexColor.rgb*lambient; //the ambient light

    //=== Diffuse ===//
        vec3 surf2light=normalize(position-lightPos2);
        float dcont=max(0.0, 
                    dot( normalize(nMat*(-normal)), nMat*surf2light) );
        vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

    //=== Specular ===//
        vec3 surf2view = normalize(lightPos-position);
        surf2light=nMat*normalize(-vertex);
        vec3 reflection=reflect(-surf2view,normalize(normal));

        float scont=pow(max(0.0,dot(surf2light,reflection)),shininess);
        vec3 specular=scont*lspecular;

        gl_FragColor=vec4((ambient+diffuse+specular)*att,1.0);
}
ratchet freak
  • 47,288
  • 5
  • 68
  • 106

1 Answers1

0

You are transforming the normals. But at least for part of the lighting calculations, you're using a light source position that is also transformed into the same coordinate space. If you transform both the normals and the light source, the direction of the normals relative to the light source will be the same again.

Extracting the key lines from the vertex shader:

    position=vec3(gl_ModelViewMatrix*gl_Vertex);
    lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
    normal=gl_NormalMatrix*gl_Normal;

gl_NormalMatrix corresponds to gl_ModelViewMatrix, with the necessary adjustments to transform direction vectors instead of points. Therefore, the modelview transformation has been applied to all of position, lightPos2 and normal.

Then, all three of these values (with interpolation applied) are passed into the fragment shader, where you have this calculation for the diffuse lighting term:

    vec3 surf2light=normalize(position-lightPos2);
    float dcont=max(0.0, 
                dot( normalize(nMat*(-normal)), nMat*surf2light) );
    vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

Now, there's a couple of issues here:

  • You're applying nMat, which is the normal matrix, to both vectors again, even though they were already transformed. It does no harm, since the dot product does not change if you apply the same rotation to both vectors, but it does not make sense.
  • All the values used (position, lightPos2, normal) were transformed by the modelview matrix. So their relative positions/directions are exactly the same as they were originally. The result of the calculation will be the same as it would be if it were applied to the corresponding untransformed vectors.

You need to decide which coordinate system you want to use for the lighting calculations. There are at least a couple of options. The easiest one for you is probably to use eye coordinate space. To do this, you can apply the view transformation to the light position before passing it into the shader, and then use this light position directly, without any additional transformations, in the shader code.

Since you say that the specular lighting works as desired, and you're using the uniform lightPos there, it might be as simple as using that variable instead of lightPos2 in the diffuse calculation.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133