Subsurface Scattering

What is it?

This week I’ve been working on a shader technique called subsurface scattering (SSS), Pluralsight describes subsurface scattering as “[it] works by simulating how light penetrates a translucent surface like a grape for instance, and it is absorbed and scattered and exits the surface at a different location” (Pluralsight, Understanding Subsurface Scattering, 2014).

Example of Subsurface Scattering. (Studio-daVinci-Dijon, Trans-luminesence – Subsurface Scattering, 2016).

Above image is a good example of subsurface scattering, the final image shows the light coming in from bottom right and as it bounces around the object it is absorbed and results in a darker colour at the top left of the object.

Subsurface scattering can be observed in real life very easily, if you take a light and flash hit close to the back of your fingers and look through the other side you will notice that the light is coming out dimmer and with a shade of red, this is because the light rays are bouncing around your finger and coming out at a different angle.

Alan Zucconi describes that “most modern engines rely on massive simplification that, despite being unable to reproduce photorealism, can produce believable approximation” (Zucconi, Fast Subsurface Scattering in Unity, 2017), as carrying out real time accurate calculations would be too much and would cause the game to run at unplayable framerate.

Transparency vs translucency; the difference how light ray is affected. (Zucconi, Fast Subsurface Scattering in Unity, 2017)

In Unity the default materials use alpha blending to achieve transparency, and the transparent object is rendered on top of the other objects with certain parts being not rendered; this works for many materials, but transparency only affects how much light is let through while translucency can affect and alter the path of a light ray.

Translucency is a very expensive calculation as it requires calculating of light scattering inside of a material, where each ray can split into many new light rays and reflecting hundreds of times inside the material. In 2011 at GDC, Colin Barre-Brisebois and Marc Bouchard in their talk they described their implementation in Frostbite 2 engine; it isn’t physically accurate simulation, but it creates a believable effect at a small cost.

Colin describes that in computer graphics “we rely heavily on BRDFs for describing local reflections” (Barré-Brisebois, 2011), which are simple and cheap for opaque object with good results achieved, but this doesn’t work for many objects in nature as they are “(partly) translucent” (Barré-Brisebois, 2011); for this reason BRDFs are not sufficient enough. BSSRDFs can be used for better effect, but they are more expensive and most of the time too expensive for computer graphics.

In their Frostbite 2 implementation they have used BSDFs (which are a combination of BRDF + BTDF) and with some elements of BSSRDF to achieve realistic looking effect, which is cheap to use in video game.


BRDF vs BSSRDF

BRDF (Griggs, Specular BRDF, 2017).

BRDF stands for bidirectional reflectance distribution function, it “describes the reflectance properties of a surface by specifying the amount of radiance incident from one direction that is reflected into another direction, with respect to the surface normal” (Griggs, Specular BRDF, 2017).

BRDF vs BTDF (Wikipedia, n.d.)

BTDF stands for bidirectional transmittance distribution function, and it works like BRDF, but the effect is applied on the opposite side of the surface. In the image above, as the ray hits the surface of the object, the reflected ray is called BRDF but as it passes through the object and comes out on the other side it is called BTDF.

Implementation

Sphere with Subsurface Scattering on left, and sphere with standard surface shader on right.

After following Alan’s adaptation of the shader in Unity I was able to get something similar working, but I couldn’t figure out if it was working properly or not. Alan starts by implementing his own lighting calculation in the surface shader, this allows him to expand what he can do with the lighting which is the crucial part in subsurface scattering.

// Expanding Unity's Surface light function
#include "UnityPBSLighting.cginc"
inline fixed4 LightingStandardTranslucent (SurfaceOutputStandard s,
    fixed3 viewDir, UnityGI gi)
{
    fixed4 pbr = LightingStandard(s, viewDir, gi);

    pbr.rgb = pbr.rgb + gi.light.color * I;
    return pbr;
}

void LightingStandardTranslucent_GI (SurfaceOutputStandard s,
    UnityGIInput data, inout UnityGI gi)
{
    LightingStandard_GI(s, data, gi);
}
How light affects the back face in translucent objects. (Zucconi, Fast Subsurface Scattering in Unity, 2017)

To calculate the subsurface scattering the L V & H variables are required, from the graph above, the L variable is the light direction which can be accessed from Unity’s Global Illumination; V is the view direction, which can be accessed in surface shader from the viewDir variable; finally, the normal can be accessed from Surface Output (s.Normal).

// Inside custom lighting function
float3 L = gi.light.dir;
float3 V = viewDir;
float3 N = s.Normal;

float3 H = L + N * _Distortion;
float VdotH = pow(saturate(dot(V, -H)), _Power) * _Scale;
float3 I = _Attenuation * (VdotH + _Ambient) * thickness;

// Inside surface function
thickness = tex2D(_LocalThickness, IN.uv_MainTex).r;

Above equation is a direct translation of the equations provided in Alan’s post about subsurface scattering, and with this I was able to achieve the effect seen on the sphere in screenshot above, but I couldn’t tell if it was working properly as I didn’t have the thickness texture; Alan describes how to create your own thickness texture, but I’m not very familiar with 3D software, so I have opted out to purchase the completed project from his patron and test it on the same model, and the effect worked perfectly.

Final version of the shader with Alan’s model and texture applied, as seen on the screen the subsurface scattering is working very well on this model.
For comparison, this is the same model with slightly different lighting taken straight from Alan’s Patreon Unity project.

As per Alan’s request under his post, I will not be supplying the model and the texture in my GitHub repository, but I will be leaving the shader file itself there, in case it needs to be tested. To create the thickness map, the normals on the model need to be flipped and the ambient occlusion baked; this will create the fake thickness of the model, and finally the colours need to be inverted on the AO map.

In the final version I will replace the model and AO texture with a model I found on the internet, with a makeshift AO map just to test that it works; credit to model on GitHub repository.

Conclusion

Subsurface scattering is a key technique when creating realistic looking materials, and while in computer graphics we can’t have physically realistic subsurface scattering, Colin and Alan have shown a great way to mimic this and how to create a shader that will look good enough to be used in computer graphics.

I will continue working on the ice shader, I will be implementing the refraction from the previous shader and hopefully I’ll be able to add this subsurface scattering solution into the shader to achieve a realistic looking blue ice.


Bibliography

Barré-Brisebois, C., 2011. GDC 2011 – Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look. [Online]
Available at: https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/
[Accessed 15 04 2020].

Pluralsight, 2014. Understanding Subsurface Scattering – Capturing the Appearance of Translucent Materials. [Online]
Available at: https://www.pluralsight.com/blog/film-games/understanding-subsurface-scattering-capturing-appearance-translucent-materials
[Accessed 19 04 2020].

Studi-daVinci-Dijon, 2016. Trans-luminesence – Subsurface Scattering. [Online]
Available at: https://www.deviantart.com/studio-davinci-dijon/art/Trans-luminescence-Subsurface-scattering-651025152
[Accessed 15 04 2020].

Wikipedia, n.d. Bidirectional scattering distribution function. [Online]
Available at: https://en.wikipedia.org/wiki/Bidirectional_scattering_distribution_function
[Accessed 16 04 2020].

Zucconi, A., 2017. Fast Subsurface Scattering in Unity. [Online]
Available at: https://www.alanzucconi.com/2017/08/30/fast-subsurface-scattering-1/
[Accessed 10 04 2020].

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s