Perlinノイズで地形生成
はじめに
この記事は Aizu Advent Calendar の15日目の記事です。
14日目
15日目
ソースコードはここにあります
今回は実装の説明よりはアルゴリズムの説明を中心にするのでソースコードの説明はありません。
要望があったら書くかもしれないです。
Perlinノイズとは
Wikipediaによると
パーリンノイズ(英: Perlin noise)とは、コンピュータグラフィックスのリアリティを増すために使われるテクスチャ作成技法。擬似乱数的な見た目であるが、同時に細部のスケール感が一定である。このため制御が容易であり、各種スケールのパーリンノイズを数式に入力することで多彩なテクスチャを表現できる。パーリンノイズによるテクスチャは、CGIで自然な外観を物に与えるためによく使われる。 Ken Perlin が Mathematical Applications Group, Inc. で勤務しているときに開発した。彼はこの業績により、1997年、映画芸術科学アカデミーからアカデミー科学技術賞(Technical Achivement)を受賞した。
Wikipedia
らしいです。
簡単に言うといい感じ
にできるノイズです。
画像だとこんな感じ
このノイズを使ってHightマップを作って地形を作ろうという魂胆です。
実はこのノイズ、1から作ろうとすると結構面倒なのですがUnityでは標準の数学クラス(Mathfクラス)のメソッドとして定義されてます!!
だから、すぐに地形が作れちゃう!!やったね!!Unity最高!!アドベントカレンダー終わり!!
っという訳にはいかないのでいろいろ工夫してみます。
ちょっと工夫してみる
これだけだとノイズが均一で地形っぽくないので何個かノイズを重ねてみます。 その際、重ね合わせるノイズのスケールを大きく・振れ幅を小さくしていきます。
- 3回重ね合わせる
+ + = - 5回重ね合わせる
+ + + + =
いいかんじになった!
もう少し工夫してみる
マスクを書けて見ます
- 矩形のマスク
* = - 円形のマスク
* =
もうちょっとだけ工夫してみる
今の感じだと
- 低い部分はなだらかにしたい!
- 高い部分は勾配を急にしたい!
と言ったような細かい調整が難しいです。
そこでUnityのAnimationCurvesを使ってうまく調整ができるようにします。
上の曲線を適応すると が になります
HightマップをTerrainで表示してみる
これで地形を作る準備ができたので作ったノイズ(Hightマップ)をTerrainで表示してみます。
今回は8回重ね合わせたノイズ
に
のマスクをかけたHightマップ
を使って見ます。
これを使うと・・・
なんか想像してたのと違う・・・
問題はTerrainの最高の高さが高すぎること
今回作ったHightマップは最低が0、最高が1になるため1の地点がTerrainの最高の高さになってしまいます。(デフォルトだと600m)
なので、いい感じの高さに最高値を変更してあげます。(今回は100mにしました)
それっぽいのでは!?
テクスチャをつける
このままだと真っ白で地形感がないのでテクスチャをつけていきます。
Hightマップの0 ~ 0.2の範囲では草を生やして
0.2 ~ 0.5の範囲では岩と草が混じった感じのテクスチャにして
0.5 ~ 1.0の範囲では岩のテクスチャにします。
そうするとこんな感じ
だんだん地形っぽくなってきた!!
テクスチャをブレンドする
いまのままだと画像
のようにテクスチャとテクスチャの境界がキッパリと別れていて自然じゃないです・・・
そこである一定比率で徐々に次のテクスチャに移るようにしてみます。
また、勾配に応じて次のテクスチャをブレンドしてみます。
そうするとこんな感じになります。
だいぶ自然な感じのテクスチャになったと思います!
さいごに
これで完成です!!
ただ、近づいて見ると
画像のようにぜんぜん自然じゃない部分があります・・・
このままだと流石に使えないと思うので
自動生成 ⇒ 手を加える
と言った感じにすれば良いのかなって思います(デザイナーではないので0から地形を作るセンスがないです。。。)
今後の課題はこういう部分をどうするか、川を作ってみる、街を作ってみる、etc...
山のように課題はありますね・・・
もう少し頑張って見ます。
参考
- Procedural Landmass Generation (E01: Introduction) - YouTube:21本の動画でプロシージャルな地形生成の説明・実装をしてる動画です。英語ですがとても参考になりました。
- ランダム地形生成 Part2~フラクタルブラウン運動 - Qiita:具体的な実装の参考になりました。