Nodes/BrainDead Nodes/BD Derive PBR Maps
ComfyUI Node

BD Derive PBR Maps

Fake a full PBR set from one image + depth

By BizaNator·Created 8 months ago·Updated 3 days ago· 15
BD Derive PBR Maps
  • image
  • depth
  • normal_map
  • silhouette_mask
  • aux_shading_alpha
  • aux_detail_texture
  • metallic_zone_mask
  • albedo
  • normal
  • roughness
  • metallic
  • ao
  • packed_orm
  • packed_arm
  • status
invert_shading_alphafalse
shading_to_roughness0.40
shading_to_ao0.50
detail_to_roughness0.50
depth_sharpen0.0
roughness_modecombined
roughness_default0.50
roughness_strength1.00
metallic_modeoff
metallic_default0.00
metallic_lum_threshold0.60
metallic_sat_threshold0.20
ao_strength0.70
ao_blur2.0
normal_strength2.0
albedo_treatmentedge_pad
albedo_edge_pad_pixels32

You've got a single stylized character image and you want it to light correctly in a game engine. BD Derive PBR Maps is the node that gets you from "one picture" to "albedo, normal, roughness, metallic, and AO, plus pre-packed ORM/ARM" without any 3D baking. It's heuristic - explicitly not a measurement - which sounds like a caveat and is actually the whole point: it's the fastest way to give a background character believable material response, and it's honest about where you should hand-tune.

How it works

Everything derives from the two required inputs: image and depth (from any IMAGE-typed estimator - DepthAnythingV2, Lotus, MiDaS, Metric3D; darker = closer is the convention here). The recipe:

  • Roughness - high-frequency detail in the image (busy areas get rougher) via roughness_mode (default combined), boosted by optional line art / detail texture through detail_to_roughness.
  • Metallic - metallic_mode defaults to off (flat metallic_default), but low_sat_high_lum catches bright, desaturated metal candidates (gold, chrome) with metallic_lum_threshold / metallic_sat_threshold. Restrict where metal can appear with metallic_zone_mask - the README's recommended pipeline feeds an accessories mask in here so only the buckle and zips go metallic.
  • AO - from depth gradients (ao_strength, ao_blur).
  • Normal - derived from depth gradients unless you supply an explicit normal_map (Metric3D-NormalMapPreprocessor is the recommended source), scaled by normal_strength.

Then the outputs: albedo, normal, roughness, metallic, ao, plus packed_orm and packed_arm (AO/roughness/metallic stacked into the R/G/B channels the way Unreal and Unity like them), and status.

The two optional inputs that take it from "meh" to "good enough"

  • silhouette_mask (white = subject) - multiplies everything so background pixels don't pollute the maps and, crucially, keeps transparent-PNG edge garbage out. albedo_treatment (default edge_pad) extends foreground colors into the transparent border so you don't get halo bleed at UV seams.
  • aux_shading_alpha - this is the secret weapon for stylized art. Feed it the alpha output of a shading pass (like the pack's skin-details GLSL shader: low alpha = highlights, high alpha = shaded zones) and shaded areas get +roughness, +AO, −metallic, and highlights get the opposite. The README says this is far more accurate than the image-only heuristic, and it's right.

Installing and wiring

ComfyUI Manager → search "BrainDead" → install, or clone + pip:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead
pip install -r requirements.txt

Restart, then wire: character image → depth estimator → this node, with silhouette + shading alpha if you have them. The pack's own example runs all seven outputs into BD Bulk Save with one save-context so you get albedo/normal/roughness/metallic/ao/orm/arm files in a single run.

Where people get burned

The README is refreshingly blunt: these are heuristics for background characters - for hero assets you hand-tune downstream. People also forget that metallic_mode is off by default, so their "metal" reads as rough paint until they flip it on and feed a metallic_zone_mask. And if your normal map looks wrong, wire an explicit normal_map instead of arguing with normal_strength.

Category🧠BrainDead/Segmentation

Inputs (24)

NameTypeDefaultDescription
imageIMAGESource character/object image. Used for roughness (high-freq detail) and metallic (low-sat / high-lum heuristic) and as albedo passthrough.
depthIMAGEDepth map IMAGE from upstream estimator (DepthAnythingV2 / Lotus / MiDaS / Metric3D — all output IMAGE type). Closer surfaces darker by convention. Used for AO (cavity detection) and normal (when no explicit normal_map provided).
normal_mapoptIMAGEOptional explicit normal map IMAGE (e.g. from Metric3D-NormalMapPreprocessor or BAE-NormalMapPreprocessor). When provided, used directly. When NOT provided, normals are derived from the depth map's gradients.
silhouette_maskoptMASKOptional character/object silhouette MASK (white = subject, black = background). Multiplies all output maps so background pixels are zeroed in roughness/metallic, set to 1.0 in AO (no occlusion outside subject), and set to neutral (0.5, 0.5, 1.0) in normal map. Source: BiRefNetRMBG, BodySegment, or your existing skin/body chain.
aux_shading_alphaoptMASKOptional shading alpha map — e.g. the alpha output of your skin_details GLSL shader, where low alpha = highlights, high alpha = shaded zones. When provided: shaded areas get +roughness +AO -metallic; highlights get the opposite. This is FAR more accurate than the image-only heuristic for stylized art.
aux_detail_textureoptIMAGEOptional surface detail texture (lineart, manga lines, surface bumps). When provided, edge-detected lines boost roughness — useful for stylized character art where line detail represents real surface variation.
invert_shading_alphaoptBOOLEANfalseSet True if your shading alpha uses the opposite convention (low alpha = shaded, high alpha = highlight).
shading_to_roughnessoptFLOAT0.400–2How much shaded areas (high alpha) add to roughness. 0 = ignore shading for roughness; 0.4 = moderate boost; 1.0+ = strong (shaded → fully rough).
shading_to_aooptFLOAT0.500–2How much shading darkens AO (multiplicatively combined with depth-based AO). 0 = ignore; 0.5 = moderate; 1.0 = full (deeply shaded → near-black AO).
detail_to_roughnessoptFLOAT0.500–2How much detail texture lines boost roughness. Lines = surface detail = rougher. 0 = ignore; 0.5 = moderate; >1 = strong line emphasis.
depth_sharpenoptFLOAT0.00–3Unsharp mask the depth map before AO/normal derivation. Useful when your depth estimator (Lotus, Metric3D) gives smooth/chunky depth. 0 = no sharpen, 0.5-1.0 = moderate edge enhancement, 2-3 = aggressive.
roughness_modeoptCOMBOcombinedhigh_freq_detail: Laplacian magnitude → busy areas rougher (good for stylized art). luminance_inverted: bright = smooth, dark = rough (works for photo-lit subjects). combined: average of both. off: skip (output uses roughness_default).
roughness_defaultoptFLOAT0.500–1Used when roughness_mode=off, or as a baseline blended with the heuristic.
roughness_strengthoptFLOAT1.000–2Multiplier on the computed roughness map. <1 makes everything smoother, >1 boosts roughness contrast.
metallic_modeoptCOMBOoffoff: outputs metallic_default everywhere (typically 0). low_sat_high_lum: detect metallic candidates by bright + desaturated pixels. STRONGLY recommend wiring metallic_zone_mask too — heuristic alone gets false positives on bright skin/white cloth. With zone_mask=clothing+accessories, the heuristic becomes useful (bright desaturated pixels INSIDE clothing/accessories = metal candidates).
metallic_zone_maskoptMASKOptional MASK restricting where metallic CAN occur. Multiplies the metallic output, so only pixels inside the zone can be metal. Wire your clothing or accessories mask here (from a SAM3 'accessories,jewelry,metal' prompt, ClothesSegment, MaskResolver, etc.) — most game-character metal lives on jewelry/buckles/armor/details which align with the accessories category. Without this, metallic detection fires everywhere and produces false positives.
metallic_defaultoptFLOAT0.000–1Constant metallic value used everywhere when metallic_mode=off.
metallic_lum_thresholdoptFLOAT0.600–1Luminance above this counts toward metallic (when metallic_mode=low_sat_high_lum).
metallic_sat_thresholdoptFLOAT0.200–1Saturation below this counts toward metallic (when metallic_mode=low_sat_high_lum).
ao_strengthoptFLOAT0.700–2How much the depth gradients affect AO. 0 = pure white AO (no occlusion), 1 = full strength, >1 = exaggerated. AO is OUTPUT WHITE = no occlusion, DARK = occluded (Unreal/Unity convention).
ao_bluroptFLOAT2.00–20Gaussian blur radius for depth before computing gradients. Higher = softer AO.
normal_strengthoptFLOAT2.00.1–10Strength multiplier when deriving normals from depth. Higher = more pronounced normals. Only used when normal_map is NOT provided.
albedo_treatmentoptCOMBOedge_padHow to clean up the albedo output (was passing input through raw, which leaked transparent-area garbage colors as halo). edge_pad — extend foreground colors outward into background using Voronoi nearest-neighbor (game-engine standard 'alpha bleed'). Prevents UV edge halos. Requires silhouette_mask. silhouette_clip — multiply by silhouette_mask (background goes to black). Quick but causes black halos at UV edges in-engine. passthrough — original behavior (use input RGB as-is).
albedo_edge_pad_pixelsoptINT320–512When albedo_treatment=edge_pad: how far to extend foreground colors into transparent area. 0 = unlimited (pad everywhere — slow on huge images), 16-32 = typical for game textures, 64+ = aggressive.

Outputs (8)

NameTypeDescription
albedoIMAGE
normalIMAGE
roughnessMASK
metallicMASK
aoMASK
packed_ormIMAGE
packed_armIMAGE
statusSTRING