OpenGL:ディスプレイとglOrtho / glViewportのサイズ変更


16

私はいくつかのソースからこの質問を調査しましたが、「はい、それは正しい思考です」または「いいえ、ここでそれが行われた方法です」という確固たる答えをまだ見つけていません。

OpenGLレンダリングで解像度の独立性を確保しようとしています。私がそれについて行くべきだと思う方法は、glOrtho私が世界座標にしたいものを使って投影を作成することです。たとえば、glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0)。次に、ビューポートを画面解像度、つまり-に設定しglViewport(0, 0, 800, 600)ます。最後に、ウィンドウのサイズが変更されるたびに、glViewport更新された画面解像度でを呼び出します。これにより、フィギュアが拡大縮小されます。

これは、モデルが異なる解像度で同じ割合の画面スペースを取ることを保証する正しい方法ですか?解像度と同じ投影法を使用する必要がありますか?glOrtho他の人がウィンドウの解像度を使用するべきであると言っているのに対して、異なる必要があると答えた人もいました。

考え?

回答:


20

あなたが説明したことは、解像度の独立性を提供するために完全に適切で適切です。実際に描画するものは、常にウィンドウの同じ割合を占めます。

ただし、これ以上何もしないと、アスペクト比の問題が発生します。たとえば、書いた数字を考えると、円を描くと、それはつぶれます-横の目盛りは800 /(50 + 50)= 8で、縦の目盛りは600 /(50+ 50)= 6。

この問題の自動解決策はありません。必要なグラフィック結果を選択し、ゲームプレイへの影響を考慮する必要があります。一般的な例:

  • HUDのない透視投影3Dゲームでは、通常の簡単な解決策(OpenGLの一部として利用可能gluPerspective)は、垂直寸法に対して投影の視野を固定することです。これは、このようなゲームでは、ウィンドウを水平方向にサイズ変更すると、シーンが多少表示され、画像の中央部分がまったく変化しないことを意味します。

    同じ考え方を2D / 2.5Dビューにも適用できます。

    (これにより、プレイヤーは幅が広いが高さのないウィンドウを作成することにより、視野を水平方向に拡大できることに注意してください。これは、競争力のあるマルチプレイヤーゲームでは望ましくない場合があります。)

  • アスペクト比が固定されたビューポート塗りつぶしグラフィックス(スクロールしない2Dマップ、装飾的な境界線など)がある場合、またはレイアウトを変更できない場合は、2つの部分に黒いバーを付けるなどの操作を行う必要があります。サイドを使用して未使用のスペースを埋めます。

    または、ゲームプレイを損なうことなく、ディスプレイに合うようにトリミングできるエッジの周りにテーマ的に一貫したフィラー材料を含むグラフィックを作成できます。

  • 他のグラフィックスの上にHUDがある場合、各HUD要素がウィンドウの一部(左上、中央下など)に固定されていると判断し、その座標を計算できます。アスペクト比を変化させる「ストレッチ」は、HUD要素間の「空白」に吸収されます。

問題の特定の数学に関しては、解像度の独立性を実行していることを考えると、最初に必要なのはアスペクト比、1つの数字だけです:width / height。たとえば、ウィンドウが正方形の場合、1になります。800 x 600の場合、800/600 = 4/3 =1.333̅になります。

たとえば、ウィンドウを広げた場合に、左側と右側に追加のスペースを確保するために記述した投影を使用するとします。次のようにできます:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

これにより、少なくともウィンドウと同じ高さのウィンドウでは、x座標とy座標が-50から50の範囲内で描画したものがすべて表示されることが保証されます。

一方、ウィンドウの高さが幅よりも狭い場合は、-50から50の範囲が切り取られます。常に表示されるようにしたいとします(ウィンドウが正方形の場合、コンテンツは最大サイズになりますが、そうでない場合は小さくなります)。その場合、幅ではなく高さに対して同じことを行うだけです。

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

2番目のケースでは、乗算ではなく除算に注意してください。これは、単にアスペクト比をとしてwidth / heightではなく、として計算したためheight / widthです。そのように理解しやすいと思う場合は、逆数を取ります。

繰り返しますが、これはアスペクト比を管理する唯一の方法ではありません。これは、コンテンツが押しつぶされたり切断されたりしないようにするための非常に簡単な方法です。見つけ出すあなたが起こるしたいのか、あなたの窓が広い場合、背の高い、または何でも。それからそれの数学を解決します。


非常に洞察に満ちた対応をありがとう。私の質問に十分に答えました。
クリスヘンダーソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.