Portfolio Image

Final result

Compared to BRDF with Lambertian (left), BSSRDF (right) makes the skin much more realistic.

High-res image

1600x1200. 1024 SPP.


Low-res image

400x300. 1024 SPP.


Digital Sophie

Rendering the human is one of the most important tasks in computer graphics. According to the uncanny valley effect, people have much less tolerance of bad rendering of human than other objects. The difficulty of rendering realistic human skin is the human skin contains multiple layers of human tissue. The light transport beneath the skin is too complex to simulate accuractely. We implement BSSRDF [1] (bidirectional surface sacttering distribution function) to approximate the subsurface scattering of the human skin. In addition, we add several ornaments of different materials to make it more realistic.



We implement BSSRDF to simulate subsurface scattering of the human skin

Read More

Importance Sampling

We implement the importance sampling which accelerates the convergence of rendering.

Read More

Multi-thread Acceleration

Ray tracing of different pixels is independent. Multi-threading brings 10 times speed boost in a laptop.

Read More


The most significant different between BRDF and BSSRDF is BRDF assumes the entry point and the exit point when a ray hits a surface are the same, while BSSRDF doesn't. And BSSRDF requires an additional integral over the area. Our previous assignment framework is not compatible anymore. So we implement a new integrator in rt/integrator/bssrdftracer.cpp. Due to its simplicity, we implement the BSSSRDF based on the Normalized Diffusion [2] (bssrdftracer.cpp:L129-L169). For the fresnel terms, we follow the implementation from PBRT [3] (bssrdftracer.h:L27-L36).


Importance Sampling

Since the BSSRDF requires integral over the area. We need to sample for the incoming point, given an outgoing point. The paper of Normalized Diffusion [2] provides the cumulative distribution function and [4] provides the corresponding inverse function so that we can sample the distance (bssrdftracer.cpp:L49-L73). Given the distance, we use a disk-shape sampling method [5] to sample the incoming point (bssrdftracer.cpp:L91-L127). Additionally, we implement the Russian Roulette algorithm as the condtion of indirect illumination(bssrdftracer.cpp:L164-L170).

Multi-thread Acceleration

Since the ray tracing of each pixel is independent. We can trivially add the multi-thread acceleration (renderer.cpp:L23-L68). We use the pthread library, so we add an additional line in CMakeLists.txt: set(CMAKE_CXX_FLAGS, "--lpthread"). In practive, we gain 10 times acceleration on a 12-core laptop. Since multi-threading across different platforms might occur problems, it is disabled in the source code. It can be enabled by setting n_thread > 1 (renderer.cpp:L55).


The human model (Sophie) comes from Adobe Mixamo (https://www.mixamo.com). We change the pose of it manually using the provided rig in Blender.

The hat model is from https://www.cgtrader.com/free-3d-models/character/clothing/gangster-hats.

The earring model is from https://www.cgtrader.com/free-3d-print-models/jewelry/pendants/ornament-oval.

This website is modified based on https://sc.chinaz.com/moban/171127086060.htm.

[1] Jensen, Henrik Wann, et al. "A practical model for subsurface light transport." Proceedings of the 28th annual conference on Computer graphics and interactive techniques. 2001.

[2] Sisson, Dylan. "Approximate Reflectance Profiles for Efficient Subsurface Scattering."

[3] Pharr, Matt, Wenzel Jakob, and Greg Humphreys. Physically based rendering: From theory to implementation. Morgan Kaufmann, 2016.

[4] Sampling Burley's Normalized Diffusion Profiles, https://zero-radiance.github.io/post/sampling-diffusion/

[5] King, Alan, et al. "BSSRDF importance sampling." ACM SIGGRAPH 2013 Talks. 2013. 1-1.


Zhouyingcheng Liao