Documentation / scene / SkinSSS
Class: SkinSSS
Defined in: libs/scene/src/posteffect/skinsss.ts:49
Stylized screen-space skin scattering pass.
Remarks
SkinMaterial writes the diffusible part of its lit color - the stylized diffuse ramp plus back-lit transmission, without specular - into a side buffer. This pass diffuses that buffer with a channel-dependent kernel and swaps it back in:
result = base + (diffused - original) * scatterTint * strength + diffused * glowBecause the term added back replaces exactly the term subtracted, the redistribution is energy conserving: light that appears on the dark side of the terminator is light that left the lit side, rather than light invented on top of a finished image. With scatterTint white and glow zero the total radiance is preserved to within the kernel's normalization error.
Two things follow from that formulation and are worth knowing:
- Nothing happens where the diffusion changes nothing, so a disabled or zero-radius pass is a true no-op, and quantization from an 8-bit side buffer largely cancels between the subtracted and added terms instead of banding across the whole face.
scatterTintcolors only the light that actually moved. Tinting the whole diffuse - what the material used to do withscatterColor- is what made the old look read as red haze.
Stylization survives in two places. The material owns the direct lighting ramp (wrap, softness, shadow tint, brightening) and this pass diffuses whatever ramp it produced; and profile selects the channel radii, so the wax and jade presets are as reachable as skin.
This is intentionally separate from the profile-based SSS pass, which supports per-pixel profiles via a profile-slot MRT. Here a single global profile lives in uniforms.
Extends
Constructors
Constructor
new SkinSSS():
SkinSSS
Defined in: libs/scene/src/posteffect/skinsss.ts:72
Returns
SkinSSS
Overrides
AbstractPostEffect.constructor
Properties
_enabled
protected_enabled:boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:118
Inherited from
_layer
protected_layer:PostEffectLayer
Defined in: libs/scene/src/posteffect/posteffect.ts:119
Inherited from
Accessors
disposed
Get Signature
get disposed():
boolean
Defined in: libs/base/dist/index.d.ts:6107
Returns
boolean
Inherited from
enabled
Get Signature
get enabled():
boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:130
Whether this post effect is enabled
Returns
boolean
Set Signature
set enabled(
val):void
Defined in: libs/scene/src/posteffect/posteffect.ts:133
Parameters
val
boolean
Returns
void
Inherited from
layer
Get Signature
get layer():
PostEffectLayer
Defined in: libs/scene/src/posteffect/posteffect.ts:137
Whether this post effect will be rendered at opaque phase
Returns
Inherited from
profile
Get Signature
get profile():
SubsurfaceProfile
Defined in: libs/scene/src/posteffect/skinsss.ts:109
Subsurface profile supplying the per-channel scatter radii and falloff.
Remarks
Defaults to SubsurfaceProfile.getDefaultSkinProfile when unset. Only the channel ratios of scatterRadius and the falloffColor are read; the absolute distance comes from SkinSSS.scatterRadius, so switching profiles changes the color of the bleed without changing how far it reaches.
The channel ratios are what make skin read as skin - red travels several times further than blue, which is the red-to-orange-to-yellow gradient at the terminator. They are also the main stylization lever: the wax and jade presets are the same code path with different ratios.
Returns
Set Signature
set profile(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:112
Parameters
val
Returns
void
strength
Get Signature
get strength():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:117
Final blend strength of the conserving redistribution. 1 fully diffuses the skin diffuse.
Returns
number
Set Signature
set strength(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:120
Parameters
val
number
Returns
void
glow
Get Signature
get glow():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:133
Additive, deliberately non-conserving bleed layered on top of the conserving result.
Remarks
0 (the default) keeps the pass energy conserving. Raising it adds the diffused term a second time without subtracting anything, which is the glow-heavy look the pass produced before it conserved energy; around 1 approximates it. Use it when the art direction wants skin to read as lit from within rather than as a physical surface.
Returns
number
Set Signature
set glow(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:136
Parameters
val
number
Returns
void
scatterTint
Get Signature
get scatterTint():
Vector4
Defined in: libs/scene/src/posteffect/skinsss.ts:149
Tint applied to the redistributed light.
Remarks
White (the default) leaves the pass energy conserving. A warm tint pushes the classic reddish terminator further than the profile's channel radii do on their own. Because it multiplies only the difference between the diffused and original diffuse, it cannot wash the whole surface - only the light that moved.
Returns
Vector4
Set Signature
set scatterTint(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:152
Parameters
val
Vector4
Returns
void
opacity
Get Signature
get opacity():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:157
Skin mask coverage threshold. Scattering fades in as the blurred mask coverage exceeds this.
Returns
number
Set Signature
set opacity(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:160
Parameters
val
number
Returns
void
sampleStep
Get Signature
get sampleStep():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:174
Maximum pixel spacing between blur taps. Caps the projected scatter radius for close-ups.
Remarks
With SKIN_SSS_TAPS taps per side the kernel reaches sampleStep * SKIN_SSS_TAPS pixels, so this is the real limit on scatter width. The separable form makes taps cheap enough that the default no longer has to be tight: the old single-pass 9x9 kernel capped out at 8 pixels, and a face in close-up projects a 2 cm scatter radius far past that - the shot that needs the most scattering used to get the least.
Returns
number
Set Signature
set sampleStep(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:177
Parameters
val
number
Returns
void
scatterRadius
Get Signature
get scatterRadius():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:182
World-space scatter radius. The blur width shrinks with distance to keep this constant.
Returns
number
Set Signature
set scatterRadius(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:185
Parameters
val
number
Returns
void
smoothness
Get Signature
get smoothness():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:199
Skin smoothing amount ("beauty filter"). Blends the lit color toward a mask- and depth-weighted blur of itself on skin pixels, removing pore and albedo detail while facial features stay sharp wherever the skin mask excludes them (eyes, brows, lips). 0 disables smoothing.
Remarks
This is separate from the diffusion and stacks on top of it. The diffusion blurs lighting only; albedo detail such as pores and blemishes passes through it untouched, which is correct but is not what a beauty filter is for.
Returns
number
Set Signature
set smoothness(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:202
Parameters
val
number
Returns
void
depthScale
Get Signature
get depthScale():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:207
Depth rejection scale. The reference shader uses 80.
Returns
number
Set Signature
set depthScale(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:210
Parameters
val
number
Returns
void
colorBoost
Get Signature
get colorBoost():
number
Defined in: libs/scene/src/posteffect/skinsss.ts:215
Multiplier applied to the diffused irradiance before compositing.
Returns
number
Set Signature
set colorBoost(
val):void
Defined in: libs/scene/src/posteffect/skinsss.ts:218
Parameters
val
number
Returns
void
Methods
on()
on<
K>(type,listener,context?):void
Defined in: libs/base/dist/index.d.ts:630
IEventTarget.on
Type Parameters
K
K extends "dispose"
Parameters
type
K
listener
EventListener<{ dispose: []; }, K>
context?
unknown
Returns
void
Inherited from
once()
once<
K>(type,listener,context?):void
Defined in: libs/base/dist/index.d.ts:634
IEventTarget.once
Type Parameters
K
K extends "dispose"
Parameters
type
K
listener
EventListener<{ dispose: []; }, K>
context?
unknown
Returns
void
Inherited from
off()
off<
K>(type,listener?,context?):void
Defined in: libs/base/dist/index.d.ts:638
IEventTarget.off
Type Parameters
K
K extends "dispose"
Parameters
type
K
listener?
EventListener<{ dispose: []; }>
context?
unknown
Returns
void
Inherited from
dispatchEvent()
dispatchEvent<
K>(type, ...args):void
Defined in: libs/base/dist/index.d.ts:642
IEventTarget.dispatchEvent
Type Parameters
K
K extends "dispose"
Parameters
type
K
args
...object[K]
Returns
void
Inherited from
AbstractPostEffect.dispatchEvent
dispose()
dispose():
void
Defined in: libs/base/dist/index.d.ts:6108
Returns
void
Inherited from
needFlip()
needFlip(
device):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:145
Check if the post effect should be rendered upside down.
Parameters
device
AbstractDevice
The device object
Returns
boolean
true if the post effect should be rendered upside down
Inherited from
requireDepthAttachment()
requireDepthAttachment(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:159
Checks whether this post effect requires the scene depth buffer
Parameters
_ctx
Returns
boolean
true if the scene depth buffer is required.
Inherited from
AbstractPostEffect.requireDepthAttachment
requireMotionVectorTexture()
requireMotionVectorTexture(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:166
Checks whether this post effect requires the motion vector texture
Parameters
_ctx
Returns
boolean
true if the motion vector texture is required.
Inherited from
AbstractPostEffect.requireMotionVectorTexture
requireHiZTexture()
requireHiZTexture(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:170
Checks whether this post effect requires the Hi-Z depth pyramid.
Parameters
_ctx
Returns
boolean
Inherited from
AbstractPostEffect.requireHiZTexture
requireHiZNearest()
requireHiZNearest(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:181
Checks whether this post effect requires the Hi-Z pyramid's nearest-depth channel, which answers "how close is the nearest surface in this screen region" rather than the farthest-depth channel's occlusion question.
Implies AbstractPostEffect.requireHiZTexture; an effect that needs the nearest channel does not have to request the pyramid separately.
Parameters
_ctx
Returns
boolean
Inherited from
AbstractPostEffect.requireHiZNearest
requireSceneNormalTexture()
requireSceneNormalTexture(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:185
Checks whether this post effect requires opaque-scene world normals.
Parameters
_ctx
Returns
boolean
Inherited from
AbstractPostEffect.requireSceneNormalTexture
requireSceneRoughnessTexture()
requireSceneRoughnessTexture(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:189
Checks whether this post effect requires opaque-scene roughness data.
Parameters
_ctx
Returns
boolean
Inherited from
AbstractPostEffect.requireSceneRoughnessTexture
requireShadowMask()
requireShadowMask(
_ctx):boolean
Defined in: libs/scene/src/posteffect/posteffect.ts:200
Checks whether this post effect requires the screen-space shadow mask.
When true and the mask was produced this frame, the effect can sample DrawContext.shadowMaskTexture in its apply() body; the graph keeps the mask alive for the effect's pass.
Parameters
_ctx
Returns
boolean
true if the shadow mask is required.
Inherited from
AbstractPostEffect.requireShadowMask
setup()
setup(
s):RGHandle
Defined in: libs/scene/src/posteffect/posteffect.ts:239
Declare this effect's passes on the render graph.
The default implementation wraps AbstractPostEffect.apply into a single graph pass, so effects only overriding apply() work unchanged. Multi-pass effects override this method to declare each internal step as its own pass, calling PostEffectSetupContext.createOutput inside the final pass.
Parameters
s
Build-time setup context.
Returns
The effect's output color handle.
Inherited from
passThrough()
protectedpassThrough(ctx,inputColorTexture,srgbOutput,renderStates?):void
Defined in: libs/scene/src/posteffect/posteffect.ts:344
Parameters
ctx
Draw context
inputColorTexture
Texture2D
Input color texture
srgbOutput
boolean
Whether the result should be gamma corrected
renderStates?
RenderStateSet
Returns
void
Inherited from
AbstractPostEffect.passThrough
drawFullscreenQuad()
protecteddrawFullscreenQuad(renderStateSet?):void
Defined in: libs/scene/src/posteffect/posteffect.ts:363
Draws a fullscreen quad
Parameters
renderStateSet?
RenderStateSet
Render states that will be used when drawing the fullscreen quad.
Returns
void
Inherited from
AbstractPostEffect.drawFullscreenQuad
onDispose()
protectedonDispose():void
Defined in: libs/scene/src/posteffect/posteffect.ts:376
Returns
void
Inherited from
requireLinearDepthTexture()
requireLinearDepthTexture():
boolean
Defined in: libs/scene/src/posteffect/skinsss.ts:222
Checks whether this post effect requires the linear depth texture
Returns
boolean
true if the linear depth texture is required.
Overrides
AbstractPostEffect.requireLinearDepthTexture
apply()
apply(
ctx,inputColorTexture,sceneDepthTexture,srgbOutput):void
Defined in: libs/scene/src/posteffect/skinsss.ts:226
Apply the post effect
Parameters
ctx
inputColorTexture
Texture2D
The previous scene color texture
sceneDepthTexture
Texture2D
The linear scene depth texture
srgbOutput
boolean
Whether the result should be gamma corrected
Returns
void
Remarks
The frame buffer of the post effect is already set when apply() is called.