
This algorithm tries to follow this path of incoming light for the different material input and calculates the outgoing color.
The treatment of the material inputs and the calculations of certain fator change based on whether the material is metallic or dielectric.
The fresnel is calculated differently for metallic and dielectrics. It decides how much light enters the object and how much light is reflected back as it is.
Metals cannot absorb the light, so all of it reflected after being tinted by the base color.
Dielectrics absorb the light, and based on the tranmission factor, transmit the light through their interior or diffuse it back out.
We take advantage of the multiple samples processed per pixel, and calculate the light color as if the object was fully metal, or fully dielectric, fully transmissive of fully diffuse.
For N samples the object will take on the absolute properties close to the value of the input. e.g. for metalness value of 0.5 the object will be fully metallic for 0.5 * N runs, and dielectric for the rest.
So for each sample we draw a uniform random number between 0 and 1, for each of the inputs that we are considering. The material is fully transmissive if transmission value is greater than random number drawn. Similar check is performed for the other inputs.
for each sample
for each hit on a triangle
wi = sample_ggx_hemisphere()
is_metallic = random_number(0, 1)
if (is_metallic > metalness) // fully metallic object
fresnel = calculate_metallic_fresnel()
is_fresnel = random_number(0, 1)
if (fresnel < is_fresnel) // incoming light has entered the object
is_diffuse = random(0, 1)
if (is_diffuse <= 0.04) // metals diffuse 0.04 of the light
wi = sample_cosine_distribution()
calculate diffuse lighting
else
the rest of light is reflected out tinted by the base color along wi
else
nothing to be done, new ray will be sent along wi to get the environment as is
else // fully dielectric object
fresnel = calculate_dielectric_fresnel()
is_fresnel = random_num(0, 1)
if (fresnel < is_fresnel) // incoming light has entered the object
is_transmitting = random(0, 1)
if (transmission > is_transmitting)
wi = sample_ggx_transmission()
light will pass through the object tinted by base color
else
wi = sample_cosine_distribution()
calculate diffuse lighting
In visual form
graph TD;
Z(For each Sample) --> A
A(For each hit) --> B[Sample GGX hemisphere, update wi];
B --> C{Is metallic?}
C -- Yes --> D{Effect of Fresnel}
D -- Light Entered --> E[Outgoing color tinted by basecolor]
D -- Light Reflected --> F[Reflect incoming light]
C -- No --> G{Effect of Fresnel}
G -- Light Entered --> H{Is transmitting?}
G -- Light Reflected --> I[Reflect incoming light]
H -- Yes --> J[Sample GGX transmission, update wi and tint outgoing light by basecolor]
H -- No --> K[Sample Cosine distribution, update wi and calculate diffuse lighting]
I implemented this in Satori with Optix and Chizen-rs with vulkan and slang, here are the results.
| | Brute Force | Blender | | ———————– | —————————- | ———————————— | | Breakfast Room 0 | link | link | | Breakfast Room 1 | link | link | | Breakfast Room 2 | link | link | | Cornel Box | link | link | | Metal and Glass Dragons | link | link | | Emissive Test | link | link | | Glass and Candle | link | link | | Living Room | link | link | | Mosquito in Amber | link | link | | Transmission Test | link | link | | Transmission Thin Wall | link | link |
| | Satori | | ———————– | ————————– | | Beautiful Game | link | | Breakfast room 0 | link | | Breakfast room 1 | link | | Breakfast room 2 | link | | Cornell Box | link | | Metal and Glass Dragons | link | | Emissive Test | link | | Flight Helmet | link | | Glass and Candle | link | | Helmets | link | | Horse Statue | link | | Living Room | link | | Mosquito in Amber | link | | Salle de Bain | link | | San Miguel 0 | link | | San Miguel 1 | link | | San Miguel 2 | link | | Transmission Roughness | link | | Transmission Test | link | | Transmission Thin wall | link |
Raytracing in One Weekend
Physically Based Rendering
This answer on StackExchange
Sampling Microfacet BRDF
Shaders Monthly Series