Nodes/WAS Affine/KSampler Affine
ComfyUI Node

KSampler Affine

Detail enhancement baked into the sampler, no bolt-on

By WASasquatch·Created about a year ago·Updated 4 months ago· 5
KSampler Affine
  • model
  • positive
  • negative
  • latent_image
  • affine_schedule
  • external_mask
  • options
  • noise_options
  • LATENT
  • MASK
seed0
steps20
cfg4.5
sampler_name
scheduler
denoise1.00
affine_interval1
max_scale1.200
max_bias0.000
patternwhite_noise
affine_seed0
affine_seed_incrementfalse
merge_inactive_stepstrue

KSampler Affine is a drop-in replacement for the plain KSampler that applies the WAS Affine transform inside the sampling loop instead of as a separate node between passes. Same idea as the two-sampler manual workflow - nudge the latent where a mask says so - but the sampler handles the scheduling, so you get the effect without wiring up a second KSampler and a Latent Affine in the middle.

How it works

All the standard KSampler inputs are there - model, positive, negative, latent_image, seed, steps, cfg, sampler_name, scheduler, denoise. On top of them sit the affine controls:

  • affine_interval (default 1) - apply affine every N steps. 1 = every step, 2 = every other step. Doesn't change total steps.
  • max_scale / max_bias - the peak values at the schedule's strongest point. Scale is interpolated as 1 + (max_scale - 1) * t where t comes from your schedule; bias as max_bias * t.
  • pattern - the mask pattern (default white_noise).
  • affine_seed / affine_seed_increment - a seed separate from the sampler seed, so the mask changes independently of the image content. Increment rolls it per application, which is what you want for temporal masks.
  • affine_schedule - a DICT from WASAffineScheduleOptions, interpreted over total steps. Leave it unplugged and the defaults apply.
  • Optional: external_mask (gates where affine applies), options and noise_options (mask tuning DICTs), and merge_inactive_steps (greedily merges steps outside the active schedule window into bigger batches to save time; default on).

The schedule is the real control. From the author's own comparison workflow, the sensible starting shape is start 0.1 → end 0.3 with easeInOutSine: affine bites in the early-to-mid steps, then gets out of the way while the sampler settles detail. Pair it with a high-pass pattern (highpass_white, perlin) for texture, or green/pink for natural-ish detail.

Outputs: LATENT (your sampled latent, straight to VAE Decode) and MASK (the mask from the last affine application - preview it to see what got affected).

Why reach for it

It's the integrated path the README sells as "Option 2": automatic scheduling, no manual node choreography, and everything stays in latent space so it's cheap. If you're already tweaking a KSampler workflow and the image is close but the detail reads flat or the contrast looks burned (classic speed-LoRA symptom), this is a low-friction experiment: swap the KSampler, set max_scale ~1.05–1.1, and A/B it.

Installing

Part of WAS Affine by WASasquatch. ComfyUI Manager → Install Custom Nodes → search "WAS Affine" → install → restart, or:

cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was_affine

Restart ComfyUI. ComfyUI 1.0.0+, torch and numpy, no model downloads.

Common issues

The usual mistake is max_scale way too high. 1.2 is the default ceiling, not a suggestion - at that strength with a hard pattern you'll reshape the image, not enhance it. Also remember the affine seed is independent: same sampler seed, different affine_seed, different result, so when you're chasing a seed, don't forget there are two of them. And if you see banding, that's the mask edges - blur them via options (blur_sigma ~1.5).

Categorysampling/ksampler

Inputs (21)

NameTypeDefaultDescription
modelMODELDiffusion model to sample with.
positiveCONDITIONINGPositive prompt conditioning.
negativeCONDITIONINGNegative prompt conditioning.
latent_imageLATENTInput latent to continue sampling from.
seedINT00–2147483647Random seed for the sampler.
stepsINT201–200Number of denoising steps.
cfgFLOAT4.50–100Classifier-free guidance scale. Can be a single float value or a list of float values for per-step CFG. If list is shorter than total steps, the last value will be repeated for remaining steps.
sampler_nameCOMBOThe algorithm used when sampling, this can affect the quality, speed, and style of the generated output.
schedulerCOMBOThe scheduler controls how noise is gradually removed to form the image.
denoiseFLOAT1.000–1Fraction of noise to remove (lower = stronger preserve).
affine_intervalINT11–100Interval in steps to apply affine (1 = every step). Does not change total steps.
max_scaleFLOAT1.2000–2Upper bound on multiplicative affine strength applied at schedule peak.
max_biasFLOAT0.000-2–2Upper bound on additive bias applied at schedule peak.
patternCOMBOwhite_noiseMask/noise pattern used when applying affine between sampling steps.
affine_seedINT00–2147483647Seed for affine mask generation (separate from sampler seed).
affine_seed_incrementBOOLEANfalseIf enabled, increment affine seed for each group application (temporal masks).
affine_scheduleDICTUse WASAffineScheduleOptions (interpreted over total steps).
external_maskoptIMAGEOptional external mask image; when provided and pattern != external_mask, it gates where affine applies.
optionsoptDICTBase options DICT for affine (e.g., common or full options).
noise_optionsoptDICTPattern-specific overrides that layer onto 'options'.
merge_inactive_stepsoptBOOLEANtrueGreedily merge steps outside the active schedule window into larger batches.

Outputs (2)

NameTypeDescription
LATENTLATENT
MASKMASK