A light model describes how light is emitted in the different directions of the space.
It takes as input the position of a point $x$ of an object and it returns two elements:
- a vector that represents the direction of the light received (as convention the sign is chosen to make the ray pointing toward the light source) $(d_x, d_y, d_z)$
- the intensity of light received by point $x$ for every wavelength $(l_R, l_G, l_B)$
The three basic direct light models are:
- Direct light
- Point light
- Spot light
Directional lights are used to model distant sources, so that they uniformly influence the entire scene.
The rendering equation reduces to:
$$L\left(x, \omega_r\right)=\boldsymbol{l} * f_r\left(x, \boldsymbol{d}, \omega_r\right)$$
The position $\boldsymbol{p}=\left(p_x, p_y, p_z\right)$ and the color $\boldsymbol{l}=\left(l_R, l_G, l_B\right)$ characterize a point light.
$$\begin{array}{l}
L\left(x, \omega_r\right)=\sum_l L(l, \overrightarrow{l x}) f_r\left(x, \overrightarrow{l x}, \omega_r\right) \\
L(l, \vec{x})=\boldsymbol{l}\left(\frac{g}{|\boldsymbol{p}-\boldsymbol{x}|}\right)^\beta \end{array}$$
vec3 lightDir = lightPos - fragPos;
vec3 lightColor = lightColor.rgb * pow(g/length(lightDir), beta);
Note that the light direction is normalized to make it an unitary vector:
$$\overrightarrow{l x}=\frac{p-x}{|\boldsymbol{p}-\boldsymbol{x}|}$$
Also note that we write $p - x$ because the ray is oriented from the object to the light source, as for the direct light case.
So at the end:
$$L\left(x, \omega_r\right)=\boldsymbol{l}\left(\frac{g}{|\boldsymbol{p}-\boldsymbol{x}|}\right)^\beta * f_r\left(x, \frac{\boldsymbol{p}-\boldsymbol{x}}{|\boldsymbol{p}-\boldsymbol{x}|}, \omega_r\right)$$
The decay factor $\beta$ is either constant, inverse-linear or inverse-squared.
Spot lights are characterized by two angles $\alpha _{IN}$ and $\alpha _{OUT}$ that divide the illuminated area into three zones: constant $\alpha _{IN}$, decay (between $\alpha _{IN}$ and $\alpha _{OUT}$) and absent (outside $\alpha _{OUT}$).
Spot lights are implemented by confining other light sources with the dimming term:
$$L(l, \overrightarrow{l x})=L_0(l, \overrightarrow{l x}) \cdot \operatorname{clamp}\left(\frac{\frac{\boldsymbol{p}-\boldsymbol{x}}{|\boldsymbol{p}-\boldsymbol{x}|} \cdot \boldsymbol{d}-c_{O U T}}{c_{I N}-c_{O U T}}\right)$$
$$L(l, \overrightarrow{l x})=\boldsymbol{l}\left(\frac{g}{|\boldsymbol{p}-\boldsymbol{x}|}\right)^\beta \cdot \operatorname{clamp}\left(\frac{\frac{\boldsymbol{p}-\boldsymbol{x}}{|\boldsymbol{p}-\boldsymbol{x}|} \cdot \boldsymbol{d}-c_{O U T}}{c_{I N}-c_{O U T}}\right)$$
where $\operatorname{clamp}(y)=\left{\begin{array}{cc}0 & y<0 \ y & y \in[0,1] \ 1 & y>1\end{array}\right.$
vec3 lightDir = lightPos - fragPos;
float dimmingTerm = clamp(( dot(normalize(lightDir),lightDir) - cosout)/(cosin - cosout), 0.0f, 1.0f);
float light = pow(g/length(lightDir), beta);
vec3 lightColor = lightColor.rgb * light * dimmingTerm;
Ambient lighting is the simplest approximation for indirect illumination which is caused by lights that bounces from other objects. A slight extension of ambient lighting is the hemispheric lighting whcih simulates a "sky/ground" model using two ambient light colors (the “upper” or “sky” color, and the “lower” or “ground” color) and a direction vector. The technique creates an ambient light color factor by “blending” the two colors, with respect to the orientation of the object.
The "evolution" to the hemispheric lightning is to have a function that return the color received by any point $x_i$ (of any objected). Each point is thus illuminated according the function. These functions can be computed either from specially taken pictures or from high quality off-line rendering of the environment (hdri maps).