opengl-esglsllightphong

Phong shader didn't work


I would like to render by using phong shading. I use OpenGl ES 3.0 and I implemented gouraud shading and it worked. But when I render objects by using phong shading, it didn't work. I think there are problems in my shader code, but I can't find where it is.

Here is Vertex Shader

#version 300 es

precision highp float;

uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewMatrixInvTrans;  

layout (location = 0) in vec3 v_position;
layout (location = 1) in vec3 v_normal;
layout (location = 2) in vec2 a_tex_coord;

out vec3 v_position_EC;
out vec3 v_normal_EC;
out vec2 v_tex_coord;

void main(void) {   
    v_position_EC = vec3(ModelViewMatrix*vec4(v_position, 1.0f));
    v_normal_EC = normalize(ModelViewMatrixInvTrans*v_normal);  
    v_tex_coord = a_tex_coord;

    gl_Position = ModelViewProjectionMatrix*vec4(v_position, 1.0f);
}

Here is Fragment Shader

#version 300 es

precision highp float;

struct LIGHT {
    int light_on;
    vec4 position; // assume point or direction in EC in this example shader
    vec4 ambient_color, diffuse_color, specular_color;
    vec3 spot_direction;
    float spot_exponent;
    float spot_cutoff_angle;
    vec4 light_attenuation_factors; // compute this effect only if .w != 0.0f
};

struct MATERIAL {
    vec4 ambient_color;
    vec4 diffuse_color;
    vec4 specular_color;
    vec4 emissive_color;
    float specular_exponent;
};

#define NUMBER_OF_LIGHTS_SUPPORTED 4

uniform vec4 global_ambient_color;
uniform LIGHT light[NUMBER_OF_LIGHTS_SUPPORTED];
uniform MATERIAL material;

uniform int flag_texture_mapping;

uniform sampler2D base_texture;

const float zero_f = 0.0f;
const float one_f = 1.0f;

in vec3 v_position_EC;
in vec3 v_normal_EC;
in vec2 v_tex_coord;

layout (location = 0) out vec4 final_color;

vec4 lighting_equation_textured(in vec3 P_EC, in vec3 N_EC, in vec4 base_color) {
    vec4 color_sum;
    float local_scale_factor, tmp_float; 
    vec3 L_EC;

    color_sum = material.emissive_color + global_ambient_color * base_color;

    for (int i = 0; i < NUMBER_OF_LIGHTS_SUPPORTED; i++) {
        if (light[i].light_on == 0) continue;

        local_scale_factor = one_f;
        if (light[i].position.w != zero_f) { // point light source
            L_EC = light[i].position.xyz - P_EC.xyz;

            if (light[i].light_attenuation_factors.w  != zero_f) {
                vec4 tmp_vec4;

                tmp_vec4.x = one_f;
                tmp_vec4.z = dot(L_EC, L_EC);
                tmp_vec4.y = sqrt(tmp_vec4.z);
                tmp_vec4.w = zero_f;
                local_scale_factor = one_f/dot(tmp_vec4, light[i].light_attenuation_factors);
            }

            L_EC = normalize(L_EC);

            if (light[i].spot_cutoff_angle < 180.0f) { // [0.0f, 90.0f] or 180.0f
                    float spot_cutoff_angle = clamp(light[i].spot_cutoff_angle, zero_f, 90.0f);
                    vec3 spot_dir = normalize(light[i].spot_direction);

                    tmp_float = dot(-L_EC, spot_dir);
                    if (tmp_float >= cos(radians(spot_cutoff_angle))) {
                        tmp_float = pow(tmp_float, light[i].spot_exponent);
                    }
                    else 
                        tmp_float = zero_f;
                    local_scale_factor *= tmp_float;
            }
        }
        else {  // directional light source
            L_EC = normalize(u_light[i].position.xyz);
        }   


        if (local_scale_factor > zero_f) {              
            vec4 local_color_sum = light[i].ambient_color * material.ambient_color;

            tmp_float = dot(N_EC, L_EC);

            if (tmp_float > zero_f) {
                local_color_sum += light[i].diffuse_color*base_color*tmp_float;

                vec3 H_EC = normalize(L_EC - normalize(P_EC));
                tmp_float = dot(N_EC, H_EC); 
                if (tmp_float > zero_f) {
                    local_color_sum += light[i].specular_color
                                           *material.specular_color*pow(tmp_float, material.specular_exponent);
                }
            }

            color_sum += local_scale_factor*local_color_sum;
        }
    }
    return color_sum;
}

void main(void) {   
    vec4 base_color;
    vec2 tex_coord = v_tex_coord;

    if (flag_texture_mapping == 1)
        base_color = texture(base_texture, tex_coord);
    else
        base_color = material.diffuse_color;

    vec4 lighting_color = lighting_equation_textured(v_position_EC, normalize(v_normal_EC), base_color);
    final_color = vec4(lighting_color.rgb, 1.0f);
    //final_color = material.diffuse_color;
}

Solution

  • The fragment shader code does not compile, because you are using the undefined variable ulight in the line:

    L_EC = normalize(u_light[i].position.xyz);
    

    Use light instead of u_light:

    L_EC = normalize(light[i].position.xyz);
    

    Note, you should check if a shader has compiled successfully by glGetShaderiv

    GLint status = GL_TRUE;
    glGetShaderiv( shaderObj, GL_COMPILE_STATUS, &status );
    

    And error messages can be retrieved by glGetShaderInfoLog