Advertisement
here2share

# awesome_plasma.html

Apr 25th, 2020
708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 7.15 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <meta charset="utf-8" />
  3. <body
  4.  style="position: fixed; left: 0px; right: 0px; top: 0px; bottom: 0px; overflow: hidden; margin: 0; padding: 0;"
  5. >
  6.   <canvas
  7.    id="canvas"
  8.    style="width: 100%; height: 100%; padding: 0;margin: 0;"
  9.  ></canvas>
  10.   <script>
  11.     const canvas = document.getElementById("canvas");
  12.     const c = canvas.getContext("2d");
  13.  
  14.     // size of canvas
  15.     const imgSize = 512;
  16.  
  17.     canvas.width = imgSize;
  18.     canvas.height = imgSize;
  19.  
  20.     // init image data with black pixels
  21.     const image = c.createImageData(imgSize, imgSize);
  22.     for (let i = 0; i < image.data.length; i += 4) {
  23.      image.data[i] = 0; // R
  24.      image.data[i + 1] = 0; // G
  25.      image.data[i + 2] = 0; // B
  26.      image.data[i + 3] = 255; // A
  27.    }
  28.  
  29.    // size of our height maps
  30.    const mapSize = 1024;
  31.  
  32.    // returns the distance of point x,y from the origin 0,0
  33.    const distance = (x, y) => Math.sqrt(x * x + y * y);
  34.  
  35.     // init height map 1
  36.     const heightMap1 = [];
  37.     for (let u = 0; u < mapSize; u++) {
  38.      for (let v = 0; v < mapSize; v++) {
  39.        // index of coordinate in height map array
  40.        const i = u * mapSize + v;
  41.  
  42.        // u,v are coordinates with origin at upper left corner
  43.        // cx and cy are coordinates with origin at the
  44.        // center of the map
  45.        const cx = u - mapSize / 2;
  46.        const cy = v - mapSize / 2;
  47.  
  48.        // distance from middle of map
  49.        const d = distance(cx, cy);
  50.  
  51.        // stretching so we get the desired ripple density on our map
  52.        const stretch = (3 * Math.PI) / (mapSize / 2);
  53.  
  54.        // wavy height value between -1 and 1
  55.        const ripple = Math.sin(d * stretch);
  56.  
  57.        // wavy height value normalized to 0..1
  58.        const normalized = (ripple + 1) / 2;
  59.  
  60.        // height map value 0..128, integer
  61.        heightMap1[i] = Math.floor(normalized * 128);
  62.      }
  63.    }
  64.  
  65.    const heightMap2 = [];
  66.    for (let u = 0; u < mapSize; u++) {
  67.      for (let v = 0; v < mapSize; v++) {
  68.        const i = u * mapSize + v;
  69.        const cx = u - mapSize / 2;
  70.        const cy = v - mapSize / 2;
  71.  
  72.        // skewed distance as input to chaos field calculation,
  73.        // scaled for smoothness over map distance
  74.        const d1 = distance(0.8 * cx, 1.3 * cy) * 0.022;
  75.        const d2 = distance(1.35 * cx, 0.45 * cy) * 0.022;
  76.  
  77.        const s = Math.sin(d1);
  78.        const c = Math.cos(d2);
  79.        // height value between -2 and +2
  80.        const h = s + c;
  81.  
  82.        // height value between 0..1
  83.        const normalized = (h + 2) / 4;
  84.        // height value between 0..127, integer
  85.        heightMap2[i] = Math.floor(normalized * 127);
  86.      }
  87.    }
  88.  
  89.    // color helpers
  90.  
  91.    const interpolate = (c1, c2, f) => {
  92.       return {
  93.         r: Math.floor(c1.r + (c2.r - c1.r) * f),
  94.         g: Math.floor(c1.g + (c2.g - c1.g) * f),
  95.         b: Math.floor(c1.b + (c2.b - c1.b) * f)
  96.       };
  97.     };
  98.  
  99.     // returns a random color
  100.     const randomColor = () => {
  101.       const r = Math.floor(Math.random() * 255);
  102.       const g = Math.floor(Math.random() * 255);
  103.       const b = Math.floor(Math.random() * 255);
  104.       return { r, g, b };
  105.     };
  106.  
  107.     // returns a random color palette with 256 color entries
  108.     const makeRandomPalette = () => {
  109.       const c1 = randomColor();
  110.       const c2 = randomColor();
  111.       const c3 = randomColor();
  112.       const c4 = randomColor();
  113.       const c5 = randomColor();
  114.  
  115.       return makeFiveColorGradient(c1, c2, c3, c4, c5);
  116.     };
  117.  
  118.     const makeFiveColorGradient = (c1, c2, c3, c4, c5) => {
  119.       const g = [];
  120.  
  121.       for (let i = 0; i < 64; i++) {
  122.        const f = i / 64;
  123.        g[i] = interpolate(c1, c2, f);
  124.      }
  125.  
  126.      for (let i = 64; i < 128; i++) {
  127.        const f = (i - 64) / 64;
  128.        g[i] = interpolate(c2, c3, f);
  129.      }
  130.  
  131.      for (let i = 128; i < 192; i++) {
  132.        const f = (i - 128) / 64;
  133.        g[i] = interpolate(c3, c4, f);
  134.      }
  135.  
  136.      for (let i = 192; i < 256; i++) {
  137.        const f = (i - 192) / 64;
  138.        g[i] = interpolate(c4, c5, f);
  139.      }
  140.  
  141.      return g;
  142.    };
  143.  
  144.    // offsets for moving height maps
  145.    let dx1 = 0;
  146.    let dy1 = 0;
  147.  
  148.    let dx2 = 0;
  149.    let dy2 = 0;
  150.  
  151.    // adjust height maps offsets
  152.    const moveHeightMaps = t => {
  153.       dx1 = Math.floor(
  154.         (((Math.cos(t * 0.0002 + 0.4 + Math.PI) + 1) / 2) * mapSize) / 2
  155.       );
  156.       dy1 = Math.floor((((Math.cos(t * 0.0003 - 0.1) + 1) / 2) * mapSize) / 2);
  157.       dx2 = Math.floor((((Math.cos(t * -0.0002 + 1.2) + 1) / 2) * mapSize) / 2);
  158.       dy2 = Math.floor(
  159.         (((Math.cos(t * -0.0003 - 0.8 + Math.PI) + 1) / 2) * mapSize) / 2
  160.       );
  161.     };
  162.  
  163.     // two palettes we interpolate between
  164.     const palettes = [makeRandomPalette(), makeRandomPalette()];
  165.  
  166.     // current palette is edstablished durting animation
  167.     let palette = [];
  168.  
  169.     // stores whether we're interpolating colors
  170.     // from palette 0 -> 1 (1) or 1 -> 0 (-1)
  171.     let prevDirection = 1;
  172.  
  173.     const updatePalette = t => {
  174.       const timeScale = 0.0005;
  175.       const x = t * timeScale;
  176.  
  177.       // normalized value 0..1 used to interpolate palette colors
  178.       const inter = (Math.cos(x) + 1) / 2;
  179.  
  180.       // did we switch direction, and should ergo pick a new palette
  181.       // random palette to interpolate towards?
  182.  
  183.       const direction = -Math.sin(x) >= 0 ? 1 : -1;
  184.       if (prevDirection != direction) {
  185.         prevDirection = direction;
  186.         if (direction == -1) {
  187.           palettes[0] = makeRandomPalette();
  188.         } else {
  189.           palettes[1] = makeRandomPalette();
  190.         }
  191.       }
  192.  
  193.       // create interpolated palette for current frame
  194.       for (let i = 0; i < 256; i++) {
  195.        palette[i] = interpolate(palettes[0][i], palettes[1][i], inter);
  196.      }
  197.    };
  198.  
  199.    const updateImageData = () => {
  200.       for (let u = 0; u < imgSize; u++) {
  201.        for (let v = 0; v < imgSize; v++) {
  202.          // indexes into height maps for pixel
  203.          const i = (u + dy1) * mapSize + (v + dx1);
  204.          const k = (u + dy2) * mapSize + (v + dx2);
  205.  
  206.          // index for pixel in image data
  207.          // remember it's 4 bytes per pixel
  208.          const j = u * imgSize * 4 + v * 4;
  209.          // height value of 0..255
  210.          let h = heightMap1[i] + heightMap2[k];
  211.          // get color value from current palette
  212.          let c = palette[h];
  213.          // h = heightMap2[i];
  214.          // c = { r: h, g: h, b: h };
  215.          // set pixel data
  216.          image.data[j] = c.r;
  217.          image.data[j + 1] = c.g;
  218.          image.data[j + 2] = c.b;
  219.        }
  220.      }
  221.    };
  222.    // helper to create a linear gradient palette
  223.    const linearGradient = (c1, c2) => {
  224.       const g = [];
  225.  
  226.       // interpolate between the colors
  227.       // in the gradient
  228.  
  229.       for (let i = 0; i < 256; i++) {
  230.        const f = i / 255;
  231.        g[i] = interpolate(c1, c2, f);
  232.      }
  233.  
  234.      return g;
  235.    };
  236.  
  237.    const tick = time => {
  238.       moveHeightMaps(time);
  239.       updatePalette(time);
  240.       updateImageData();
  241.  
  242.       c.putImageData(image, 0, 0);
  243.  
  244.       requestAnimationFrame(tick);
  245.     };
  246.  
  247.     requestAnimationFrame(tick);
  248.   </script>
  249. </body>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement