0
\$\begingroup\$

I am using OpenGL 2.1 and GLSL 1.20 .

I am trying to compute the fragment color applying the Phong lighting model.

This is the formula I have (the original formula has a summation, but since the light is only one it's not needed):

Ip = Ka * Ia + Kd * (Lm • N) * Id + Ks * (Rm • V)^s * Is

With:

Ka, Kd, Ks, s respectively material's ambient, diffuse, specular and shininess values;
Ia, Id, Is respectively light ambient, diffuse and specular values;
N surface normal;
Lm direction vector point-light;
Rm= 2.0 * (Lm • N) * N - Lm .

So this is the vertex shader:

#version 120

varying vec3 position; // I'll pass the position and the normal to
varying vec3 normal;   // the fragment shader
varying vec4 diffuse; // I'll compute here the ambient and diffuse
varying vec4 ambient; // values and pass them to the fragment shader

void main()
{
    gl_Position = ftransform();
    position= vec3(gl_Position);
    gl_TexCoord[0] = gl_MultiTexCoord0;

    normal= normalize(gl_NormalMatrix * gl_Normal);
    ambient= gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
    ambient+= gl_LightModel.ambient * gl_FrontMaterial.ambient;
    diffuse= gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
}

And this is the fragment shader:

#version 120

varying vec3 position;
varying vec3 normal;
varying vec4 diffuse;
varying vec4 ambient;

void main()
{
    gl_FragColor= ambient+diffuse;
    vec3 Lm= vec3(normalize(position-vec3(gl_LightSource[0].position)));
    vec3 V= vec3(normalize(-position));
    float LdotN= max(dot(Lm,normal),0.0);  // Since I'll use this two times
                                           // I compute it just once and reuse it
    vec3 Rm= 2.0* LdotN * normal-Lm;
    // First part of the formula: Kd * (Lm • N) * Id
    gl_FragColor+= gl_FrontMaterial.diffuse * LdotN * gl_LightSource[0].diffuse;
    // Second part: Ks * (Rm • V)^s * Is
    gl_FragColor+= gl_FrontMaterial.specular* pow(max(dot(Rm,V),0.0),gl_FrontMaterial.shininess)* gl_LightSource[0].specular;
}

The result is unrealistic, it seems like the specular light is not really applied:

enter image description here

I tried with a teapot and this is the result:

enter image description here

After changing the camera position (the teapot was covering the light):

enter image description here

I think it's ok.

enter image description here

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Are you sure the light position is such that the specular reflection should be visible? I suggest testing with a sphere or other highly curved geometry to more completely display the effects of your lighting. \$\endgroup\$
    – Kevin Reid
    Commented Feb 3, 2013 at 5:25
  • \$\begingroup\$ With a teapot it's more realistic, but I think there is still some problem, it doesn't seem 3D. \$\endgroup\$ Commented Feb 3, 2013 at 12:54
  • \$\begingroup\$ Ok but the light was covered by the teapot, I just changed the camera position making it be between the light and the teapot, and it's all ok. If you make it an answer I'll accept it. \$\endgroup\$ Commented Feb 3, 2013 at 12:57
  • 3
    \$\begingroup\$ Not sure if this affects the lighting, but you have some issues with backface culling / z-ordering. This is clearly visible in the second image. \$\endgroup\$
    – msell
    Commented Feb 3, 2013 at 13:55
  • \$\begingroup\$ I did an extra normalization when calculating the normal, I changed it to normal= gl_NormalMatrix * gl_Normal; Now there isn't that shadow but I still have the doubt that it's not correct. Now it looks like the last image. \$\endgroup\$ Commented Feb 3, 2013 at 23:40

3 Answers 3

5
\$\begingroup\$

I think there are at least three major problems:

  • You do not normalise the interpolated normal vector in the fragment shader, therefore losing all the benefits of Phong shading because the resulting normal can have a length much smaller than 1.
  • The position value you pass to the fragment shader is in clip space, but the vector V is computed using the eye position in view space. You cannot do the light calculations in different spaces; you should choose view space instead (ie. apply model-view to the vertex instead of model-view-projection). Also, make sure the light position is passed in view space, too.
  • Your normal is most likely pointing outside the object; however Lm is computed as pointing from the light to the object; you should invert the sign of Lm.
\$\endgroup\$
1
\$\begingroup\$

[Moved from comment on request and expanded.] I don't know what the actual problem is, so here's some advice on troubleshooting lighting.

Are you sure the light position is such that the specular reflection should actually be visible on that (apparently) flat square? Most ‘shiny’ objects are curved and so have greater opportunities to have a visible specular ‘hot spot’.

I suggest instead testing with a sphere or other highly curved geometry to more completely display the effects of your lighting.

\$\endgroup\$
1
  • \$\begingroup\$ Sorry that I told you I was accepting this answer, but later I discovered there were more problems with the code. \$\endgroup\$ Commented Feb 4, 2013 at 0:40
1
\$\begingroup\$

There is some problem in the shader program: 1) The normal must be normalized. 2) Change the direction of Lm 3)V should not be normalized as it is the position of vertex in camera space

Hope it will give you the correct result.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .