Badge Height Locked Base V1 (DAELab)
Relief rendered with maths instead of a model
- flat_image
- height_map
- foreground_mask
- height_locked_base
- base_lightness
- normal_preview
- report
What it is and why you'd reach for it
Here's the honest pitch: if you already know where every surface sits in Z, you don't need a generative model to shade it. You need a normal map and a light.
Badge Height Locked Base V1 takes your discrete six-level height map, differentiates it, builds normals, runs a Lambert term against a fixed key light, darkens slope edges, multiplies that shading over your flat artwork, and hands back a rendered badge. No API call, no seed, no drift, no bill. Run it a hundred times and you get the same pixels. That determinism is the entire point of the pack's "Strict" category, and it's what makes the generative passes downstream checkable - you always have a mathematically correct base to compare a GPT candidate against.
How it works
The height map is first validated against the legal set {0, 0.2, 0.4, 0.6, 0.8, 1.0}; anything more than a rounding hair off those values raises height_map is not a legal six-level reference. Then normals are built from central differences: forward/backward gradients in x and y, scaled by normal_strength (default 5.0, range 0–20), with the z component fixed at 1 and the vector normalized. Higher normal_strength exaggerates the tilt at each step, which reads as a sharper shoulder.
Lighting is one fixed directional light with the direction (-0.35, -0.45, 0.82) normalized - top-left, front-facing. key_strength (0.24) scales the diffuse term, ambient (0.78) lifts the floor, and edge_darkening (0.08) subtracts based on local slope magnitude so the base of each step gets a dark contact line. The final shading multiplier is clamped to [0.55, 1.20], so nothing blows out or crushes to black, and gets multiplied into the flat artwork. Pixels outside the foreground are replaced with pure white.
enforce_1024 is on by default and this node genuinely means it - a non-1024² input raises. That's not pedantry: the pack's masks, registration and height maps are all in the 1024 canvas, and rendering at another size would silently break the coordinate correspondence everything else assumes.
Three outputs beyond the image: base_lightness is the L channel of the shaded result in OKLab, which is the number generative constraint nodes need when they're asked to keep low-frequency lightness from wandering. normal_preview visualizes the normals (remapped to 0–1) so you can see the relief geometry as colour - very handy for spotting a missing tier that shading hides. report is JSON: canvas, legal-level max error, lighting values, deterministic: true.
Inputs and outputs that matter
flat_image is your design in colour, at 1024², foreground-filled. height_map from the height layer or the align node. foreground_mask decides what gets shaded at all. Then four knobs: normal_strength is the one you'll actually feel. ambient / key_strength control how dramatic the relief reads - 0.78/0.24 is a flat, catalogue-ish look; pushing key to 0.4 and ambient to 0.65 gives a much more product-photo feel without touching the geometry.
Outputs: height_locked_base is your deterministic badge, and either the final answer or the base a GPT stage is constrained against. base_lightness into a constraint node. normal_preview and report for QA.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/TeutonicMepheles/ComfyUI-DAELab-Custom-Nodes-Library
Restart ComfyUI. This is a V3-schema node, so you need a reasonably current ComfyUI - No module named 'comfy_api' in the log means update core, not pip install comfy_api. The module imports OpenCV; the pack's requirements.txt doesn't list it, so pip install opencv-python-headless if the node doesn't appear.
Common issues
requires a 1024x1024 canvas. Resize upstream. Turnenforce_1024off only for debugging, because every mask downstream is 1024-native.height_map is not a legal six-level reference. Something resampled your height map with bicubic/bilinear interpolation and produced 0.37. Height maps must go through nearest-neighbour, andBadge Height Reference Align V1exists partly to guarantee that.- The relief looks like a sticker with a drop shadow.
normal_strengthis too low for the step size - the shading is only visible where there's gradient. Try 8–12. - Colours look dulled. They shouldn't: this multiplies shading and clamps at 1.20, so it never brightens above the source and darkens by up to 45%. Compare against
base_lightnessbefore blaming the node.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| flat_image | IMAGE | — | |
| height_map | MASK | — | |
| foreground_mask | MASK | — | |
| normal_strength | FLOAT | 5.00–20 | — |
| ambient | FLOAT | 0.780–1 | — |
| key_strength | FLOAT | 0.240–1 | — |
| edge_darkening | FLOAT | 0.080–0.5 | — |
| enforce_1024 | BOOLEAN | true | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| height_locked_base | IMAGE | — |
| base_lightness | MASK | — |
| normal_preview | IMAGE | — |
| report | STRING | — |