2013-09-30 75 views
3

因此,我一直试图在Dart制作一个简单的柏林噪声发生器的过去几个小时。要做到这一点,我决定使用二维生成伪码上this page柏林噪声飞镖实施失败

这是我的飞镖实现是什么样子(伟大的阅读!):http://pastebin.com/NZF0U6ju

不幸的是,当我渲染到画布上,我只因为这图所示获得随机产生的斜线:

my render

用于渲染的图像我用下面的脚本:

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); 
    } 
    } 
} 

有谁知道是什么原因导致了这种行为,以及我的实施出错的地方?

回答

6

我看到你的代码的一些问题:

  • 行42:它应该是double fracY = y-intY;而不是double fracY = x-intY;
  • _noise功能是对称的:_noise(x, y) == _noise(y, x)。该文章使用不是对称的x+y*57
  • 快速阅读the page you mentioned据我所知,_interpolatedNoise,_smoothNoise_noise应该采取额外的i参数。

每次迭代调用不同噪声函数,通过Noisei表示。

编辑:这是实现2D培林噪声尝试:

  • 我有改变的_noise
  • perlinNoise为0和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'); 
} 
+0

不错电子!这让我更接近实际结果。谢谢!尽管如此,修复并没有真正给出想要的结果。正如你可能已经注意到的那样,我试图用种子来控制随机化,但是在我的新版本中它看起来并不正确。 新版本:[链接](http://tny.cz/d53629ff) – handyface

+0

我用似乎有效的东西更新了答案。欢呼:) –

+0

哇。非常感谢你! – handyface