柏林噪聲原理

外文鏈接:
http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
翻譯鏈接
http://www.cnblogs.com/Memo/archive/2008/09/08/1286963.html
圖片
Many people have used random number generators in their programs to create unpredictability, make the motion and behavior of objects appear more natural, or generate textures. Random number generators certainly have their uses, but at times their output can be too harsh to appear natural. This article will present a function which has a very wide range of uses, more than I can think of, but basically anywhere where you need something to look natural in origin. What’s more it’s output can easily be tailored to suit your needs.

很多人在他們的程序中使用隨機數生成器去創造不可預測,使物體的行爲和運動表現的更加自然,或者生成紋理。隨機數生成器當然是有他們的用途的,但是它們似乎過於苛刻。這篇文章將會展示一個用途十分廣泛的功能,甚至其用途比我想到的還要廣泛,其結果可以輕易的適合你的需求。

If you look at many things in nature, you will notice that they are fractal. They have various levels of detail. A common example is the outline of a mountain range. It contains large variations in height (the mountains), medium variations (hills), small variations (boulders), tiny variations (stones) … you could go on. Look at almost anything: the distribution of patchy grass on a field, waves in the sea, the movements of an ant, the movement of branches of a tree, patterns in marble, winds. All these phenomena exhibit the same pattern of large and small variations. The Perlin Noise function recreates this by simply adding up noisy functions at a range of different scales.

如果你觀察自然界中很多事物,你會注意到它們是分形的。它們有着很多層次細節。最平常的例子是山峯輪廓。它包含着高度上的很大變化(山峯),中等變化(丘陵),小的變化(礫石),微小變化(石頭)…你可以繼續想象。觀察幾乎所有事物:片狀分佈於田間草,海中的波浪,螞蟻的運動方式,樹枝的運動,大理石的花紋,風。所有這些現象表現出了同一種的大小的變化形式。柏林噪聲函數通過直接添加一定範圍內,不同比例的噪聲函數來重現這種現象。

To create a Perlin noise function, you will need two things, a Noise Function, and an Interpolation Function.

爲了創建一個柏林噪聲函數,我們需要兩個東西,一個噪聲函數和一個插值函數。

Introduction To Noise Functions

噪聲函數介紹

A noise function is essentially a seeded random number generator. It takes an integer as a parameter, and returns a random number based on that parameter. If you pass it the same parameter twice, it produces the same number twice. It is very important that it behaves in this way, otherwise the Perlin function will simply produce nonsense.

一個噪聲函數基本上是一個種子隨機發生器。它需要一個整數作爲參數,然後返回根據這個參數返回一個隨機數。如果你兩次都傳同一個參數進來,它就會產生兩次相同的數。這條規律非常重要,否則柏林函數只是生成一堆垃圾。

Here is a graph showing an example noise function. A random value between 0 and1 is assigned to every
point on the X axis.

這裏的一張圖展現了噪聲函數的一個例子。X軸上每個點被賦予一個0到1之間的隨機數。

By smoothly interpolating between the values, we can define a continuous function that takes a non-integer as a parameter. I will discuss various ways of interpolating the values later in this article.

通過在值之間平滑的插值,我們定義了一個帶有一個非整參數的連續函數。我們將會在後面的內容中討論多種插值方式。

Definitions

定義

Before I go any further, let me define what I mean by amplitude and frequency. If you have studied physics, you may well have come across the concept of amplitude and frequency applied to a sin wave.

當我們準備深入之前,讓我定義下什麼是 振幅 (amplitude) 和 頻率 (frequency) 。如果你學過物理,你可能遇到過在正弦波中振幅(amlitude)和頻率(frequency)的概念。

Sin Wave
The wavelength of a sin wave is the distance from one peak to another. The amplitude is the height of the wave. The frequency is defined to be 1/wavelength.

正弦波
正弦波的波長(wavelength)是兩個波峯只間的距離。振幅是此波的高度。頻率我們定義爲 1/波長(wavelength)。

Noise Wave
In the graph of this example noise function, the red spots indicate the random values defined along the dimension of the function. In this case, the amplitude is the difference between the minimum and maximum values the function could have. The wavelength is the distance from one red spot to the next. Again frequency is defined to be 1/wavelength.

噪聲波
圖中這個噪聲波的例子中,紅點表示定義沿着在函數維上的隨機值。在這種情況下,振幅是這個函數的最大值與最小值的差值。波長(wavelength)是兩個紅點之間的距離。同樣的頻率(frequency)定義爲1/波長(wavelength)。

Creating the Perlin Noise Function

創建柏林噪聲函數

Now, if you take lots of such smooth functions, with various frequencies and amplitudes, you can add them all together to create a nice noisy function. This is the Perlin Noise Function.
現在,如果你使用很多平滑函數,分別擁有各種各樣的頻率和振幅,你可以把他們疊加在一起來創建一個漂亮的噪聲函數。這個就是柏林噪聲函數。

Take the following Noise Functions
使用以下的噪聲函數

Add them together, and this is what you get.
將他們疊加起來,你將會得到:-)

You can see that this function has large, medium and small variations. You may even imagine that it looks a little like a mountain range. In fact many computer generated landscapes are made using this method. Of course they use 2D noise, which I shall get onto in a moment.
你能發現這個函數擁有大的,中的和小的變化。你甚至可以它已經有點像山的輪廓了。事實上很多電腦生成地形景觀也是使用了這種方法,當然那使用的是2D的噪聲,我們將過一下來研究這個。

You can, of course, do the same in 2 dimensions.
你當然同樣的可以在二維下也這麼做。

Some noise functions are created in 2D
一些2D的噪聲函數

Adding all these functions together produces a noisy pattern.
把這些函數疊加起來產生的噪聲樣式。

Persistence

持續度

When you’re adding together these noise functions, you may wonder exactly what amplitude and frequency to use for each one. The one dimensional example above used twice the frequency and half the amplitude for each successive noise function added. This is quite common. So common in fact, that many people don’t even consider using anything else. However, you can create Perlin Noise functions with different characteristics by using other frequencies and amplitudes at each step. For example, to create smooth rolling hills, you could use Perlin noise function with large amplitudes for the low frequencies , and very small amplitudes for the higher frequencies. Or you could make a flat, but very rocky plane choosing low amplitudes for low frequencies.

當你把噪聲函數疊加的時候,你可能想了解每次具體使用了什麼振幅和頻率。上面一維的例子對於每個連續疊加的噪聲函數使用 了兩倍的頻率和二分之一倍的振幅。這個太普通了,事實上太普通,以至於很多人甚至從來都沒有考慮過使用其他什麼。儘管如此,你可以通過在每步使用其他的頻率和振幅來創建不同特徵的柏林噪聲函數。例如,爲了創建一個平滑滾動的丘陵,你可以使用大的振幅和小的頻率的柏林噪聲函數,同時小的振幅和高的頻率,你可以創建一個平地,另外要創建非常顛簸的平面,應該選擇小的振幅和低的頻率。

To make it simpler, and to avoid repeating the words Amplitude and Frequency all the time, a single number is used to specify the amplitude of each frequency. This value is known as Persistence. There is some ambiguity as to it’s exact meaning. The term was originally coined by Mandelbrot, one of the people behind the discovery of fractals. He defined noise with a lot of high frequency as having a low persistence. My friend Matt also came up with the concept of persistence, but defined it the other way round. To be honest, I prefer Matt’s definition. Sorry Mandelbrot. So our definition of persistence is this:

爲了讓這些更簡單易懂,同時爲了避免重複振幅和頻率這兩個詞,我們用一個數來表示每個頻率下的振幅,這個數就是 持續度(Persistence) 。這裏的詞和它的真實意義有些歧異。這個術語原本是Mandelbrot提出的, 他是發現分形現象的人中的一個。他定義噪聲擁有大量的高頻率將體現出低的持續度。我的朋友Matt也想出了持續度的概念,但是是通過另外一種方式定義它 的。誠然,我更喜歡Matt的定義方式。對不起了,Mandelbrot. 所以我們這樣定義持續度(persistence):

frequency = 2i
amplitude = persistencei

Where i is the ith noise function being added. To illustrate the effect of persistence on the output of the Perlin Noise, take a look at the diagrams below. They show the component noise functions that are added, the effect of the persistence value, and the resultant Perlin noise function.

i 是表示第i個被疊加的噪聲函數。爲了展示柏林函數在輸出上持續度的表現效果,請看下下面的圖表。他們展示了疊加的每個組成部分,持續度的效果和最終的柏林函數。

Octaves

倍頻

Each successive noise function you add is known as an octave. The reason for this is that each noise function is twice the frequency of the previous one. In music, octaves also have this property.

每個你所疊加的噪聲函數就是一個倍頻。因爲每一個噪聲函數是上一個的兩倍頻率。在音樂上,倍頻也有着這項屬性。

Exactly how many octaves you add together is entirely up to you. You may add as many or as few as you want. However, let me give you some suggestions. If you are using the perlin noise function to render an image to the screen, there will come a point when an octave has too high a frequency to be displayable. There simply may not be enough pixels on the screen to reproduce all the little details of a very high frequency noise function. Some implementations of Perlin Noise automatically add up as many noise functions they can until the limits of the screen (or other medium) are reached.

具體多少倍頻你疊加在一起,這完全取決於你。你可以疊加很多也可以很少。儘管如此,還是讓我給你一些建議吧。如果你正使用柏林噪聲函數在屏幕上渲染圖象的話,如果倍頻頻率太高將會使縮成一個點以至於不能顯示,這就是因爲你屏幕的分辨率不夠。一些柏林噪聲函數的實現會自動疊加噪聲函數直到達到屏幕分辨率的極限。

It is also wise to stop adding noise functions when their amplitude becomes too small to reproduce. Exactly when that happens depends on the level of persistence, the overall amplitude of the Perlin function and the bit resolution of your screen (or whatever).

當振幅變的很小的時候,也應該明智的停止再疊加噪聲函數。屆時當發生依靠持續度的等級,柏林函數整體的振幅和屏幕的分辨率。

Making your noise functions

創造你的噪聲函數

What do we look for in a noise function? Well, it’s essentially a random number generator. However, unlike other random number generators you may have come across in your programs which give you a different random number every time you call them, these noise functions supply a random number calculated from one or more parameters. I.e. every time you pass the same number to the noise function, it will respond with the same number. But pass it a different number, and it will return a different number.

我們需要什麼樣的噪聲函數?好,基本上就是一個隨機數發生器。儘管如此,它不像你在程序中遇到的那中每次調用它都返回不同的隨機數的隨機函數,這些噪聲函數生成一個隨機數是通過一個或者多個參數計算而來。例如,每次你傳入一個相同的數到噪聲函數裏,它將每次也返回相同的隨機數。但是如果傳入一個不同的數,那麼它又將返回一個不同的數。

Well, I don’t know a lot about random number generators, so I went looking for some, and here’s one I found. It seems to be pretty good. It returns floating point numbers between -1.0 and1.0.

好,我對隨機數生成器並不懂太多,所以我去找了一些,這裏我找到了一個,好象很好用。它返回一個浮點數,範圍是-1.0到1.0

function IntNoise(32-bit integer: x)
x = (x<<13) ^ x;
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end IntNoise function

Now, you’ll want several different random number generators, so I suggest making several copies of the above code, but use slightly different numbers. Those big scarey looking numbers are all prime numbers, so you could just use some other prime numbers of a similar size. So, to make it easy for you to find random numbers, I have written a little program to list prime numbers for you. You can give it a start number and an end number, and it will find all the primes between the two. Source code is also included, so you can easily include it into your own programs to produce a random prime number. Primes.zip

現在,你將要需要幾個不同的隨機數生成器,所以我建議把上面的代碼複製幾個拷貝,然後稍微修改下里面的參數。那些可怕的數字都是質數,所以你可以改成其他差不多大小的質數(讓我想起了 hash key生成),爲了讓你輕鬆的找的隨機數,我已經寫了一個小程序來爲你列出質數。你只用輸入一個起始值和一個結束值,它找到所有在兩值之間的質數。源代碼也提供,所以你可以輕鬆的包含到你自己的程序中來生成隨機的質數。

Interpolation

插值

Having created your noise function, you will need to smooth out the values it returns. Again, you can choose any method you like, but some look better than others. A standard interpolation function takes three inputs, a and b, the values to be interpolated between, and x which takes a value between 0 and1. The Interpolation function returns a value between a and b based on the value x. When x equals 0, it returns a, and when x is 1, it returns b. When x is between 0 and1, it returns some value between a and b.

當創建了你的噪聲函數,你將需要平滑下他的返回值。再次,你可以選擇任何你喜歡的方式, 但是有一些效果更好。一個標準的插值函數需要三個輸入,a 和 b, 需要在a和b之間進行插值,還有x,它取值範圍是0到1。插值函數返回a到b之間取決與x的一個值。當x等於0,它返回a,當x等於1時,它返回b。當x 是0到1之間時,它將返回a到b之間的某值。

Linear Interpolation:

線性插值

Looks awful, like those cheap ‘plasmas’ that everyone uses to generate landscapes. It’s a simple algorithm though, and I suppose would be excusable if you were trying to do perlin noise in realtime.

看起來很齷齪的,像那些每個人用來生成地形的廉價’plasmas’一樣,它是一個簡單的算法,如果你想實時的使用柏林噪聲函數,這種插值方式是一個選擇。

function Linear_Interpolate(a, b, x)
return a*(1-x) + b*x
end of function

Cosine Interpolation:

餘弦插值

This method gives a much smother curve than Linear Interpolation. It’s clearly better and worth the effort if you can afford the very slight loss in speed.

這個方法線性插值生成了更平滑的曲線。它當然有着更好的效果,如果你願意稍微損失點速度的話。

function Cosine_Interpolate(a, b, x)
ft = x * 3.1415927
f = (1 - cos(ft)) * .5
return a*(1-f) + b*f
end of function

Cubic Interpolation:
立方插值

This method gives very smooth results indeed, but you pay for it in speed. To be quite honest, I’m not sure if it would give noticeably better results than Cosine Interpolation, but here it is anyway if you want it. It’s a little more complicated, so pay attention. Whereas before, the interpolation functions took three inputs, the cubic interpolation takes five. Instead of just a and b, you now need v0, v1, v2 and v3, along with x as before.

這個方法的確是生成了非常平滑的結果,但是你付出的代價就是速度。老實說,我不那麼確定它能給你比餘弦插值好很多的效果,但是如果你無論如何要使用它的話,它有一點點的複雜,所以這裏請注意,之前,插值函數只需要三個參數,但是立方插值需要五個,取代了a和b,現在你需 要v0,v1,v2,v3,x和以前一樣也需要。

這些是:
v0 = a 前面一點
v1 = a 點
v2 = b 點
v3 = b 後面一點

function Cubic_Interpolate(v0, v1, v2, v3,x)
P = (v3 - v2) - (v0 - v1)
Q = (v0 - v1) - P
R = v2 - v0
S = v1
return Px3 + Qx2 + Rx + S
end of function

Smoothed Noise

平滑的噪聲

Aside from Interplolation, you can also smooth the output of the noise function to make it less random looking, and also less square in the 2D and 3D versions. Smoothing is done much as you would expect, and anyone who has written an image smoothing filter, or fire algorithm should already be familiar with the process.
Rather than simply taking the value of the noise function at a single coordinate, you can take the average of that value, and it’s neighbouring values. If this is unclear, take a look at the pseudo code below.

除了插值,你也可以平滑噪聲函數的輸出來使它看起來不那麼隨機,和讓2D和3D的版本少一點方塊。平滑的結果和你所想的差不多,只要是寫過平滑過濾或者火焰算法的人都應該相當熟悉此過程。相比在一個單獨的座標上取得噪聲值,你可以取平均的噪聲值,和它臨近的值。如果你不清楚這個,可以看看下面的僞代碼。

On the right, you can see a little diagram illustrating the difference between smoothed noise, and the same noise function without smoothing. You can see that the smooth noise is flatter, never reaching the extremes of unsmoothed noise, and the frequency appears to be roughly half. There is little point smoothing 1 dimensional noise, since these are really the only effects. Smoothing becomes more useful in 2 or three dimensions, where the effect is to reduce the squareness of the noise. Unfortunately it also reduces the contrast a little. The smoother you make it, obviously, the flatterthe noise will be.

在右面(這裏看下面),你可以看見一個小的圖展示了不同平滑函數的區別,和同樣的一個噪聲但未進行平滑處理。你可以看見平滑函數,從來都沒有到底那個未平滑函數的極限值,並且頻率顯得只有大 約一半。那裏有小點平滑一維的噪聲,只有這一個效果。平滑過程在二維和三維中,顯得更有用處,那就是它減少了噪聲大方塊。不幸的是它也降低了一點對比度。 你讓它越平滑,這個噪聲就會越平坦。

1-dimensional Smooth Noise
一維噪聲函數
function Noise(x)
.
.
end function

function SmoothNoise_1D(x)
return Noise(x)/2 + Noise(x-1)/4 + Noise(x+1)/4
end function

2-dimensional Smooth Noise
二維噪聲函數
function Noise(x, y)
.
.
end function

function SmoothNoise_2D(x>, y)
corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16
sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8
center = Noise(x, y) / 4
return corners + sides + center
end function

Putting it all together

把它們組合在一起

Now that you know all that, it’s time to put together all you’ve learned and create a Perlin Noise function. Remember that it’s just several Interpolated Noise functions added together. So Perlin Noise it just a function. You pass it one or more parameters, and it responds with a number. So, here’s a simple 1 dimensional Perlin function.

發佈了76 篇原創文章 · 獲贊 23 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章