Nodes/MKRShift_Nodes/Surface Dust Mask
ComfyUI Node

Surface Dust Mask

Surface Dust Mask builds the grime without the tedium

By criskb·Created 7 months ago·Updated 5 months ago· 0
Surface Dust Mask
  • image
  • source_mask
  • mask
  • image
  • mask
  • dust_info
settings_json{"source_mode":"combined_dust","top_bias":0.52,"cavity_bias":0.44,"breakup":0.3,"amount":0.82,"coverage":0.54,"contrast":1.2,"gamma":1.0,"blur_radius":1.2,"invert_values":false,"mask_feather":8.0,"invert_mask":false}

The last 10% of a weathered prop is always dust, and the last 10% of that is sitting in places you'd rather not paint by hand - on top surfaces, in the creases, where the object actually rests against the world. x1SurfaceDustMask reads your texture and hands you a dust-accumulation mask, complete with natural breakup, without you touching a brush. It's part of a whole family of surface-weathering nodes in the MKRShift pack, and it's the one you start with when a material needs to look like it's been sitting somewhere.

How it works

It scores every pixel for "would dust collect here," then normalizes that into a mask. The key insight is that dust follows geometry: top_bias (0.52) steers the mask toward upward-facing, light/flat regions where dust settles, while cavity_bias (0.44) pulls in the darker creases and recesses where dust gets trapped. The source_mode (combined_dust by default) blends the image's luma, color, and detail signals into that score - switch to a plain channel if your texture has an unusual tell.

Two knobs make it look like real dust rather than a smooth gradient. breakup (0.30) adds organic, noisy variation so the mask isn't a clean blob - dust never distributes evenly. coverage (0.54) is the threshold slider: it decides how much of the surface the dust actually claims. amount (0.82) is how strong the whole effect is, and contrast (1.20) + gamma (1.0) shape the mask's response curve.

The inputs that matter

Settings live in a settings_json string, prefilled when the node drops:

  • top_bias (0.52) - how much dust favors upward-facing geometry.
  • cavity_bias (0.44) - how much dust favors crevices. In practice these two are the "what kind of dust" control.
  • breakup (0.30) - the natural variation. Zero gives you a sterile gradient; too high turns it to static.
  • amount (0.82) / coverage (0.54) - overall strength and how much surface it claims.
  • invert_values - flip to get a clean mask instead (dust-free regions), useful for layering.

The optional source_mask restricts which pixels are analyzed (so a background doesn't register as a dusty surface), and mask feathers the output. Outputs are image, mask (the dust mask, ready to wire into a roughness map, a blend, or an overlay), and dust_info (settings + coverage log).

Installing it

Part of the MKRShift Nodes pack. ComfyUI Manager: search "MKRShift", install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes

Restart after. No models - numpy math on the texture, CPU-friendly.

Gotchas

The honest caveat: on a flat, uniform texture the node has very little signal to work with, and you'll get a mask that's mostly breakup noise. Feed it a texture with some luma/detail contrast, or combine it with a slope or cavity mask from the pack (x1SlopeMaskFromNormal) to supply the geometry it can't see from albedo alone. That combo - slope/cavity for structure, this node for the dust itself - is the real workflow. And as always with these MKRShift nodes: valid JSON in settings_json, or it silently falls back to defaults.

CategoryMKRShift Nodes/Surface/Effects

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"source_mode":"combined_dust","top_bias":0.52,"cavity_bias":0.44,"breakup":0.3,"amount":0.82,"coverage":0.54,"contrast":1.2,"gamma":1.0,"blur_radius":1.2,"invert_values":false,"mask_feather":8.0,"invert_mask":false}
source_maskoptMASK
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
dust_infoSTRING