Nodes/kubakub nodes/kubakub render passes
ComfyUI Node

kubakub render passes

Your own render passes, as a picture plus a mask per pass

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub render passes
  • matrix
  • beauty
  • depth
  • normal
  • masks
  • names
  • report
◄folder►
◄render►
◄invert►
◄exclude►
◄depthas rendered►
◄exr_layers►

You already have the render. You don't need Blender, you don't need the 3D file, and you don't need to segment anything - the passes you exported are already a segmentation, just an unfriendly one. kubakub render passes reads a folder of them and gives you the picture plus one mask per pass, which means your existing pipeline becomes a region-based repainting rig in two connections.

It's the least AI-flavoured node in the pack and one of the most practical.

The naming contract

Give it a folder with PNG, JPG, TIFF, WebP or EXR files named <render>_<pass>:

facade_beauty.png     <- the picture
facade_depth.png      <- depth, comes out as an image
facade_normal.png     <- normals, comes out as an image
facade_cut.png        <- a mask, named "cut"
facade_windows.png    <- another mask, named "windows"

beauty is recognised under a few aliases (_rgb, _combined, _color, _clay, _render), and so are depth and normal. Every other pass of that render becomes a mask, named by its pass, white = inside. invert lists the ones where black is inside instead, and exclude names the ones that aren't masks at all. A file that belongs to no render - facade_mask.png sitting next to facade_a_beauty.png and facade_b_beauty.png - becomes a mask for every render in the folder. Plain names work for a folder with one render. render picks which render when there are several; the report lists them.

Colour pictures among the passes (an ID map) get left out with a note, because that's a different node's job.

EXRs get converted on the way in: the picture goes linear→sRGB, depth in scene units is stretched to 0..1 with near as black, normals in −1..1 are packed to 0..1, and a mask takes its R G B, Y, Z or A channel. Where a PNG copy of the same pass sits next to the EXR, the PNG wins.

The multilayer EXR case

This is the 0.3.0 addition and it's a big one for anyone working with Houdini, Nuke or a Maya/Arnold pipeline, where everything arrives as one .exr. Paste the file's path (or its folder) into folder and the node shows a button for every layer inside, with a guess at what each one is: violet for picture / depth / normal, orange for read-as-a-mask, grey for not read (colour passes, position data, ID and cryptomatte layers). Click to toggle.

The buttons are just writing the exr_layers text field, which means you can type it yourself, wildcards included (wall*), and where the guess is wrong you say so:

picture = C
depth = Z_render
normal = N_world
mask = diffuse
skip = name

A plain name is a mask unless that layer is already the picture, depth or normal. Empty means every layer that looks like a mask. The report lists every layer of the file with its channels and what it was used as - which is genuinely useful even when the buttons behave, because it's how you find out what the renderer actually wrote. Listing the layers only reads the file header, so it's fast even on a fat EXR; actually reading PIZ or DWA-compressed files goes through Blender, and only the first part of a multipart file is read.

Outputs, and where they go

beauty is the image for the region sampler. depth and normal come out as images (black when the folder has none). masks is a batch and names is one per line - and those two go directly into kubakub regions from masks (masks, names, and matrix = beauty). From there it's region plan → region sampler, and the parts of your render outside the regions stay exactly as rendered.

One detail that pays off: with split_masks = cut in the regions node, every separate shape in the cut pass becomes its own region (cut_01, cut_02…). So "the fifteen places I redesigned in 3D" each get their own prompt from a single pass.

matrix fits a render of another size to your matrix, picture, depth, normal and masks together, at one uniform scale. A render with different proportions is refused - render in the matrix's aspect.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt

Manager → kubakub nodes. ComfyUI 0.37.0+, OpenCV. No Blender, no models - this is one of the nodes that runs on a plain install, and folder empty runs built-in sample passes so you can see the outputs before you have a folder ready.

If you're reading EXRs in regions from id maps, note the pack's separate note that imageio is the optional package for EXR ID maps (PNG ID maps work without it). Here, EXR reading is built in for the compression types Blender and most renderers write by default.

Model-free test: tests/test_render_passes.py. Workflow: example_workflows/render_passes_to_final.json.

One honest expectation

Masks that come from render passes are per-pass, not per-object. A cut pass is one shape; a windows pass is every window at once, so it becomes one region, not forty. If you want a region per window, that's what the ID-render node or a cryptomatte is for. This node is for "these specific areas of the render get repainted, everything else stays".

Categorykubakub/3d/from renders

Inputs (7)

NameTypeDefaultDescription
folderSTRINGThe folder with your passes, or one multilayer .exr file: paste its path (Explorer: Copy as path; the quotes are fine). Empty: built-in sample passes, so the node runs as it is.
renderoptSTRINGWhich render, when the folder holds several (facade_a for facade_a_beauty.png). Empty: the first one; the report lists them.
invertoptSTRINGMasks where black means inside (names, wildcards, comma separated).
excludeoptSTRINGPasses that are no masks (names, wildcards, comma separated).
depthoptCOMBOas renderedHow the depth output reads. The last two stretch it over the whole range.
matrixoptIMAGEYour matrix: a render of another size is fitted to it (picture, depth, normal and masks; same proportions only). Without: the render's own size.
exr_layersoptSTRINGFor a multilayer EXR: which layers become masks, one name per line (wildcards work: wall*). Click the layer buttons on the node, or type. Empty: every layer that looks like a mask. The picture, depth and normal are found by their names; to say it yourself write 'picture = C', 'depth = Z_render', 'normal = N_world', 'mask = diffuse' or 'skip = name'. A plain name is a mask, unless that layer is the picture, depth or normal. The report lists every layer of the file.

Outputs (6)

NameTypeDescription
beautyIMAGEThe picture: the image for the region sampler / versions.
depthIMAGEThe depth pass (black when the folder has none).
normalIMAGEThe normal pass (black when the folder has none).
masksMASKEvery other pass as a mask (batch) -> kubakub regions from masks, masks.
namesSTRINGThe masks' names, one per line -> kubakub regions from masks, names.
reportSTRINGWhat was found in the folder.