17/21

7. Illumination

So far pixels belonging to objects are assigned a specific color. In the case of a uniform color, the rendered object would appear with a constant color. This doesn’t allow to perceive the 3D geometry of the object. Indeed, in real life, even uniform color objects are appearing with varying intensity depending on the illumination and local geometry.

Shading refers to modeling a material appearance of a shape with respect to illumination and view point. One of the simplest shading is the one called Gouraud illumination defining three components.

  • Ambiant component: the base uniform color of the object. Allows to differenciate the presence of an object without direct illumination, but doesn’t provide visual local geometry information.

  • Diffuse component: taking into account an object is locally illuminated when its local geometry is facing the light direction, and no illuminated when orthogonal to the light direction. This component brings the visual information of local geometry.

  • Specular component: taking into account that reflective materials may reflect source light directly into the viewer eye. This component brings the visual information of reflective material such as metal in modeling a bright spot under certain viewing direction.

Let us consider a point \(p\) on a 3D shape with unit normal \(n\) illuminated receiving light from a direction given by the unit vector \(u\).

  • The diffuse component is computed as \(n\cdot u\). To only consider a front face illumination, only the positive component of \(n\cdot u\) is considered.

  • The specular component is computed as \((r\cdot t)^\alpha\), where \(t\) is the view direction, \(r\) is the symmetric of \(u\) with respect to the normal \(n\), and \(\alpha\) is an arbitrary exponent modeling whether the bright spot is concentrated or diffuse. We typically consider \(\alpha=2^{6-8}\). Similarly to the diffuse part, only the positive component of \(r\cdot t\) is considered.

In practice such shading is computed within the shaders. Thus, in addition of positions (and colors), vertices must also contain information of normals. The procedure - called Phong shading - is the following.

  • Send to shader per-vertex position and normal information.

  • Fragment shader receives interpolated values of position and normal.

  • Compute Gouraud illumination on each fragment.

Application

The following code implements Phong shading using Gouraud illumination.

  • vertex shader

#version 430 core

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec4 normal;

layout (location = 0) out vec4 position_out;
layout (location = 1) out vec4 color_out;
layout (location = 2) out vec4 normal_out;

uniform mat4 perspective;

void main()
{
    color_out = color;
    normal_out = normal;
    position_out = position;

    gl_Position = perspective * position;
}
  • fragment shader

#version 430 core

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec4 normal;

out vec4 FragColor;

vec3 light = vec3(0.0, 0.0, 5.0);

void main()
{
    vec3 n = normalize(normal.xyz);
    vec3 u = normalize(light-position.xyz);
    vec3 r = reflect(-u,n); // see documentation of reflect
    vec3 t = normalize(vec3(0.0, 0.0, 0.0)-position.xyz); // camera position is at (0,0,0)

    float ambiant  = 0.2;
    float diffuse  = 0.8 * clamp( dot(u,n), 0.0, 1.0);
    float specular = 0.5 * pow( clamp( dot(r,t), 0.0, 1.0), 128.0);

    vec3 white = vec3(1.0);
    vec3 c = (ambiant+diffuse)*color.rgb + specular*white;

    FragColor = vec4(c, 1.0);
}


illumination

  • Change the position of the light source in the shader, and observe the effect on the illumination.