Search code examples
openglglsl

What am I doing wrong in this Phong Shader?


I've been trying for some time now to debug this simple Phong-Shader and just came up short. The diffuse part is fine but the specular is not. It doesn't move with the camera.

Here's from one side:

Here's from one side

And here from the other:

And here from the other

As far as I can see, I did convert the Position to Viewspace, but, apparently, I made another mistake of some kind.

Vertex Shader:

#version 330
#extension GL_ARB_explicit_attrib_location : enable


layout(location=0) in vec3 aPosition;
layout(location=1) in vec3 aNormal;

out vec3 vPosition;
out vec3 vNormal;

uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;

void main(void) 
{
    vPosition = vec3(uModel * vec4(aPosition,1.0f));
    vNormal =   vec3(uModel * vec4(aNormal,  0.0f));
    gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
}

And my Fragment Shader

#version 330

out     vec4 FragColor;

in      vec3 vPosition;
in      vec3 vNormal;

uniform mat4 uView;
uniform vec3 uColor;
uniform vec3 uLightpositions[10];
uniform vec3 uLightcolors[10];
uniform float uPhongSpecular;


void main(void)
{
    FragColor = vec4(0.4*uColor, 1.0);//Ambient Value
    for(int i = 0; i < 5; i++){
        vec3 lVec = normalize(uLightpositions[i] - vPosition);
        vec3 nVec = normalize(vNormal);
        
        float diffuse = max(dot(lVec,nVec), 0);
        FragColor += 0.5* vec4(uLightcolors[i] * diffuse,0.0f);
        
        vec3 rVec = normalize(reflect(lVec,nVec));
        vec3 vVec = -normalize(vec3(uView * vec4(vPosition,1.0)));
        
        float specular = 0;
        if(dot(rVec,vVec) < 0.0)
        {
            specular = pow(max(dot(-rVec,vVec),0),uPhongSpecular);
        }
        FragColor += 0.2*vec4(uLightcolors[i] * specular,0.0f);
    }
}

Solution

  • The problem is dot(-rVec, vVec). vVec is a vector in view space, however, rVec is a vector in world space. Convert rVec from world space to view space:

    vec3 rVec = normalize(reflect(lVec, nVec));

    vec3 rVec = normalize(mat3(uView) * reflect(lVec, nVec));