Introduction to lighting in WebGL

Incoming energy

The surface of an object receives more energy per area $dS$ when the light comes perpendicularly than when the light comes tangentially:

Incoming light energy as a function of the light direction.

(a) Incoming light nearly tangent to the surface
(b) Incoming light perpendicular to the surface
(c) Incoming light energy as a fuction of incoming direction $s$

This incoming energy per area is: $$ L_i = L_s n.s$$ where $n$ is the normal to the surface, $s$ is the direction where the light comes from, and $L_i$ is the power of the light source in this direction.

Perfect reflection and refraction

Under some conditions, a fraction of the light bounces on object boundaries (vector $r$) while a fraction of traverses the surface (vector $t$).

Reflection and refraction of light hitting the boundary between material 1 and 2.

The Descartes law relates the vectors and the physical parameters of the materials:
$$ \nu_1 \cos \theta_1 = \nu_2 \cos \theta_2 $$
where $\nu_1$ and $\nu_2$ ane the refraction indices of materials 1 and 2, respectively ($\nu=1$ in empty space)...

This type of reflection/refraction is typically not simulated in WebGL, since they require complex, recursive mappings of objects on each other. This is tractable using another image synthesis technique called ray-tracing. Some multi-pass OpenGL techniques are able to implement one level of reflection.


On most real-world surfaces, light is reflected in all directions, but not uniformly:

The BRDF describes the distribution of reflection of light.

The BRDF (bidirectional light distribution function)  $f(s,v)$ describes the distribution as a function of the incoming direction $s$ and the outcoming direction $v$.
The energy reflected from direction $s$ to direction $v$ is the product of the incoming energy with the BRDF:
\begin{equation} \label{eq brdf}
L_r (s,v) = L(s) n.s f(s,v)
When there are several light sources, the reflected energy is the sum of their contributions:
$$ L_r(s,v) = L(s_1) n.s_1 f(s_1,v) + L(s_2) n.s_2 f(s_2,v) + ... $$

The Phong lighting model

A popular model of the BRDF function is to represent it as the sum of two functions, $f = f_d + f_s$:

BRDF modeled as the sum of a two functions: diffuse (shown in blue) and specular (shown in red)

The diffuse component (also called Lambertian) distibutes the light uniformly. Its value is given by a simple parameter $k_d$, which represents the percentage of light reflected this way:
\begin{equation}\label{eq diffuse}
f_d = k_d

The specular component distributes most of the light in the direction $r$ of the perfect reflection. It is modeled using two parameters, $k_s$ which represents the percentage of light reflected this way. The value is computed using the dot product of the two directions:
\begin{equation} \label{eq specular}
f_s = (r.s)^\beta
The brightess parameter $\beta$ represents the concentration of light in this direction (the higher value, the thinner red shape centered on $r$).
Since energy can not be negative, the formula is actually $max(0,(r.s)^\beta)$

Color and material

Parameters $k_d$, $k_s$ and $\beta$ represent the material of the object.
Color is represented using three values (channels) for Red, Green, Blue. Each value represents energy.
Equations \ref{eq brdf},\ref{eq diffuse} and \ref{eq specular} are defined for each color channel.
Light source energy is thus defined by three values

Implementation of the Phong lighting model in a vertex shader

(work in progress)

Implementation of the Phong lighting model in a fragment shader

(work in progress)


  1. Save and edit locally
  2. Add forms to interactively tune the parameters of the lights  and the material of the cube.
  3. Create controls to move the light source interactively
  4. Insert a second light source in the scene
  5. Add a texture to the cube

Francois Faure, University of Grenoble. Main page