Nodes/MKRShift_Nodes/Texture Albedo Safe
ComfyUI Node

Texture Albedo Safe

Texture Albedo Safe rescues it

By criskb·Created 7 months ago·Updated 5 months ago· 0
Texture Albedo Safe
  • image
  • mask
  • image
  • mask
  • albedo_safe_info
settings_json{"target_black":0.04,"target_white":0.82,"saturation_limit":0.85,"shadow_lift":0.35,"highlight_rolloff":0.55,"midtone_preserve":0.28,"mask_feather":8.0,"invert_mask":false}

PBR albedo maps have one rule that new texture sets break constantly: they must never reach pure black or pure white. Pure black in an albedo means "this surface absorbs all light" (energy out of nowhere), pure white means "this surface reflects everything" (blown out, plastic-looking, and it cheats every light in the scene). AI-generated textures and sloppy photo scans are full of both. x1TextureAlbedoSafe is the node that fixes it: it remaps your albedo into a physically sane range and caps the saturation while it's at it.

How it works

The node compresses the image's tonal range into a PBR-friendly envelope instead of a straight clamp (which would just clip). target_black (0.04) and target_white (0.82) define the envelope: darkest pixels land at 4% brightness, brightest at 82% - the standard ballpark for energy-conserving albedo. The remap is curved, not linear: shadow_lift (0.35) controls how gently the darks are raised toward that 4% floor (too aggressive and the texture goes flat and milky), and highlight_rolloff (0.55) does the same on the bright end, easing whites down toward 82% without crushing the color out of them.

The saturation half matters almost as much. PBR works best with modest color, and saturation_limit (0.85) caps how vivid any pixel can get - this is what keeps a bright red texture from turning into a neon sign in the renderer. midtone_preserve (0.28) is the clever one: it blends the corrected result back toward the original in the middle of the range, so the remap fixes the extremes without washing out the actual material color in the midtones where most of your texture lives.

The inputs that matter

Settings live in a settings_json string, prefilled:

  • target_black (0.04) / target_white (0.82) - the albedo envelope. Adjust if your renderer's convention differs (some engines want a higher black point).
  • shadow_lift (0.35) / highlight_rolloff (0.55) - how gently the ends are pulled in.
  • saturation_limit (0.85) - the color cap.
  • midtone_preserve (0.28) - how much original midtone color survives.

Optional mask input restricts the fix to a region (useful if only part of a scanned sheet is out of range). Outputs are image, mask, and albedo_safe_info (a text log of the range it found and applied).

Installing it

Part of the MKRShift Nodes pack. ComfyUI Manager: search "MKRShift", install, restart. Or:

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

Restart after. No models - a tone curve applied in numpy.

Gotchas

Don't overdo shadow_lift. The point is to pull pure blacks off the floor, not to brighten the texture - crank it and you'll lift every dark crevice into a flat haze, which kills the normal map's work. Also, run this before you bake any AO or multiply the albedo against occlusion; if you fix it afterward, the AO pass will happily push your blacks right back out of range. Sequence it early in the material graph, and it slots naturally in front of the pack's x1PBRPack for a full, renderer-ready map set.

CategoryMKRShift Nodes/Surface/Texture

Inputs (3)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"target_black":0.04,"target_white":0.82,"saturation_limit":0.85,"shadow_lift":0.35,"highlight_rolloff":0.55,"midtone_preserve":0.28,"mask_feather":8.0,"invert_mask":false}
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
albedo_safe_infoSTRING