Slope Mask From Normal
The tech-art trick that makes weathering stick to the right faces
- image
- mask
- image
- mask
- slope_info
Real materials don't wear evenly. Dirt settles on top surfaces, grime collects in crevices, paint chips off edges that face up into the weather. Recreating that in a texture by hand means painting masks for hours. x1SlopeMaskFromNormal does it from the normal map in about a second: it reads which way every surface is facing and emits a mask of exactly the faces you asked for. This is the same trick Substance Painter's slope masking does, and it's a small node in ComfyUI that saves you a lot of manual masking.
How it works
A tangent-space normal map stores surface direction as RGB - the X and Y channels encode tilt, the Z channel encodes how much the surface points up out of the plane. The node decodes those channels and extracts the one you pick with mode:
+z(default) - surfaces pointing up (flat tops, horizontal ledges). Perfect for dust and fallen-leaf debris.-z- surfaces pointing down (undersides, ceilings). For grime that hangs, or moisture that collects underneath.+x/-x,+y/-y- the four wall directions. For one-sided weathering like north-side moss or wind-driven rain streaks on a specific face.rim- the special one: it's1 - Z, so it highlights everything not pointing up, i.e. all the sloped and vertical geometry at once. Great for edge-wear before you split it further.
strength (1.0) scales how aggressively the mask responds, and gamma (1.0) reshapes the falloff - lower gamma pushes midtones toward white, which fattens the masked areas. invert_values flips it, which you'll want constantly (dirt on +z means dust on tops; invert for grime in crevices).
The inputs that matter
Unlike the JSON-blob MKRShift nodes, this one is all discrete widgets, and there are only a handful:
mode- the direction dropdown. This is 90% of the node.strength(1.0) andgamma(1.0) - how strong and how soft.invert_values- flip the mask.mask_feather(8.0) andinvert_mask- the output feather, plus an optionalmaskinput to restrict where the slope mask is even emitted.
Outputs are image (the grayscale slope map, viewable as a texture), mask (the same thing as a MASK you can wire into a blend, a roughness map, or any other map socket), and slope_info (a text summary). Feed the mask into the pack's x1SurfaceDustMask or x1EdgeWearMask as a source mask and you've built a full weathering stack without painting a single pixel.
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 to download - pure numpy on the normal map.
Gotchas
The normal map needs to be tangent space (the standard R+G = tilt, B = up encoding) or the directions come out meaningless; a world-space normal from a photo scan will produce a mask that's correct in spirit but misaligned with your UVs. Also, this works on the geometry direction, not on height or cavities - if you want dust in crevices, use a cavity or AO map instead of this node. They solve different problems and you'll reach for both.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mode | COMBO | 7 options: +x, -x, +y, -y, +z, -z, +1 | |
| strength | FLOAT | 1.000–4 | — |
| gamma | FLOAT | 1.000.1–4 | — |
| invert_values | BOOLEAN | false | — |
| mask_feather | FLOAT | 8.00–256 | — |
| invert_mask | BOOLEAN | false | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| slope_info | STRING | — |