首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > perl python >

3D数学之柏林噪音(Perlin Noise)

2013-10-08 
3D数学之柏林噪声(Perlin Noise)经过四天的努力,终于自己实现了3D柏林噪声,当第一次用它成功渲染出茶壶的

3D数学之柏林噪声(Perlin Noise)

经过四天的努力,终于自己实现了3D柏林噪声,当第一次用它成功渲染出茶壶的时候,感觉自己跟《当幸福来敲门》的男主角chris一样,当时不由自主为自己鼓起了掌.

3D数学之柏林噪音(Perlin Noise)

3D数学之柏林噪音(Perlin Noise)


4天时间啊,这4天时间基本上没有背单词,白天一个人去教室面对冰冷的代码.晚上回寝室熬夜到2,3点,到处在网上找资料,找源码,但是当自己把茶壶渲染出来的时候,突然觉得这一切都是值得的,因为它那斑驳的颜色温暖了我的心!!!

3D数学之柏林噪音(Perlin Noise)

好了,转入正题.


其实它的原理并不是很难,但是由于网上实现的版本太多太杂,真要实现起来竟然不知从何处下手,而且自己写的时候会遇到各种各样的问题.最终写出来了,所以很欣然.


先看下,我在网上找的一些资料吧


3D数学之柏林噪音(Perlin Noise)

另外我还下载了libnoise源码,可以说这个是我能成功渲染出茶壶的关键.后面我会提到.


好了,这里我只讲1到3D的柏林噪声,4D的我没有实现,实在没有时间,不能在这个环节浪费太多了时间,因为项目里面只用到了2D的柏林噪声来渲染海面.


由于网上理论资料也很详细,我这里主要讲解实现过程中需要注意的地方.


先简单提一下理论,

Perlin噪声由多个coherent noise组成,每一个coherent noise称为一个octave.

octave越多,Perlin噪声就越细致,但计算时间也越长。

具体理论知识见

http://blog.sina.com.cn/s/blog_68f6e8a901013t7d.html

http://www.cnblogs.com/babyrender/archive/2008/10/27/BabyRender.html


coherent 噪声函数

输入为对应维数的向量(对于一维来说就是一个float,对于二维来说就是一个float[2],以此类推)

输出为[-1,1]的float

现在拿一维来举例,首选我们需要在值为整数的点为其生成随机的梯度(1维下是斜率),然后找出输入的float数f左边和右边的两个整数x0,x1,然后找到x0,x1到的梯度g0,g1,算出点f到点x0和x1的向量r0 = f - x0, r1 = f - x1 =  r0 - 1,最后分别将两个整数点的梯度与f到这两个整数点的向量相乘,得到u,v两个值,最后需要通过r0算出混合权值h,公式为

h = s_curve_new(r0),最后得到范围在[-1,1]的随机数 u + h * (v - u)


#define s_curve(t) ( t * t * (3. - 2. * t) ) //即3t^2 - 2t^3 ,旧版本
#define s_curve_new(t) ( t * t * t * (t * (t * 6 - 15) + 10) )  //即 6t^5 - 15t^4 + 10t^3,新版本



好了,下面就一个版本一个版本的讲吧


首先是两个官方版本:

http://mrl.nyu.edu/~perlin/noise

第一个版本,只实现了3D的coherent noise

下面是我自己的代码




这个结果表面看上去能接受,但是要拿来真正渲染的时候就会出问题,所以我们需要对输入的数据进行处理,后面我会讲


第二个版本比较详细,实现了1到3D的noise

http://mrl.nyu.edu/~perlin/doc/oscar.html


下面我的代码



看了一下输出结果,不是太理想,绝对值超过0.5的数几乎没有.哎,官方版本也坑啊!!!!!!尽管如此,我的茶壶例子还是基本这个版本的3D noise写的,谁叫它是官方版本呢,



但是我看了下libnoise的输出,0.6,0.7都很常见,以后估计我会用libnoise这个库



另外,我根据<<三维游戏引擎设计技术及其应用>>这本书的提示生成了一个2D Perlin noise渲染了上面Displacement mapping讲过的海洋,只不过这里的移位贴图是我们通过2D Perlin noise生成的,不是预先设定的,虽然版本有点山寨,但是效果还是可以接受


它的倍频的采样方法有点特别,最低倍频,波长最长,振幅最大,如果我们需要生成129*129的2D图(它的方法最好采用2^n + 1的大小的图),最低倍频,我们设波长为32,那么我们就分别

在0,32,64,96,128处进行采样(也就是生成0到振幅的随机数),然后中间的进行以这些点进行插值,当为2倍频时,周期减少一倍为16,则在,0,16,32,48,64,80,96,112,128处进行采样,然后进行插值,注意采样时这里振幅也会减少一倍.后面的依次类推,最后将它们全部累加得到的就是2D的perlin noise


用这个版本渲染的海洋

3D数学之柏林噪音(Perlin Noise)


用这个版本生成的海洋以及对应的位移贴图,颜色越白,海面越高

3D数学之柏林噪音(Perlin Noise)


用这个版本生成 的2D Perlin noise(即移位贴图,只不过是两张Perlin noise按照某一权值比重进行累加后的结果)

3D数学之柏林噪音(Perlin Noise)


下面给出这个DEMO的源代码





最后,说下4D perlin noise虽然我没有去实现,但是它还是有它的作用的,因为多出来的一维可以作成时间的维数,这样,你的3D纹理就可以动态变化了,

同时,3D perlin noise也可以当作动态的2D perlin noise纹理.呵呵,大功造成,perlin noise就告一段落吧,下一阶段目标是projected grid,好了今天晚上就不找资料,太累了,睡觉了.明天继续我的伟大航程3D数学之柏林噪音(Perlin Noise)





热点排行