Particle Swarm in Nuke 16 using Blinkscript

BlinkScript in Nuke is a powerful way to create custom GPU-accelerated tools, and here’s a fun example: BugSwarm. This script simulates a swarm of tiny bugs flying randomly inside a defined area, adding life and motion to a shot without the need for external particle plugins.

This blink script works only Nuke 16 and above!!

Why It’s Interesting

  • It’s a great example of how BlinkScript can mimic particle systems inside Nuke.
  • The math is lightweight, meaning it runs fast on the GPU.
  • Parameters are fully customizable, making it easy to adjust the mood—from a slow drifting swarm to chaotic buzzing.

Creative Uses

  • Add background detail to an outdoor shot.
  • Simulate gnats, flies, or tiny floating debris.
  • Combine with glow or color shifts for surreal or magical effects.

Full Code

// BugSwarm: Simulates bugs flying randomly in a bounded area
kernel BugSwarm : ImageComputationKernel<ePixelWise>
{
  Image<eWrite, eAccessPoint> dst;

param:
  int    nBugs;
  float2 center;
  float  areaRadius;
  float  bugSize;
  float  time;
  int    seed;
  float  speed;
  float  turbulence;
  float  brightness;

  void define() {
    defineParam(nBugs,      "NumBugs",    80);
    defineParam(center,     "SwarmCenter", float2(400.0f, 400.0f), eParamProxyScale);
    defineParam(areaRadius, "SwarmRadius", 150.0f, eParamProxyScale);
    defineParam(bugSize,    "BugSize",     4.0f, eParamProxyScale);
    defineParam(time,       "Time",        0.0f);
    defineParam(seed,       "Seed",        777);
    defineParam(speed,      "FlySpeed",    40.0f);
    defineParam(turbulence, "Turbulence",  20.0f);
    defineParam(brightness, "Brightness",  1.5f);
  }

  inline float randF(int s) {
    s = (s << 13) ^ s;
    return (1.0f - ((s * (s * s * 15731 + 789221) + 1376312589) 
                   & 0x7fffffff) / 1073741824.0f);
  }

  inline float falloff(float2 pos, float2 c, float size) {
    float d = length(pos - c);
    return exp(-(d * d) / (size * size));
  }

  // Bug colour: dark with slight highlight
  inline float3 bugColour(float flicker) {
    float3 dark = float3(0.05f, 0.05f, 0.05f);
    float3 highlight = float3(0.2f, 0.2f, 0.1f);
    return dark + highlight * flicker;
  }

  void process(int2 pos) {
    float2 uv = float2(pos.x, pos.y);
    float3 finalCol = float3(0.0f);

    for (int i = 0; i < nBugs; i++) {
      int pSeed = seed + i * 71;

      // Each bug gets its own orbit radius + speed
      float orbitR = areaRadius * (0.4f + 0.6f * randF(pSeed + 33));
      float orbitSpeed = speed * (0.5f + randF(pSeed + 44));

      // Bug moves in circular + noisy path
      float angle = time * orbitSpeed * 0.01f + randF(pSeed + 55) * 6.28318f;
      float2 posBug = center + float2(cos(angle), sin(angle)) * orbitR;

      // Add turbulence jitter
      posBug += float2(
        sin(time * 3.1f + i) * turbulence,
        cos(time * 2.3f + i * 1.3f) * turbulence
      ) * 0.2f;

      // Wing flicker
      float flicker = 0.5f + 0.5f * sin(time * 15.0f + i);

      // Colour + fade
      float3 col = bugColour(flicker);
      float density = falloff(uv, posBug, bugSize);

      finalCol += col * density;
    }

    finalCol *= brightness;

    SampleType(dst) result(0.0f);
    result[0] = finalCol.x;
    result[1] = finalCol.y;
    result[2] = finalCol.z;
    dst() = result;
  }
};
Tagged:
5 1 vote
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x