ComfyUI Node

Generate AO Map

Real ambient occlusion from a height map, computed not faked

By lilquail·Created 9 months ago·Updated 9 months ago· 1
Generate AO Map
  • height_map
  • IMAGE
auto_levelstrue
radius_percent3.0
strength2.5
contrast1.0
bias0.001
num_samples24
blur_radius1.5

Lots of "AO" you see in texture pipelines is a darkening gradient slapped on for looks. Generate AO Map is not that. It does actual height-field ambient occlusion: it takes your height map, casts many sample rays per pixel across the height field, and computes where the surface would block the light. The result is a real AO mask you can trust - baked from geometry, not guessed.

It's the centerpiece of this pack's PBR generation story. Feed it a height map (DeepBump Normal to Height and the pack's height tools are right there to produce one), and out comes an AO map that'll sit under your albedo in-engine and ground the lighting.

How it works

The height field is treated as a grayscale surface (white high, black low), and for each pixel the node samples num_samples points within a radius, checks the local height differences, and accumulates occlusion with falloff. It's fully vectorized PyTorch using grid_sample, and it runs on CUDA automatically when ComfyUI's PyTorch has a GPU available, falling back to CPU.

The inputs that matter:

  • height_map - grayscale, white = high.
  • auto_levels (default on) - stretches the height map to full 0–1 range before processing. Leave it on unless your map is already normalized.
  • radius_percent (default 3) - the AO sampling radius as a percentage of image size, so it scales with resolution. Bigger radius = broader, softer ambient shadows.
  • strength (default 2.5) - how dark the shadows get. Higher = darker.
  • contrast (default 1) - the falloff curve; higher gives sharper shadow edges, lower gives soft gradients.
  • bias (default 0.001) - the anti-"acne" offset that prevents self-shadowing speckle on flat surfaces. Lower = more detail but more noise.
  • num_samples (default 24) - samples per pixel. 16–32 is the sweet spot; higher is smoother and slower.
  • blur_radius (default 1.5) - a final Gaussian blur to clean up noise. 0 disables it.

Output and use

One IMAGE, grayscale AO. It feeds straight into a DDS Saver (BC4_UNORM, Linear) or sits alongside your other PBR maps in a material chain.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/lilquail/ComfyUI-Leputen-Utils

Restart, find it under Leputen-Utils → PBR. It uses ComfyUI's existing PyTorch - no extra model downloads, no ONNX runtime, nothing to clone. That's the good news about this node: it's compute, not ML.

Troubleshooting

  • Speckle/acne on flat areas - raise bias. It's the tradeoff knob: too high and you lose shallow detail, too low and flat surfaces sparkle.
  • Noisy result - bump num_samples and/or blur_radius. 24 samples plus a light blur handles most textures.
  • AO too strong/weak - strength is the master volume; contrast shapes the edges. Don't fight either with the others set to defaults first.
  • CPU slog at high res - AO is O(samples × radius) per pixel; on CPU a 2K map with 64 samples will take a while. It's CUDA-accelerated when available, which is most of the time on a real ComfyUI rig.

The pleasant surprise of this node is that it's predictable. You can reason about what radius_percent and strength do, adjust them, and the output does what you expect - unlike the AI-derived maps in the pack, which are a bit more "vibes."

CategoryLeputen-Utils/PBR

Inputs (8)

NameTypeDefaultDescription
height_mapIMAGEThe input grayscale height map (white is high, black is low).
auto_levelsBOOLEANtrueAutomatically stretch the height map's contrast to use the full 0-1 range before processing.
radius_percentFLOAT3.00.1–20Sample radius as percentage of image size. Scales automatically with resolution.
strengthFLOAT2.50–10Controls the intensity of the AO effect. Higher values result in darker shadows.
contrastFLOAT1.00.1–4Adjusts the falloff curve. Higher = sharper shadows, Lower = softer gradients.
biasFLOAT0.0010–0.1Helps prevent 'acne' artifacts on flat surfaces. Lower = more detail but more noise.
num_samplesINT244–128Number of samples per pixel. Higher = smoother but slower. 16-32 is usually sufficient.
blur_radiusFLOAT1.50–50Final Gaussian blur to smooth the result. Set to 0 to disable.

Outputs (1)

NameTypeDescription
IMAGEIMAGE