kimziv / oglsuperbible5

GLTools and OpenGL SuperBible (5th Edition) OpenGL超级宝典第五版
41 stars 16 forks source link

Chapter 6: Incorrect computation of Specular component #47

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Specular component in ADSGourad and ADSPhong are computed with an incorrect 
equation.

The correct specular component should be computed by the scalar product of the 
reflection vector and the normalized position vector of the fragment/vertex 
with respect to the camera (which is normalized(vPosition3) for ADSGourad)

The incorrect code...

    // Specular Light
    vec3 vReflection = normalize(reflect(-vLightDir, vEyeNormal));
    float spec = max(0.0, dot(vEyeNormal, vReflection));
    if(diff != 0) {
        float fSpec = pow(spec, 128.0);
        vVaryingColor.rgb += vec3(fSpec, fSpec, fSpec);
    }

The code below fixes the specular calculation and also makes a small 
optimization... if diff is zero, we dont need to calculate the specular 
component.

    // Specular Light
    if (diff != 0){ // do this only if diffusion is non zero.
        vec3 vReflection = normalize(reflect(-vLightDir, vEyeNormal));
        vec3 vNormPos3 = normalize(vPosition3);
        float spec = max(0.0, -dot(vNormPos3, vReflection)); // correct specular component
        float fSpec = pow(spec, 128.0);
        vVaryingColor.rgb += fSpec * specularColor.rgb;
    }

The same problem also affects ADSPhong. The fix is as follows...

Add new out attribute vVaryingPosition to ADSPhong.vp

smooth out vec3 vVaryingLightDir;
smooth out vec3 vVaryingPosition;// new line
...
...
    vVaryingLightDir = normalize(vLightPosition - vPosition3);
    vVaryingPosition = vPosition3; // new line

and add correct specular calculation to ADSPhong.fp

smooth in vec3 vVaryingLightDir;
smooth in vec3 vVaryingPosition; // new line
...
...
    // Specular Light
    if(diff != 0) {
        vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
        float spec = max(0.0, -dot(normalize(vVaryingPosition), vReflection));
        float fSpec = pow(spec, 128.0);
        vFragColor.rgb += fSpec * specularColor.rgb;
    }

The incorrect and correct Phong lighting outputs are attached.

Original issue reported on code.google.com by nag.ra...@gmail.com on 17 Sep 2012 at 11:21

Attachments: