Nodes/MKRShift_Nodes/Roughness Map
ComfyUI Node

Roughness Map

The hard part of PBR from an image, solved by a default

By criskb·Created 7 months ago·Updated 5 months ago· 0
Roughness Map
  • image
  • source_mask
  • mask
  • image
  • mask
  • roughness_info
settings_json{"source_mode":"combined_roughness","normalize_mode":"auto_percentile","value_min":0.0,"value_max":1.0,"percentile_low":2.0,"percentile_high":98.0,"detail_radius":2.0,"detail_strength":0.45,"gamma":1.0,"contrast":1.1,"blur_radius":0.0,"invert_values":false,"mask_feather":8.0,"invert_mask":false}

Roughness is the PBR map people underestimate. Metalness is binary-ish, normals are mechanical, but roughness is where materials actually read as real - the difference between a mirror and a matte plastic lives entirely in that one grayscale map. And it's the hardest one to fake from a flat image, because roughness isn't in any single channel; it's in the interplay of highlights, micro-detail, and saturation. x1RoughnessMap from MKRShift Nodes is built to handle exactly that interplay.

It's part of the pack's Surface/Maps family, and the author's honest framing is the right one: combined_roughness is a practical lookdev default, not a physically measured solve. It mixes luminance, fine surface detail, and saturation into one scalar, normalizes it, and hands you a map your renderer will read correctly.

How the default solve works

With source_mode set to combined_roughness (the default), the node blends three signals - luminance, isolated fine detail, and saturation - weighted toward what reads as roughness on a real surface. Higher output values = rougher, less mirror-like. The blend weights are in the source: roughly half luma, a strong detail term (boosted by detail_strength), and a smaller saturation contribution. It's a heuristic, but it's a well-chosen one for the "turn a render into a material" job.

The rest is the family's shared vocabulary:

  • normalize_mode - auto_percentile (default), manual_range, or auto_range
  • percentile_low / percentile_high (2–98) - throw away the noisy extremes so the map doesn't get stretched by specular spikes
  • detail_radius / detail_strength - how aggressively fine surface detail is pulled into the solve. This is the dial that brings out grain, pores, and weave
  • gamma, contrast (1.1 default), blur_radius, invert_values - shape, smooth, and flip the result

All of it in a settings_json string, per the pack's house style. The defaults are genuinely good - contrast 1.1 gives the map presence without making it binary.

Inputs and outputs

Required: image and settings_json. Optional: source_mask (when source_mode is mask, or to constrain the solve) and mask (limits where the roughness map is emitted).

  • image - the grayscale roughness map
  • mask - the normalized scalar as a MASK
  • roughness_info - summary string of the resolved settings and normalization range

Where it slots in

The canonical flow: x1RoughnessMap + x1MetalnessMap + x1NormalMap → preview on x1PreviewMaterial's shader ball → pack with x1PBRPack. This is the answer to the recurring community question - people literally ask "how do I get roughness/metalness/AO nodes" on r/StableDiffusion - and the pack's Surface branch is a coherent response to it. If your material looks "too clean," the first knob to turn is detail_strength, not the base model.

Installing it

ComfyUI Manager (search "MKRShift Nodes") or:

cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes

Restart, no requirements, no model downloads, no ffmpeg. Big repo, coherent small family - worth it if material work is a regular thing.

Where people get burned

The same trap as x1MetalnessMap: expecting measurement. combined_roughness will call a glossy surface "smooth" when the image gives it no highlight info to work with, and it guesses on dark scenes. If a region reads wrong, either feed it a better-lit source or switch source_mode to luma and drive the map yourself. And watch contrast: above ~1.4 the map collapses toward all-black/all-white, which is how you lose the midrange roughness that makes surfaces feel physical.

CategoryMKRShift Nodes/Surface/Maps

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"source_mode":"combined_roughness","normalize_mode":"auto_percentile","value_min":0.0,"value_max":1.0,"percentile_low":2.0,"percentile_high":98.0,"detail_radius":2.0,"detail_strength":0.45,"gamma":1.0,"contrast":1.1,"blur_radius":0.0,"invert_values":false,"mask_feather":8.0,"invert_mask":false}
source_maskoptMASK
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
roughness_infoSTRING