javaScripts生成噪声地形

参考 https://zhuanlan.zhihu.com/p/206271895

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
</head>

<body>
  <canvas id="canvas" width="1000" height="1000"></canvas>
  <script type="text/javascript">
    let seed = 63;

    function psrandom() {
      seed = (seed * 9301 + 49297) % 233280;
      return seed / 233280.0;
    }

    function getGrad(x, y) {
      return gradfun(x, y);
    }

    function gradfun(x, y) {
      var vec = [];
      vec[0] = x * 127.1 + y * 311.7;
      vec[1] = x * 269.5 + y * 183.3;

      var geadSeed = 461;
      var numb = (geadSeed * 9301 + 49297) % 233280;

      var sin0 = Math.sin(vec[0]) * numb;
      var sin1 = Math.sin(vec[1]) * numb;
      vec[0] = (sin0 - Math.floor(sin0)) * 2.0 - 1.0;
      vec[1] = (sin1 - Math.floor(sin1)) * 2.0 - 1.0;

      // 归一化,尽量消除正方形的方向性偏差
      var len = Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
      vec[0] /= len;
      vec[1] /= len;

      return vec;
    }

    var min = 1;
    var max = 0;
    var zeronum = 0;

    var size = 6;

    function perlin(x, y) {
      x = x / size;
      y = y / size;

      var p0x = Math.floor(x); // P0坐标
      var p0y = Math.floor(y);
      var p1x = p0x; // P1坐标
      var p1y = p0y + 1;
      var p2x = p0x + 1; // P2坐标
      var p2y = p0y + 1;
      var p3x = p0x + 1; // P3坐标
      var p3y = p0y;

      var g0x = getGrad(p0x, p0y)[0]; // P0点的梯度
      var g0y = getGrad(p0x, p0y)[1];
      var g1x = getGrad(p1x, p1y)[0]; // P1点的梯度
      var g1y = getGrad(p1x, p1y)[1];
      var g2x = getGrad(p2x, p2y)[0]; // P2点的梯度
      var g2y = getGrad(p2x, p2y)[1];
      var g3x = getGrad(p3x, p3y)[0]; // P3点的梯度
      var g3y = getGrad(p3x, p3y)[1];

      var v0x = x - p0x; // P0点的方向向量
      var v0y = y - p0y;
      var v1x = x - p1x; // P1点的方向向量
      var v1y = y - p1y;
      var v2x = x - p2x; // P2点的方向向量
      var v2y = y - p2y;
      var v3x = x - p3x; // P3点的方向向量
      var v3y = y - p3y;

      var product0 = g0x * v0x + g0y * v0y; // P0点梯度向量和方向向量的点乘
      var product1 = g1x * v1x + g1y * v1y; // P1点梯度向量和方向向量的点乘
      var product2 = g2x * v2x + g2y * v2y; // P2点梯度向量和方向向量的点乘
      var product3 = g3x * v3x + g3y * v3y; // P3点梯度向量和方向向量的点乘

      // P1和P2的插值
      var d0 = x - p0x;
      var t0 = 6.0 * Math.pow(d0, 5.0) - 15.0 * Math.pow(d0, 4.0) + 10.0 * Math.pow(d0, 3.0);
      var n0 = product1 * (1.0 - t0) + product2 * t0;

      // P0和P3的插值
      var n1 = product0 * (1.0 - t0) + product3 * t0;

      // P点的插值
      var d1 = y - p0y;
      var t1 = 6.0 * Math.pow(d1, 5.0) - 15.0 * Math.pow(d1, 4.0) + 10.0 * Math.pow(d1, 3.0);
      var val = n1 * (1.0 - t1) + n0 * t1;

      val = (val + 0.69) / 1.39;
      if (val < min) min = val;
      if (val > max) max = val;
      if (val == 0) zeronum++;
      if (val < 0) val = 0;
      if (val > 1) val = 1;
      return val
    }


    var width = 100;

    for (var x = 0; x < width; x++) {
      for (var y = 0; y < width; y++) {
        var val = perlin(x, y)
        var color = "rgba(0,0,0," + val + ")";
        if (val < 0.3) color = "rgba(0,0,255," + (val + 0.1) + ")";
        if (val > 0.6) color = "rgba(0,255,0," + (val - 0.5) / 0.4 + ")";
        if (val > 0.8) color = "rgba(255,0,0," + (val - 0.7) / 0.2 + ")";
        rect(x, y, color);
      }
    }


    function rect(x, y, color) {
      var ctx = document.getElementById("canvas").getContext("2d");
      ctx.fillStyle = color;
      ctx.fillRect(x * 10, y * 10, 10, 10);
    }

    console.log(min, max);

    // line(0, 10, 200, 10);


    function line(x1, y1, x2, y2) {
      var ctx = document.getElementById("canvas").getContext("2d");
      ctx.beginPath();
      ctx.lineWidth = "1";
      ctx.strokeStyle = "green"; // Green path
      ctx.moveTo(x1, y1);
      ctx.lineTo(x2, y2);
      ctx.stroke(); // Draw it
    }
  </script>
</body>

</html>
posted @ 2022-08-18 10:01  溟天有雨  阅读(85)  评论(0)    收藏  举报