3
$\begingroup$

I implemented a Phong shader in GLSL, but there is a bug.

What you are (supposed) to see down below:

  • A point light source rotating around the center of the world,

    • with a radiance of (0, 100, 0)
  • A textured quad with kd of (1, 0, 0).

The problem is:

  • Why is there a a green line to the center of the world instead of a green spot light where the quad is lit? (where the center of the point light source is)

    • (Btw in this case there would be only a yellow spot of light, because red + green = yellow)

enter image description here

Vertex Shader:

#version 330

uniform mat4 ModelMatrix, ViewMatrix, ProjectionMatrix;   

uniform vec4 wLiPos[5];       // pos of light source 
uniform vec3 wEye;         // pos of eye
uniform int lightSize;      //number of lights

layout(location = 0) in vec3 vtxPos;
layout(location = 1) in vec3 vtxNorm;
layout(location = 2) in vec2 vtxUV;

out vec2 texCoord;
out vec3 wNormal;           // normal in world space
out vec3 wView[5];             // view in world space
out vec3 wLight[5];            // light dir in world space

void main() {
    gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vtxPos, 1);
    texCoord = vtxUV;
    vec4 wPos = ModelMatrix * vec4(vtxPos, 1);
    wNormal = (vec4(vtxNorm, 0) * inverse(ModelMatrix)).xyz;
    for(int i = 0; i < lightSize; i++) {
        wView[i] = wEye * wPos.w - wPos.xyz;
        wLight[i] = wLiPos[i].xyz * wPos.w - wPos.xyz * wLiPos[i].w;
    }
}

Fragment shader:

#version 330

uniform sampler2D samplerUnit;

uniform vec3 kd, ks, ka;   // diffuse, specular, ambient ref
uniform vec3 La, Le[5];    // ambient and point source rad
uniform float shininess;    // shininess for specular ref
uniform int lightSize;

in vec2 texCoord;    
in vec3 wNormal;       // interpolated world sp normal
in vec3 wView[5];         // interpolated world sp view
in vec3 wLight[5];        // interpolated world sp illum dir


layout(location = 0) out vec4 fragmentColor;

void main() {     
    vec3 color = vec3(0, 0, 0);
    for(int i = 0; i < lightSize; i++) {
        vec3 N = normalize(wNormal);
        vec3 V = normalize(wView[i]);
        vec3 L = normalize(wLight[i]);
        vec3 H = normalize(L + V);
        float cost = max(dot(N,L), 0);
        float cosd = max(dot(N,H), 0);
        color += ka * La + (kd * cost + (ks * pow(cosd, shininess)) * Le[i]) / pow(length(wLight[i]), 2);
    }
    vec3 gamma = vec3(1.0/2.2);
    fragmentColor = vec4(pow(color * vec3(texture2D(samplerUnit, texCoord)), gamma), 1);
}
$\endgroup$
  • $\begingroup$ Also, why are multiplying the light position by the w component of the position? $\endgroup$ – aces May 8 '17 at 4:08
  • $\begingroup$ I was about to comment the same thing. Division by W is typical for things that have had a perspective matrix performed on them. It should not be needed for the world positions of lights. $\endgroup$ – PaulHK May 8 '17 at 6:23
  • $\begingroup$ wLiPos is a vec4, and I have to avoid dividing by zero, so I cross multiplied in the formula. $\endgroup$ – Tudvari May 8 '17 at 6:45
  • $\begingroup$ Now I multiple by the transpose of the inverse of the modelMatrix, but nothing changed. wNormal = (vec4(vtxNorm, 0) * transpose(inverse(ModelMatrix))).xyz; $\endgroup$ – Tudvari May 8 '17 at 6:46
  • $\begingroup$ You don't need the W component for world transformations. You can truncate the vec4*mat4 result to a vec3. $\endgroup$ – PaulHK May 8 '17 at 9:25
2
$\begingroup$

I forgot to set the wEye uniform, so it was always (0, 0, 0).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.