I have a question related to SSS and especially transmittance. I've looked at several papers about that topic, most of them from Jorge Jimenez, which are very interesting and, I admit, a bit hard for me.

Here is one of the papers : http://www.iryoku.com/translucency/

I have some difficulties to understand the way it works and the way it calculates the distance the light traveled through the object. I think that I understand the very big lines but I am also a bit confused as I am trying to integrate this into the Unity engine and I have some difficulties to match Unity engine available values such as the shadows maps, the shadows coords, etc... to make them fit the way they are used in the paper.

So here it is, I am a bit lost in the "in-between" and I hope that somebody might be able to help me.

Thanks a lot.

EDIT : added the shader code from referenced paper

float distance(float3 posW, float3 normalW, int i) {
  // Shrink the position to avoid artifacts on the silhouette:
  posW = posW - 0.005 * normalW;

  // Transform to light space:
  float4 posL = mul(float4(posW, 1.0), lights[i].viewproj);

  // Fetch depth from the shadow map:
  // (Depth from shadow maps is expected to be linear)
  float d1 = shwmaps[i].Sample(sampler, posL.xy / posL.w);
  float d2 = posL.z;

  // Calculate the difference:
  return abs(d1 - d2);

// This function can be precomputed for efficiency
float3 T(float s) {
  return float3(0.233, 0.455, 0.649) * exp(-s * s / 0.0064) +
         float3(0.1,   0.336, 0.344) * exp(-s * s / 0.0484) +
         float3(0.118, 0.198, 0.0)   * exp(-s * s / 0.187)  +
         float3(0.113, 0.007, 0.007) * exp(-s * s / 0.567)  +
         float3(0.358, 0.004, 0.0)   * exp(-s * s / 1.99)   +
         float3(0.078, 0.0,   0.0)   * exp(-s * s / 7.41);

// The following is done for each light 'i'.

// Calculate the distance traveled by the light inside of the object:
// ('strength' modulates the strength of the effect; 'normalW' is the vertex
//  normal)
float s = distance(posW, normalW, i) / strength;

// Estimate the irradiance on the back:
// ('lightW' is the regular light vector)
float irradiance = max(0.3 + dot(-normalW, lightW), 0.0);

// Calculate transmitted light:
// ('attenuation' and 'spot' are the usual spot light factors, as in regular
//  reflected light):
float3 transmittance = T(s) * lights[i].color *
                       attenuation * spot * albedo.rgb * irradiance;

// Add the contribution of this light:
color += transmittance + reflectance;
  • \$\begingroup\$ I'm going to read through the paper you sent when I get home but in the mean time, give this a look. We used it to implement a Ray-Tracing solution on the GPU but I don't think it would be too different to do in Unity. They use a thickness map (which is really AO with normals flipped) and just query that instead of his shadow maps solution. colinbarrebrisebois.com/category/subsurface-scattering \$\endgroup\$ May 19, 2016 at 16:13


You must log in to answer this question.

Browse other questions tagged .