Microfacet BRDFs from Scratch
In this article, I will derive these famous Specular and Diffuse BRDFs from scratch.
I will try to make the derivations as intuitive as possible with figures and explanations. The interactive HTML sections have been written by AI (The free version of Claude) as I don't know how to do frontend HTML programming. The other figures were made by me using inkscape.
This derivation is not novel, I read through 5 very important papers shuffling all of them at once, and I got the idea while going through them, to create a straight-forward article for someone like me, who is interested in mathematics and derivations of equations, but for whom, certain jumps in derivations don't come so naturally.
Contents
- Important Symbols
- The BRDF
- Microgeometry and Microfacets
- Visible Microfacets
- Statistical BRDFs
- Specular BRDF
- Diffuse BRDF
- Deriving the Diffuse Micro-BRDF
- Conclusion
- References
Important Symbols
| Symbol | Meaning |
|---|---|
| Outgoing radiance | |
| Irradiance | |
| Incoming radiance | |
| Macrosurface normal | |
| Outgoing direction (w.r.t. surface normal) | |
| Incoming direction (w.r.t. surface normal) | |
| Elevation angle - angle w.r.t. the polar axis of the sphere | |
| Azimuth angle - angle w.r.t. the equatorial plane of the sphere | |
| Half-vector: | |
| Differential solid angle | |
| Normal Distribution Function (NDF) | |
| Masking-shadowing function | |
| Fresnel factor | |
| Clamped dot product. |
The BRDF
When a light hits any "thing", it will either be transmitted (refracted), reflected, or absorbed. Absorption happens when the atom that is hit by the light takes the energy of the light and it reaches an excited state. Eventually, the energy is spit out, if it's emitted as visible light then that phenomenon is known as Photoluminescence. This isn't really important to Rendering as we rarely have to simulate that phenomena on production or real-time renderers. BRDF deals with the reflection of light. If we want to emulate the transmission as well, it'll require another function with a very similar name, the BTDF.
Bi-directional Reflectance Distribution Function (BRDF) is a scary name, but it is quite simple. It gets a bad reputation because when people try to learn it, they get met with very scary looking equations (some of which we will derive in this article).
The BRDF is simply the ratio of outgoing radiance in a given direction to the differential irradiance from a specific incoming direction. Radiance is the power of light in a point in a single direction. Irradiance is the power of light in a point from all directions. That is why we use differential irradiance. If we take an integral of the differential irradiance, we get the whole irradiance. I came across this cheatsheet in the graphics programming discord for important terms in rendering such as radiance, irradiance and what not.
So, BRDF then? Yes! But, we don't actually know the in rendering. We will have to figure out the Irradiance by taking the incoming light from each angle around the point and integrating it. Taking the irradiance of each angle is not practical at all, there's infinite angles as there are infinite numbers. So we use something called a differential solid angle, which is an infinitesmally small surface 'patch' in a sphere. As that patch is extremely small, the irradiance along the surface at any point will be virtually the same, so we can measure the irradiance at one point in the surface and then project that patch to the point.
The surface area of the patch, despite being extremely small, is larger than that of a singular 'point' of whose BRDF we are measuring. Depending on the angle at which the patch is located with respect to the normal, the incoming light gets spread out and misses the point.
Figure 1. Interactive visualiser showing how the same solid angle projects onto a larger surface element as the incident angle increases.
Due to this, the incoming light at a point through a solid angle will then become:
(irradiance through dω)
is the incoming light from a direction , is the light incident angle wrt normal, and is the differentiable solid angle.
So the BRDF is:
In rendering, we mostly want to figure out the Radiance to a specific directions, so we write it as:
BRDFs have two physical properties:
Conservation of energy — the total reflected energy cannot exceed the incident energy:
Reciprocity — swapping incoming and outgoing directions leaves the BRDF unchanged:
Microgeometry and Microfacets
A 'smooth' surface to our eye will have extreme difference in elevation as we zoom in. There will be many bumps in the microscopic scale.
Figure 2. A macrosurface that appears smooth has microsurfaces with varying normals at the microscopic scale.
If we want a realistic simulation of light then we cannot ignore this scale. We are not going to nanogeometry however, we will only think of any surface as being built up of very small microsurfaces. Each point we want to sample on the macrosurface (which may appear as a pixel on our screen) will have microsurfaces. So if we want to figure out the total radiated light in a certain direction for a certain point in the macrosurface, we need to find the radiation for that direction throughout all the points in the microsurface and sum all of it. Since these microsurfaces are very small, the out-radiance angle for each point of the microsurface will be parallel to one-another. This can be visualised as each point projecting itself to a straight line.
Figure 3. The microsurface points all project onto a line of width in the outgoing direction .
The area of the projection will be:
The points in the microsurface will have different normals so each point's out-radiance will be spread out in the outgoing direction. If the normal of a point in the microsurface is parallel to the outgoing direction, the out-radiance will be projected 1:1 to the projected 'line', while for any other angle the out-radiance will be spread out.
Let be the Micro-geometry.
This formula acts as a weighted average of the out-radiance of each point of the microsurface. An intuitive metaphor is to imagine a folding phone, if it's folded 90 degrees and you're looking at it. The folded screen that is directly facing your eyes will contribute more to the brightness than the one that is facing up, and is 90 degrees to your eyes.
Figure 4. The folding phone analogy: the screen directly facing the viewer contributes more brightness than the one at 90 degrees. Each microsurface point contributes proportionally to its projected area.
For a macrosurface with microsurfaces, let us create a function which counts the amount of points in the microsurface with a specific normal .
is known as a dirac delta, think of it as a function that discards what is not expected. means that the delta will discard every input which isn't . gives the normal of the microsurface point . So, gives the total points in the microsurface with the given normal .
There's an infinite amount of vectors as normals that a point can have. These normals exist in a unit sphere as well. A unit sphere also has all the normals in 3-D. For each point in the microsurface with a normal , there's a point in the unit sphere with that normal. For a subset of point in the microsurface , there is a subset of unit sphere with the same normals.
Integrating for each point in gives the same 'area' as integrating for each point in a unit sphere with the same normals, because gives the weight for each of those normals. Reminder that even in the unit sphere integral, the goes through each point in the microsurface and checks the normal of each point. So, for the whole microsurface, or the whole unit circle, it gives the microsurface area.
Visible microfacets
Since a surface is made up of microsurfaces (Figure 2), the projections will be that of each point in the microsurfaces. Not all the points in the microsurfaces are actually visible, depending on the viewing angle. The visibility also depends on what's known as a 'microsurface profile'. The same distribution of normals can have different behaviors and have different visibility depending on how the normals are distributed along the microsurfaces.
Figure 5. Two microsurfaces with the same normal distribution but different profiles can have different visibility. Some points are occluded depending on the viewing direction .
The projected area of the microsurfaces can be viewed as such:
here is a function that evaluates to 0 if a point is blocked, and 1 if it's not blocked. Clamp function is used to cull out backfacing microgeometries, as it'll clamp negative value to 0, so if there's a point which faces the opposite of , it'll not contribute to the projected area. We can create another function that takes instead of [2]. For that:
Here, gives weight to the specific . Meaning, if there's more points with a specific which are also visible, their contribution has more weight. Since the projected area is the area of all visible points in the microsurface, for a surface of unit area, we know that its area from (ii). From (ii) and (v) we get:
In equation (iii), let us replace the denominator with (ii). We can replace the whole integral in the numerator with another numerator that also takes the area (v), and for the function , which is a function of the point, we can just convert it to a function of : . (The reason it's so easy to convert is because the radiance depends on the normal of the point regardless).
Here, acts as a distribution of the visible normals, it gives value between 0 and 1.
Statistical BRDFs
is the outgoing radiance at a direction . Using basic calculus, we can rewrite it as:
Basically, we differentiate the function wrt and integrate it along . From (i), we can say that the micro BRDF, (It is a function of , , and ) for a specific microsurface is:
We can ignore the back faces using the clamp, so:
Now, let's differentiate equation (viii) with respect to the incoming irradiance:
We replace from (xi) in (xiv):
The macro BRDF is given in (i). We can replace the with (xv), then replace from (ix). and can be taken out of the integral and written as and as they depend on the macro surface normal:
This statistical model of BRDF covers the light before it bounces from the microsurface. After it bounces, it could get blocked by another microsurface, for that, we use a function known as the shadow-masking function (). It will take into account the incident direction of the light as well. This is the general form of a BRDF. If we assume the microfacets to be a perfect mirror then we will get Specular BRDF and if we assume it to be a perfect lambertian surface that diffsue light, then we get the Diffuse BRDF.
Specular BRDF
A simple generic specular BSDF will look like this [3]:
is the fraction of out-radiance. is the angle of specular reflection. is there to cancel out the numerator in the macro surface BSDF integral.
If we assume only a specular reflection then for a given and , there is at most only 1 that scatters the energy from to directly. That normal is and (also known as the half vector): .
In this case, we can re-write in terms of :
The is just a shorthand for writing . We want the equation (xvii) in the form of and instead. The delta will be changed to . The dirac delta always has an associated element [3]. The dirac delta in (xvii) has associated with itself. When changing it to be associated with , we need to find the jacobian so that it scales properly.
The jacobian must be . Since the delta function means that only those that are are considered, we can say that . So, .
The jacobian can be written as:
This gives the ratio of how much a change in solid angle of corresponds to a change in the solid angle of . We will see that the size of the solid angle patch depends on the length of the vector.
Figure 6. Interactive Jacobian visualiser. Drag the i (red) and o (green) arrowheads or use the sliders. The green wedge lives on the circle centred at the tip of ; the dark wedge lives on the central unit sphere. The dashed lines show the projection. Notice how when and are nearly parallel.
We know . If we do a dot product of a vector with its unit self, we get its length, as , only the magnitude will remain. Putting this magnitude value in (xix):
( because is a bisector of and .)
Putting this value in (xviii):
For reflection, the fraction of out radiance is the Fresnel factor. Since is the micro brdf for specular reflections, We replace with in (xvi). Due to the delta function, we can discard all the s that are not and we can remove the integral. Cancelling the dot products:
This is the Specular form of the macro BRDF. It can be solved by choosing appropriate and functions. Most of the engines in real time rendering use the GGX and functions.
Diffuse BRDFs
It is well known that the Diffuse micro BRDF . So the diffuse BRDF will just be: