Clear coat PBR example and tint color

I was reading Master Physically Based Rendering (PBR) - Babylon.js Documentation and testing the sample https://www.babylonjs-playground.com/#FEEK7G#7 about clear coat color and tinting.

However, modifying the “At distance” and “Tint thickness” sliders seems to not change anything in the rendering. I know PBR effects can be subtle, but here I can’t see any pixel changing color whatever the values for these two slides.

Is it expected or am I missing something?

Pinging el maestro @sebavan

The thing is this controls what the colors looks a a certain amount of distance under the surface.

I ll be totally inacurate but I hope it helps to better understand it. It is like sea water could look blue 5 meter under the surface and the other parameters controls how deep is the sea so you can define visible colors without infinitesimal precision to setup the dark blue of the bottom.

That said it does nothing in this example cause we use beer lambert law to compute absorption (or search for cocaLambert for the alcohol free version in our sources… yes I am proud of it :slight_smile: )

    // From beer lambert law I1/I0 = e −α′lc
    // c is considered included in alpha
    // https://blog.selfshadow.com/publications/s2017-shading-course/drobot/s2017_pbs_multilayered.pdf page 47
    vec3 cocaLambert(vec3 alpha, float distance) {
        return exp(-alpha * distance);
    }

    // where L on a thin constant size layer can be (d * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))
    vec3 cocaLambert(float NdotVRefract, float NdotLRefract, vec3 alpha, float thickness) {
        return cocaLambert(alpha, (thickness * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))));
    }

    // From beerLambert Solves what alpha should be for a given result at a known distance.
    vec3 computeColorAtDistanceInMedia(vec3 color, float distance) {
        return -log(color) / distance;
    }

    vec3 computeClearCoatAbsorption(float NdotVRefract, float NdotLRefract, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
        vec3 clearCoatAbsorption = mix(vec3(1.0),
            cocaLambert(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness),
            clearCoatIntensity);
        return clearCoatAbsorption;
    }

As our color is exactly 1 here the division leads to an infinite value which then ends up being 1 no matter the distance. So try it on this pg where the tint is not full one and you ll feel way more the impact of both sliders: https://www.babylonjs-playground.com/#FEEK7G#106

Those are basically helpers to help setting up your color with better precision using real absorption vs simple linear slider on the color itself.

3 Likes

Thanks a lot for the explanation!

The thing I’m continually impressed by is how many of these problems you guys have solved and merged into the core features of Babylon. In other libraries I’ve had to write custom shaders but so far in Babylon all my use cases are covered. Just saying thanks :slight_smile:

2 Likes