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;
}
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