Simple GPU Path Tracing, Part. 3.2 : Physically Based Material
- Simple GPU Path Tracing : Introduction
- Simple GPU Path Tracing, Part. 1 : Project Setup
- Simple GPU Path Tracing, Part. 1.1 : Adding a cuda backend to the project
- Simple GPU Path Tracing, Part. 2.0 : Scene Representation
- Simple GPU Path Tracing, Part. 2.1 : Acceleration structure
- Simple GPU Path Tracing, Part. 3.0 : Path Tracing Basics
- Simple GPU Path Tracing, Part. 3.1 : Matte Material
- Simple GPU Path Tracing, Part. 3.2 : Physically Based Material
- Simple GPU Path Tracing, Part. 3.4 : Small Improvements, Camera and wrap up
- Simple GPU Path Tracing, Part. 4.0 : Mesh Loading
- Simple GPU Path Tracing, Part. 4.1 : Textures
- Simple GPU Path Tracing, Part. 4.2 : Normal Mapping & GLTF Textures
- Simple GPU Path Tracing, Part. 5.0 : Sampling lights
- Simple GPU Path Tracing, Part 6 : GUI
- Simple GPU Path Tracing, Part 7.0 : Transparency
- Simple GPU Path Tracing, Part 7.1 : Volumetric materials
- Simple GPU Path Tracing, Part 7.2 : Refractive material
- Simple GPU Path Tracing, Part 8 : Denoising
- Simple GPU Path Tracing, Part 9 : Environment Lighting
- Simple GPU Path Tracing, Part 10 : Little Optimizations
- Simple GPU Path Tracing, Part 11 : Multiple Importance Sampling
We now have implemented the simplest form of brdf.
It's time to implement a new one that can represent materials with more properties.
We'll be using a physically based brdf that is commonly used in computer graphics, which allows some parameterization to change the material properties and visual (Metallic and roughness parameters).
As for the matte brdf, we need to write 3 functions :
- One for sampling a direction from this brdf
- One for evaluating the value of the brdf, given 2 directions
- One for evaluating the probability of generating a given direction from that brdf.
I'll go over the theory of physically based BRDF, and show how it's implemented in the code.
I won't go in too much details, but see at the end of this page for more resources.
Theory
Here I'll briefly review the basic theory of the physically based BRDF we will implement.
It's actually going to be composed of 2 BRDFs that we will combine together :
- A diffuse brdf that accounts for the light that scatters inside the surface and escapes in any direction across the hemisphere
- A specular brdf that accounts for the light that gets reflected straight away from the surface leaning more towards the reflection direction of the light on the surface.
The factor that dictates which brdf is going to be used for a given sample is given by the fresnel equations that tell us how much light is reflected from a surface, given the angle at which light arrives and the viewing angle.
We already have a diffuse brdf : the one we were using just before will work perfectly.
Now let's discuss the specular component of our brdf.
Specular BRDFs are based on microfacet theory. At a microscopic level, all surfaces are made of micro surfaces of different slopes and heights. Each individual microfacet is usually modeled as a perfect mirror surface.
We can use a "roughness" parameter to modulate the profile of those microfacets. A low roughness parameter will present microfacets that are almost parallel to the underlying surface. Conversely, a high roughness parameter will present microfacets that have a lot of crevices and slopes.
Example of a rough material with its microfacets shown
Example of a smooth material with its microfacets shown
So how do we model a brdf using this microfacet theory ? Here I'll present a global view of how that's done, but I won't dive into the low level maths of how it works. I'll link some useful resources that explain more in depth the theory.
First, let's see the general equation for our microfacets based BRDF, and we'll then explain each term :
A microfacet BRDF is defined by 3 important functions :
- D : Microfacet distribution function, which defines how the microfacets vary in slopes and height. It will define how smooth/rough the microfacets are distributed (See previous images)
- G : Geometric attenuation function, which accounts for mutual shadowing and masking of microfacets : Some microfacets might shadow or mask other microfacets.
Microfacets shadowing : A ray of light blocked by a microfacet will shadow the one behind.
Microfacet masking : A reflected ray that's blocked by another microfacet.
- F : Fresnel function, which as said earlier tells us how much of incoming light is reflected straight away from the surface.
Now let's see the other parameters :
N : Normal of the surface
L : Direction towards the Light (or Outgoing direction)
V : Direction towards the Eye (or Incoming direction)
H : "Half Vector", which is the vector halfway between L and V
The reason D depends on H is because it actually returns the fraction of microfacets that are oriented like H.
All the microfacets that are oriented towards H will reflect all the light coming from L to V, because as we said individual microfacets are treated are mirror-like surface.
A mirror surface will reflect the incoming light to a single direction, called the reflection direction :
So if microfacets are all treated like mirror surfaces, it gives something like that :
So as you can see, the outgoing direction can get quite random on the hemisphere if the roughness is high, which is exactly what we want.
Implementation
Let's go through the individual D, G, F functions now :
Distribution
And its implementation in our code :
Geometric attenuation
Fresnel
On the foregreound of the image, we see through the water : No light is reflected.
In the background, we see more and more the reflections and less and less through the water.
The fresnel equations are quite hairy and involve complex numbers and account for polarization of light. Luckily, there's a simplified approximation of those equations, introduced by Christophe Schlick in this paper.
Here's the equation :
Where
- u is the cosine of the angle between N and V
- F90 is equal to the reflectance value at 90 degrees, (the biggest angle we can view a surface from)
- F0 which is the reflectance value when looking at the surface from 0 degree angle.
However, F90 is always 1 : All the light is reflected when looking from a 90 angle. F0, however, may vary, depending on the index of refraction of the material. The formula to find F0 is the following :
where eta_1 is the index of refraction of the material that the light is entering, and eta_2 is the index of refraction of the material the light is escaping. In our case, the light is escaping the air, which has an index of refraction of 1, so we can simplify this formula and implement it like that :
And here's the implementation of the main formula :
So that's quite simple, but we'll add a bit of complexity to it, because because we want to have a parameter that will define how "metallic" the material is.
High metallic value will simulate a conductor-like material, meaning most of the light that enters the surface gets absorbed and never escapes the surface again. That's because in metals, electrons are not tightly bound to individual atoms but are free to move throughout the material. When light hits a metal surface, it interacts with these free electrons, causing a phenomenon called "Plasmon", that makes the electrons oscillate, and absorbing the energy of the incoming light.
Low metallic value, on the other hand, will tend to what's called "dielectric", or "insulator" material, with a low absorption, meaning most of the light that enters will eventually escape the surface elsewhere:
This metallic parameter will effectively change the colour of the reflections that the material exhibits. Indeed, in metallic materials, as all the light is absorbed within the surface, the tint of the reflections will lean more towards the colour of the material itself, whereas for dielectrics, the colour of the light will not get absorbed, and we will still see some of that colour coming out of the surface
To implement this behaviour, we can calculate F0 by blending between the default reflectance at 0 angle, which is a grey tint, and the base colour for metal.
This way, at 0 angle, for a dielectric material, the reflection will be the result of our EtaToReflectivity function, which is a grey colour between 0 and 1, and for a metallic material, it will be the base colour of the material.
So to calculate the fresnel term, we do that :
Putting it all together
This is a simple transposition of the equation, with also the cosine term from the rendering equation, and the diffuse part of the BRDF that's multiplied by 1-F.
That's it !
We also need to define functions for sampling this brdf, and for evaluating the PDF given a direction.
Sampling a direction :
Here, we first calculate the fresnel term that will dictate if the light is being reflected or scattered inside the shape. Based on that value, we either sample a cosine distribution, or a microfacet distribution.
Evaluating the pdf :
Here, we evaluate the fresnel term again, and then weight the PDF of the microfacet distribution and the PDF of the cosine weighted distribution with it.
The microfacet distribution PDF function is defined as follows :
Remember, the microfacet distribution returns the fraction of microfacets that are oriented towards the halfway vector. We simply factor that with the cosine between the normal and the halfway, and we're done.
Wrapping up
We will also change the material struct to include a roughness and a metallic parameters :
and we can then use those when creating a material :
and we can use that in the BSDF functions :
...Annnd that's it ! Here's the result :
As you can see, we have some nice reflections in the walls.
Some sources
- Crash Course in BRDF Implementation by Jakub Boksansky. For me it's simply the best resource for an overview of all BRDF that are used in computer graphics. Very well explained and detailed, and also contains all the references to the papers and articles that defined all those BRDFs. It also contains the sources of all the BRDFs that are discussed in the article, and this is all actually being used in practice in a "Reference Path Tracer" as well.
- Background: Physics and Math of Shading by Natty Hoffman. That's also a great course that goes through all the maths and physics of BRDF, with some quite in depth explanations.
- Microfacet Models for Refraction through Rough Surfaces by Walter et al. That's the actual paper that defined most of the formulas we used for implementing our BRDF, so very well worth a read. Granted that it's more involved, but really helps understanding the topic more in depth!
- The Microfacet Models chapter of pbrt, that goes through all the theory and implementation of physically based BRDF. As for the rest of this book, it's an excellent resources that really goes in depth on the maths and physics foundations of BRDFs.
Next Post : Simple GPU Path Tracing, Part. 3.4 : Small Improvements, Camera and wrap up
Commentaires
Enregistrer un commentaire