kubakub relief mould prep / anti perch
Round your relief before the mould laughs at you — relief mould prep
- field
- field
- preview
- report
- height
Generated depth is not manufacturable depth. A depth model will happily hand you knife-edge ridges, hairline slots and undercut walls, and a mould made from that won't release from its casting, a ball-nose cutter can't reach into the corners, and an inspector who is checking for "no sharp or pointed elements" will fail the piece. This node is the boring, necessary fix, and it's the one in the relief chain people skip until it costs them a mould.
What it does to your geometry
Two operations, both borrowed from classic image morphology, and both worth understanding because they're the reason your relief loses height.
Minimum edge radius is a greyscale closing followed by an opening using a spherical structuring element of that radius. The practical meaning: a physical ball of that radius can touch the surface from both sides, everywhere. That is the same property a safety inspector means by "no sharp edges" and the same one a ball-nose cutter needs.
Draft angle is an infimal convolution with a cone, which gives you the largest possible surface that lies below yours and is Lipschitz with constant cot(draft). Say it plainer: nothing is steeper than the draft angle, measured from the pull direction, so there are no undercuts and a one-piece mould releases cleanly. Undercut-heavy relief is the single most common reason a 3D-printed prototype looks great and the cast panel comes out torn.
Both operations only ever remove material, so the report is the honest part of this node: it tells you the relief depth before and after and the percentage of detail lost.
The inputs you'll touch
field comes in from relief field (from depth), or from mesh to relief field if you started from a mesh instead of a depth map.
min_edge_radius_mm defaults to 20. The pack's own reasoning is that it's comfortably above the usual 2 mm code minimum and easy to mill. Drop it toward 5 if you're chasing fine detail on a small panel; push it to 40 on big concrete work and accept that it eats the thin features.
draft_angle_deg defaults to 4, with 3 as the practical floor for glass-fibre-reinforced concrete on a milled foam mould and 5 called comfortable. If a detail keeps disappearing, dropping from 4 to 3 usually brings it back - it's a small number that does a lot.
max_work_px (default 1024) is a speed dial: the relief is worked at most that many pixels on the long side and then scaled back. Higher is finer and slower. On a 4K depth map, 1024 is the reason this node returns in a breath instead of a coffee break.
Outputs
field goes on to anti perch or straight to the checks and exports. preview is your grey sanity image. report is JSON with relief_before_mm, relief_after_mm, detail_lost_pct, the settings you used and height_range_mm - that last one is what you need when you use the height MASK downstream, because a MASK is 0–1 and this tells you what 1 actually means in millimetres. If you're feeding the height into a displacement shader, that number is not optional information, it's the scale.
Installing it
Same pack, so same route: ComfyUI Manager → search kubakub nodes → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt
The one dependency this adds is opencv-python-headless if you don't already have OpenCV; it needs ComfyUI 0.37.0+. No Blender - the relief nodes are pure numpy geometry (kubakub/relief_core.py), which is why this group runs happily on the same 12 GB machine the author tested on. No models either.
Where people get burned
Draft angle and edge radius are not free. Run the workflow, look at detail_lost_pct, and if it's in the double digits, you've sanded your relief flat - go back and lower the radius or the angle rather than pushing on to export and discovering it on the mill.
If your relief nodes are missing from the menu entirely, check kubakub.ini in the pack folder: copying kubakub.ini.example and setting 3d = off or 3d/fabricate = off stops those modules loading, and workflows that use them show up as missing nodes.
And the one structural trap: this node expects a relief field, not an image. Wire a raw depth PNG into field and nothing happens - there's no pixel-to-millimetre scale on an image, and that scale is the whole point of the chain.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| field | RELIEFFORGE_FIELD | The relief from relief field (or another relief node). | |
| min_edge_radius_mm | FLOAT | 200–200 | Smallest rounding on every edge and corner, in mm (no sharp edges, and a ball-nose cutter reaches everything). 0 = no rounding. |
| draft_angle_deg | FLOAT | 4.00–45 | Minimum draft angle in degrees, measured from the pull direction, so the cast releases from a one-piece mould. 3 is the usual minimum, 5 is comfortable. |
| max_work_px | INT | 1024128–4096 | The relief is worked on at most this many pixels on its long side, then scaled back. Higher = finer but slower. |
| anti_perchopt | BOOLEAN | false | On: after the mould prep every flat ledge is shaved into a sloped sill, so birds and people cannot perch, stand or sit on it. Vertical faces and undersides stay as they are. |
| sill_angle_degopt | FLOAT | 4510–80 | anti_perch: slope of the new sills, in degrees from horizontal. 45 is the common value; 60 is aggressive and eats more of the relief. |
| max_span_mmopt | FLOAT | 40020–2000 | anti_perch: how far down, in mm, a sill slope can reach below a ledge. Larger = deep ledges get fully sloped, but slower. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| field | RELIEFFORGE_FIELD | The mould-ready relief. |
| preview | IMAGE | Grey preview of the mould-ready relief. |
| report | STRING | Relief depth before and after, the share of detail lost and the settings used (json). |
| height | MASK | The relief as a mask: 0 = the lowest, 1 = the highest point (the same picture as preview), to use as a depth or displacement map. The report gives the range in mm (height_range_mm). |