ChromeballMask
The boring geometry node that tells DiffusionLight where to paint the chrome ball
- IMAGE
This is the least glamorous node in the DiffusionLight pack, and I love it for that. No diffusion model, no weights, no VRAM spike - it's a circle drawn in a black rectangle. But it's where the whole trick starts, and if you understand it you'll understand what DiffusionLight is actually doing to your photo.
Quick context on the pack, because it shapes everything: DiffusionLight is a research pipeline that extracts lighting from a single photograph. The core idea is that a mirrored ball in a scene reflects all the light hitting it, so if you could photograph one you'd have a cheap environment map. DiffusionLight skips the ball - it uses SDXL inpainting to paint a chrome ball into your image, then unwraps that reflection into an HDR environment map. ChromeballMask supplies the "paint it here" instruction.
What it actually outputs
Run it and you get a floating-point IMAGE: white disc on a black background, exactly ball_size pixels across, dead center of a width × height canvas. White means "this is the ball," black means "this is scene that stays." It's pure math - a disc where 1 - x² - y² >= 0 over a grid, no model involved - so it runs in microseconds and costs you nothing.
The workflow wires that mask in two places. It blends with the depth map (ImageBlend) to build the ControlNet condition, and it gets converted to a real mask (ImageToMask → VAEEncodeForInpaint) so the sampler only rewrites the ball region while the rest of the photo stays put. Get the mask wrong and you're either inpainting the whole image or painting a ball that doesn't sit where you think it does.
The inputs that matter
Only three, and only one needs your attention:
- height / width - canvas size. Set these to match your padded input image (the pack's PadBlackBorder node produces 1024×1024 by default, and the defaults line up). If they don't match what's downstream, the mask won't align with the image.
- ball_size - diameter of the disc in pixels. Default 256 on a 1024 canvas is a sane starting point. Bigger ball = more of the scene gets inpainted and the reflection reads better, at the cost of more original detail.
The gotcha that trips people
The output is an IMAGE, not a MASK tensor. That's a deliberate choice by the author - the stock workflow blends it with the depth map, which needs an image - but if you plug it straight into an inpaint node expecting a mask, ComfyUI will quietly complain. Route it through ImageToMask first, exactly like the shipped diffusionlight-workflow.json does.
Second gotcha: this node is the only part of the pack with zero dependencies. Everything around it - the SDXL checkpoint, the two LoRAs, the depth ControlNet, comfyui_controlnet_aux for the MiDaS preprocessor - is what actually eats your time to install. Don't be fooled into thinking the whole pack is this easy.
Installing and running it
Same for every node in the pack. In ComfyUI Manager, search "DiffusionLight-ComfyUI" and install, or:
cd ComfyUI/custom_nodes
git clone https://github.com/pureexe/DiffusionLight-ComfyUI
then restart ComfyUI. To actually run the pipeline you also need the four model files and comfyui_controlnet_aux from the README - but this node by itself needs nothing, which is why it's the friendliest way to confirm the pack loaded.
The honest verdict: you'll never use this node alone, and it's the most boring one in the pack. But it's also the one that tells you, in one glance, whether you've got the resolution wiring right. If your ball is off-center or clipped, you've got a canvas-size mismatch, and it's cheaper to catch it here than after a full sampler run.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| height | INT | 10241–8192 | — |
| width | INT | 10241–8192 | — |
| ball_size | INT | 2561–8192 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |