Photorealistic Skin Shading
Reviewed and annotated by Christophe Hery.
In this tutorial, we'll use RenderMan's Pixar Surface Material to get a photorealistic render with this (now classic?) head scan from Lee Perry-Smith. We'll use Subsurface Scattering, Fuzz and 2 specular lobes, combined with displacements and bump mapping to achieve a natural looking head in RenderMan 21.
We're also using Layered Pixar Surface Material, for extendability, including sweat, paint, etc...If you feel your asset will be a hero asset, consider always using the Layered version of Pixar Surface.
Photorealistic skin can be a challenge. There is a lot of nuance in skin and a lot of the effect is dependent on very small visual differences, especially in light absorption and specular intensity. Because of the lack of accurate reference for this bust, we've taken some artistic liberties. let's break down some of the most important aspects of making realistic skin.
We are combining Displacements and Bump mapping to achieve the most detail possible from the 16-bit integer displacement map. We're doing this by using PxrDisplace which deals with the amount of displacement, and a PxrDispTransform, which deals with the encoding of the displacement file.
In our case, our texture map is a traditional grayscale displacement map, so we're using Scalar as our data type in the PxrDispTransform node. We're also modifying the Remapping Mode, given that our texture map is black and white and has no negative values to tell the surface when to displace inward. To encode the values correctly, we are using a remap value of "Centered" which will tell RenderMan that the undisplaced value is 0.5, instead of black. This will displace the surface inward with values bellow 0.5, and outward with any value above.
It is important to use the highest bit depth possible for data maps to avoid compression or banding artifacts.
Sorry Lee, you're not that wrinkly, I exaggerated the bumpiness a bit in order to illustrate surface properties more clearly and their interaction with the different subsurface models...
As we can see in the Layered shading network below (I recommend looking at the high-resolution image in the gallery), we are sharing the same texture file for our bump and displacement.
The bump and displacement amounts need to be dialed in manually. Some attributes to keep in mind are " Adjust Amount" in the PxrBump node, which tells RenderMan to keep the edges from flipping the normals and creating artifacts, as well as "Displacement Bound" which is a crucial attribute in RenderMan for specifying a bounding box for the displacement. For our head, 0.1 will extend the surface bounding box 10%, which is enough to account for any slight displaced skin features such as moles.
Setting the Displacement Bound too high is inefficient and can make your render slow, so try to set this value as tight as possible.
The heart of realistic skin shading lies in Subsurface Scattering, which is the penetration and resulting scattering of light into a surface. The resulting luminance created by this complex scattering of light, gives the skin a glow of scattered light, softening the light terminator. RenderMan's Pixar Surface Material has 5 different subsurface algorithms which can handle these effects very well, from cartoony to realistic.
It is important to note that skin has no perfect direct light reflection, so we are not using the diffuse lobe. For energy to be accurate, we will set our subsurface gain to 1, this way all incoming light will be scattered.
RenderMan gives the user lots of flexibility by providing 4 different subsurface models, plus 1 single scatter model...so which subsurface model do I use? Well...for realistic skin, the most natural is Burley Normalized. This subsurface model will provide the sharpness we need in pores and wrinkles. Jensen and DEon dipole on the other hand, are great for gummy surfaces which need to scatter light more sparsely, this could be great for cartoony characters.
RenderMan also provides a manual Multiple Mean Free Path mode, for artistic control. This could be great for further per-dermis layer customization\, but we will focus on the recommended workflow.
Dipole Diffusion models have energy distribution limitations in very thin and backlit geometry, so it is always important to add Single Scattering for areas which are prone to these limitations, such as the nose, lips and ears. This will ensure the most accurate energy distribution.
The differences in subsurface models are small, but added accuracy, as small as it might seem, is important for photorealism.
The Subsurface Color is the most important attribute for the look of our skin, and lucky us, we have a great albedo map based on a real-life scan. To do this, we're using a file node and plugging into the Subsurface Color attribute. We need to make sure this texture map is color managed and linearized.
Diffuse Mean Free Path or DMFP is one of the most crucial attributes, it will tell the surface how deep light can penetrate into the geometry.
All 3 Diffusion models in RenderMan include an albedo inversion technique (see paragraph 4.2 - pages 77 to 79), and an implementation derivation for D'Eon. With this approach, a non varying DMFP (distance and color) will be automatically “modulated" (ie solved/inverted) from the varying albedo, in our case, the head color texture map.
Well, that escalated quickly... Think about it this way, deep down, SSS works with volumetric absorption and scattering properties, but these are not artist friendly and moreover have a sort of non linear relationship to the final color. So instead, we take a diffuse albedo map and a single constant DMFP value, and internally derive (solve/invert) the varying absorption and scattering properties. Once this is done, the albedo is not used anymore (contrary to a regular BRDF, where we post multiply the response by the albedo).
So...since RenderMan calculates SSS absorption automatically, does this mean I lose control? No. In fact, I'm using manually painted DMFP maps to further control the variance of subsurface across the skin. This flexibility can be great to exaggerate these effects, but keep in mind that if you were to set a single value for DMFP, RenderMan will modulate the SSS depth automatically...we're just adding a bit of artistic touch, which RenderMan excels at.
Here we can see an automatic vs manual DMFP modulation. All we are doing to compare these images is to have a constant DMFP value of 0.3, instead of a texture map. There are pluses and negatives for this particular model (keep in mind hair is part of the model instead of separate hair primitives). On the plus side, some of the skin features are softened a bit, but some unwanted brightness is showing up on top of the eyes and we lose some skin detail.
As we can see below, we can try to get closer to the sharpness of the manual DMFP by setting the DMFP value to 0.15, but then we compromise on the ears as they start to lose their gummy effect, even if we try mixing in Single Scatter at different directionality, because of this, I think the best approach for this model is to manually make choices on subsurface, although this is a subjective aesthetic, given the lack of reference material.
For our purposes, we'll make choices on photorealism as educated guesses. For this, I've painted a depth map in order to isolate areas of the face which usually have more fat or cartilage (more penetration) or are closer to the bone or have hair (less penetration). I've painted these maps in black and white for ease of painting, but we need to remap these values to an appropriate range for Pixar Surface Material.
We're driving the DMFP distance with a painted texture map and a PxrRemap node, to bring the values within a useful range. I chose to remap the texture to a range between 0.15 - 0.3.
There are 2 attributes to consider for DMFP:
- Mean Free Path Distance
- Mean Free Path Color
Mean Free Path Color is the most important of the two, because it specifically allows per-channel wavelength penetration, meaning if RGB values are, for example: 4,1,8, light would penetrate 4 units in the red channel, 1 unit in green and 8 units in blue. This allows for complex scattering effects. The default values work well for caucasian skin, but I'm choosing to go with the values from the documentation table as a sanity check. We don't have to map DMFP color, we need to set a color with the swatch.
We are making our choices based on a table of values available in the documentation, which gives us a great starting point for many real-world materials, including skin.
Mean Free Path Distance is the multiplier for the color, by manipulating this single value, we can modify the distance without having to compensate for 3 separate RGB values. This is very helpful if the scale of the model changes and we want to tweak easily. We are using our painted texture map to control the DMFP Distance.
Since we are doing this manually, the DMFP needs to change depending on reference imagery, because SSS depends on age, cartilage, skin fat, melanin amounts and many other unique skin traits in every person. Again, RenderMan will modulate this automatically, but I wanted added control.
Lighting can play tricks on your shading judgement, so it's best when we have accurate data to match the CG counterpart.
The use of Single Scatter is very important for thin surfaces, but might make surfaces appear too gummy, so we've decided to modulate the effect manually with the same DMFP map used in the Subsurface model. We're also keeping the DMFP color the same and plugging the albedo into the Color attribute...basically the same workflow as the main Subsurface lobe, but our intentions are to isolate ears and nose with the advanced attributes.
Two important attributes in the advances tab are the Directionality and Blur.
We are setting the Directionality to 0.8, which will ensure we keep the areas of effect mainly to the ears, nose and mouth. We are also setting the Blur to 1, which will spread and soften the effects of Single Scatter, this will make sure we don't get any harsh falloff.
We can keep the Single Scatter Gain to 1 and RenderMan will figure out energy conservation.
Although "Physical" specular type can be very accurate, we are taking some creative liberties and choosing "Artistic" as our specular type, which will give us the control we need for the fresnel response.
Adjusting the specular under different lighting scenarios is crucial for aesthetic purposes, just like a make-up artist will powder an actor's face to limit sweat or flatten unwanted skin features in a specific shot .
Since I painted black for no specular and white for specular, we need to adjust these values for Roughness, which are inverse...meaning white is rougher (less shiny) and black is sharper (more shiny). For this, we are also using a PxrRemap node to remap the black and white values into a reasonable range. We are using values between 0.2 - 0.6 for both Rough and Primary specular. These values are up to you and depend on the look you are after. In my case, they worked well for the still, but were too shiny for the daylight HDRI map, so make sure you always consider the lighting.
All people are covered in a large amount of fine hair, usually referred to as Peach Fuzz. This is usually simulated with actual hair follicles, but we can trick the effect with the Fuzz attribute. Fuzz will add a velvet-like lobe to our face, so it's important we use a texture to break it down and simulate hair follicles or the effect can be jarring and unrealistic.
In our case, we are using a very small noise pattern generated in photoshop and manipulated with some blur and contraction filters to give it a random appearance.
We're also changing the Cone Angle to 10 to accentuate the Fuzz a bit further. The effect is subtle, so I'm increasing the exposure a bit in the following image to show the effect.
Well this is short...we are using a simple rectangular light from the top with a very slight tilt, in order to get close to the little reference images found online. For the animated turntable we are using a single dome light with 3 different HDRI maps.
I'm using a neutral temperature of 5500k for the top light and a cool 9500k for the back light to make sure our skin doesn't get lit by perfectly white light, which is not realistic.
For the final image, I'm not doing color correction or levels manipulation, to make sure we're getting as close as possible with only RenderMan. After RenderMan Denoise gives me my clean image, I'm adding a complementary colored background in photoshop to accentuate the skin tone.
- Choose the right subsurface model for your needs, although differences are subtle, realism is important.
- All Dipole models need Single Scatter for correct energy distribution, especially with thin surfaces.
- Pixar Surface can modulate subsurface absorption automatically, while also providing manual controls.
- Always remap painted values for DMFP to coincide with scale of scene.
- Use Fuzz to fake fine peach fuzz hair in the skin.
- Try using high bit depth displacement and bump maps to avoid artifacts.
- Mixing Bump and Displacements maps can make minute detail easier to tweak.
- Specular amounts need to be adjusted depending on the lighting, just like live action.
- Try to use natural lighting temperatures and intensities.
Thanks to Christophe Hery, Senior Lead Software Engineer at Pixar and co-architect with Ryusuke Villemin of Pixar Surface Material, for ensuring the best workflow possible.
Infinite, 3D Head Scan by Lee Perry-Smith is licensed under a Creative Commons Attribution 3.0 Unported License. Based on work at www.triplegangers.com. Permissions beyond the scope of this license may be available at http://www.ir-ltd.net/ Downloaded from: http://www.ir-ltd.net/infinite-3d-head-scan-released
About the Author
From pitch to delivery, Leif Pedersen is a CG Generalist who's worn many hats in production for over 10 years. His background in traditional arts mixed with technical foundations has allowed him to work with a varied client list in both television and commercial work, and has now joined Pixar's RenderMan team.