0
votes

I am trying to implement the Phong reflection model using GLSL 3.3. I have followed a tutorial for it, and although I have changed my code to match up what the tutorial has, I am still unable to create the effect. I have a weird spotlight effect coming from origin to wherever the light source is instead of any Phong reflection. Here is the vertex shader:

#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out vec3 Color;
out vec3 NormalCamSpace;
out vec3 EyeDir;
out vec3 PositionWorldSpace;
out vec3 LightDirCamSpace;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 lightPos;

void main() {
    NormalCamSpace =(V*M *vec4(normal,0.0)).xyz;
    PositionWorldSpace = (M * vec4(position,1.0)).xyz;
    vec3 PositionCamSpace = (V*M*vec4(position, 1.0)).xyz;
    EyeDir = -PositionCamSpace;
    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;
    Color = vec3(0.0, 1.0, 1.0);
    gl_Position = MVP * vec4(position, 1.0 );
}

And here is the frag shader:

#version 330
in vec3 Color;
in vec3 NormalCamSpace;
in vec3 PositionWorldSpace;
in vec3 EyeDir;
in vec3 LightDirCamSpace;
uniform vec3 lightPos;
uniform float ambientIntensity;

out vec3 outColor;

void main() {
    vec3 n = normalize(NormalCamSpace);
    vec3 l = normalize (LightDirCamSpace);
    float cosTheta = clamp(dot(n, l),0,1);

    vec3 E = normalize(EyeDir);
    vec3 R = reflect(-l, n);
    float cosAlpha = clamp(dot(E, R),0,1);
    cosAlpha = pow(cosAlpha, 5);
    float attenIntensity = 1.0 + 0.01*distance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace);
    outColor = Color*cosTheta /attenIntensity+
    Color* vec3(0.3, 0.3, 0.3) * cosAlpha/attenIntensity+
    vec3(0.8, 0.8, 0.8) * ambientIntensity;
}

lightPos is in world space.

This is the tutorial if it's relevent. Everything works except specular lighting.

2

2 Answers

1
votes

I think your shader is fine. The only thing that's missing is the check for dot(n, l)>0 when computing the specular term, but it doesn't really matter. The problem is probably that your normals are wrong.

Here's what I get when using your shader. I set the diffuse color to red, and the specular color to green, which adds up to yellow at the specular highlight. Looks pretty ok to me.

enter image description here

I'd also like to note that LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir; is correct. But I think writing that as LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz - PositionCamSpace; makes it clearer.

By the way, instead of distance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace) you should use

vec3 lightVec = lightPos - PositionWorldSpace;
float attenIntensity = 1.0 + 0.01 * dot(lightVec, lightVec);

Also, lighting in view space is fine, there's no need to do it in world space.

0
votes

You should use the world space of the normal and light direction vectors, not the view space. Think of it as comparing two vectors in 3D space, it doesn't matter where you are viewing from, the normals and light directions don't change.

Edit: another issue

    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;

The light direction should be the light position minus the vertex position (the vector going from the vertex to the light), again in world space. Should be

    LightDirCamSpace = lightPos - PositionWorldSpace;

CORRECTION: Disregard this, you can calculate lighting in either view space or world space, sorry for the misinformation, check out the other answer.