C++ 自分用新手筆記6 : 進階亂數 ii – 程序式生成 、 噪音


雖然標題是C++ 自分用新手筆記,
但實際上內容和C++和亂數並沒有什麼實際聯繫,
主要是我個人在測試與學習噪音(Noise)的一些筆記和心得,
如果再開一個標題可能會太混亂,
因此依舊放在C++ 自分用新手筆記進階亂數裡。
而且由於我實在沒有太多時間寫文章,
內容不會太細節到實務層面,這些部分以後有空再整理。

在上一篇文章裡,
講了兩種基礎的亂數分佈模式,分別是「均勻分佈」和「常態分佈」。
這兩種分佈的亂數已經能在程式設計和遊戲設計上實現不少內容,
但要如何利用這些亂數來實現更加複雜的內容,
例如Minecraft等遊戲的隨機地圖等機制就是一個更複雜的問題。

無論是均勻分佈和常態分佈的亂數都存在一個屬性使它無法生成自然性質的地形,
這屬性就在於亂數與亂數之間並沒有任何關聯性
如果要單純以亂數來形成一個遊戲世界會導致一切的地形極端起伏。
其原因在於有對機率學有基礎了解的人都應該會知道
每一個亂數都是獨立的隨機事件(Events),否則就不算是真正的亂數,
然而這個世界的大多數據卻都是連續的
例如一座山,會有最高的山頂,但也會有坡度較低的山脊,
那山頂、山脊的海拔便會是一系列的連續數,
因此,如果簡單的用亂數是不可能完成一個隨機且複雜的世界。

而為了取得一系列連貫但非人手設計的數據,
我們便需要一個概念名為「程序式生成(Procedural Generation)」。
程序式生成故名思義,用一系列的程序來生成數據,
聽起來很是廢話,但卻是個事實。
先生成一個種子碼,並把這個種子碼加入到一個數學的函式裡,來計算出其他數據。但
要留意的是程序式生成其實與亂數沒什麼直接關係,這一點經常會被誤解,
只要輸入相同的種子碼,必然會出然相同的生成結果,
之所以用進階亂數來作為標題只在於程序式生成經常與亂數一起被使用。

這裡舉個程序式生成簡單的例子,只要中學畢業都能理解的例子,
如果種子碼是一個亂數,我們先定義它的變數名為s,
而使用的函式是f(x) = s + x,
這次抽出來的亂數結果是10,
最終函式便會變成f(x) = 10 + x,
那我們只要輸入1 – 10的x值,我們便可以獲得一個數列 :
11、12、13、14、15、16、17、18、19、20
這一系列的數據很明顯的,相比起我直接生成10個亂數會顯得加更有連貫性
而且也不是被設計好的數列,只要重新再生成一個新的亂數種子碼,便能有不一樣的數列
當然所使用的函式非常簡單,生成出來的數列很容易被猜出後面的結果
因此,一般遊戲裡的程序式生成會用更複雜的函式來生成之後的結果,
而且程序式生成大多數都會同時用x和y來生成二維的數據,也就是每個中學生都一定學過的二元一次方程式。

由一個數字變成無數個數字就是程序式生成。

最重要的是,大多數程序式生成在生成出數據後,
還會再加入各種條件來加工,以得出更多樣性、符合各種使用情境的數據
例如當 f(x) 大於 16 時,所有數據都會被16覆蓋,那我們便會得出。
11、12、13、14、15、16、16161616
這些數據就會從一個斜坡變成一個高地

當然這都只是非常簡單的例子,一般應用在遊戲裡的函式為了避免太容易被玩家猜中,
會用更為複雜的函式,而且因為不是每個開發者都應用數學滿級,能設計出合理又複雜的函式,
因此大多數人都會用其他專業人士設計出來的函式,
而當中的一部分函式能夠生成出幾乎無法被預測的複雜數據,其數據又有如山嶺起伏般自然。
那些函式通常會被叫做「梯度噪聲算法」,或者更常見的名字「噪音(Noise)」。

所謂的噪音就只是一個能得出難以用人腦預測結果、且存在多於一個變數的數學函式,
輸入兩個變數(種子碼 和 x軸)的叫「一維噪音」,
輸入三個變數(種子碼 、 x軸 和 y軸)的叫「二維噪音」,
它就是一個數學函式,數學函式可以應用在各個情境和領域,
不要因為「噪音」這個名字而把它想太複雜,或者太過限定在什麼領域。

噪音界當中最有名的人叫做Ken Perlin,如Perlin NoiseSimplex Noise都是出自他手筆,
在1985年7月1日,Ken Perlin在SIGGRAPH上發佈了一個即時運算圖像合成器的概念1
其用意是為了使3D物件上的貼圖能夠加入真實且隨機的紋路,雖然實際應用上有不少的改進,
但其核心概念至今仍在被不斷應用在各大領域,從此以後Ken Perlin便坐穩了程序式生成式界的教父之位。

而這個原本用在3D貼圖上的生成技術也被應用在其他領域,
從遊戲開發到最近十多年流行的人工智能訓練都會見到它的身影。

接下來再說說一些簡單的使用實例。

<未完待寫>

  1. An image synthesizer – Ken Perlin https://dl.acm.org/doi/10.1145/325165.325247 ↩︎

Published by

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *