Sheen
Open the live demo · Read the source · View on GitHub
Velvet, felt and brushed cotton are made of fibres that stand up off the surface. Light that grazes them bounces back towards you, so the cloth is brightest at its edges, where you look along the fibres. A plain rough material gets darker towards its edges instead, and cloth drawn with it looks like painted plastic.
The sheen layer adds that bright rim. This page draws the same red cloth twice, bare on the left and with a sheen on the right.
Step 1: A colour for the rim #
The sheen has a colour of its own, and it does not have to match the cloth. Black means
no sheen at all, which is the default. The colour is linear, unlike the material's
baseColor: nothing paints it, so there is no authored sRGB form to convert from.
/// Linear colours: the sheen is not painted, so it is not sRGB.
Vector3 _sheenColour() => switch (colour) {
0 => Vector3(0.2, 0.4, 1.0),
1 => Vector3(1.0, 1.0, 1.0),
_ => Vector3(1.0, 0.75, 0.3),
};
Step 2: The cloth #
sheenColor and sheenRoughness live in MaterialExtensions, which only
LightingModel.pbrLayered reads. The bare cloth on the left is the same model with no
extensions.
final Material bare = Material(
name: 'bare cloth',
lighting: LightingModel.pbrLayered,
baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
roughness: 0.6,
);
_cloth = Material(
name: 'cloth with sheen',
lighting: LightingModel.pbrLayered,
baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
roughness: 0.6,
extensions: MaterialExtensions(
sheenColor: _sheenColour(),
sheenRoughness: sheenRoughness,
),
);
Compare the two edges. The bare sphere darkens towards its outline; the right one keeps a coloured rim there, strongest on the side the light reaches.
Step 3: Change it while it runs #
MaterialExtensions cannot be changed in place, so the page makes a new one each frame
from the controls and gives it to the material.
_cloth.extensions = MaterialExtensions(
sheenColor: _sheenColour(),
sheenRoughness: sheenRoughness,
);
Pick White and the rim reads as dust or fine fuzz; Blue on red shows plainly which part of the light is the sheen. Sheen roughness changes how the rim spreads across the sphere. The slider starts at 0.07 because the engine never draws a sheen smoother than that: below it, the lobe's exponent would overflow a half float.
Note. The light the sheen reflects is taken off what reaches the cloth beneath, so a bright sheen dims the base colour a little.