惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
V
V2EX
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Announcements
Recent Announcements
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Latest news
Latest news
Vercel News
Vercel News
The Register - Security
The Register - Security
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
小众软件
小众软件
L
Lohrmann on Cybersecurity
GbyAI
GbyAI
P
Privacy & Cybersecurity Law Blog
T
Tor Project blog
AWS News Blog
AWS News Blog
美团技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
K
Kaspersky official blog
B
Blog RSS Feed
G
Google Developers Blog
量子位
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
Intezer
雷峰网
雷峰网
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
IT之家
IT之家
F
Full Disclosure
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
The Hacker News
The Hacker News
U
Unit 42
S
SegmentFault 最新的问题
I
InfoQ
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
罗磊的独立博客
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes

博客园 - 任程

运动捕捉数据的行为分割 主元分析(PCA)在计算机图形学中的应用 本博客代码公布(本文会不断更新) 机器人逆动力学(Robot Inverse Dynamics) 刚体动力学(Rigid Body Dynamics) Flock of Birds——总结使用过的虚拟现实设备之二(A Brief Summary of Several VR Devices) 多通道软件同步——代码设计 多通道的同步问题 《自己实现EarthSculptor的Splatting地形》的源代码 Interesting story about DI-Guy 利用billboard实现云的仿真 OST试验版 透视校正插值(Perspective-Correct Interpolation) Ogre中在SceneNode节点旁显示二维字的代码 虚拟现实现状——设备篇(译:State of VR-Devices) 多线程中Sleep函数的调用 用WiiRemote进行头部跟踪(Head Tracking for Desktop VR Displays using the WiiRemote) 分析碰撞检测库Opcode 用NVPerfHUD来分析3D程序
Perlin噪声
任程 · 2008-02-21 · via 博客园 - 任程

本文资源来自libnoise网站和GPU Gems一书。

一.什么是Coherent noise

Coherent noise由coherent noise函数生成,具备三个特点:

1)        相同的输入总得到相同的输出

2)        输入的小变化引起输出的小变化

3)        输入的大幅变化引起输出的随机变化


coherent-noise函数输出


non-coherent-noise函数输出

如何生成Coherent noise将会在第四部分给出。

二.什么是Perlin Noise

Perlin Noise是几个Coherent noise的叠加,这几个coherent noise间的关系是:频率递增,振幅递减。

下图中为f为频率,a为振幅。


以上几个噪声的和就组成了Perlin噪声:


Ken Perlin1983年发明Perlin噪声,1985年发表相应文章。

三.Perlin噪声中的各个术语

1.         Octave

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

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

2.         振幅Amplitude

每个Coherent noise函数所能输出的最大值,在有名的libnoise库中振幅为n的函数输出范围为-n~n

3.         频率Frequency

单位长度内Coherent noise函数循环的次数,每次循环的起点函数输出为0

4.         Lacunarity

两个连续octave间频率frequency递增的速度的度量。

当前octave的频率f * lacunarity = 下一个octave的频率f1

5.         Persistence

两个连续octave间振幅amplitude递增的速度的度量。

当前octave的振幅A * Persistence = 下一个octave的振幅A1

6.         Seed

用于改变Coherent noise函数的输出。改变Seed值,则Coherent noise函数的输出改变。

四.如何生成Coherent noise

Perlin噪声由Coherent noise叠加生成,那么只要知道了如何生成Coherent noise ,就能生成Perlin噪声了。下面将逐步说明。

1.         Integer-noise函数

给定一个整数作为输入,则一维Integer-noise函数输出一个伪随机浮点数(通常在-11之间)。NInteger-noise函数需要n个整数作为输入,输出仍是一个伪随机浮点数(通常在-1-1之间)。


下面是一个这样的函数:

double IntegerNoise (int n)

{

 n = (n >> 13) ^ n;

 int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;

 return 1.0 - ((double)nn / 1073741824.0);

}

2.         Interger-noise间进行插值

线形插值linear interpolation: lerp(a, b, w) = a * (1 - w) + b * w权重值w01之间。

函数如下:

double CoherentNoise (double x)

{

 int intX = (int)(floor (x));

 double n0 = IntegerNoise (intX);

 double n1 = IntegerNoise (intX + 1);

 double weight = x - floor (x);

 double noise = lerp (n0, n1, weight);

 return noise;

}

二维函数用双线性插值bilinear interpolation,三维函数用三线性插值trilinear interpolation

下图是一维插值后的输出:


二维输出:


线性插值的缺点在于生成的纹理有creasing瑕疵,也就是说界线太明显,图像不自然。在生成凹凸纹理时尤其明显,如下图:


3.         在线性插值的基础上进一步改进

线性插值的方法保证了插值函数的输出在插值点上取得了正确的结果,但不能保证插值函数在插值点上的导数值。

利用Hermit插值可以在保证函数输出的基础上保证插值函数的导数在插值点上为0,这样就提供了平滑性。

插值点为01,结果值为01,导数为00,则可以求得Hermit插值函数为s(x) = -2x3 + 3x2 也就是所谓的S曲线函数。

用立方插值(S曲线插值)代替线性插之后的代码为:

double CoherentNoise (double x)

{

 int intX = (int)(floor (x));

 double n0 = IntegerNoise (intX);

 double n1 = IntegerNoise (intX + 1);

 double weight = x - floor (x);

 // double noise = lerp (n0, n1, weight);

 double noise = lerp (n0, n1, SCurve (weight));

 return noise;

}

如果再使插值函数的二阶导数值在插值点处为0,则可以进一步平滑。五次插值函数:s(x) = 6x5 - 15x4 + 10x3

      

           五次插值                              三次插值                                线性插值

ps:libnoise开源库可以生成Perlin noise。