Real-Time 3D Graphics with WebGL 2
上QQ阅读APP看书,第一时间看更新

Goraud Shading with Lambertian Reflections

The Lambertian reflection model only considers the interaction of diffuse material and diffuse light properties. In short, we assign the final color as follows:

aVertexColor = Id;

The following value is seen:

Id = lightDiffuseProperty * materialDiffuseProperty * lambertCoefficient;

Under Goraud shading, the Lambert coefficient is obtained by calculating the dot product of the vertex normal and the inverse of the light-direction vector. Both vectors are normalized before finding the dot product.

Let's take a look at the vertex shader and the fragment shader from the provided example, ch03_01_goraud_lambert.html:

Here's the vertex shader:

#version 300 es
precision mediump float;

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

in vec3 aVertexPosition;
in vec3 aVertexNormal;

out vec4 vVertexColor;

void main(void) {
// Calculate the normal vector
vec3 N = normalize(vec3(uNormalMatrix * vec4(aVertexNormal, 1.0)));
// Normalized light direction
vec3 L = normalize(uLightDirection);
// Dot product of the normal product and negative light direction vector
float lambertTerm = dot(N, -L);
// Calculating the diffuse color based on the Lambertian reflection model
vec3 Id = uMaterialDiffuse * uLightDiffuse * lambertTerm;
vVertexColor = vec4(Id, 1.0);
// Setting the vertex position
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}

Here's the fragment shader:

#version 300 es
precision mediump float;

// Expect the interpolated value fro, the vertex shader
in vec4 vVertexColor;

// Return the final color as fragColor
out vec4 fragColor;

void main(void) {
// Simply set the value passed in from the vertex shader
fragColor = vVertexColor;
}

We can see that the final vertex color that we processed in the vertex shader is carried into a varying variable to the fragment shader. Remember that the value that arrives to the fragment shader is not the original value that we calculated in the vertex shader. The fragment shader interpolates the vVertexColor variable to generate a final color for the respective fragment. This interpolation takes into account the vertices that enclose the current fragment.