real multilayer sss in cycles

It seems to me that blender cycles is quite limited for doing a real multilayer sss...

What I want to achieve is something like that. Here is my bench, a shape with an increasing thickness

in renderman, you can define a multilayer sss like this:

and you obtain something like this

which is exactly what I want. To explain with a little graph, here the way I want my scatter to behave:

But in blender cycles, it seems that you cannot achieve something better than that:

The reason for that is that you can tell the sss shader to be present from 0 thickness to x (via scale and radius), but there is no way to set presence from a to b where a > 0. The graph looks like something like that in blender cycles:

the deep layer is overlapping every layers...

very simple dummy node setup to summurize what is performed for any skin shader I found or tried to do (also this is a very bad setup here, no energy conservation):

Is there a way in blender cycles to know the deepness of the scatering? Or am I thinking my shader the wrong way?

Thanks a lot! (and sorry for my average english...)

edit: digging... I have made a pretty nice step forward using absorption and translucency. It seems that sss is not absorbing the light rays, thus, make impossible the use of raylength, whereas translucency of course does. Here is the same bench:

with suzanne (right one has a quick white skull using solidify)

edit 2 Still digging around I have created a node setup to create a 3 colors ramp. It is quite usefull for my current tests: (cursor here is the V coordinate, should be the deepness in the final shader)

edit3 What about this attempt? I am not sure about energy conservation here, I think the add shader at the end should be balanced with something in the diffuse shader... maybe not. Any idea? The 8.0 value is just to make the effect more obvious. Should be 1.0 in real world I guess.. Also, isn't there a IOR coefficient in real world? I have tried the glass shader with 1.0 of roughness, but it clearly doesn't make the trick... anyway, here it is:

• Why can't you just multiply your ray length by sinus to make it 0 at start? It could require rescaling/shifting but maybe this simple trick do the work for you? Apr 13, 2017 at 1:12
• @piotao thanks a lot for your comment. I would be glad to simplify, but I must admit I don't really understood where you would add a sinus and why. Could you precice what you would have done please? Is it a replacement of the "sss ramp" group or something like that? Apr 13, 2017 at 8:08
• I just looked at the graphs showing SSS scatter you provided and immediately I saw how this could be 'fitered' by using a sin function. Then, your graphs denoting cycles should become more like the graphs with nice curves you pasted first. If you've got something like this bad result from cycles, it "should" be enough to artificially put it to sin due to characteritics it will 'reshape' the input. I did not build any nodes for that, this is just an idea. It may work however, because each RGB channel is in fact nothing more like just numeric data, isn't it? Apr 14, 2017 at 20:41
• BlenderDiplom has a rather in depth tutorial on absorption in cycles! Apr 25, 2017 at 22:17
• youtube.com/watch?v=qkqsx951gcg Apr 25, 2017 at 22:17

This can be achieved by combining multiple Subsurface Scattering shader nodes to 'cancel out' part of the scatter at short distances. This allows the scatter profiles to be manipulated as desired.

As explained in your question, standard Subsurface Scattering shader only provides control of the 'radius' of the scatter in each of the channels - ie, how far each of the colors is scattered within the surface with falloff over distance - with no control over when the scattering actually starts. This means that close to the point of illumination all colors are scattered equally and each drops off at it's own rate as the distance increases.

Using the default 'Cubic' sub-surface scatter mode, the distribution follows the Cubic distribution function :

y = e ^ -((x^3)/(a^3))


For Quadratic, the distribution is very similar :

y = e ^ -((x^2)/(a^2))


Online tools are available to graph these functions so that they can be easily manipulated - for example, https://www.desmos.com/calculator, which allows you to instantly see the result of changes to the function.

To control the scattering we need to be able to manipulate the profile of those graphs and this can be achieved by combining multiple scatters, each with different properties. For example, by adding two shaders together we can produce a more interesting distribution :

In order to block the scattering at 'short' distances we would need to subtract one distribution from the other. eg, 'y = (e ^-((x^3)/(a^3)) - e^-((x^3)/(b^3)))*c' with carefully selected values for 'a', 'b', 'c' (a controls one Cubic, b controls the other Cubic, c scales the result).

Under normal circumstances it's not possible to subtract the effect of one shader from another - since we only have an 'Add' shader and a 'Mix' shader but no 'Subtract'. However, there is a trick we can use to subtract the effect of a shader by using 'negative' color values. The color of a surface is represented by a Vector of 3 values - Red, Green, Blue. These values are usually in the range of 0.0 to 1.0 but are equally valid to be outside of that range. For values greater than 1.0, the surface will have the effect of amplifying any incoming light rays. However, values less than 0.0 result in any incoming 'positive' light rays being converted into "negative" light. Combining such negative rays with the output of another shader using the Add shader will result in the negative light being subtracted from the positive light. Care should be taken to ensure that the overall effect does not result in negative light escaping the system - this can cause some unexpected effects - but this can be used to 'cancel out' the effect of one shader with that of another.

The Subsurface Scattering Shader consists of two elements - effectively a 'Diffuse' element to handle the surface interaction and the 'Subsurface' element for the below-surface scattering. Subtracting one Subsurface Scattering shader from another will remove the 'Diffuse' element, so we need to add it in again - so we need 3 shaders : one for the 'base' subsurface (which should have Radius set to 0,0,0 to disable scattering), one for the 'positive' subsurface scatter and another for the 'negative' subsurface scatter.

This can be implemented with the following nodes :

The material consists of three Subsurface Scattering nodes. The top one has its Radius set to 0,0,0 so that it does not perform any scattering - it acts effectively as a Diffuse shader (and, in fact, it could be replaced by one - although my tests seem to show that it's not actually more efficient that way) to provide the surface interaction. The next Subsurface Scattering node provides the 'positive' element of the scattering. Its Radius is fed from a Combine XYZ node which can be set to the desired scattering parameters. The final Subsurface Scattering node provides the 'negative' element of the scattering and it also has a Combine XYZ to provide the scattering parameters. A Vector Subtract node generates the 'negative' color from the input RGB node by subtracting from 0,0,0. The Color is also multiplied by an additional Combine XYZ node to provide scaling to adjust each channel. The outputs from the three Subsurface Scattering shaders are combined using Add shader nodes to provide the final output - ie, 'surface' + 'positive' - 'negative'.

I used the same online graphing tool mentioned above to adjust the parameters until I was happy with the parameters for each channel. The values of a,b,c can be simply plugged into the 3 Combine XYZ nodes in the above material - 'a' into the Radius input of the 'positive' shader, 'b' into the 'negative' shader, 'c' into the multiplier for the Color input.

An interactive version of this should be available here : https://www.desmos.com/calculator/jp3nbgellf.

To see how Quadratic would affect the distribution, see here : https://www.desmos.com/calculator/zycoycntdl

To demonstrate on a back-lit wedge :

Blend file attached

• This is absolutely brillant. The negative color trick is awesome. Also cristal clear explanation, thank you so much for sharing this answer Jun 2, 2017 at 21:08
• You're very welcome - glad to help. I've particularly enjoyed working on this one and learned a lot along the way. I was quite inspired by your various solutions in your question and its edits. I've been quite interested in negative color for some time and been looking for a way to put it to good use :-) Jun 2, 2017 at 22:42