kubakub scene render
The Blender bridge that does the actual hard work
- projector
- clay
- ids_preview
- depth
- normal
- coverage
- folder
- scene_json
- report
- scene
- depth_gray
This is the node the 3D half of the pack is built on. You give it the architect's model, it gives you the projector's view of the facade plus a machine-readable description of every surface in it - so "give every window its own prompt" stops being a masking exercise and becomes a checkbox.
kubakub scene render accepts .blend, .fbx, .obj, .abc, .glb, .gltf, .stl, .ply and USD, runs Blender 4.x headless as a subprocess, and returns a clay render, metric depth, normals, and a folder of ID passes that kubakub regions from id maps already knows how to read.
How it works, because the mechanism is the good part
Blender flattens everything render-visible into world-space meshes (modifiers applied, instances made real), renders a Workbench clay view, and takes a single Cycles sample without AA that stores, per pixel, which face it sees plus that face's world position and normal. The ID passes themselves are then computed in numpy from that buffer - which is why changing a threshold doesn't trigger another render. The pack's test facade is 20k faces at 3200×2160 and takes about 4.5 s on the GPU.
The result is cached per file, camera, size and frame in ComfyUI/temp/kuba_scene3d.
Which passes to ask for
passes is one space-separated line, and the defaults are a good starting set:
shelves- the facade's depth steps, found from the depth histogram along the facade normal and named by their offset from the main wall.shelf_+0.35mmeans 35 cm proud of the wall.shelf_min_step_mdecides how close two steps can be and still count separately.layers- fixed depth bands around the main plane (deep_recess / recess / facade / relief / projection), set bylayer_bands_mas four limits in metres, + toward the camera.facing- front / top / underside / side / back relative to the facade normal. This is how you select every upward-facing ledge at once.planes- connected coplanar patches, tuned byplane_angle_degandplane_offset_m.parts- loose parts: every separately modelled stone, frame, cornice.elements,sections,floors- the architecture passes, and the most useful of the lot.elementssplits the facade into windows (including blind windows, with arcades split per arch), window_frames, columns, cornices, other relief, wall and roof.sectionsgives left / centre / right where the wall actually steps forward or back.floorsgives ground_floor, floor_1, floor_2, roof, derived from the rows of windows and the cornice belts.objects/materials/collections- straight from the file, written only when there's more than one.
Names from these passes are group and tag fodder downstream: group:windows, tag:left, tag:floor_1 group:windows. Grouping "*" splits every window and column into its own region, grouped by class. On the test facade, parts as regions gives 423 regions - every stone, voussoir, frame and pediment.
preview_pass chooses which map shows on ids_preview (default shelves). min_size_m (default 0.5) merges pieces smaller than that across the wall into whichever neighbour they border most - the crowd can't read them, and 3018 plane patches become 1352 at 0.5 m. Set it to 0 if you're doing fabrication work and want every stone.
Camera, units and outputs
file empty means the built-in sample building, so the node runs as-is. For your own file, paste the path - right-click in Explorer, Copy as path, quotes and all.
camera takes an object name; otherwise the file's active camera, else its first camera, else a front camera framing the model (it finds the facade side by itself - a facade is wide and shallow). A connected projector overrides all of that and places the virtual projector in real metres. Set width / height to match; 0 means "the file's render resolution". FBX, OBJ and Alembic carry no resolution, so the node looks for a size in the camera name (that's why you'll see names like RENDER_CAM_3200_2160PX in these pipelines) and otherwise defaults to 1920×1080 with a note. FBX round-trips like to flip lens shift; when the imported camera sees almost none of the model and the flipped shift frames it, the node uses the flipped one and tells you.
unit_scale multiplies the model into metres - 0.01 for a centimetre file. This is not optional housekeeping: some FBX exports arrive about 0.5 m wide, and the report warns when a model is under 2 m or over 2 km. Trust that warning; every distance downstream depends on it.
Ten outputs, and they all earn their place: clay (the projection view), ids_preview, depth (near = bright), normal, coverage (1 where the model is - a scope for the region nodes), folder (the ID-map folder, into kubakub regions from id maps), scene_json (camera matrices, resolution, names, main plane, shelves), report, scene (into scene measure / preview / relight / pieces), and depth_gray - linear depth from near = white, which is what you feed to a depth-to-relief node if you're going as far as milling a physical panel.
save_folder copies the ID maps, legends, clay and scene.json out to somewhere permanent, in the format Houdini and After Effects tools read. Worth doing at the start of a project rather than re-deriving passes later.
Install
cd ComfyUI/custom_nodes && git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt
Then install Blender 4.x. The pack finds it in C:\Program Files\Blender Foundation or via blender_path / blender = ... in kubakub.ini. Blender is never imported into ComfyUI's Python - it's a subprocess - and this is the design decision that makes the 3D half of this pack installable at all. Compare it to the CUDA-extension node packs that need matching PyTorch, Visual Studio build tools and a pinned wheel to even import.
Two limits worth knowing before you plan around it. .c4d can't be read outside Cinema 4D - export FBX or Alembic. And the source file is only ever read, never saved; if your scene relies on modifiers or simulations, they're evaluated by that Blender version, which is why the pack is tested against 4.5 specifically.
If the node errors, the report is usually explicit: it tells you the faces, the camera chosen, the depth range, the shelves found, which passes were written, whether it hit the cache, and where the ID-map folder is. Nine times out of ten the answer is in there.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| file | STRING | Your scene file: paste its path (Explorer: right click, Copy as path; the quotes are fine). Empty: the built-in sample building, so the node runs as it is. | |
| width | INT | 00–16384 | Picture width in pixels. 0 = the render size set in the scene (usually your matrix size). Set it for a projector with another resolution. |
| height | INT | 00–16384 | Picture height in pixels. 0 = the render size set in the scene. |
| frame | INT | -1-1–100000 | Which frame of an animated scene (moving camera, Alembic). -1 = the frame the scene is on. |
| passes | STRING | elements sections floors shelves layers facing planes parts objects materials collections | Which region maps to make (each one cuts the facade in a different way), separated by spaces: elements sections floors shelves layers facing planes parts objects materials collections (objects / materials / collections only when the file has more than one). elements = windows, columns, cornices; sections = left / centre / right; floors = the storeys. |
| preview_pass | COMBO | shelves | Which region map the preview shows. elements = windows / columns / cornices, floors = storeys, sections = left / centre / right, shelves = depth steps, layers = in front of / behind the wall, facing = which way surfaces look, planes = flat faces, parts = separate pieces. |
| shelf_min_step_m | FLOAT | 0.0500.005–2 | For the shelves map: parts of the facade less than this far apart in depth count as one shelf. Bigger = fewer, coarser shelves (try 0.15 for a scan). |
| plane_angle_deg | FLOAT | 3.00.1–30 | For the planes map: neighbouring faces that bend less than this many degrees count as one flat plane. Bigger = fewer, larger planes. |
| plane_offset_m | FLOAT | 0.0200–1 | For the planes map: faces also must lie within this distance of each other to count as one plane. |
| layer_bands_m | STRING | -0.5 -0.05 0.05 0.5 | For the layers map: 4 distances from the main wall (m, + = towards you) that cut it into deep recess | recess | facade | relief | projection. |
| cameraopt | STRING | Camera object name. Empty: the file's active camera, else the first camera, else a front camera framing the model (it finds the facade side by itself). A connected projector replaces the file's camera. Live: the 'live camera' list picks one of the app's cameras; empty = what you look through in the app. | |
| save_folderopt | STRING | A folder to copy the region maps, their legends, the clay picture and scene.json into (for Houdini / After Effects). Empty = only ComfyUI's cache. | |
| blender_pathopt | STRING | blender.exe or its folder. Empty: the blender setting in kubakub.ini or the newest C:\Program Files\Blender Foundation install. | |
| unit_scaleopt | FLOAT | 0.0000–10000 | Multiplies the model (and the camera position) into metres, e.g. 0.01 for a file in cm. 0 = auto: a model over 300 units across is read as cm (or mm for a very big one), else as metres; the report says what it took. Any other value is used as it is. |
| min_size_mopt | FLOAT | 0.500–50 | Pieces smaller than this across the wall (largest of width / height, m) merge into the neighbour they share the longest border with - the crowd cannot read them anyway. 0 = keep everything. |
| projectoropt | KUBA_PROJECTOR | From kubakub projector: where the projector stands (metres from the wall, height, throw). Used instead of the file's camera; set width / height to the projector's resolution. | |
| sourceopt | COMBO | file | file: the path in 'file'. live blender / live houdini: the scene open in that app right now (its kubakub live link, tools/blender or tools/houdini): press refresh on this node and the app sends the scene as it is, seen from your viewport (or the camera you look through; a name in 'camera' wins). Your scene file is not saved or changed. |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| clay | IMAGE | Workbench clay render from the projection camera. |
| ids_preview | IMAGE | The preview_pass ID map. |
| depth | IMAGE | Camera depth, near = bright (turbo colours). |
| normal | IMAGE | World normals as colours. |
| coverage | MASK | 1 where the model is (a scope for the region nodes). |
| folder | STRING | ID-map folder -> kubakub regions from id maps. |
| scene_json | STRING | Camera, resolution, names, main plane, shelves. |
| report | STRING | Faces, camera, depth range, shelves, ID passes, cache use and the ID-map folder; warns when the model scale looks wrong. |
| scene | KUBA_SCENE | -> kubakub scene measure / kubakub scene preview. |
| depth_gray | IMAGE | Camera depth as grey, near = white, linear over the model's depth range (for Relief Field and depth nodes). |