Nihal Kenkre

Banner

Material behaviour

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.

Flow

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.

Algorithm

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.

Chizen-rs Brute Force vs Blender vs Satori

| | 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 - Direct Light Sampling + Indirect

| | 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 |

References

Raytracing in One Weekend
Physically Based Rendering
This answer on StackExchange
Sampling Microfacet BRDF
Shaders Monthly Series