kubakub region sampler
Diffuse a facade one window at a time, and leave the rest pixel-exact
- model
- clip
- vae
- plan
- image
- style
- material
- change
- upsampler
- image
- changed
- report
Here's the thing nobody tells you about generating a building: a diffusion model is bad at it. Ask Flux or Qwen for "a facade with 40 windows" and you get a painting of a facade, with windows that don't line up, don't match each other, and don't correspond to the actual stonework you're projecting onto. Projection mapping doesn't want a painting of a facade. It wants this facade, with the windows replaced.
kubakub region sampler does that. It takes a plan (from kubakub region plan) and a canvas exactly the size of your regions, and runs the model region by region, pasting each result back into its own mask. Everything outside the regions is untouched - not re-encoded, not gently degraded by a VAE round trip, untouched. That guarantee is the entire product, and it's the same one the Inpaint Crop-and-Stitch pattern won the community over with.
How it actually works, per region
This is worth understanding because it explains the settings:
- It takes a box around the region plus
context_px(64 target pixels by default) so the model can see what it's attached to. - That box is scaled uniformly and exactly to roughly
region_mpmegapixels (1 by default), snapped to whole 16-pixel blocks, and capped atmax_upscale(4) for small regions. A 270×310 window box becomes ~864×992. A whole-floor wall gets scaled down. Nothing is stretched, ever - the pack treats non-uniform scaling as a bug. - The mask is the region grown by the plan's
dilate_px, and the crop's own latent goes in as a reference latent (reference = selfin the plan). - Flux 2 gets sampled with core's
Flux2Schedulersigmas for the crop size. Denoise works like a normal KSampler. - The result is scaled back by the exact inverse, colour matched to the original crop (
color_match:none,mean_std,mkl), and pasted with afeather_pxsoft edge that can never reach outside the mask or the scope.
Then the canvas updates, so later regions see earlier ones. That's what stops a floor of windows looking like it was assembled from forty unrelated images - window 39 was inpainted into an image where windows 1–38 already exist.
The single biggest creative lever is reference in the plan. self (default) keeps the structure that's already there, so Klein behaves like an editor - perfect for materials, weathering, stone repair. none lets the region be freely repainted, which is what you want for turning a dark window into a lit room. And with none, denoise matters enormously; with self, much less.
The inputs you'll actually set
model, clip, vae (Flux 2 Klein 4B or 9B is auto-detected; Qwen Image 2.1 too - adapter on auto does it, and there's a generic path for everything else). plan and image.
Then steps and cfg, both defaulting to 0, which means "use the model's default" - Klein 4 steps at CFG 1, Qwen Image 2.1 at 25. Someone who knows Klein will tell you to try 8 steps and CFG 1.2–1.5 when anatomy or texture starts going wrong; that advice applies here too, per region. sampler_name is euler and scheduler only matters for generic models, because Flux 2 always brings its own schedule.
region_mp is the work resolution per region crop, and it's the main quality/speed dial. max_upscale stops a tiny cornice detail from being blown up 8× into invented nonsense. schedule has two special values worth knowing: qwen21_turbo_5 and pruna_qwen21_8 are the trained step schedules of two Qwen Image 2.1 LoRAs, and with those loaded the node starts partial denoise at the matching step. seed_offset is how you ask for "the same plan, different take" across every region at once.
Two optional inputs earn their keep. only takes the same selector syntax as the plan (group:Windows, W_F1_*, !W_F1_*) and processes just those - how you iterate on one floor instead of the whole building. style is a style image, used by regions whose plan says reference = style.
Outputs and the cache
image is the canvas with every processed region pasted in. changed is a mask of where pixels were actually replaced - wire that into kubakub seam pass so only the new material gets harmonised. report gives you the model, cache usage, timing and one line per region.
The cache is the feature that makes this usable. Results are held in RAM, keyed on the crop pixels, masks, prompt, seed, settings and models. Change one prompt and only that region re-samples - plus any later regions whose crops overlap it, because they saw the old pixels. Default budget is region_cache_mb = 4096 and cond_cache_mb = 2048 in kubakub.ini; 0 turns it off, which you should not do.
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, or comfy node install comfyui-kubanodes. ComfyUI 0.37.0+; OpenCV is the only added package. You need an image model - the sample workflow uses Klein 4B, the smallest option, per the pack's docs/MODELS.md. Any quantisation works: bf16, fp8, int8, NVFP4, GGUF, pick your file in the loader.
Where it goes wrong
The canvas must be exactly the size of the regions. Not roughly. This node never resizes to fit, and a mismatch is the difference between a paste and a smear.
Overlapping regions, one going the wrong way. Regions are processed in plan order (order = largest_first by default), and overlap means the later one wins in its own mask. If your wall region runs after your window regions, it will repaint over them. That's what order is for. And the cache includes the model, so loading a different LoRA strength invalidates everything.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The image model (Flux 2 Klein, Flux 3 Klein, Qwen Image 2.1 or a generic model), with any LoRAs already applied. | |
| clip | CLIP | The text encoder that matches the model. | |
| vae | VAE | The VAE that matches the model. | |
| plan | KUBA_PLAN | From kubakub region plan. | |
| image | IMAGE | The canvas, exactly the size of the regions (e.g. the 3840x2160 facade render or photo). | |
| steps | INT | 00–200 | Used where the plan says steps = 0. 0 = the model's default (Klein 4, Qwen Image 2.1 25, Flux 3 Klein 50 for the base, 20 for the sd file or a LoRA on the base). |
| cfg | FLOAT | 0.00–30 | Used where the plan says cfg = 0. 0 = the model's default (1.0; the Flux 3 base 3.5). |
| sampler_name | COMBO | euler | Sampler for every region (euler is a safe default). |
| scheduler | COMBO | simple | Generic models only; Flux 2 always uses its own schedule (core Flux2Scheduler for the crop size). |
| region_mp | FLOAT | 1.000.1–4 | Work megapixels per region crop (region + context), and the size of frame_in_frame scenes. Small regions are scaled up to this, large ones down. |
| max_upscale | FLOAT | 4.001–8 | Small regions are scaled up at most this much. |
| schedule | COMBO | auto | auto: steps / sampler / scheduler as set. qwen21_turbo_5: the 5 trained steps of the Viggle Qwen-Image-2.1 turbo LoRA (load it with LoraLoaderModelOnly); pruna_qwen21_8: the 8 trained steps of the Pruna Qwen-Image-2.1 LoRA (strength 1.0). Partial denoise starts at the matching step, steps is ignored. Sampler as set (euler, or res_2s / deis_2m for more detail). |
| seed_offset | INT | 00–4294967295 | Added to every region seed, for a new variation of all regions. |
| adapter | COMBO | auto | Model family; auto detects Flux 2, Flux 3 and Qwen Image 2.1. |
| onlyopt | STRING | Process only these regions, to work on a few. Empty = all. Written as in kubakub region plan: names with wildcards ('W_F1_*'), 'group:Windows', 'tag:front', 'region:3-7'; comma or Enter = or, space = and, '!' = not. | |
| styleopt | IMAGE | A style image for the regions whose plan says reference = style: the model sees it as a second reference next to the region's own crop (scaled to about 1 megapixel). Of a batch the first image is used. | |
| material_atopt | FLOAT | 0.300–1 | A clip on 'material' or 'change' (a kubakub shader gives one): which of its frames is used, 0 = the first, 1 = the last. |
| materialopt | IMAGE | A picture the painted regions start from, e.g. the images of a kubakub shader with the same regions connected: the model paints from its forms and colours (Flux 2 Klein follows it well at denoise 0.8). A region whose plan says reference = material keeps its own start and is shown the material instead (the way Qwen Image follows it best). Regions with strategy = keep stay as they are. Of a clip the frame at material_at is used. | |
| changeopt | MASK | How much each place of a painted region may change, e.g. the masks of a kubakub shader: white = all of the region's denoise, black = nothing. With a 4 or 5 step model the map has that many levels. | |
| upsampleropt | CLIP | A prompt upsampler (load qwen3.5_9b_flux3_prompt_upsampler with a Load CLIP node, type flux3). Connected, it turns every region's short prompt into a full instruction while it looks at the region's crop (and the style picture), and the first pass's instruction while it looks at the whole picture. Flux 3 Klein follows such an instruction far better. The instructions are in the report and kept for the session; about 6-9 s for each new one. | |
| first_passopt | FLOAT | 0.000–1 | 0 = off. Above 0: the whole picture is first edited in one pass at this denoise (1.0 = a full edit) from one instruction made of the plan's prompts, with the picture as reference, and pasted where the painted regions are; then every region refines it at its own denoise (0.5 works well). One coherent picture first, the detail from the regions. Flux 3 Klein is told where each prompt goes: the boxes of its regions (its layout table), so the window prompt lands in the windows and the wall prompt on the wall. |
| after_first_passopt | COMBO | regions refine it | Only with first_pass above 0. 'regions refine it': every painted region is then sampled from its crop at its own denoise (the detail; ~10 s each). 'nothing: whole picture only': the first pass is the result, one sample for the whole facade (fast, one light, nothing stitched; the plan's per-region denoise is not used, first_pass is the one denoise). Either way only the painted regions change; keep regions and the black stay pixel exact. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | The image with all processed regions pasted in. |
| changed | MASK | Where pixels were replaced (paste alpha). |
| report | STRING | Model, cache use, time, and one line per region (status, crop box and scale). |