2013-09-30 72 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