By Lups
"Whatever happens, happens."
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.'
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.
BRDFs can also be photorealistic (i.e. physically based), but in order to do so they must satisfy a set of conditions:
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.
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).
- 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 | || | || | || | || `""' `""'