Modern GLSL ( opengl 3+ ) : Implementing phong effect correctly;

262 views Asked by At

I am implementing a basic phong lighting GLSL shader; I have looked up some things on the internet, and found that the phong effect was created by adding an ambient, diffuse, and specular layer on the object (see image below, from tom dalling's site); problem is I have seen a lot of examples, and none of them really suits my GLSL set-up. Can any of you give me a code example of the correct way to implement the phong effect which would fit my GLSL set-up ? :

PS : This question could be put on hold because of the fact that it may be based on user opinion : In my mind, it is not, because I would like to know the most effective, and better way of implementing it.

Here is my vertex shader :

#version 120

uniform mat4 modelView;
uniform mat4 MVP;
uniform float time;

attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;

varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;


void main()
{
    //Updating varyings...
    position0 = position;
    texCoord0 = texCoord;
    normal0 = (MVP * vec4(normal, 0.0)).xyz;
    modelView0 = modelView;

    //set position
    gl_Position = MVP *  vec4(position, 1.0);
} 

and my fragment shader :

#version 120

varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;

uniform sampler2D diffuse;

void main()
{

    vec4 surfaceColor = texture2D(diffuse, texCoord0);
    gl_FragColor = (texture2D(diffuse, texCoord0))
        * clamp(dot(-vec3(0.0, 0.5, 0.5), normal0), 0, 1.0);

}

enter image description here

2

There are 2 answers

3
agnu17 On BEST ANSWER

try this:

void main() 
{ 
    vec4 texread = texture2D(diffuse, texCoord0);
    vec3 normal = normalize(normal0);

    vec3 material_kd = vec3(1.0,1.0,1.0);
    vec3 material_ks = vec3(1.0,1.0,1.0);
    vec3 material_ka = vec3(0.2,0.2,0.2);
    vec3 material_ke = vec3(0.0,0.0,0.0);
    float material_shininess = 60;

    vec3 lightpos = vec3(0.0,10.0,5.0);
    vec3 lightcolor = vec3(1.0,1.0,1.0);

    vec3 lightdir = normalize(lightpos - worldPosition);

    float shade = clamp(dot(lightdir, normal), 0.0, 1.0); 
    vec3 toWorldpos = normalize((worldPosition) - u_eyePos); 
    vec3 reflectDir = reflect( toWorldpos, normal ); 

    vec4 specular = vec4(pow(clamp(dot(lightdir, reflectDir),0.0,1.0), material_shininess) * lightcolor * material_ks, 1.0); 
    vec4 shaded = texread * vec4(material_kd, 1.0) * vec4(lightcolor , 1.0) * shade;

    vec4 ambient = texread * vec4(material_ka, 1.0);
    vec4 emission = vec4(material_ke, 1.0);

    gl_FragColor = shaded + specular + emission + ambient;

}

it may have some compilation errors though as i didnt run it... you may need to upload your eye position as a uniform (u_eyePos), and calculate the worldposition (worldPosition) for it to work

0
AudioBubble On

I made my own sphong shader : here is the code :

fragment shader :

#version 150

uniform mat4 modelView;
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;

uniform sampler2D materialTex;
uniform float materialShininess;
uniform vec3 materialSpecularColor;

uniform vec3 lightPosition;//light settings
uniform vec3 lightIntensities;
uniform float lightAttenuation;
uniform float lightAmbientCoeff;

in vec3 position0;
in vec2 texCoord0;
in vec3 normal0;

out vec4 fragmentColor;

void main()
{
    //calculate normal in world coordinates
    vec3 normal = normalize(normalMatrix * normal0);

    //calculate the location of this fragment (pixel) in world coordinates
    vec3 surfacePos = vec3(modelView * vec4(position0, 1));

    //color of the current fragment
    vec4 surfaceColor = texture(materialTex, texCoord0);


    //calculate the vector from this pixels surface to the light source
    vec3 surfaceToLight = normalize(lightPosition - surfacePos);

    //cam distance
    vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);

    ///////////////////////////DIFUSE///////////////////////////////////////

    //calculate the cosine of the angle of incidence
    //float diffuseCoeff = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
    float diffuseCoeff = max(0.0, dot(normal, surfaceToLight));
    vec3 diffuse = diffuseCoeff * surfaceColor.rgb * lightIntensities;

    /////////////////////////AMBIENT////////////////////////////////////////
    vec3 ambient = lightAmbientCoeff * surfaceColor.rgb * lightIntensities;

    /////////////////////////SPECULAR//////////////////////////////////////
    float specularCoeff = 0.0;
    if(diffuseCoeff > 0.0)
        specularCoeff = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
    vec3 specular = specularCoeff * materialSpecularColor * lightIntensities;

    ////////////////////////ATTENUATION///////////////////////////////////
    float distanceToLight = length(lightPosition - surfacePos);
    float attenuation = 1.0 / (1.0 + lightAttenuation * pow(distanceToLight, 2));

    /////////////////////////////////FINAL/////////////////////////////////

    vec3 linearColor = ambient + attenuation * (diffuse +  specular);

    //finalColor with gamma correction
    vec3 gamma = vec3(1.0/2.2);
    fragmentColor = vec4(pow(linearColor, gamma), surfaceColor.a);
    //fragmentColor = vec4(diffuseCoeff * lightIntensities * surfaceColor.rgb, surfaceColor.a);
}