パーリンノイズ

 

パーリンノイズ

参考URL
https://mrl.cs.nyu.edu/~perlin/doc/oscar.html
https://github.com/a-i-to/perlin-noise-sample
GitHubから引用

        function PerlinNoise(random) {
          if (random) {
            this._random = random;
          } else {
            this._random = Math.random;
          }
          this._gradient = {};
        }
        
        PerlinNoise.prototype._randomGradient = function(x) {
          if (this._gradient[x] || this._gradient[x] === 0) {
            return this._gradient[x];
          }
          var g = this._random() * 2 - 1;
          this._gradient[x] = g;
          return g;
        };
        
        PerlinNoise.prototype.noise = function(x) {
          var x0 = Math.floor(x);
          var x1 = x0 + 1;
          var r0 = x - x0;
          var r1 = r0 - 1;
        
          var u = r0 * this._randomGradient(x0);
          var v = r1 * this._randomGradient(x1);
        
          var sx = r0 * r0 * (3 - 2 * r0);
        
          return 2 * (u + sx * (v - u));
        };
        
        this.PerlinNoise = PerlinNoise;
      
書き直したもの

        class PerlinNoise {
          constructor (random = Math.random) {
            this.random   = random;
            this.gradient = new Map;
          }
          
          randomGradient (x) {
            if (! this.gradient.has (x))
              this.gradient.set (x, this.random () * 2 -1);
            return this.gradient.get (x);
          }
        
          noise (x) {
            let
              x0 = x |0, x1 = x0 + 1,
              r0 = x - x0, r1 = r0 - 1,
              u = r0 * this.randomGradient (x0),
              v = r1 * this.randomGradient (x1),
              sx = r0 * r0 * (3 - 2 * r0);
        
            return 2 * (u + sx * (v - u));
          }
        }
      
CANVAS に描画してみる

        const
          PN = new PerlinNoise,
          canvas = CV0,
          ctx = canvas.getContext ('2d'),
          width = canvas.offsetWidth,
          height = canvas.offsetHeight / 2,
          centerY = height / 2,
          wave = 5,
          waveH = 100;
        
        canvas.width = width;
        ctx.beginPath ();
        ctx.moveTo (0, centerY);
        ctx.strokeStyle = 'rgba(255,0,0,.5)';
      
        for (let px = 0; px < width; px += 1) {
          let py = centerY - PN.noise (px * wave / width) * waveH + waveH / 2;
          ctx.lineTo (px, py);
        }
        ctx.stroke ();