2Dゲームと最新のOpenGL


10

事前概念

わかりました、それで私がこれまでに集めたのはこれです:

  • 固定パイプラインを使用しない(非推奨または非推奨)
  • vbosは「オブジェクトモデル」を格納します(n頂点データ、ほとんど)
  • vaosは、データがどのように配置されるかを記述し、描画呼び出しが各vboのどの部分がどの種類の頂点情報に対応するかを認識します(1つのvaoは複数のvboを参照でき、その逆は少し難しい)
  • 各描画呼び出しは、シェーダーに頂点データも送信します

3Dの見方(オプション)

これらの情報があれば、3Dの複雑なオブジェクトの描画が最新のOpenGLで非常に優れていることがわかります。基本的に、(おそらくBlenderまたは他の同様のソフトウェアからの)オブジェクトモデルの束をローカル座標を持つVBOにロードし、次に、オブジェクトの各インスタンスに異なるシェーダーパラメーター(オフセット)を指定して、ワールドスペースに描画します。

問題/質問

ただし、2Dでは問題と優先順位はまったく異なります。それほど複雑なオブジェクトを描画する必要はありません。複雑な投影行列は必要ありません。シェーダーははるかに単純です。

最新のOpenGLで頻繁に(実際には頻繁に、基本的にすべてのフレームで)変化するジオメトリを描画するための最良の方法は何でしょうか?

次の段落では、問題のいくつかの考え(円と四角形の問題)を見ることができます。これにより、興味のある変更の種類をより明確に識別できます。

私の試み(オプション)

そこで、基本的な2Dジオメトリを画面に描画する方法を考え始めました。

  • 正方形:[(1, 0), (1, 1), (0, 1), (0, 0)]ローカル空間で正方形のジオメトリのVBOを読み込み、シェーダーに正方形の実際の幅と世界座標および色情報を提供します

涼しく、簡単に見えます。円に移動しましょう:

  • 円:三角ファン...ええ。どのくらいの精度(頂点の数)?小さな円の精度は小さく、バグの円の精度は高くなければなりません。明らかに1 VBOをロードしても、すべてのケースに対応できるわけではありません。円のサイズが大きくなるために精度を上げる必要がある場合はどうなりますか?

かっこいい。少し簡単な長方形に移動しましょう。

  • 長方形:ええ。「一般的な長方形のジオメトリ」はありません。幅と高さの比率があればそれだけですが、サイズが変化すると、各長方形はおそらく異なります。

ご覧のとおり、物事はそこから下り坂になります。特に複雑なポリゴンなどではそうです。

コードポリシーなし:P

アイデアの概要が必要なだけで、コードは必要ありません。特にCまたはC ++コードは必要ありません。「この頂点データでVBOを作成し、それをバインドする...」のように言ってください。


私はあなたが何を求めているのか理解していると思いますが、この質問をもう少し指示したいと思うかもしれません。何が尋ねられているかは少し不明確です-これは実際には近い理由です。
Lysol 2014

@AidanMuellerどういう意味かはわかりませんが、必要に応じて、ご意見をお寄せください。
2014

現在、トップの回答は「あなたの主な質問は次のようだ」と言うことから始まります。それはあなたが何を求めているのかはっきりしないことを示しています。多分あなたは質問の最後にあなたが知る必要のないことの要約を与えるべきです。結局これは質疑応答であり、議論ではありません。
Lysol

@AidanMuellerそういう文脈ではないと思います。「あなたの主な質問は...のようです」と書かれていて、彼/彼女は私が投稿した質問を引用しています。これは実際には、引用するのに十分明確であることを示しています。また、このフレーズは、私の質問が不明確であることを示しているのではなく、メインの質問と別の副次的な質問があることを示しています(つまり、私が提示した特定のケースの解決策は何ですか)。私は現在の質問で問題を実際には見ていません。また、回答者も非常に有用であり、適切なものであることがわかったため、回答者もそうではなかったようです。
2014

フラグメントシェーダーで正確な円を描くことができます。
user253751

回答:


5

あなたの主な質問は次のようです:

最新のOpenGLで頻繁に(実際には頻繁に、基本的にすべてのフレームで)変化するジオメトリを描画するための最良の方法は何でしょうか?

ほとんどの場合、2D OpenGLと3D OpenGLの間に大きな違いはありません。グラフィックスパイプラインには、1つの追加座標Zがあります。これは、2Dではあまり使用されませんが、それだけです。

各描画でジオメトリを変更する方法はいくつかあります。

  • CPUが提供する新しい頂点をフレームごとにプッシュできます。(バッファの再利用に関する注意事項については、https://stackoverflow.com/questions/14155615/opengl-updating-vertex-buffer-with-glbufferdataを参照してください。)

  • を使用すると、既存のバッファのさまざまな部分を描画できglDrawArrays(mode, first, count)ます。アニメーションがループする場合、異なる頂点リストを含む事前計算されたフレームを1つの大きなバッファーに入れ、各フレームにバッファーの適切な部分を描画できます。

  • 均一な配列やテクスチャなど、他のデータで頂点リストに影響を与えることができます。頂点シェーダーで、このデータを読み取り、適切に適用します。これらは、GPUにデータを提示するためのその他のイディオムであり、おそらくパフォーマンスに大きな違いはありません。

  • 同じジオメトリの多数のインスタンスがある場合(属性の影響を受ける可能性があります)、glDrawElementsInstanced()役立つ場合があります

  • 頂点、ジオメトリ、またはテッセレーションシェーダーでアルゴリズム的に頂点リストに影響を与えることができます。アニメーションを数学的に説明できる場合は、同じ頂点リストを保持し、各フレームでいくつかのシェーダーのユニフォームのみを変更できる可能性があります。

そしておそらくあなたのアニメーションは純粋なテクスチャとして表現され、すべてのアニメーションはCPUによってピクセルごとに行われるか、ディスクから事前にレンダリングされます。

全体的に言って、「コンピュータは高速です。できる限り簡単に動作させることができます。おそらく、フレームごとに新しいCPUで作成された頂点を設定することです。次に、それが十分かどうかを確認します。バッテリー/ CPUの使用状況をプロファイルします。まず、メモリフットプリント、次に。」

他の質問、言い換えると、「円や長方形を描くのに良い方法は何ですか?」

サークル。

  • テッセレーションシェーダー(またはジオメトリシェーダー)を使用すると、ジオメトリを動的にすることができます。

  • 正方形を描くことができ、フラグメントシェーダーでは、半径内でのみ不透明(アルファ= 1.0)、半径外では透明(アルファ= 0.0)になります。そして、それは毎回完璧なピクセルです。(正方形の頂点を-1から+1にし、フラグメントシェーダーではのようなものにしoutColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;ます。エッジを少し滑らかにすることもできますが、見栄えが良いでしょう...)

  • たとえば、120三角形のファンをいつでも使用できます。おそらく十分良い。

長方形。

  • あなたはそれについてあなた自身の質問に答えたと思います。あなたが提案することはうまくいきます!

フラグメントシェーダー/半径は非常にきれいです。私自身の質問への回答に関して、私はあなたの意味が理解できないと思います。

ああ、正方形と同じように、幅を制御することについて(ユニフォームを使用すると思います)、「幅/高さの比率があり、それだけですが、サイズが変化する場合、各長方形はおそらく異なる」と書いてあります。 。したがって、長方形の場合も正方形と同じようにしますが、3(x、y、w)ではなく4つの値(x、y、w、h)が必要になります。または、4つのユニフォームとして(xlow、xhigh、ylow、yhigh)を渡します。(0,0)から(1,1)までの入力があれば、頂点シェーダーが必要なことを行うのに十分です。
david van brink

ああ、そうですね。

固定機能パイプラインからのGL_TRIANGLE_FANのような最新のGLに自動ファンはありますか?
John P

5

私はこの主題の専門家であるとは言えません、そして私のゲームプロジェクトでは3D側により集中しているので、私の2D側は一般的に3D側のために作られたものを使用してかなり単純です。そして、明らかに、私の視点はゲーム側にあるので、私の2Dグラフィックスは、ジオメトリよりもスプライトをブリッティングすることについてです。その観点から、

1)正方形と長方形は非常に簡単です。私はすべてをブリットするために使用するVBOに1x1ボックスを1つだけ持っています。この「ユニットボックス」を使用してMVPマトリックスをシェーダーに渡し、それを追加のスケーリングと組み合わせて、ボックスを正しい次元にスケーリングしました。ご存知のように、xとyのスケールを変えることができます。

私の目的のために、私は「ユニットボックス」の使用から2Dスプライトをブリットするためのある種のパーティクルエンジンに移行することを考えていましたが、それは別の話です。

2)サークルをあまり使用していません。特定の数の頂点を持つ固定VBOを使用しています。しかし、円に描画される頂点の数に影響を与えるために、いくつかのストライド調整を行うことができると想像できました。

VBOデータをシェーダー属性に接続するときは、glVertexAttribPointerを使用します。インターリーブされたデータ(私が使用します)に使用するためのストライドパラメーターがあります。ただし、次のように使用できる場合があります。

glVertexAttribPointer(..., n * sizeof(VERTEX_DATA), ...);

...バッファからn番目ごとの頂点を選択するため、円に描画される頂点の数に影響します。サークルに描画される頂点の数に影響するストライドが異なる同じVBOを持つ複数のVAOを作成できます。私はそれを試していません、と思いました。

一般に、はい、VBOなどを使用すると、CPU側の微調整が少し複雑になります。なぜGPU側(シェーダー)で微調整するためにさまざまなことを研究してきたのでしょうか。それでも、この記事によると、多くのCPU側の「介入」が必要な場合でも、最新のハードウェアではVBOを使用する方が効率的です。

http://www.quelsolaar.com/opengl_performance.txt

これがあなたのデザインと方向を決めるのに少し役立つことを願っています


2
「ストライドを微調整して、サークルに描画される頂点の数に影響を与える」とてもクールです。
david van brink
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.