上周在研究噪声函数,作为一个纯新手,过程可谓艰辛,一个一维噪声足足啃了我两整天的时间,才悟出一点眉目,说多了都是泪,特写此文献给同我一样的小白,希望可以能够为你们节约一些宝贵的时间。
本人图形学基础为零,若有错误之处请勿喷,欢迎指正。
本文编程基于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;
}