Apply Dense Diffusion Conditioning (SDXL)
The Dense Diffusion node that gives every material its own masked prompt
- model
- clip
- mat_msks_lst
- model
- positive
- negative
If you've ever stared at an architectural render and wished the wood siding, the concrete, and the glass each got to be prompted separately - not smeared into one global sentence - this is the node you were looking for. Apply Dense Diffusion Conditioning (SDXL) is Pseudocomfy's centerpiece: it takes a stack of material prompts, a stack of masks, and an SDXL model, and patches the model so each masked region of the image is conditioned by its own prompt. One render, five materials, five voices that don't argue.
This is regional prompting, done the way the ComfyUI community actually does it. The node is adapted from huchenlei's ComfyUI_densediffusion, which is the pack people point to when they want to put two characters (or two materials) in one frame without their attributes bleeding together. The trick: instead of setting conditioning areas and hoping, DenseDiffusion patches the cross-attention layers themselves so each mask literally controls which text tokens attend to which latent pixels. It's an Omost-style mask-masked attention, and it's the strongest way to do this on SDXL short of training something.
What you feed it
Everything required, and everything comes from wires - the author set INPUT_IS_LIST = True, so the material inputs expect lists, not single values. In the stock Pseudocomfy graph they arrive from PseudoUnpackModelSnapshot or PseudoProcessMaterialPrompts:
mat_txts_lst- the per-material prompt strings (e.g. "white oak planks, matte finish")mat_msks_lst- one mask per prompt, shaped[1, H, W]. If a mask isn't already atwidth/height, the node rescales it silently, but it will hard-error on a mask that isn't three-dimensional with batch size 1, so don't hand it a raw[H, W].env_scene,env_style,env_negative- the global scene, a style that gets appended to every material prompt, and the negative.width,height- the target canvas the masks are scaled toward.
The three outputs are model, positive, and negative. The patched model and both conditioning tensors go straight into a KSampler - the positive is built from scene + style + all material prompts joined with ; , plus a full-canvas solid mask so nothing is left unconditioned.
The gotchas that will actually bite you
- Mask shape errors. The node raises
ValueError: Mask at index i must have shape [1, width, height]. This is the #1 failure for people wiring their own masks in instead of using the snapshot pipeline. - Regional bleed is a feature you manage. Overlapping masks let regions interact; sharp abutting masks isolate them. Reddit's dense diffusion users lean on slightly overlapping gradients so regions don't produce composition seams.
- It's built for SDXL. The helper detects the model's SD version and patches the right cross-attention blocks for it; the pack's whole pipeline is SDXL-shaped, so run it with an SDXL checkpoint, not a 1.5 one.
- The unconditional pass isn't conditioned. Dense diffusion applies to the positive run only, which is why the node returns its own
negative- feed that one to the sampler, not your usual negative.
Install is the pack-wide story: clone Pseudocomfy into custom_nodes, and on Windows portable you must .\python_embeded\python.exe -m pip install diffusers first. It's niche - this whole pack exists for the Rhino Pseudorandom plugin's snapshot JSON - but if you're doing per-region architectural prompting on SDXL, there isn't a smoother path.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| mat_txts_lst | STRING | — | |
| mat_msks_lst | MASK | — | |
| env_scene | STRING | — | |
| env_style | STRING | — | |
| env_negative | STRING | — | |
| width | INT | — | |
| height | INT | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |