Goraud Shading with Phong Reflections

Different from the Lambertian reflection model, the Phong reflection model considers three properties: the ambient, diffuse, and specular, and ultimately yields a more realistic reflection. Following the same analogy that we used in the previous section, consider the following example:

finalVertexColor = Ia + Id + Is;

Where:

Ia = lightAmbient * materialAmbient;
Id = lightDiffuse * materialDiffuse * lambertCoefficient;
Is = lightSpecular * materialSpecular * specularCoefficient;

Notice that:

  • As we use Goraud interpolation, we still use vertex normals to calculate the diffuse term. This will change when using Phong interpolation, where we will use fragment normals.
  • Both light and material have three properties: the ambient, diffuse, and specular colors.
  • On these equations, we can see that IaId, and Is receive contributions from their respective light and material properties.

Based on our knowledge of the Phong reflection model, let's see how to calculate the specular coefficient in ESSL:

float specular = pow(max(dot(lightReflection, eyeVector), 0.0), shininess);

Where:

  • eyeVector is the view vector or camera vector
  • lightReflection is the reflected light vector
  • shininess is the specular exponential factor or shininess
  • lightReflection is calculated as lightReflection = reflect(lightDirection, normal);
  • normal is the vertex normal, and lightDirection is the light direction that we have been using to calculate the Lambert coefficient

Let's take a look at the ESSL implementation for the vertex and fragment shaders. Here's the vertex shader:

#version 300 es
precision mediump float;

uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat4 uNormalMatrix;
uniform vec3 uLightDirection;
uniform vec4 uLightAmbient;
uniform vec4 uLightDiffuse;
uniform vec4 uMaterialDiffuse;

in vec3 aVertexPosition;
in vec3 aVertexNormal;

out vec4 vVertexColor;

void main(void) {
vec3 N = vec3(uNormalMatrix * vec4(aVertexNormal, 1.0));
vec3 light = vec3(uModelViewMatrix * vec4(uLightDirection, 0.0));
vec3 L = normalize(light);
float lambertTerm = dot(N,-L);
vec4 Ia = uMaterialDiffuse * uLightAmbient;
vec4 Id = uMaterialDiffuse * uLightDiffuse * lambertTerm;
vVertexColor = vec4(vec3(Ia + Id), 1.0);
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}

We can obtain negative dot products for the Lambert term when the geometry of our objects is concave or when the object is in the way between the light source and our point of view. In either case, the negative of the light-direction vector and the normals will form an obtuse angle, producing a negative dot product, as shown in the following diagram:

For that reason, we are using the ESSL built-in clamp function to restrict the dot product to the positive range. If we obtain a negative dot product, the clamp function will set the lambert term to zero and the respective diffuse contribution will be discarded, generating the correct result.

Given that we are still using Goraud interpolation, the fragment shader is the same as before:

#version 300 es
precision mediump float;

in vec4 vVertexColor;

out vec4 fragColor;

void main(void) {
fragColor = vVertexColor;
}

In the next section, we will explore the scene to see what it looks like when we have negative Lambert coefficients that have been clamped to the [0,1] range.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.152.162