2

私が取り組んでいるゲームでは、スクロールスターフィールドを実装したいと思います。これまでのすべてのゲームはOpenGLプリミティブから描画されており、これを継続したいと思います。gl_pointsは適切と思われます。

私はpyglet(python)を使用しており、束全体またはポイントの位置を保存して更新し、手動で移動することでこれを実現できることを知っていますが、より適切な代替手段があることを望んでいました。

編集: イアン・マレットに答えて、私が尋ねようとしているのは、私がたくさんのポイントを生成するかどうかだと思います、これらをある種の表面またはバッファーにブリットしてバックグラウンドでスクロールする方法はありますか?

また、この段階で私が生成しようとしているすべてのスターフィールドの種類については、トップダウンゲーム用の単純な単一レイヤーを目指しています。これは、小惑星での場合とほぼ同じです。

4

2 に答える 2

3

無限の手続き型スターフィールドパターン

特徴:視差スクロール

基本的なレシピは次のとおりです。

  • ランダムジェネレーターのシード(フレームごとに同じシード)
  • N個のランダムな点(X、Y)と「Z」値を生成します(たとえば、すべての点に対して0.5 ... 2)

  • すべてのポイントの位置を翻訳する:(X,Y) += scrollXY * Z
    それは難しい部分です。ポイントごとにZ値が異なるため、異なる速度でスクロールします。これは「視差スクロール」と呼ばれ、驚くべき効果をもたらします。

  • ポイントをラップします(画面サイズを法として)。

フレームごとに同じシードを使用すると、ランダムなスターフィールドパターンが得られますが、フレームごとに永続的です(スクロール値によってのみ変更されます)。

楽しい事実

このアルゴリズムは簡単に変更できるため、N個すべての位置を実際にメモリに保存する必要はありません。必要なのは、ランダムなベース(X、Y)座標(および深さ)を提供し、定数値といくつかの星の数がシードされるジェネレーターだけです。

擬似コード:

for (int i=0; i<1000; ++i) {

    RandomGenerator rnd;
    rnd.seed(SomeConstantSeed + i*10293);

    // determine i-th star's position
    var basePosition = vec2(rnd.next(800), rnd.next(600));
    var depth = rnd.next(0.5, 2);

    // parallax scrolling and wrapping
    var realPosition = basePosition + scrollXY * depth; 
    var wrappedPosition = realPosition modulo vec2(800, 600);

    // these are our coordinates! let's draw
    renderStar(wrappedPosition);
}

ここでは、すべての星がオンデマンドで生成され、フレーム間でその値をメモリに保持する必要はありません。フレームごとに同じ(ただしアニメーション化された)スターフィールドを生成するには、ランダムジェネレータシードが一定であるだけで十分です。

同じ手法を使用して、各星に異なるランダムな(ただし永続的な)色を割り当てることができます。


OpenGLを使用して効率的に実装する方法は?

最も簡単で効果的な方法は、頂点シェーダーでその場で位置を生成することです。

  • VBOでスタージオメトリを準備します。1つの頂点(ポイントスプライトの場合)、テクスチャ付きのクワッドなど、何でもかまいません。

  • を使用してレンダリングします。希望する星の数はglDrawArraysInstancedどこですかprimcount

  • 頂点シェーダーで、上記の擬似コードからループの本体を実装し、をに置き換えgl_InstanceIDますi。次に、上記のように、各頂点の入力XY画面位置(VSの属性変数)をスクロール値(変数として渡される)で変更しuniform vec2ます。

いくつかの脚注:

  • 頂点シェーダーにランダムジェネレーターが必要になります。1Dノイズテクスチャを使用して実装するか、こちらをご覧ください
  • 星のジオメトリが1ポイントより多い場合(つまり、ポイントスプライトではなくクワッドを使用する場合)、星の一部の頂点がラップされ、残りの頂点がラップされない状況を回避するために、画面のラップにさらに注意する必要があります。これはもう少しトリッキーですが、実行可能です。ポイントスプライトの使用は簡単です。
于 2012-09-18T16:15:20.570 に答える
1

どんなスターフィールドを明確にできますか?2Dスクロール(横スクロールゲームまたは上スクロールゲームの場合、レイヤーが異なる場合があります)または3D(非常に高速な宇宙船でスターフィールドを実際に飛行するようなもの)?

前者では、テクスチャ(または追加的にブレンドされたテクスチャのレイヤー)がおそらく最もクリーンで最速のアプローチです。[編集:テクスチャは断然最善のアプローチですが、本当にテクスチャを使用したくない場合は、次のことを行うことができます。これは次善の策です。

  • 静的VBOを作成するか、スクロール方向に必要なサイズの6倍のポイントのリストを表示します(たとえば、800x600画面を実行していて、水平方向にスクロールしている場合は、4800x600グリッドでポイントを生成します)。
  • これらのポイントを2回描画し、幅とスクロール変数でオフセットします。たとえば、xをスクロール変数とします(0から始まり、4800(ポイントの幅)に達するまでインクリメントされてから、折り返され、0から再開されます)。各フレームで、glTranslatef(x、0,0)を使用してポイントを描画します。次に、glTranslatef(x + 4800,0,0)を使用してそれらを再度描画します。
  • このようにして、ポイントは一見連続してスクロールします。定数(上記の6つを選択)は、アルゴリズムにはあまり関係ありません。値を大きくすると、繰り返しは少なくなりますが、パフォーマンスは低下します。
  • また、さまざまなスクロール定数を使用して上記のすべてを数回実行して、奥行きのある錯覚を与えることもできます(複数のレイヤーを使用)。

]

後者には、私が考えることができる巧妙なアルゴリズムがたくさんありますが、生のポイント(空想を感じている場合はポイントスプライト)を使用することをお勧めします。GPUを静的VBOまたはディスプレイリストに配置すると、GPUはこれを処理できます。ポイントが小さい場合は、パフォーマンスに目立った影響を与えることなく、一度に数千を投げることができます。

于 2012-09-18T05:55:17.447 に答える