にわとりになる日まで

ひよこな大学生のブログ

Perlinノイズで地形生成

はじめに

この記事は Aizu Advent Calendar の15日目の記事です。
14日目
15日目

ソースコードここにあります
今回は実装の説明よりはアルゴリズムの説明を中心にするのでソースコードの説明はありません。
要望があったら書くかもしれないです。

Perlinノイズとは

Wikipediaによると

パーリンノイズ(英: Perlin noise)とは、コンピュータグラフィックスのリアリティを増すために使われるテクスチャ作成技法。擬似乱数的な見た目であるが、同時に細部のスケール感が一定である。このため制御が容易であり、各種スケールのパーリンノイズを数式に入力することで多彩なテクスチャを表現できる。パーリンノイズによるテクスチャは、CGIで自然な外観を物に与えるためによく使われる。 Ken Perlin が Mathematical Applications Group, Inc. で勤務しているときに開発した。彼はこの業績により、1997年、映画芸術科学アカデミーからアカデミー科学技術賞(Technical Achivement)を受賞した。
Wikipedia

らしいです。
簡単に言うといい感じにできるノイズです。
画像だとこんな感じ
f:id:uzimaru0601:20171122011503p:plain

このノイズを使ってHightマップを作って地形を作ろうという魂胆です。

実はこのノイズ、1から作ろうとすると結構面倒なのですがUnityでは標準の数学クラス(Mathfクラス)のメソッドとして定義されてます!!
だから、すぐに地形が作れちゃう!!やったね!!Unity最高!!アドベントカレンダー終わり!!









っという訳にはいかないのでいろいろ工夫してみます。

ちょっと工夫してみる

これだけだとノイズが均一で地形っぽくないので何個かノイズを重ねてみます。 その際、重ね合わせるノイズのスケールを大きく・振れ幅を小さくしていきます。

  • 3回重ね合わせる
    f:id:uzimaru0601:20171203023328p:plain + f:id:uzimaru0601:20171203023331p:plain + f:id:uzimaru0601:20171203023334p:plain = f:id:uzimaru0601:20171122011505p:plain
  • 5回重ね合わせる
    f:id:uzimaru0601:20171203023328p:plain + f:id:uzimaru0601:20171203023331p:plain + f:id:uzimaru0601:20171203023334p:plain + f:id:uzimaru0601:20171203023337p:plain + f:id:uzimaru0601:20171203023340p:plain = f:id:uzimaru0601:20171122011832p:plain

いいかんじになった!

もう少し工夫してみる

マスクを書けて見ます

  • 矩形のマスク
    f:id:uzimaru0601:20171122011832p:plain * f:id:uzimaru0601:20171122011508p:plain = f:id:uzimaru0601:20171122011458p:plain
  • 円形のマスク
    f:id:uzimaru0601:20171122011832p:plain * f:id:uzimaru0601:20171122011435p:plain = f:id:uzimaru0601:20171122011450p:plain

もうちょっとだけ工夫してみる

今の感じだと

  • 低い部分はなだらかにしたい!
  • 高い部分は勾配を急にしたい!

と言ったような細かい調整が難しいです。
そこでUnityのAnimationCurvesを使ってうまく調整ができるようにします。
f:id:uzimaru0601:20171122011532p:plain

上の曲線を適応すると f:id:uzimaru0601:20171122011458p:plainf:id:uzimaru0601:20171122011447p:plain になります

HightマップをTerrainで表示してみる

これで地形を作る準備ができたので作ったノイズ(Hightマップ)をTerrainで表示してみます。
今回は8回重ね合わせたノイズ
f:id:uzimaru0601:20171203024032p:plain

f:id:uzimaru0601:20171124123438p:plain
のマスクをかけたHightマップ
f:id:uzimaru0601:20171124123441p:plain
を使って見ます。
これを使うと・・・

f:id:uzimaru0601:20171124123457p:plain





なんか想像してたのと違う・・・

問題はTerrainの最高の高さが高すぎること
今回作ったHightマップは最低が0、最高が1になるため1の地点がTerrainの最高の高さになってしまいます。(デフォルトだと600m)
なので、いい感じの高さに最高値を変更してあげます。(今回は100mにしました)
f:id:uzimaru0601:20171124123459p:plain

それっぽいのでは!?

テクスチャをつける

このままだと真っ白で地形感がないのでテクスチャをつけていきます。
Hightマップの0 ~ 0.2の範囲では草を生やして
0.2 ~ 0.5の範囲では岩と草が混じった感じのテクスチャにして
0.5 ~ 1.0の範囲では岩のテクスチャにします。
そうするとこんな感じ
f:id:uzimaru0601:20171124123502p:plain
だんだん地形っぽくなってきた!!

テクスチャをブレンドする

いまのままだと画像
f:id:uzimaru0601:20171203044545p:plain
のようにテクスチャとテクスチャの境界がキッパリと別れていて自然じゃないです・・・
そこである一定比率で徐々に次のテクスチャに移るようにしてみます。
また、勾配に応じて次のテクスチャをブレンドしてみます。
そうするとこんな感じになります。
f:id:uzimaru0601:20171203044957p:plain
だいぶ自然な感じのテクスチャになったと思います!

さいごに

f:id:uzimaru0601:20171203050023p:plain
これで完成です!!
ただ、近づいて見ると
f:id:uzimaru0601:20171203045110p:plain
画像のようにぜんぜん自然じゃない部分があります・・・
このままだと流石に使えないと思うので
自動生成 ⇒ 手を加える
と言った感じにすれば良いのかなって思います(デザイナーではないので0から地形を作るセンスがないです。。。)

今後の課題はこういう部分をどうするか、川を作ってみる、街を作ってみる、etc...
山のように課題はありますね・・・
もう少し頑張って見ます。

参考