Nodes/kubakub nodes/kubakub frame in frame
ComfyUI Node

kubakub frame in frame

Real rooms and parasites behind every window

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub frame in frame
  • plan
  • viewer
  • matrix
  • media
  • world
  • image
  • plan
  • area
  • generate
  • back
  • walls
  • shadow
  • frames_json
  • report
  • regions
◄shadow_strength0.45►
◄shadow_angle_deg60►
◄shadow_length0.70►
◄wall_level0.70►
◄window_hulltrue►
◄media_names►

What it's for

The single most convincing trick in facade projection mapping isn't a bright colour or a big animation. It's making the audience believe there's a room behind the wall. The window stops being a lit rectangle and becomes an opening - parallax, side walls, a back wall in shadow - and the building suddenly has depth it doesn't physically have.

kubakub frame in frame is the node that builds that in the viewer's perspective. Every region whose plan gives it a depth in metres becomes a frame seen from where the audience actually stands. Positive depth means a room behind the frame; negative depth means a parasite - something sticking out of the facade toward the viewer, with a shadow on the wall behind it, which is the other half of the illusion and the more surprising one.

It replaced the older lab node (frame guide) and it's the better tool: the guide node gives you masks, this one also gives you media placement, the plan entries for a diffusion pass, and a generate mask that tells the sampler exactly which pixels to repaint.

How it works

Three sources per frame, and they're chosen per region in the region plan via fif_source:

  • generate - the node draws the perspective guide and you feed the image to the region sampler with a high denoise (~0.95) and the reference set to self. The model invents the room inside the geometry you drew, so you get light and detail that obey the perspective rather than fighting it.
  • media - corner-pin one of your images onto the back wall. Wire a batch into media and name them with media_names; regions pick one with fif_media = <name> or by index.
  • world - one shared world image behind the whole facade. It's stretched to the matrix so that, through the viewer projection, it maps 1:1 onto the building - which means a single panorama can become the city behind every window at once.

fif_depth_m is the switch in the plan. 3 means a room 3 metres deep; -0.5 means a balcony sticking half a metre out. Windows made of several panes are treated as one opening by window_hull (on by default), so the mullions stay in front of the glass instead of being carved up.

The parasites get their own physics: shadow_strength (0.45), shadow_angle_deg (60, where 0 is right / 90 is down / 180 is left) and shadow_length per metre of protrusion. That shadow is what sells it. Side walls of media and world frames get shaded in the content's own colour, with brightness set by wall_level (0.7) - a wall that's too bright reads as a lit flat surface and kills the depth.

Inputs and outputs

Required: plan (from kubakub region plan, with fif_depth_m / fif_source / fif_media set per region), viewer (from kubakub audience viewpoint - this is where the perspective comes from and without it there is no frame), matrix (the full projection image the frames are drawn into), plus the shadow and wall tuning above.

Optional: media for fif_source = media, plus media_names, and world for the shared world behind the facade.

Outputs, and the ones that matter:

  • image - the matrix with every frame drawn in; generate frames carry the perspective guide.
  • generate - the mask the region sampler should paint. That's your hand-off into diffusion.
  • plan - passed on with every parasite added as a new region <name>_out (frame + walls + front face) carrying the frame's settings.
  • area, back, walls, shadow - the masks, if you want to grade or diffuse them separately.
  • regions - the plan's regions with the parasite regions included, so they work in anything that takes regions.
  • frames_json - per frame: depth, source, scale, outline, back_quad. The back_quad is the corner pin, i.e. exactly where your media image has to be warped to sit on that back wall.
  • report - the frames with their depth and source.

Install

Manager → search kubakub nodes → install → restart. Manual:

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

ComfyUI 0.37.0+. The only added package is opencv-python-headless (keep your own OpenCV build if you have one). For the generate path you need an image model - Flux 2 Klein 4B is the smallest the pack's examples use; for media and world you need nothing but your own pictures. No Blender required here, even though it's a 3D-looking result.

Common issues

  • Nothing appeared. fif_depth_m is 0 for those regions. In the plan's syntax that's a rule like [W_F1_*] / fif_depth_m = 3 - no depth, no frame, by design.
  • The room looks flat and pasted. Check the viewer: a viewpoint that's centred and close makes every room's walls converge almost identically. Move the audience spot off-axis and the parallax appears.
  • Parasites don't pop. Push shadow_strength and shadow_length, and check wall_level - bright side walls are the classic reason an object reads as a sticker rather than a box.
  • Diffusion ignored your geometry. Feed generate (the mask), not area, and set denoise high with the reference on self, which is what the pack's example workflow does.
Categorykubakub/2d/generate

Inputs (11)

NameTypeDefaultDescription
planKUBA_PLANregion plan with fif_depth_m / fif_source / fif_media per region.
viewerKUBA_VIEWERFrom kubakub audience viewpoint: where the audience stands.
matrixIMAGEThe matrix (the full projection image at delivery size) the frames are drawn into.
shadow_strengthFLOAT0.450–1Parasites (fif_depth_m < 0) cast a shadow on the facade; 0 = none.
shadow_angle_degFLOAT60-180–180Direction the shadow falls in the facade plane: 0 right, 90 down, 180 left.
shadow_lengthFLOAT0.700–10Shadow length per metre the parasite sticks out (1 = light at 45 deg).
wall_levelFLOAT0.700–2Brightness of the side walls of media / world frames.
window_hullBOOLEANtrueOn: a frame made of several parts (glass panes) is one opening, the gaps (mullions) stay in front. Off: the largest part only.
mediaoptIMAGEImages for fif_source = media (a batch; cover-fitted to each back wall).
media_namesoptSTRINGOne name per media image, for fif_media = <name>. Or use indices.
worldoptIMAGEThe shared world behind the facade (stretched to the matrix: through the viewer projection it maps 1:1 onto the facade).

Outputs (10)

NameTypeDescription
imageIMAGEThe matrix with all frames; generate frames carry the guide.
planKUBA_PLANThe plan for the region sampler: every parasite is a new region '<name>_out' (frame + walls + front face) with the frame's settings.
areaMASKAll frame pixels.
generateMASKFrames the region sampler should paint (fif_source = generate).
backMASKBack walls (rooms) and front faces (parasites).
wallsMASKSide walls.
shadowMASKWhere parasites darken the facade.
frames_jsonSTRINGPer frame: depth, source, scale, outline, back_quad (corner pin).
reportSTRINGThe frames with their depth, source and scale.
regionsKUBA_REGIONSThe regions of the plan output, with the '<name>_out' regions of the parasites: for masks, previews and other nodes that take regions. Without parasites these are the plan's own regions.