CompStart

ProУрокиКурсыЭлементыСофт

CompStart

Осваивайте визуальные эффекты и передовые техники.

Обучение

КурсыУрокиPro-функцииРесурсыСофт

Tools

Tech CheckDisplay CheckMotion BlurCIE 1931PhysLightNuke Tools

Компания

InstructorМиссияImpressumКонфиденциальностьУсловия

Проекты

Moray RenderEXR ConverterOCIO.ccNuke ToolsDerekVFX

Follow

YouTubeInstagramTikTokThreadsКонтакты

© 2026 CompStart. Все права защищены.

Спектральная аберрация

ToolSets / Lens
Lens

2026-09-07

ToolSets/lens/spectralAberration.nk

объектив
хроматическая аберрация
Калифорния
оптический
бахрома
blinkscript
дисперсия
полезность
View on GitHub

Хроматическая аберрация, определяемая по длине волны для Nuke — радиальная, линейная или спиновая хроматическая аберрация, полученная из дисперсионных кривых, а не из масштаба канала RGB.

Спектральная аберрация создает хроматическую аберрацию путем выборки длин волн в определенном диапазоне и восстановления RGB с использованием весовых коэффициентов на основе CIE. Это не просто масштабирование или смещение каналов RGB.

Используйте его для согласования хроматической аберрации пластинчатой линзы или для добавления контролируемой каймы. Режимы охватывают радиальную (боковая хроматическая аберрация), линейную (размытие призмы), вращательную (вихревое движение в стиле «Гелиос») и радиальную с последующим вращением. Варианты дисперсии: линейная длина волны, BK7 Коши и флинт SF10. Параметр «Количество» задает интенсивность; параметры «Защита» и «Спад» обеспечивают чистоту центра. Фокусировка длины волны, минимальное/максимальное значение лямбда, количество отсчетов, насыщенность каймы, соотношение сторон, инвертирование и формирование центра каймы определяют форму каймы.

Альфа-канал может оставаться на исходном изображении или расширяться до краев. Пересканирование, сохранение ограничивающей рамки, маска и смешивание подходят для стандартного использования в композиции. Эффект работает на BlinkScript и требует коммерческой версии Nuke; привязывайте регуляторы после перекомпиляции ядра, если они не управляют процессом.

Script code

set cut_paste_input [stack 0]
version 17.0 v3
push $cut_paste_input
Group {
 name spectralAberration
 help "spectralAberration v1.2\n\nWavelength-sampled CA. Not RGB channel scale.\n\nIf the Viewer looks unchanged:\n1. Ctrl+Enter into this Group\n2. Select SpectralCA_kernel\n3. BlinkScript tab → factory Recompile\n4. Click Bind knobs on this Group\n5. Set amount to 0.05 and protect to 0. Look at the corners.\n\nBlinkScript requires commercial Nuke.\nderekvfx.ca"
 onCreate "n = nuke.thisNode()\nk = n.node('SpectralCA_kernel')\nif k is not None:\n    try:\n        src = k\['kernelSource'].value()\n        k\['kernelSource'].setValue(src)\n    except Exception:\n        pass\n    try:\n        if 'rebuild' in k.knobs():\n            k\['rebuild'].setValue('')\n    except Exception:\n        pass\n    pairs = \[\n        ('SpectralCA_amount', 'parent.amount'),\n        ('SpectralCA_samples', 'parent.samples'),\n        ('SpectralCA_focusNm', 'parent.focusNm'),\n        ('SpectralCA_lambdaMin', 'parent.lambdaMin'),\n        ('SpectralCA_lambdaMax', 'parent.lambdaMax'),\n        ('SpectralCA_mode', 'parent.mode'),\n        ('SpectralCA_curve', 'parent.curve'),\n        ('SpectralCA_invert', 'parent.invert'),\n        ('SpectralCA_alphaMode', 'parent.alphaMode'),\n        ('SpectralCA_aspect', 'parent.aspect'),\n        ('SpectralCA_protect', 'parent.protect'),\n        ('SpectralCA_falloff', 'parent.falloff'),\n        ('SpectralCA_angleDeg', 'parent.angleDeg'),\n        ('SpectralCA_spinDeg', 'parent.spinDeg'),\n        ('SpectralCA_fringeSat', 'parent.fringeSat'),\n    ]\n    for knob, expr in pairs:\n        if k.knob(knob):\n            try:\n                k\[knob].setExpression(expr)\n            except Exception:\n                pass\n    if k.knob('SpectralCA_center'):\n        try:\n            k\['SpectralCA_center'].setExpression('parent.center.x', 0)\n            k\['SpectralCA_center'].setExpression('parent.center.y', 1)\n        except Exception:\n            pass\n    if k.knob('SpectralCA_formatSize'):\n        try:\n            k\['SpectralCA_formatSize'].setExpression('width', 0)\n            k\['SpectralCA_formatSize'].setExpression('height', 1)\n        except Exception:\n            pass\n"
 tile_color 0x421010ff
 label "spectral CA"
 selected true
 xpos 507
 ypos 971
 addUserKnob {20 User l spectralAberration}
 addUserKnob {22 bindBtn l "Bind knobs" t "Wire Group knobs to the inner Blink kernel. Does not call execute() on PythonKnobs. If it says 0 knobs bound, use the factory Recompile inside SpectralCA_kernel first." -STARTLINE T "n = nuke.thisNode()\nk = n.node('SpectralCA_kernel')\nif k is None:\n    nuke.message('SpectralCA_kernel not found. Ctrl+Enter into the Group and check.')\nelse:\n    try:\n        src = k\['kernelSource'].value()\n        k\['kernelSource'].setValue(src)\n    except Exception:\n        pass\n    try:\n        if 'rebuild' in k.knobs():\n            k\['rebuild'].setValue('')\n    except Exception:\n        pass\n    try:\n        if 'recompileCount' in k.knobs():\n            k\['recompileCount'].setValue(int(k\['recompileCount'].value()) + 1)\n    except Exception:\n        pass\n    pairs = \[\n        ('SpectralCA_amount', 'parent.amount'),\n        ('SpectralCA_samples', 'parent.samples'),\n        ('SpectralCA_focusNm', 'parent.focusNm'),\n        ('SpectralCA_lambdaMin', 'parent.lambdaMin'),\n        ('SpectralCA_lambdaMax', 'parent.lambdaMax'),\n        ('SpectralCA_mode', 'parent.mode'),\n        ('SpectralCA_curve', 'parent.curve'),\n        ('SpectralCA_invert', 'parent.invert'),\n        ('SpectralCA_alphaMode', 'parent.alphaMode'),\n        ('SpectralCA_aspect', 'parent.aspect'),\n        ('SpectralCA_protect', 'parent.protect'),\n        ('SpectralCA_falloff', 'parent.falloff'),\n        ('SpectralCA_angleDeg', 'parent.angleDeg'),\n        ('SpectralCA_spinDeg', 'parent.spinDeg'),\n        ('SpectralCA_fringeSat', 'parent.fringeSat'),\n    ]\n    bound = 0\n    missing = \[]\n    for knob, expr in pairs:\n        if k.knob(knob):\n            try:\n                k\[knob].setExpression(expr)\n                bound += 1\n            except Exception:\n                missing.append(knob)\n        else:\n            missing.append(knob)\n    if k.knob('SpectralCA_center'):\n        try:\n            k\['SpectralCA_center'].setExpression('parent.center.x', 0)\n            k\['SpectralCA_center'].setExpression('parent.center.y', 1)\n            bound += 1\n        except Exception:\n            missing.append('SpectralCA_center')\n    else:\n        missing.append('SpectralCA_center')\n    if k.knob('SpectralCA_formatSize'):\n        try:\n            k\['SpectralCA_formatSize'].setExpression('width', 0)\n            k\['SpectralCA_formatSize'].setExpression('height', 1)\n            bound += 1\n        except Exception:\n            missing.append('SpectralCA_formatSize')\n    else:\n        missing.append('SpectralCA_formatSize')\n    if bound == 0:\n        nuke.message('Kernel params are not built yet.\\n\\nCtrl+Enter into the Group, select SpectralCA_kernel, open the BlinkScript tab, click the factory Recompile button, then click Bind knobs again.\\n\\nOr just drive amount on the Kernel Parameters tab (try 0.05, protect 0).')\n    else:\n        nuke.message('Bound %d kernel knobs.\\nSet amount to 0.05 and protect to 0, then look at the frame corners.' % bound)\n"}
 addUserKnob {26 ""}
 addUserKnob {4 mode t "radial = lateral CA.\nlinear = prism smear.\nspin = Helios swirl.\nradial+spin = radial then swirl." M {radial linear spin radial+spin}}
 addUserKnob {4 curve l dispersion t "linear λ = even hues.\nBK7 Cauchy = crown glass.\nflint SF10 = heavier blue." M {"linear λ" "BK7 Cauchy" "flint SF10"}}
 curve "flint SF10"
 addUserKnob {7 amount t "0.05 is obvious. 0.008-0.02 matches plates. 0 is identity." R -0.2 0.2}
 amount 0.022
 addUserKnob {3 samples}
 samples 22
 addUserKnob {6 invert t "Flip red/blue sides." -STARTLINE}
 addUserKnob {26 ""}
 addUserKnob {7 focusNm l "focus (nm)" R 400 700}
 focusNm 550
 addUserKnob {7 lambdaMin l "λ min" R 380 500}
 lambdaMin 400
 addUserKnob {7 lambdaMax l "λ max" R 600 780}
 lambdaMax 700
 addUserKnob {7 fringeSat l "fringe sat" R 0 2}
 fringeSat 1
 addUserKnob {26 ""}
 addUserKnob {12 center}
 center {{width/2} {height/2}}
 addUserKnob {22 snapCenter l "snap / lock center" -STARTLINE T "n = nuke.thisNode()\nn\['center'].clearAnimated()\nn\['center'].setExpression('width/2', 0)\nn\['center'].setExpression('height/2', 1)\n"}
 addUserKnob {22 unlockCenter l unlock -STARTLINE T "n = nuke.thisNode()\ntry:\n    x = n.width()/2.0\n    y = n.height()/2.0\nexcept:\n    x = n\['center'].getValue(0)\n    y = n\['center'].getValue(1)\nn\['center'].clearAnimated()\nn\['center'].setValue(\[x, y])\n"}
 addUserKnob {7 aspect R 0.25 4}
 aspect 1
 addUserKnob {7 protect t "0 = aberration everywhere. 0.2 = clean center."}
 addUserKnob {7 falloff l "protect gamma" R 0.1 4}
 falloff 1
 addUserKnob {26 ""}
 addUserKnob {7 spinDeg l swirl R -45 45}
 addUserKnob {7 angleDeg l "linear angle" R -180 180}
 addUserKnob {26 ""}
 addUserKnob {4 alphaMode l alpha M {"source alpha" "dilate to fringe"}}
 addUserKnob {7 overscan R 0 200}
 overscan 32
 addUserKnob {6 preserveBBox l "preserve bbox" +STARTLINE}
 preserveBBox true
 addUserKnob {26 ""}
 addUserKnob {41 maskChannelMask l mask T MergeOut.maskChannelMask}
 addUserKnob {41 invert_mask l invert T MergeOut.invert_mask}
 addUserKnob {41 mix T MergeOut.mix}
 addUserKnob {26 ""}
 addUserKnob {26 lbl l "" +STARTLINE T "spectralAberration v1.2"}
 addUserKnob {22 btn l DerekVFX.ca T "nuke.tcl('start', 'https://derekvfx.ca')" +STARTLINE}
}
 Input {
  inputs 0
  name Input
  xpos 0
  ypos -400
 }
set Nd44d4f00 [stack 0]
 Input {
  inputs 0
  name mask
  xpos 280
  ypos -400
  number 1
 }
 AddChannels {
  channels rgba
  name AddChannels1
  xpos 280
  ypos -376
 }
push $Nd44d4f00
push $Nd44d4f00
 AdjBBox {
  numpixels {{parent.overscan}}
  name AdjBBox1
  xpos 0
  ypos -300
 }
 BlinkScript {
  recompileCount 2
  ProgramGroup 1
  KernelDescription "3 \"SpectralCA\" iterate pixelWise b3cabcc9dea6241db8efaa5ebee73a76791c436fdfcf30f63f6d4d77719a322d 2 \"src\" Read Random \"dst\" Write Point 17 \"amount\" Float 1 CtcjPQ== \"samples\" Int 1 CwAAAA== \"focusNm\" Float 1 AIAJRA== \"lambdaMin\" Float 1 AADIQw== \"lambdaMax\" Float 1 AAAvRA== \"mode\" Int 1 AAAAAA== \"curve\" Int 1 AQAAAA== \"invert\" Int 1 AAAAAA== \"alphaMode\" Int 1 AAAAAA== \"center\" Float 2 AABwRAAAB0Q= \"formatSize\" Float 2 AADwRAAAh0Q= \"aspect\" Float 1 AACAPw== \"protect\" Float 1 zcxMPg== \"falloff\" Float 1 AACAPw== \"angleDeg\" Float 1 AAAAAA== \"spinDeg\" Float 1 AAAAAA== \"fringeSat\" Float 1 AACAPw== 17 \"amount\" 1 1 Default \"samples\" 1 1 Default \"focusNm\" 1 1 Default \"lambdaMin\" 1 1 Default \"lambdaMax\" 1 1 Default \"mode\" 1 1 Default \"curve\" 1 1 Default \"invert\" 1 1 Default \"alphaMode\" 1 1 Default \"center\" 2 1 Default \"formatSize\" 2 1 Default \"aspect\" 1 1 Default \"protect\" 1 1 Default \"falloff\" 1 1 Default \"angleDeg\" 1 1 Default \"spinDeg\" 1 1 Default \"fringeSat\" 1 1 Default 4 \"wRGB\" Float 3 32 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= \"disp\" Float 1 32 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= \"n\" Int 1 1 AAAAAA== \"maxRadius\" Float 1 1 AAAAAA=="
  kernelSource "kernel SpectralCA : ImageComputationKernel<ePixelWise>\n\{\n  Image<eRead, eAccessRandom, eEdgeClamped> src;\n  Image<eWrite> dst;\n\n  param:\n    float amount;\n    int samples;\n    float focusNm;\n    float lambdaMin;\n    float lambdaMax;\n    int mode;\n    int curve;\n    int invert;\n    int alphaMode;\n    float2 center;\n    float2 formatSize;\n    float aspect;\n    float protect;\n    float falloff;\n    float angleDeg;\n    float spinDeg;\n    float fringeSat;\n\n  local:\n    float3 wRGB\[32];\n    float disp\[32];\n    int n;\n    float maxRadius;\n\n  void define() \{\n    defineParam(amount,     \"amount\",     0.04f);\n    defineParam(samples,    \"samples\",    11);\n    defineParam(focusNm,    \"focusNm\",    550.0f);\n    defineParam(lambdaMin,  \"lambdaMin\",  400.0f);\n    defineParam(lambdaMax,  \"lambdaMax\",  700.0f);\n    defineParam(mode,       \"mode\",       0);\n    defineParam(curve,      \"curve\",      1);\n    defineParam(invert,     \"invert\",     0);\n    defineParam(alphaMode,  \"alphaMode\",  0);\n    defineParam(center,     \"center\",     float2(960.0f, 540.0f));\n    defineParam(formatSize, \"formatSize\", float2(1920.0f, 1080.0f));\n    defineParam(aspect,     \"aspect\",     1.0f);\n    defineParam(protect,    \"protect\",    0.2f);\n    defineParam(falloff,    \"falloff\",    1.0f);\n    defineParam(angleDeg,   \"angleDeg\",   0.0f);\n    defineParam(spinDeg,    \"spinDeg\",    0.0f);\n    defineParam(fringeSat,  \"fringeSat\",  1.0f);\n  \}\n\n  float cmfX(float lam) \{\n    float t1 = (lam - 442.0f) * ((lam < 442.0f) ? 0.0624f : 0.0374f);\n    float t2 = (lam - 599.8f) * ((lam < 599.8f) ? 0.0264f : 0.0323f);\n    float t3 = (lam - 501.1f) * ((lam < 501.1f) ? 0.0490f : 0.0382f);\n    return 0.362f * exp(-0.5f * t1 * t1)\n         + 1.056f * exp(-0.5f * t2 * t2)\n         - 0.065f * exp(-0.5f * t3 * t3);\n  \}\n\n  float cmfY(float lam) \{\n    float t1 = (lam - 568.8f) * ((lam < 568.8f) ? 0.0213f : 0.0247f);\n    float t2 = (lam - 530.9f) * ((lam < 530.9f) ? 0.0613f : 0.0322f);\n    return 0.821f * exp(-0.5f * t1 * t1)\n         + 0.286f * exp(-0.5f * t2 * t2);\n  \}\n\n  float cmfZ(float lam) \{\n    float t1 = (lam - 437.0f) * ((lam < 437.0f) ? 0.0845f : 0.0278f);\n    float t2 = (lam - 459.0f) * ((lam < 459.0f) ? 0.0385f : 0.0725f);\n    return 1.217f * exp(-0.5f * t1 * t1)\n         + 0.681f * exp(-0.5f * t2 * t2);\n  \}\n\n  float3 xyzToRec709(float3 xyz) \{\n    return float3(\n       3.2404542f * xyz.x - 1.5371385f * xyz.y - 0.4985314f * xyz.z,\n      -0.9692660f * xyz.x + 1.8760108f * xyz.y + 0.0415560f * xyz.z,\n       0.0556434f * xyz.x - 0.2040259f * xyz.y + 1.0572252f * xyz.z\n    );\n  \}\n\n  float iorDelta(float lamNm, float focus) \{\n    if (curve == 0) \{\n      return (focus - lamNm) / max(lambdaMax - lambdaMin, 1.0f);\n    \}\n    float u  = lamNm * 0.001f;\n    float uf = focus * 0.001f;\n    float B  = (curve == 2) ? 0.01342f : 0.00420f;\n    return (B / max(u * u, 1.0e-8f)) - (B / max(uf * uf, 1.0e-8f));\n  \}\n\n  float smstep(float e0, float e1, float x) \{\n    float t = clamp((x - e0) / max(e1 - e0, 1.0e-8f), 0.0f, 1.0f);\n    return t * t * (3.0f - 2.0f * t);\n  \}\n\n  void init() \{\n    n = samples;\n    if (n < 3) n = 3;\n    if (n > 32) n = 32;\n\n    float l0 = min(lambdaMin, lambdaMax);\n    float l1 = max(lambdaMin, lambdaMax);\n    if (l1 - l0 < 1.0f) l1 = l0 + 1.0f;\n    float focus = clamp(focusNm, l0, l1);\n\n    float sign = (invert != 0) ? -1.0f : 1.0f;\n    float maxAbs = 1.0e-4f;\n    int i;\n    for (i = 0; i < 32; i++) \{\n      wRGB\[i] = float3(0.0f, 0.0f, 0.0f);\n      disp\[i] = 0.0f;\n      if (i < n) \{\n        float t = (n > 1) ? float(i) / float(n - 1) : 0.5f;\n        float lam = l0 + t * (l1 - l0);\n        float d = iorDelta(lam, focus);\n        disp\[i] = d;\n        float ad = fabs(d);\n        if (ad > maxAbs) maxAbs = ad;\n      \}\n    \}\n\n    float3 sumW = float3(0.0f, 0.0f, 0.0f);\n    for (i = 0; i < 32; i++) \{\n      if (i < n) \{\n        float t = (n > 1) ? float(i) / float(n - 1) : 0.5f;\n        float lam = l0 + t * (l1 - l0);\n        disp\[i] = (disp\[i] / maxAbs) * sign;\n\n        float3 xyz = float3(cmfX(lam), cmfY(lam), cmfZ(lam));\n        float3 rgb = xyzToRec709(xyz);\n        rgb = float3(max(rgb.x, 0.0f), max(rgb.y, 0.0f), max(rgb.z, 0.0f));\n        float lum = (rgb.x + rgb.y + rgb.z) * 0.33333334f;\n        float sat = clamp(fringeSat, 0.0f, 2.0f);\n        rgb = float3(\n          lum + (rgb.x - lum) * sat,\n          lum + (rgb.y - lum) * sat,\n          lum + (rgb.z - lum) * sat\n        );\n        wRGB\[i] = rgb;\n        sumW += rgb;\n      \}\n    \}\n\n    sumW = float3(max(sumW.x, 1.0e-8f), max(sumW.y, 1.0e-8f), max(sumW.z, 1.0e-8f));\n    for (i = 0; i < 32; i++) \{\n      if (i < n) \{\n        wRGB\[i] = float3(wRGB\[i].x / sumW.x, wRGB\[i].y / sumW.y, wRGB\[i].z / sumW.z);\n      \}\n    \}\n\n    float2 fs = formatSize;\n    if (fs.x < 1.0f) fs.x = 1.0f;\n    if (fs.y < 1.0f) fs.y = 1.0f;\n    float asp = (aspect <= 0.0f) ? 1.0f : aspect;\n    maxRadius = 0.5f * length(float2(fs.x, fs.y * asp));\n    if (maxRadius < 1.0f) maxRadius = 1.0f;\n  \}\n\n  void process(int2 pos) \{\n    float2 p = float2(float(pos.x) + 0.5f, float(pos.y) + 0.5f);\n    SampleType(src) srcCol = bilinear(src, p.x, p.y);\n\n    float2 c = center;\n    float asp = (aspect <= 0.0f) ? 1.0f : aspect;\n    float2 v = p - c;\n    v.y *= asp;\n    float rNorm = length(v) / maxRadius;\n\n    float fade = 1.0f;\n    if (protect >= 0.999f) \{\n      fade = 0.0f;\n    \} else if (protect > 0.0f) \{\n      fade = smstep(protect, 1.0f, rNorm);\n      fade = pow(max(fade, 0.0f), max(falloff, 0.01f));\n    \}\n\n    float amountEff = amount * fade;\n    if (fabs(amountEff) < 1.0e-8f) \{\n      dst() = srcCol;\n      return;\n    \}\n\n    float ang = angleDeg * 0.017453292519943295f;\n    float2 dirLin = float2(cos(ang), sin(ang));\n    float spinMax = spinDeg * 0.017453292519943295f;\n\n    float3 acc = float3(0.0f, 0.0f, 0.0f);\n    float aMax = srcCol.w;\n\n    int i;\n    for (i = 0; i < 32; i++) \{\n      if (i < n) \{\n        float d = disp\[i] * amountEff;\n        float2 dir = v;\n\n        if (mode == 2 || mode == 3) \{\n          float th = spinMax * disp\[i] * fade;\n          float cs = cos(th);\n          float sn = sin(th);\n          dir = float2(dir.x * cs - dir.y * sn, dir.x * sn + dir.y * cs);\n        \}\n\n        float2 sPos = p;\n        if (mode == 1) \{\n          sPos = p - float2(dirLin.x, dirLin.y / asp) * (d * maxRadius);\n        \} else if (mode == 2) \{\n          dir.y /= asp;\n          sPos = c + dir;\n        \} else \{\n          float scale = 1.0f + d;\n          if (fabs(scale) < 1.0e-4f) scale = (scale < 0.0f) ? -1.0e-4f : 1.0e-4f;\n          dir = dir / scale;\n          dir.y /= asp;\n          sPos = c + dir;\n        \}\n\n        SampleType(src) s = bilinear(src, sPos.x, sPos.y);\n        acc.x += s.x * wRGB\[i].x;\n        acc.y += s.y * wRGB\[i].y;\n        acc.z += s.z * wRGB\[i].z;\n        if (s.w > aMax) aMax = s.w;\n      \}\n    \}\n\n    float4 outp;\n    outp.x = acc.x;\n    outp.y = acc.y;\n    outp.z = acc.z;\n    outp.w = (alphaMode == 1) ? aMax : srcCol.w;\n    dst() = outp;\n  \}\n\};\n"
  rebuild ""
  SpectralCA_amount {{parent.amount}}
  SpectralCA_samples {{parent.samples}}
  SpectralCA_focusNm {{parent.focusNm}}
  SpectralCA_lambdaMin {{parent.lambdaMin}}
  SpectralCA_lambdaMax {{parent.lambdaMax}}
  SpectralCA_mode {{parent.mode}}
  SpectralCA_curve {{parent.curve}}
  SpectralCA_invert {{parent.invert}}
  SpectralCA_alphaMode {{parent.alphaMode}}
  SpectralCA_center {{parent.center.x} {parent.center.y}}
  SpectralCA_formatSize {{width} {height}}
  SpectralCA_aspect {{parent.aspect}}
  SpectralCA_protect {{parent.protect}}
  SpectralCA_falloff {{parent.falloff}}
  SpectralCA_angleDeg {{parent.angleDeg}}
  SpectralCA_spinDeg {{parent.spinDeg}}
  SpectralCA_fringeSat {{parent.fringeSat}}
  rebuild_finalise ""
  name SpectralCA_kernel
  xpos 0
  ypos -200
 }
 Merge2 {
  inputs 2+1
  operation copy
  name MergeOut
  xpos 0
  ypos -80
 }
 CopyBBox {
  inputs 2
  name CopyBBox1
  xpos 0
  disable {{!parent.preserveBBox}}
 }
 Output {
  name Output1
  xpos 0
  ypos 80
 }
end_group