ComfyUI Node

rgb2x

Rgb2x Generates Albedo, Normal, and Roughness Passes

By toyxyz·Created 2 years ago·Updated about a year ago· 130
rgb2x
  • image
  • IMAGE
aovalbedo
seed0
steps50

If you've ever wanted to take a flat image and pull real material passes out of it - the albedo, the normal map, the roughness - this is the node. rgb2x feeds a regular photo into a diffusion model and generates one of five PBR/AOV maps: albedo, normal, roughness, metallic, or irradiance. It's the "decompose the photo" half of RGB↔X, a research project that went both directions (photo → material maps and maps → photo). This wrapper only ships the one direction, but that's the direction people actually want: nobody in r/comfyui gets excited about synthesizing a photo from roughness maps.

The original RGB↔X is a bare Python repo. The usual response when someone asks how to generate specular or material maps is "RGB-X says it'll do it, you'll have to run it yourself or write your own ComfyUI wrapper." This pack is that wrapper, and it's exactly as minimal as that framing suggests - one node, three dials, one output.

How it works

Under the hood it's a full Stable Diffusion pipeline (StableDiffusionAOVMatEstPipeline from diffusers) that conditions the denoising on your input image instead of a text prompt, then renders the map you asked for. The prompt is baked in per AOV ("Albedo (diffuse basecolor)", "Camera-space Normal", etc.) - you don't type anything. The scheduler is DDIM with rescale_betas_zero_snr=True and timestep_spacing="trailing", which is the zero-SNR setup that makes the steps input actually matter for perceptual quality.

Before inference your image gets gamma-corrected to linear (photo**2.2), resized so its longest side is 1000px, and snapped to a multiple of 8 for the VAE. That means your output resolution is capped around 1000px on the long side - these are material passes for relighting and compositing, not print assets. Roughness and metallic come out as single-channel maps that get broadcast to RGB, which is the standard convention.

The inputs that matter

Only four inputs, and only two you'll really touch:

  • aov - the map to generate: albedo, normal, roughness, metallic, or irradiance (default albedo).
  • steps - DDIM steps, default 50. Lower it to 30 for drafts; this is a full diffusion run per map, so speed adds up.
  • seed - the model is stochastic, so the same photo and AOV give different results per seed. The default 0 is fine to start.
  • image - your source photo.

The output is a single IMAGE, one AOV per run. Want all five? That's five separate node instances or five reruns at 50 steps each. Plan accordingly.

Install

Via ComfyUI Manager (search "ComfyUI_rgbx_Wrapper") or the usual clone:

cd ComfyUI/custom_nodes
git clone https://github.com/toyxyz/ComfyUI_rgbx_Wrapper

Then restart ComfyUI. Dependencies are torch, diffusers, imageio, numpy, opencv-python, transformers, huggingface-hub - most are already in a working ComfyUI. The real download is the model: on first run it pulls zheng95z/rgb-to-x from HuggingFace into a model_cache/ folder inside the node and it's not tiny, so the first queue run will hang on "downloading" for a while. Grab a coffee.

Where people get burned

  • CUDA only. The code hardcodes .to("cuda") and a CUDA generator. There is no CPU path - on a CPU-only box it just crashes.
  • It's slow, and it doesn't batch. Only the first image in a tensor is processed (image[0]), so feeding a whole batch silently discards everything but the first frame. One map per run, period.
  • Output is capped at ~1000px. Don't plan on 2K PBR textures coming out the other end; you'd upscale afterwards, and normal maps upscale poorly unless you know what you're doing.
  • The author literally files these under "ToyxyzTestNodes." That's the whole README energy too - two lines, one GIF. It works, but don't expect polish, options, or a fix trail. This is a thin wrapper around a research model, and it behaves like one.
  • Don't feed it EXR/HDR frames. The underlying code has EXR loaders, but the node takes ComfyUI's IMAGE type (0–1 floats), so you feed it ordinary LDR images.

Where's this actually useful? Relighting work is the big one: an estimated normal or roughness pass pairs well with IC-Light-style workflows when you want lighting to move without dragging the whole image with it, and people doing 2D-to-3D parallax or texture-style compositing reach for exactly these maps. It's niche, it's fiddly, and if you're not doing material-aware work you don't need it - but when you do need an albedo or a normal map from a photo, there isn't much else that does it.

CategoryToyxyzTestNodes

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
aovCOMBOalbedo5 options: albedo, normal, roughness, metallic, irradiance
seedINT00–18446744073709550000
stepsINT501–18446744073709550000

Outputs (1)

NameTypeDescription
IMAGEIMAGE