Search code examples
c++opengllightingopengl-compat

opengl light reduce reflection


I am trying to apply a light in my scene. However all objects are reflecting extremely and the colors get distorted.

enter image description here

How can I get a reflection similar to this example:

enter image description here

I assume I am choosing the wrong values for the materials?

This is how I setup light and materials:

void createLight() {

    GLfloat mat_specular[] = {0.3, 0.3, 0.3, 1.0};
    GLfloat mat_shininess[] = { 1.0 };
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);

    // Lighting set up
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    // Set lighting intensity and color
    GLfloat qaAmbientLight[]    = {0.2, 0.2, 0.2, 1.0};
    GLfloat qaDiffuseLight[]    = {0.8, 0.8, 0.8, 1.0};
    GLfloat qaSpecularLight[]   = {1.0, 1.0, 1.0, 1.0};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight);

    // Set the light position
    GLfloat qaLightPosition[]   = {12, 8, 12, 0.4};
    glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);

}

Solution

  • The values for the light are to high. Note in the standard light model the ambient, diffuse and specular part of the light are summed.

    The standard OpenGL Blinn-Phong light model is calcualted like this:

    Ka ... ambient material
    Kd ... difusse material
    Ks ... specular material
    
    La ... ambient light
    Ld ... diffuse light
    Ls ... specular light
    sh ... shininess
    
    N  ... norlmal vector 
    L  ... light vector (from the vertex postion to the light) 
    V  ... view vector (from the vertex psotion to the eye)
    
    Id    = max(dot(N, L), 0.0);
    
    H     = normalize(V + L);
    NdotH = max(dot(N, H), 0.0);
    Is    = (sh + 2.0) * pow(NdotH, sh) / (2.0 * 3.14159265);
    
    fs    = Ka*La + Id*Kd*Ld + Is*Ks*Ls;
    

    Since your specular light values are initialized by {1.0, 1.0, 1.0, 1.0};, this may give a sum which is greater than 1.0 in the cases where the normal vector of the object points to the light. This causes that the rendered objects looks almost white.

    I recommend to use a small ambient light part, because it is added to the entire object independent of the incident light.

    Use a strong lambertian diffuse light component, which reflects the direction of the light well.
    See How does this faking the light work on aerotwist?

    With the specular light component you have to experiment. Its effect depends strongly on the shininess parameter. But start by using a small value for the specular light and a shininess of about 10.0.

    GLfloat mat_shininess[]   = {10.0};
    GLfloat qaAmbientLight[]  = {0.2, 0.2, 0.2, 1.0};
    GLfloat qaDiffuseLight[]  = {0.6, 0.6, 0.6, 1.0};
    GLfloat qaSpecularLight[] = {0.3, 0.3, 0.3, 1.0};