3

それで、私は過去数時間、Dart で単純な Perlin ノイズ ジェネレーターを作ろうとしてきました。これを行うために、このページの 2D 生成に疑似コードを使用することにしました(よく読んでください!)。

これは、私のダートの実装がどのように見えるかです: http://pastebin.com/NZF0U6ju

残念ながら、キャンバスにレンダリングすると、次の画像のようにランダムに生成された対角線しか表示されません。

私のレンダリング

画像をレンダリングするために、次のスクリプトを使用しました。

void main() {
  PerlinNoise p = new PerlinNoise(octaves:5);
  CanvasElement c = query('canvas');
  CanvasRenderingContext2D con = c.context2D;
  ImageData id= con.createImageData(1,1);
  List d= id.data;
  d[3]=255;  
  for (var i=0;i<c.width;i++) {
    for (var j=0;j<c.height;j++) {
      int val = (p.perlinNoise(i.toDouble(), j.toDouble())*200).toInt();
      d[0] = val;
      d[1] = val;
      d[2] = val;
      con.putImageData(id, i, j);
    }
  }
}

この動作の原因と、実装がどこで失敗したかを知っている人はいますか?

4

1 に答える 1

7

私はあなたのコードにいくつかの問題を見ました:

  • 42行目:double fracY = y-intY;代わりにdouble fracY = x-intY;
  • あなたの_noise関数は対称です: _noise(x, y) == _noise(y, x). x+y*57対称ではない物品の使用。
  • あなたが言及したページをすばやく読んだことで、それを理解し_interpolatedNoise、追加のパラメーターを取る必要があり_smoothNoiseます。_noisei

各反復は、Noiseiで示される異なるノイズ関数を呼び出します。

編集: 2D パーリン ノイズを実装する試みは次のとおりです。

  • の実装を変更しました_noise
  • perlinNoise0 ~ 1 の番号でコールする必要がありました( を参照main
import 'dart:html';
import 'dart:math' as Math;

class PerlinNoise {
  int _octaves;
  double _persistence;
  Map<int, Map<int, Map<int, double>>> _noises = {};
  final _rand = new Math.Random();

  PerlinNoise({int octaves: 1, double persistence:1.0}) :
    _octaves = octaves,
    _persistence = persistence;

  double _noise(int i, int x, int y) =>
      _noises.putIfAbsent(i, () => {})
        .putIfAbsent(x, () => {})
          .putIfAbsent(y, () => 2 * _rand.nextDouble() - 1);

  double _smoothNoise (int i, int x, int y) {
    double corners = (_noise(i, x - 1, y - 1) +
                      _noise(i, x + 1, y - 1) +
                      _noise(i, x - 1, y + 1) +
                      _noise(i, x + 1, y + 1)) / 16;
    double sides  = (_noise(i, x - 1, y    ) +
                     _noise(i, x + 1, y    ) +
                     _noise(i, x    , y - 1) +
                     _noise(i, x    , y + 1)) / 8;
    double center = _noise(i, x, y) / 4;
    return corners + sides + center;
  }

  double _interpolate (double a,double b,double x) {
    double ft = x * Math.PI;
    double f = (1 - Math.cos(ft)) * 0.5;
    return a * (1 - f) + b * f;
  }

  double _interpolatedNoise (int i, num x, num y) {
    int intX = x.floor();
    int intY = y.floor();

    double fracX = (x - intX).toDouble();
    double fracY = (y - intY).toDouble();

    double v1 = _smoothNoise(i, intX    , intY    );
    double v2 = _smoothNoise(i, intX + 1, intY    );
    double v3 = _smoothNoise(i, intX    , intY + 1);
    double v4 = _smoothNoise(i, intX + 1, intY + 1);

    double i1 = _interpolate(v1, v2, fracX);
    double i2 = _interpolate(v3, v4, fracX);

    return _interpolate(i1, i2, fracY);
  }

  double perlinNoise(num x, num y) {
    var total = 0;

    for (var i = 0; i < _octaves; i++) {
      int frequency = Math.pow(2, i);
      double amplitude = Math.pow(_persistence, i);

      total += _interpolatedNoise(i, x * frequency, y * frequency) * amplitude;
    }
    return total;
  }
}

void main() {
  PerlinNoise p = new PerlinNoise(octaves: 5, persistence: 0.9);
  CanvasElement c = query('canvas');
  CanvasRenderingContext2D con = c.context2D;
  ImageData id = con.createImageData(1,1);
  List d = id.data;
  d[3] = 255;
  for (var i = 0; i < c.width; i++) {
    for (var j = 0; j < c.height; j++) {
      // my canvas is 256px x 256px
      int val = (128 + 128 * p.perlinNoise(i / 256.0, j / 256.0)).toInt();
      d[0] = val;
      d[1] = val;
      d[2] = val;
      con.putImageData(id, i, j);
    }
  }
  print('done');
}
于 2013-09-30T21:17:46.960 に答える