Bidirectional Reflectance Distribution Function

By Lups

"Whatever happens, happens."

Prerequisites

First of all, I'll give a quick introduction to three essential concepts in order to learn BRDF: radiant flux, radiance and irradiance;
three concepts that belong to radiometry.

Radiant flux is a trivial concept in radiometry because it lays the foundation for many other developments on the field.
So, radiant flux is commonly denoted with the $\Phi$ or a $\Phi _{\mathrm{e}}$ ('e' stands for energetic) sign and it basically represents the energy
emmited, reflected, transmitted or emitted per unit time by electromagnetic and gravitational radiation (radiant energy).
Mathematically, radiant flux can be represented as: $${\displaystyle \Phi _{\mathrm {e} }={\frac {dQ_{\mathrm {e} }}{dt}}}$$ where $Q_{\mathrm {e}}$ is radiant energy under the flux of a field in a closed surface and $t$ is time. But how can we measure the radiant energy?
It's simple, we can use a simple line integral: $${\displaystyle Q_{\mathrm {e} }=\int _{\Sigma }\mathbf {S} \cdot {\hat {\mathbf {n} }}\,dA}$$ in which $\Sigma$ is the closed surface, $\mathbf{S}$ is a Poynting vector, $\mathbf{n}$ is the regular vector and $A$ is the area of the closed surface.

Now that we know what a radiant flux is, let's understand radiance and irradiance. Radiance is the power per unit projected
area perpendicular to the ray per unit solid angle in the direction of the ray. Radiance is defined as $$L =\frac{d\Phi}{dT}$$ where the derivative of T is $$dT = d\overrightarrow{\omega}\cdot d\overrightarrow{A}.$$ Irradiance is when the radiant flux (the power) is received by a surface per unit area. It can be described mathematically
in two ways - as a regular (energetic, 'e') variable, or as a function -, both ways are to be shown below.
Irradiance, as a variable, is defined as $$E_{{\mathrm {e}}}={\frac {\partial \Phi _{{\mathrm {e}}}}{\partial A}},$$ in which $A$ is the area (all the other symbols were already explained above or assumed as prerequisite knowledge).
As a function, it is defined as $$E(x) = \frac{d\Phi(x)}{dA},$$ please note that radiant flux is considered as a function here. One last thing which is important to know
about irradiance is the Lambert's Cosine Law, which states that 'Irradiance at surface is proportional to
cosine of angle between light direction and surface normal.'

What is BRDF?

The Bidirectional Reflectance Distribution Function (BRDF) is a multi-variable function widely used in Computer Graphics.
BRDF is used in rendering to define how light should behave in a opaque surface, i.e. BRDF describes
how much light is reflected upon a object. This ability to manage light's behavior allows the possibility to control the
roughness of a object (BRDF Lut), for example. Moreover, BRDF permits the characterization of the reflection
properties in a object X. BRDF is commonly defined as $$f_{\text{r}}(\omega _{\text{i}},\,\omega _{\text{r}})\,=\,{\frac{\mathrm {d} L_{\text{r}}(\omega _{\text{r}})}{\mathrm {d} E_{\text{i}}(\omega _{\text{i}})}}\,=\,{\frac {1}{L_{\text{i}}(\omega _{\text{i}})\cos \theta _{\text{i}}}}{\frac {\mathrm {d} L_{\text{r}}(\omega _{\text{r}})}{\mathrm {d} \omega _{\text{i}}}}.$$ But what does each variable means? Well, let's first understand what are the inputs of the function. So, $\omega _{\text{i}}$ is the "incoming" light
to the object (incident), and $\omega _{\text{r}}$ is the refracted light (outgoing). $L$ is simply the radiance and $E$ is irradiance.

Physically based BRDF

BRDFs can also be photorealistic (i.e. physically based), but in order to do so they must satisfy a set of conditions:

  • Hemholtz reciprocity: the resulting reflectance upon swapping the incoming and outgoing direction stay congruent to
    its original direction. Algebraically it means that $$f_{\text{r}}(\omega _{\text{i}},\,\omega _{\text{r}})=f_{\text{r}}(\omega _{\text{r}},\,\omega _{\text{i}}).$$
  • Energy Conservation: there must be an equivallence between the energy received and the energy reflected from the surface. Thus, $$\forall \omega_{\text{i}}: \int_\Omega f_{\text{r}}(\omega_{\text{i}},\, \omega_{\text{r}})\,\cos{\theta_{\text{r}}} d\omega_{\text{r}} \le 1$$ notice that the cosine is important in order to represent the direction of the reflected light.

  • Implementing BRDF

    There are many ways of implementing the BRDF into real-time rendering. One of them is by applying BRDF as a 4D-matrix into 4D rendering.
    For the implementation, I will be using as a reference Chris Wynn application. In pseudocode it would look something like this: #define M_PI 3.14159265358979323846 // math.h pi double deltaT = (0.5 * M_PI) / (16-1); double deltaP = (2.0 * M_PI) / 16; double thetaI, phiI, thetaO, phiO; for (int h = 0; h < 16; h++) for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) for (int k = 0; k < 16; k++) { thetaO = h * deltaT; phiO = i * deltaP; thetaI = j * deltaT; phiI = k * deltaP; // brdf f(x) val = f(thetaI, phiI, thetaO, phiO) // storing each value into the 4D matrix BRDF[h][i][j][k] = val; } In this code, deltaT and deltaP are considered to be calculated from the sampling resolution. However, working with 4D can be
    really messy so we need to convert the BRDF matrix into a 2D-matrix. In order to convert a 4D BRDF into 2-D, we need to
    use sampling and sample each input N times. double deltaT = (0.5 * M_PI) / (N-1); double deltaP = (2.0 * M_PI) / N; double thetaI, phiI, thetaO, phiO; for (int h = 0; h < N; h++) for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int k = 0; k < N; k++) { thetaO = h * deltaT; phiO = i * deltaP; thetaI = j * deltaT; phiI = k * deltaP; // BRDF f(x) val = f(thetaI, phiI, thetaO, phiO); // 2N * 2N matrix BRDFMatrix[h*N+i][j*N+k] = val; } What we did in this code was translate the 4D-matrix BRDF into a 2D-matrix based upon 2N * 2N.

    Conclusion

    In conclusion, BRDF is a really powerful concept that has applications not only on computer graphics but also in
    real-life examples. BRDF is also a trivial concept for rendering and applying rasterization to a specific object, because
    without it, you wouldn't be able to control the flux of light through the object. Not only that, but BRDF allows the programmer
    to deepen their studies withing the field of computer graphics and study related concepts such as the Bidirectional Scattering
    Distribution Function (BSDF).

    See more

    - https://en.wikipedia.org/wiki/Bidirectional_scattering_distribution_function
    - https://www.sciencedirect.com/science/article/abs/pii/S0263224113003072
    - https://developer.nvidia.com/gpugems/gpugems/part-iii-materials/chapter-18-spatial-brdfs>

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------
                  .........
                .'------.' |       Plug and Play
               | .-----. | |
               | |     | | |
             __| |     | | |;. _______________
            /  |*`-----'.|.' `;              //
           /   `---------' .;'              //
     /|   /  .''''////////;'               //
    |=|  .../ ######### /;/               //|
    |/  /  / ######### //                //||
       /   `-----------'                // ||
      /________________________________//| ||
      `--------------------------------' | ||
       : | ||      | || |__LL__|| ||     | ||
       : | ||      | ||         | ||     `""'
       n | ||      `""'         | ||
       M | ||                   | ||
         | ||                   | ||
         `""'                   `""'