JavaScript Canvas Plasma

Example of Plasma effect in JavaScript

by Jeremy Likness

HTML

<h1>Old School: JavaScript Plasma!</h1>
<div>by <a href="https://www.twitter.com/jeremylikness" target="_blank">@JeremyLikness</a></div>
<div><a href="https://blog.jeremylikness.com/" target="_blank">Developer for Life</a></div>
<canvas id="plasma">Your browser does not support the HTML5 canvas tag.</canvas>

CSS

#plasma {
  width: 320px;
  height: 200px;
  border: 1px solid black;
}

div {
  padding: 10px;
}

}

JavaScript

(function(c) {
  var ctx = c.getContext('2d'),
    palette = [],
    sine = [],
    width = c.clientWidth,
    height = c.clientHeight,
    buffer = new Uint8ClampedArray(width * height * 4),
    pos1 = 0,
    pos3 = 0,
    tpos1 = 0,
    tpos2 = 0,
    tpos3 = 0,
    tpos4 = 0;

  function fillPalette(pal) {
    var i, r, g;
    for (i = 0; i < 64; i += 1) {
      r = i << 2;
      g = 255 - (r + 1);
      palette[i] = {
        r: r,
        g: g,
        b: 0
      };
      g = r + 1;
      palette[i + 64] = {
        r: 255,
        g: g,
        b: 0
      };
      r = g = 255 - ((i << 2) + 1);
      palette[i + 128] = {
        r: r,
        g: g,
        b: 0
      };
      g = (i << 2) + 1;
      palette[i + 192] = {
        r: 0,
        g: g,
        b: 0
      };
    }
  }

  function createSineTable(table) {
    var i, rad;
    for (i = 0; i < 512; i += 1) {
      rad = (i * 0.703125) * 0.0174532;
      table[i] = Math.floor(Math.sin(rad) * 1024);
    }
  }

  function render(table, pal, w, h) {
    var i, j, idx, x;
    tpos4 = 0;
    tpos3 = pos3;

    for (i = 0; i < h; i += 1) {

      tpos1 = pos1 + 5;
      tpos2 = 3;
      tpos3 &= 511;
      tpos4 &= 511;

      for (j = 0; j < w; j += 1) {
        tpos1 = tpos1 & 511;
        tpos2 = tpos2 & 511;
        x = table[tpos1] + table[tpos2] + table[tpos3] + table[tpos4];
        idx = Math.abs(Math.floor(128 + (x >> 4)) % 256);
        let base = (i * w + j)*4;
        buffer[base] = pal[idx].r;
        buffer[base + 1] = pal[idx].g;
        buffer[base + 2] = pal[idx].b;
        buffer[base + 3] = 255;
        tpos1 += 5;
        tpos2 += 3;
      }

      tpos4 += 3;
      tpos3 += 1;
    }

    pos1 += 9;
    pos3 += 8;
  }

  function paint(ctx, w, h) {
    var imageData = new ImageData(buffer, w, h);
    ctx.putImageData(imageData, 0, 0);
  }

  fillPalette(palette);
  createSineTable(sine);

  var iterate = function(c, s, p) {
    setTimeout(function() {
      render(s, p, width, height);
  ...