Nodes/MKRShift_Nodes/Surface Waterline Mask
ComfyUI Node

Surface Waterline Mask

Surface Waterline Mask puts the bath ring where water actually sat

By criskb·Created 7 months ago·Updated 5 months ago· 0
Surface Waterline Mask
  • image
  • source_mask
  • mask
  • image
  • mask
  • surface_waterline_info
settings_json{"source_mode":"combined_waterline","orientation":"bottom","line_height":0.72,"band_width":0.18,"capillary_rise":0.22,"cavity_bias":0.44,"breakup":0.26,"amount":0.84,"coverage":0.5,"contrast":1.2,"gamma":1.0,"blur_radius":1.0,"invert_values":false,"mask_feather":8.0,"invert_mask":false}

There's a whole class of weathering that's neither dust nor rust nor streaks - it's the mark water leaves when it sits. The tide line on a boat hull, the mineral ring around a bathtub, the hard water stain creeping up the side of a planter. It's a horizontal band, and no generic grunge map produces a convincing one. x1SurfaceWaterlineMask is the MKRShift node built for exactly this: it draws a waterline band across your texture, with the capillary creep and cavity-following behavior that makes it look like real standing water, not a rectangle.

How it works

The mask is a horizontal band placed by orientation (default bottom) and positioned by line_height (0.72) - as a fraction of the texture, so 0.72 puts the waterline toward the bottom edge. band_width (0.18) sets how tall the band is: the zone where the waterline stain actually lives. The reason it doesn't look like a painted stripe is capillary_rise (0.22) - it makes the mask creep upward into the porous material above the main line, which is how real waterline stains bleed above the water surface. And cavity_bias (0.44) pulls the mask into recesses, so the stain is stronger in pits and grooves than on smooth flat areas, exactly like minerals depositing unevenly.

breakup (0.26) breaks up the band with organic variation so it's not a clean edge - real tide lines wobble. amount (0.84) and coverage (0.50) set overall strength and how much of the band area actually claims a stain, contrast/gamma shape the falloff, and source_mode (combined_waterline) picks the driving image channel.

The inputs that matter

Settings are in a settings_json string, prefilled:

  • orientation (bottom) - which edge the waterline sits at. The pack's other surface nodes call this direction; here it's orientation, same idea.
  • line_height (0.72) - where the band sits as a fraction of the texture.
  • band_width (0.18) - how tall the band is.
  • capillary_rise (0.22) - the upward bleed above the line. This is the knob that makes it read as water, not tape.
  • cavity_bias (0.44) - how strongly stains concentrate in recesses.
  • breakup (0.26) - wobble in the band.

Optional source_mask restricts analysis, mask feathers output. Outputs are image, mask, and surface_waterline_info.

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.

Gotchas

The one thing that confuses everyone on first use: line_height is a fraction of the texture, so if your texture isn't aligned with real-world up-down (say it's a tiling trim piece), the waterline will cut across it mid-face and look wrong. The node is designed for full-surface textures like hulls and walls, not for texture sheets where "bottom" doesn't mean anything. Also remember the waterline should sit above the other weathering in your stack - water deposits stain on top of dust and rust, so layer this node after the dust/rust masks in the composite if you want the materials to tell the same story.

CategoryMKRShift Nodes/Surface/Effects

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"source_mode":"combined_waterline","orientation":"bottom","line_height":0.72,"band_width":0.18,"capillary_rise":0.22,"cavity_bias":0.44,"breakup":0.26,"amount":0.84,"coverage":0.5,"contrast":1.2,"gamma":1.0,"blur_radius":1.0,"invert_values":false,"mask_feather":8.0,"invert_mask":false}
source_maskoptMASK
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
surface_waterline_infoSTRING