Nodes/ComfyUI-TextureAlchemy/Upscale to Resolution (Multi-Pass)
ComfyUI Node

Upscale to Resolution (Multi-Pass)

Hit a target resolution, not a guess multiplier

By amtarr·Created 9 months ago·Updated 4 months ago· 58
Upscale to Resolution (Multi-Pass)
  • image
  • image
  • scale_per_pass
  • final_width
  • final_height
  • total_scale
  • info
target_width2048
target_height2048
upscaler_multiplier4.0
number_of_passes2
maintain_aspecttrue

Sometimes "4x" is the wrong way to ask. What you actually want is "this texture needs to be 2048×2048 because that's what the game's material budget says." Scale-based upscaling makes you do the arithmetic; UpscaleToResolution does it for you, then hands you the per-pass scale factors for a multi-pass chain.

It's the resolution-targeting sibling of the pack's UpscaleCalculator. Same family, same DNA: it doesn't resample anything itself. The image output is a passthrough - the node's real output is a set of numbers you feed into your actual upscaler nodes. But it answers the question you actually ask: "my map is 1024×1024, my target is 2048, how should I set up a two-pass 4x chain?"

How it works

Given a target width/height and your upscaler's native multiplier, it computes the total scale needed, then splits it across the passes with the same scale_per_pass = target_scale^(1/passes) / upscaler_multiplier math the Calculator uses. The maintain_aspect toggle matters a lot here:

  • ON (default) - it uses the smaller of the width/height scale factors so the result fits inside your target box without distortion. Your output may be a bit under 2048 on one axis, and the node tells you so in the console.
  • OFF - it averages the width and height scales and warns you when the two diverge, because that's how you get a stretched texture. Most of the time you don't want this.

It also sanity-checks the plan: if your target is bigger than input × upscaler_multiplier^passes, it warns that the target may be unreachable and suggests more passes or a bigger multiplier. Nice touch - that's the "your chain can't physically get there" case that usually bites people silently.

The inputs

  • target_width / target_height (64–16384) - where you want to land.
  • upscaler_multiplier (1–8) - your upscaler's native scale.
  • number_of_passes (1–10) - how many upscalers are in the chain.
  • maintain_aspect - keep the shape or not.

Outputs: image (passthrough), scale_per_pass, final_width, final_height, total_scale (the overall multiplier the math landed on), and info (a STRING summary).

Installing it

UpscaleToResolution is part of ComfyUI-TextureAlchemy. ComfyUI Manager → search "Texture Alchemy" → install → restart. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/amtarr/ComfyUI-TextureAlchemy
# restart ComfyUI

No extra dependencies, no models - pure PyTorch. Under Add Node → Texture Alchemist → Texture. (The README's copy-the-ComfyUI_PBR_MaterialProcessor-folder line is a pre-rebrand leftover; ignore it.)

Where people get burned

Two habits to avoid. First, assuming the node upscales - it doesn't, so if you wire its image output straight to Save Image you'll get your input back unchanged and think it's broken. Second, leaving maintain_aspect on and then being surprised the output isn't exactly your target box - that's the feature, not a bug; it's the price of not squashing the texture. For texture work this "more pixels, faithfully" framing is exactly right: you don't want a generative upscaler inventing grain on a normal or roughness map, you want a correctly-sized resample chain, and this node is the calculator for building it.

CategoryTexture Alchemist/Texture

Inputs (6)

NameTypeDefaultDescription
imageIMAGE
target_widthINT204864–16384Desired final width in pixels
target_heightINT204864–16384Desired final height in pixels
upscaler_multiplierFLOAT4.01–8The multiplier of each upscaler (e.g., 4.0 for 4× upscaler)
number_of_passesINT21–10How many upscalers will be chained
maintain_aspectBOOLEANtrueMaintain original aspect ratio (scale to fit within target dimensions)

Outputs (6)

NameTypeDescription
imageIMAGE
scale_per_passFLOAT
final_widthINT
final_heightINT
total_scaleFLOAT
infoSTRING