手続き的に生成された巨大な「荒野」の世界


76

ドワーフ要塞のようなゲームはご存知だと思います-大規模で手続き型に生成された荒野と土地。この非常に有用な記事から取られたこのようなもの

しかし、これをもっと大規模にどのように適用できるのか疑問に思っていました。Minecraftの規模が思い浮かびます(これは地球の表面の8倍の大きさではありませんか?)。擬似無限、最良の用語は次のとおりだと思います。

:D

この記事では、フラクタルパーリンノイズについて説明しています。私はそれに関する専門家ではありませんが、一般的なアイデアを得ることができます(それは、ランダムなピクセル値だけでなく、ある程度コヒーレントなランダムに生成されたノイズの一種です)。

リージョンXごとにサイズを定義し、リージョンをロードするタイプのものを追加し、1ビットのノイズでリージョンを生成できます。しかし、これは膨大な量の島になります。

もう一方の極端な例では、パーリンノイズの超巨大シートを実際に生成できるとは思いません。そして、それはただ一つの大きな島になると思います。

Perlinノイズ、または何らかのノイズが何らかの方法で答えになると確信しています。つまり、地図は本当に見栄えがいいです。そして、アスキーをタイルに置き換えて、見栄えの良いものを手に入れることができます。


9
「結果として膨大な量の島ができます」-または、土地/水を交換するだけで、湖を含む土地が生成されます。

3
それでも、かなり標準的なパターンで大量の湖を手に入れることになります。
共産主義のダック

3
@Kylotan:Mincraftのサイズは無限です(実際にはそうではありませんが、本当に大きいのです...合計ボリューム= long.MaxValue x 128 x long.MaxValue)。したがって、1回のショットで全世界を生成することも、マップ全体をメモリに保存することもありません。16x128x16ブロックの領域がまだアクセスされていない場合、非同期でディスクからロードします。
zfedoran

2
@The Communist Duck:はい、他のバイトは、後で再計算できる照明やその他のデータを表します)。ここで興味深いのは、RLEを使用して、前述のようにブロックがある程度一貫しているため、格納されたサイズを数バイトまで大幅に減らすことができることです。
zfedoran

4
「本当に大きい」とは無限と同じではなく、2つの用語を同じ意味で使用することはできません。マップが発見されたときにマップを拡大すると、それは要求に応じて拡大する有限サイズであり、無限であることとはまったく異なる命題です。成長の各ビットは、必要に応じて生成できます。Minecraftの地形データは、データ間に高度な一貫性があるため、些細な圧縮に非常に適しています。(たとえば、前述のRLE。)
Kylotan

回答:


35

私はあなたが今何を求めているかをよく理解していると思います。

ノイズはランダムではありません-ランダムに見えますが、数式に完全に基づいており、繰り返し可能です。すべての情報は式にエンコードされます。これは、無限の領域を潜在的にカバーする数式を作成し、必要な領域の座標で数式を使用できることを意味します。隣接する領域が必要な場合、新しい座標で数式を再利用するだけで、数式は連続した値を生成するため、エリアはシームレスに結合されます。

高さの生成にperlinノイズの代わりに正弦波を使用し、X軸では世界を無限に想像しますが、Y軸とZ軸では1ユニットのみの単純な例を示します。

式は次のとおりです。 height(x,y) = sin(x/20)

ゲームが開始され、近くのエリアの高さが生成されます。(0,0)から(9,0):

[0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.34, 0.39, 0.43]

丘があり、右に向かって上昇しています。最後まで歩いて、(10,0から19,0)の値を生成する必要があるとします。

[0.48, 0.52, 0.56, 0.61, 0.64, 0.68, 0.72, 0.75, 0.78, 0.81]

丘が着実に上昇し続け、(10,0)の値が(9,0)の値から順調に続くことに注意してください。これは、正弦関数が連続的であるためです。つまり、基本的に、2つの隣接する数値を入力すると、2つの隣接する結果が出力されます(隣接の特定の定義に対して)。したがって、ワールド座標を使用して、ワールドを定義する関数のパラメーターとして使用すると、一度にどれだけ生成しても、または生成しても、一緒に収まる連続したランドスケープが得られます。新しいパーツを生成すると、高さがすでに事前に決定されているため、既存のパーツから自動的に流れ出します。

世界が変更されない場合、数式から特定のポイントの高さを正確に計算できるため、何も保存する必要さえありません。Minecraftのようなものでは、明らかに世界は完全に変形可能であるため、作成時に各チャンクを保存するだけです。隣接するチャンク間に高度のコヒーレンスがある場合(つまり、1つのブロックが草である場合、その隣のブロックも草である可能性が高い)、データを非常に効率的に圧縮できます-ランレングスエンコーディングが機能しますしかし、そうであれば、ほとんどすべての標準的な圧縮アルゴリズムがそうなります。

高さを最も明白な値として説明しましたが、同じシステムを使用して必要な特性を生成できます。連続的なプロパティを使用して、入力がワールド座標である数学関数を使用します。これにより、ランドマーク、鉱床、スポーンポイントなどの存在を自由に決定できます。(明らかに、ある式の値は別の式に影響する可能性があります-空中に石炭鉱床を配置するポイントがないため、世界の高さマップを生成し、地下から十分に離れているブロックの石炭の可能性のみを計算します)


あなたは間違いなく物事を片付けるのを手伝ってくれました、ありがとう。:)しかし、ノイズ関数のようなものは連続的ではありません。そして、AFAICS、もしそれが継続的であれば、私は「ランダムな」世界を受け取らないでしょう。または、私はここで何かが欠けていますか?
共産主義のダック

二重コメントで申し訳ありませんが、上記はこれとは別に感じます。「パーリンノイズにワールド座標を使用する」と言うとき、これはノイズの「巨大な」シートを生成するのと同じ種類の効果でしょうか?今日の取り込みが少し遅いと感じています。
共産主義のダック

まあ、あなたのノイズ生成は確かに連続的である可能性があり、通常はそれを滑らかにするためです。境界を越えて滑らかにするために、境界を少し読む必要があるかもしれませんが、原理は同じままです。問題のノイズが擬似ランダムデータを必要とする場合、既知の量から生成します。世界座標のハッシュ。出力は予測可能です。
キロタン

2
ランダム性に関しては、各ワールドは計算に使用される独自のシード値を持つことができます。例えば。上記の例では、sin(x)の代わりにsin(x + seed)。それぞれ異なるシードは、異なる世界を生成します。そして、巨大なシートについて...それがどのような関連性を持っているのか分かりません。生成する量や量、または生成するタイミングは関係ありません。世界の初期状態は数式によって定義されており、その数式を使用して、必要なときにいつでもその状態を発見できます。
キロタン

32

私が何年も前に書いたこのチュートリアルは、あなたが望むもののようなものをあなたに与えるかもしれません:

代替テキスト

最後のステップで島の修正を行うと、マップの端に到達しない単一の陸地に向かう傾向があります。


7
素晴らしい視覚化!
zfedoran

3
自然現象のシミュレーションに関する修士論文を作成するときに、このチュートリアルを使用したことを覚えています。「丘」の例を使用して、3Dワールド上にスカイドームを作成しました。地形生成の概念の優れた紹介。
C.McAtackney

1
クレイジー、それは素晴らしい!私は誰も実際にそれを使用したことを知りませんでした。
10

1
ああ、神様 !!!私もこれを以前のプロジェクトで使用しました...今まで出会った中で最も簡単な地形生成方法!!!
戦争

15

大きな島を作成するために、一度にすべてを生成する必要はありません。訪問するときに非同期にリージョンを構築します。

記事で説明されているようにマスクを使用して島を作成する代わりに、パーリンノイズオクターブ波長を使用して目的の外観を実現できます。通常、最初のオクターブは地形の一般的な形状を表します。それ以降のすべてのオクターブは、より細かい粒子の詳細を追加するだけです。したがって、最初のオクターブの波長で遊んで、陸塊の大きさを制御してください。陸地を中心に配置する場合は、中心から遠ざかるにつれて高さマップを小さくするだけでノイズを正規化できます。たとえば、これら2つを組み合わせて島を作成することを想像してください。

最初のオクターブ 詳細

この記事は役立つはずです:http : //freespace.virgin.net/hugo.elias/models/m_perlin.htm

無限の3Dの世界や、ノイズの入出力で遊んで地形の外観を変更するために使用できるさまざまなトリックについて学びたい場合は、この記事をご覧くださいhttp : //http.developer.nvidia.com /GPUGems3/gpugems3_ch01.html

グラフィックパイプラインとシェーダープログラミングに精通していない場合、少し読みにくいかもしれません。


私が達成したいのは、Minecraftのマップの2Dトップダウン(ゲームではない)のようなものです...使用するオクターブが少ない場合でも、パーリンノイズの大きなシートを生成する必要はありませんか?それとも、どういうわけか、それを非常に少量だけ生成できますか?
共産主義のダック

パーリンノイズがどのように機能するかについて、まだ少し混乱していると思います。関数にperlinノイズのxおよびy座標オフセットを送信することにより、16x16ブロックのチャンクを個別に生成できます。PerlinNoise_2D(float x、float y)関数がx座標とy座標をどのように取り込むかに注意してください。言い換えると、ある(x、y)位置に対してノイズを生成します。また、生成されるオクターブが少ないことは、オクターブの波長を変更することと同じではありません。オクターブが少ない=>細かい粒子のディテールが少ない。より長い波長=>よりズームイン。
zfedoran10年

また、ズーム/より長い波長を実装する方法を示すコードを含む記事があります:dreamincode.net/forums/topic/66480-perlin-noise
zfedoran


7

パーリンノイズと友人は良い出発点ですが、おそらくそれをさらに一歩進めたいと思うでしょう。一般的なノイズベースのジェネレーターのほとんどは、かなり面白くない結果をもたらします。地形を現実的にするために、侵食効果をエミュレートするアルゴリズムを見てみたいと思います。最先端のゲーム風の世界シミュレーターの1つであるDwarf Fortressは、世界を構築するステップの1つとして侵食シミュレーションを行います。

私が見たかなりクールな解決策の1つはから描画するための資源がたくさんありますので、インターネット上で利用できる他の多くのがありますがゲームプログラミングジェムズ7の「高度な粒子堆積」資料に記載された(例えば1または2) 。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.