Nodes/ComfyUI-SuperPBR/πŸ†’ SuperPBR Material
ComfyUI Node

πŸ†’ SuperPBR Material

One photo in, albedo and ORM out, no sampler involved

By HullabaloΒ·Created 6 days agoΒ·Updated 2 days agoΒ· 0
πŸ†’ SuperPBR Material
  • image
  • model
  • vae
  • clip
  • mask
  • anchor_image
  • tilesig
  • albedo
  • orm
β—„resolution512β–Ί
β—„batch_chunk8β–Ί

You have a photo of an object, or a render that looks like one, and you want to relight it in Blender. What you actually need is the material, not the picture: base colour, roughness, metalness, a bit of AO. Normally that's Substance Painter and a lost weekend. πŸ†’ SuperPBR Material does it in one pass and gives you back two images - albedo and orm.

This is the inverse of what the 3D generation packs do. Hunyuan3D 2.1 and TRELLIS.2 made their name by shipping PBR channels alongside the mesh, because a relightable asset is worth ten baked diffuse maps. SuperPBR goes the other direction: no mesh, no multi-view, no per-face UV atlas. One 2D image of one object, decomposed into physically-plausible maps you can plug into a shader.

What's actually happening in that pass

SuperMat (ICCV 2025) is a Stable Diffusion 2.1 UNet finetuned into a single-step feed-forward network. The pack doesn't port a pipeline - it loads the checkpoint into ComfyUI's own UNetModel and does something sneaky: the final three up blocks are replicated into two heads, one decoding albedo and one decoding ORM. The rest of the diffusion machinery is bypassed. Your image is VAE-encoded (posterior mode, not a sample, so it's deterministic), fed in with zeroed latents at a pinned timestep of 999, and the two heads are decoded by the same VAE.

Why one pass works: with zeroed latents, SD 2.1's v-prediction target collapses to scale Γ— clean_signal, which the code computes once as a constant. So there's no noise, no steps, no CFG, no seed and no sampler node anywhere in the graph. Rare case of "single-step" meaning it.

The inputs you'll actually touch

Required are image, model, vae, resolution and batch_chunk.

vae has to be a 4-latent-channel SD VAE - vae-ft-mse-840000-ema-pruned.safetensors is the one the author points at. Wire an SDXL or Flux VAE and you get a clean, honest error rather than silent garbage, but it's still a wasted run. model comes from Load SuperPBR Model. resolution defaults to 512, which is what SuperMat trained at, and it bilinearly resizes your image to a square - so feed it a crop of a single object, not a full scene with a hundred things in it.

Optional, in order of usefulness:

  • mask - follows LoadImage's convention, 0 = subject, 1 = background, and the node composites background to flat 0.5 gray. SuperMat expects objects on mid-gray, so connect your matte if your background isn't already flat.
  • clip - an SD 2.1 text encoder, used only for the fixed empty prompt. Skip it. Without it the node substitutes a zero context: a negligible shift in the output, and you save ~675 MB of VRAM plus the encoder load. It is the emptiest prompt in ComfyUI; don't pay for it.
  • anchor_image and tilesig - the tile-drift fix, both from Tile Split. Connect both and the node makes one extra global pass over the whole downscaled image and blends each tile onto it with a frequency split in pixel space, so low frequencies (colour and tone) come from the global pass and high frequencies from the tile. Tile-to-tile drift dies. Note it forces the working resolution to the tile size.
  • batch_chunk (default 8) - images per UNet/VAE pass. Same output at any value; lower it when a big tile grid OOMs.

Outputs are albedo (IMAGE, [0,1]) and orm. The ORM is packed: R = ambient occlusion, G = roughness, B = metallic. Export it as a packed ORM for a Blender/Unity-style material, or run it through ORM Split to get three separate grays.

Install

ComfyUI Manager, search the pack title, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Hullabalo/ComfyUI-SuperPBR.git

Then drop supermat.pth anywhere under ComfyUI/models/diffusion_models/. Restart.

Worth saying out loud: this pack has no dependencies. pyproject.toml declares an empty list, there's no requirements.txt, and it rides on ComfyUI's own torch. In a hobby where every node pack is a dependency-conflict coin flip, that's a feature.

Where it goes wrong

The model dropdown listing nothing means your checkpoint isn't under models/diffusion_models. If you pick the wrong file from that list - it shows every .pth and .safetensors there - the loader raises ... is not a Base SuperMat checkpoint and helpfully prints the missing and unexpected keys. That's a wrong-checkpoint message, not a broken install.

Then the two visual failures. A washed-out object with a glowing halo around it usually means no mask on a non-flat background. And if your subject comes out looking like it was resized badly, it was: resolution squashes anything non-square, so crop first or go through Tile Split.

Genuinely useful shortcut: the repo ships example graphs in workflows/ - SuperPBR SuperMat basic.json and a MoGe3 variant. Load one and you skip half this article. There's essentially no community chatter on this pack yet, so those graphs are the documentation.

CategorySuperPBR

Inputs (9)

NameTypeDefaultDescription
imageIMAGEβ€”
modelSUPERMATβ€”
vaeVAEβ€”
resolutionINT512256–2048β€”
batch_chunkINT81–16Images decomposed per UNet/VAE pass; larger batches are processed in chunks of this size and concatenated back β€” same output, capped peak VRAM. Lower it if you OOM on big tile grids.
clipoptCLIPSD 2.1 text encoder, only used for the fixed empty-prompt context. Optional; a zero context (negligible output shift) is used when not connected.
maskoptMASKFollows LoadImage's MASK convention: 0 = subject (kept), 1 = background (composited to 0.5 gray).
anchor_imageoptIMAGEAnchor from Tile Split's anchor_image output (mask-composited, padded to the tile canvas). It is decomposed once and its low frequencies anchor every tile, killing tile-to-tile colour drift.
tilesigoptTILESIGGrid signature from Tile Split; needed to crop the anchor on the tile grid.

Outputs (2)

NameTypeDescription
albedoIMAGESuperMat albedo map in [0,1].
ormIMAGEORM map: R=occlusion (AO), G=roughness, B=metallic. Split into separate maps with the ORM Split node.