CompStart

ProLeccionesCursosElementosSoftware

CompStart

Domina los efectos visuales con técnicas de vanguardia.

Aprendizaje

CursosLeccionesFunciones ProRecursosSoftware

Tools

Tech CheckDisplay CheckMotion BlurCIE 1931PhysLightNuke Tools

Empresa

InstructorMisiónImpressumPrivacidadTérminos

Proyectos

Moray RenderEXR ConverterOCIO.ccNuke ToolsDerekVFX

Follow

YouTubeInstagramTikTokThreadsContacto

© 2026 CompStart. Todos los derechos reservados.

Aberración espectral

ToolSets / Lens
Lens

2026-09-07

ToolSets/lens/spectralAberration.nk

lente
aberración cromática
California
óptico
franja
blinkscript
dispersión
utilidad
View on GitHub

Aberración cromática muestreada en longitud de onda para Nuke: aberración cromática radial, lineal o de giro a partir de curvas de dispersión, no de la escala del canal RGB.

La aberración espectral genera aberración cromática mediante el muestreo de longitudes de onda en un rango y la reconstrucción de imágenes RGB con ponderaciones basadas en el estándar CIE. No se trata de una simple escala o desplazamiento de canales RGB.

Úselo para igualar la aberración cromática de la lente de placa o agregar franjas controladas. El modo abarca radial (aberración cromática lateral), lineal (desenfoque de prisma), giro (remolino estilo Helios) y radial seguido de giro. Las opciones de dispersión son longitud de onda lineal, Cauchy BK7 y SF10 de sílex. Cantidad ajusta la intensidad; protección y atenuación mantienen el centro limpio. Longitud de onda de enfoque, lambda mín./máx., muestras, saturación de franjas, aspecto, inversión y centro dan forma a las franjas.

El canal alfa puede permanecer en la fuente o dilatarse hasta el borde. El sobreescaneo, la conservación del cuadro delimitador, la máscara y la mezcla se ajustan al uso estándar de la composición. El efecto se ejecuta en BlinkScript y requiere Nuke comercial; si los controles no funcionan, vincule los potenciómetros después de recompilar el kernel.

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