上週在研究噪聲函數,作爲一個純新手,過程可謂艱辛,一個一維噪聲足足啃了我兩整天的時間,才悟出一點眉目,說多了都是淚,特寫此文獻給同我一樣的小白,希望可以能夠爲你們節約一些寶貴的時間。
本人圖形學基礎爲零,若有錯誤之處請勿噴,歡迎指正。
本文編程基於AS3。
相關文章:
[1] 隨機數生成算法 :http://blog.sina.com.cn/s/blog_4abaa7fc01009tgj.html
什麼是噪聲:
以最簡單的白噪聲舉例,白噪聲就是一大堆隨機數,所以一維白噪聲就是一個一維的隨機數數組,二維三維同理。由於AS3的隨機數無法指定種子,所以我參考網上的資料自己寫了一個隨機函數,係數似乎是出自C++?忘了抱歉。。。
默認種子爲:1
package
{
/**
* ...
* @author Christon
*/
public class Random
{
private static var r:uint = 1;
private static const A:uint = 1103515245;
private static const C:uint = 12345;
private static const M:uint = 32767;
public static function seed(value:Number):void
{
Random.r = value;
}
public static function random():Number
{
r = (r * A + C) / M;
return (r % M) / M;
}
}
}
我們可以用一個二維白噪聲圖檢驗這個算法的好壞,代碼就免了,學了二維噪聲就會寫了
噪聲很均勻,但如果我們把 C 換成100再試試:
一條黑乎乎的斜線表明了它是個失敗的隨機。接下來的學習,從一維噪聲開始。
一維噪聲
首先利用隨機函數生成一個一維噪聲數組
var width:int = 500;
var whiteNoise:Array = [];
for (var i:int = 0; i < width; i ++)
{
whiteNoise[i] = Random.random();
}
var amplitude:int = 100;
var frequency:int = 10;
function linearInterpolate(a:Number, b:Number, x:Number):Number
{
return a * (1 - x) + b * x;
}
var bmd:BitmapData = new BitmapData(whiteNoise.length * frequency, amplitude);
var d0:int = 0;
for (var i:int = 0; i < whiteNoise.length - 1; i ++)
{
//獲取相鄰的兩個噪聲值
var a:int = whiteNoise[i] * amplitude;
var b:int = whiteNoise[i + 1] * amplitude;
for (var j:int = 0; j < frequency; j ++ )
{
//求導
var d:int = this.linearInterpolate(a, b, j / frequency);
bmd.setPixel(i * frequency + j, d, ColorTools.fromRGB(0, 0, 0));
}
}
this.bitmapData = bmd;
果如下圖所示://...
//求導
//...
//補間
if (d0 != d)
{
var k:int = d0;
if (d0 < d)
{
for (; k < d; k ++ )
{
bmd.setPixel(i * frequency + j, k, ColorTools.fromRGB(0, 0, 0));
}
}
else
{
for (; k > d; k -- )
{
bmd.setPixel(i * frequency + j, k, ColorTools.fromRGB(0, 0, 0));
}
}
d0 = d;
}
//...
這次效果好多了function cosineInterpolate(a:Number, b:Number, x:Number):Number
{
var ft:Number = x * Math.PI;
var f:Number = (1 - Math.cos(ft)) * 0.5;
return a * (1 - f) + b * f;
}