Files
LNXSDK/leenkx/Shaders/std/sss.glsl
2026-08-07 02:04:01 -07:00

97 lines
3.7 KiB
GLSL

// Separable SSS Transmittance Function, ref to sss_pass
vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sampler2DShadow shadowMap, vec3 sssColor, float sssRadius
#ifdef _ShadowMapAtlas
, vec4 tileBounds
#endif
) {
const float translucency = 0.85;
vec4 shrinkedPos = vec4(p - 0.005 * n, 1.0);
vec4 shadowPos = LWVP * shrinkedPos;
vec2 shadowUV = shadowPos.xy / shadowPos.w;
#ifdef _ShadowMapAtlas
shadowUV = clamp(shadowUV, tileBounds.xy, tileBounds.zw);
#endif
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
float d1 = texture(shadowMap, vec3(shadowUV, shadowPos.z)).r;
float d2 = shadowPos.z;
d1 *= lightFar;
d2 *= lightFar;
float d = scale * abs(d1 - d2) * 1000.0;
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}
#ifdef _ShadowMapAtlas
vec3 SSSSTransmittanceCubeAtlas(sampler2DShadow shadowMap, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, int index, vec3 sssColor, float sssRadius) {
const float translucency = 0.85;
vec3 shrinkedPos = p - 0.005 * n;
vec3 ld = normalize(shrinkedPos - lightPos);
#ifdef _InvY
ld.y = -ld.y;
#endif
float d2 = lpToDepth(ld, lightProj);
int faceIndex = 0;
int lightIndex = index * 6;
vec2 uv = sampleCube(ld, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex];
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y;
#endif
float d1 = texture(shadowMap, vec3(uvtiled, d2)).r;
d1 *= lightFar;
d2 *= lightFar;
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}
#endif
vec3 SSSSTransmittanceCube(samplerCubeShadow shadowMapCube, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, vec3 sssColor, float sssRadius) {
const float translucency = 0.85;
vec3 shrinkedPos = p - 0.005 * n;
vec3 ld = normalize(shrinkedPos - lightPos);
#ifdef _InvY
ld.y = -ld.y;
#endif
float d2 = lpToDepth(ld, lightProj);
float d1 = texture(shadowMapCube, vec4(ld, d2)).r;
d1 *= lightFar;
d2 *= lightFar;
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}