Phong-specular lighting in glsl (lwjgl)

2.4k Views Asked by At

I'm currently trying to make specular lighting on an sphere using glsl and using Phong-model.

This is how my fragment shader looks like:

#version 120
uniform vec4 color;
uniform vec3 sunPosition;
uniform mat4 normalMatrix;
uniform mat4 modelViewMatrix;
uniform float shininess;
// uniform vec4 lightSpecular;
// uniform vec4 materialSpecular;

varying vec3 viewSpaceNormal;
varying vec3 viewSpacePosition;

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = (modelViewMatrix * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)).xyz;
    vec4 specular = calculateSpecular(sunPosition, normal, viewSpacePosition, vec4(0.3,0.3,0.3,0.3), vec4(0.3,0.3,0.3,0.3));
    gl_FragColor = color+specular;
}

The sunPosition is not moving and is set to the value (2.0f, 3.0f, -1.0f).

The problem is that the image looks nothing as it's supose to do if the specular calculations were correct.

This is how it looks like: https://i.stack.imgur.com/iH17K.png

The reason i don't have any ambient-/emissiv-/deffuse- lighting in this code is because i want to get the specular light part working first.

Thankful for any help!

Edit: @Darcy Rayner That indead helped alot tough it seams to be something that is still not right...

The current code looks like this:

Vertex Shader:

viewSpacePosition = (modelViewMatrix*gl_Vertex).xyz;
viewSpaceSunPosition = (modelViewMatrix*vec4(sunPosition,1)).xyz;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
viewSpaceNormal = (normalMatrix * vec4(gl_Position.xyz, 0.0)).xyz;

Fragment Shader:

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = normalize(viewSpacePosition);
    vec3 viewSpaceSunPosition = normalize(viewSpaceSunPosition);
    vec4 specular = calculateSpecular(viewSpaceSunPosition, normal, viewSpacePosition,     vec4(0.7,0.7,0.7,1.0), vec4(0.6,0.6,0.6,1.0));
    gl_FragColor = color+specular;
}

And the sphere looks like this:

-->Picture-link<--

with the sun position: sunPosition = new Vector(12.0f, 15.0f, -1.0f);

1

There are 1 best solutions below

0
On

Try not using gl_FragCoord, as it is stored in screen coordinates, (and I don't think transforming it by the modelViewMatrix will get it back to view coordinates). Easiest thing to do, set viewSpacePosition in your vertex shader as:

// Change gl_Vertex to whatever attribute you are using.
viewSpacePosition = (modelViewMatrix * gl_Vertex).xyz; 

This should get you viewSpacePosition in view coordinates, (ie. before projection is applied). You can then go ahead and normalise viewSpacePosition in the fragment shader. Not sure if you are storing the sun vector in world coordinates, but you will probably want to transform it into view space then normalise it as well. Give it a go and see what happens, these things tend to be very error prone.