SSS

SSS(Sub-Surface Scattering) (피하산란)

  • BSSRDF(Bidirectional surface-scattering reflectance distribution function)
    • 입사한 지점과 반사되는 지점이 다름.
    • 실시간으로 계산하기에는 부하가 큼
  • 여러 기법들
    • Texture-Space Diffusion
    • Scren-Space SSS
    • Pre-Integrated Skin Shading
    • other Fake/Fast/Approximated SSS

TSD / Texture-Space Diffusion

SSSSS / Scren-Space Sub-Surface Scattering

PISS / Pre-Integrated Skin Shading

  • LookUpTexture 이용

  • fwidth : abs(ddx(x)) + abs(ddy(x))

  • DirectX는 ddx_fine/ddy_fine함수도 있음.

half diffuse = LdotN;
half curvature = saturate(length(fwidth(N)) / length(fwidth(positionWS)) * curvatureScale);

half2 pissUV;
pissUV.x = diffuse;
pissUV.y = curvature;

half3 pissTex = SAMPLE_TEXTURE2D(_PissTex, sampler_PissTex, pissUV).rgb;

LocalThickness

// local thickness
half  localTicknessTex = SAMPLE_TEXTURE2D(_LocalThicknessTex, sampler_LocalThicknessTex, uv).r;
half3 H                = normalize(L + N * _Distortion);
half  VdotH            = pow(saturate(dot(V, -H)), _Power) * _Scale;
half  backLight        = _Attenuation * (VdotH + _Ambient) * localTicknessTex;

other Fake/Fast/Approximated SSS

half  halfLambert = NdotL * 0.5 + 0.5;
half3 fakeSSS     = (1 - halfLambert) * _SSSColor;
half3 color       = halfLambert + fakeSSS;
half  rim     = 1 - NdotL;
// 역광일때만 하려면 VdotL처리
// rim *= VdotL;
half3 fakeSSS = pow(rim, _SSSPower) * _SSSMultiplier * _SSSColor;
half3 color   = lambert * fakeSSS;
half  rim     = 1 - NdotL;
half3 fakeSSS = SAMPLE_TEXTURE2D(_SSS_RampTex, sampler_SSS_RampTex, half2(rim, 0)).rgb;
half2 brdfUV;
brdfUV.x = dot(N, L);
brdfUV.y = dot(N, H);

half3 brdfTex = SAMPLE_TEXTURE2D(_BrdfTex, sampler_BrdfTex, brdfUV * 0.5 + 0.5).rgb;
half LdotN = dot(L, N);
half LdotV = dot(L, V);

half2 rampUV;
rampUV.x = LdotN * 0.3 + 0.5;
rampUV.y = LdotV * 0.8;
half3 rampTex = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).rgb;

아니면 Albedo맵 / Normal맵 자체에 Blur(rgb에 가중치를 주어서)를 적용한다.

Ref