Generate PBR (Image)
Give it a photo, get tileable PBR maps back
- pipeline
- image
- basecolor
- normal
- height
- roughness
- metallic
Image-to-PBR is the workflow people keep asking for and rarely get cleanly. The usual ComfyUI route is a pile of mismatched tools - a normal-map extractor here, an AO estimate there - that never agree with each other. This node does what most of those threads want: feed it a reference image and it hands back a full PBR set - basecolor, normal, height, roughness, metallic - generated jointly by the StableMaterials diffusion model.
It sits right next to Generate PBR (Text) in the pack, and it shares the same skeleton: both take the pipeline from Load StableMaterials and both emit the same five maps. The difference is the conditioning source.
How it works
The node takes your IMAGE, converts it to a PIL image, and passes it to the pipeline alongside a few extra knobs. The one that matters is image_guidance_scale (default 1.5) - how closely the output sticks to your source photo. The optional prompt (default empty, multiline) steers it on top of that; leave it blank to just replicate the photo's material, or add "rusted" or "polished" to push it somewhere new.
There's a real gotcha hiding in the source: only image[0] is used. If you feed it a batch, the first frame is the only frame that matters - everything else is silently ignored. For a single Load Image output you'll never notice; just know that batching in means batching ignored.
Also worth knowing: tileable defaults to true, so even a non-seamless photo comes out as a texture that tiles. That's the pack's quiet superpower - a photograph of a real floor, turned into a floor material you can tile across a scene.
The inputs that matter
- image - your reference. Photo, render, or anything you've already generated.
- image_guidance_scale - default 1.5. Too high and the model copies the photo's lighting into the maps, which defeats the whole point of PBR (you want light-independent channels). Start at the default and nudge down.
- prompt - optional, off by default. Use it to steer, not to overwrite.
- steps - default 4; remember that matches the LCM loader. Standard mode means 50.
- guidance_scale - default 7.5, same as text mode.
- tileable - on by default.
Outputs are the five IMAGE maps: basecolor, normal, height, roughness, metallic. Same wiring story as the text node - Save Image x5, or PBR Preview Grid to inspect first.
Install & troubleshooting
Install is pack-wide: ComfyUI Manager → search "StableMaterials", or clone https://github.com/P5ina/comfyui-stable-materials into custom_nodes, pip install -r requirements.txt, restart. The model downloads to your HuggingFace cache on first generation.
The failure mode people hit here is trying to use it as a general image editor. It isn't - it's a material extractor. Feed it a clean, front-on photo of a surface with even lighting and you'll get a good set; feed it a moody product shot with strong shadows and the maps will carry the lighting with them. Fix the input, not the settings. And if the output looks nothing like your source, raise image_guidance_scale a little - 1.5 is a light touch by design.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| pipeline | SM_PIPELINE | — | |
| image | IMAGE | — | |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 41–50 | — |
| guidance_scale | FLOAT | 7.51–20 | — |
| image_guidance_scale | FLOAT | 1.50–5 | — |
| tileable | BOOLEAN | true | — |
| promptopt | STRING | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| basecolor | IMAGE | — |
| normal | IMAGE | — |
| height | IMAGE | — |
| roughness | IMAGE | — |
| metallic | IMAGE | — |