1

2 つのビューポートをきれいに分離するにはどうすればよいですか?

2 つのビューポートがあり、1 つは画面全体の長さで、もう 1 つは画面サイズの 4 分の 1 以下である必要があります (マップにしたい)。問題は、それらが干渉し続けることです。大きなビューポートのコンテンツから小さなビューポートのコンテンツを見ることができます。

display()これが私が使用している機能です:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_LIGHTING);


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,newWidth,newHeight);
gluPerspective(45,(float)newWidth/(float)newHeight,0.2,500);
//setup view
glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

camera.render(crntMode, radiusNew);

//ground
glColor3f(0.5,0.5,0.5);
draw_ground(50,50,2,2,-2);
...
...
...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(newWidth / 2, newHeight / 2, newWidth / 2, newHeight / 2);
gluPerspective(45,(float)newWidth/(float)newHeight,0.2,500);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

camera.render(mini_map, radiusNew);

//ground
glColor3f(0.5,0.5,0.5);
draw_ground(50,50,2,2,-2);
...
...
...
//swap buffers
glutSwapBuffers();

両方のビューポート カメラがキャラクターを追跡しています。1 つは第三者の視点から、もう 1 つは上から見たものです。 見にくいかもしれませんが、ミニマップ ビューポートの背景が大きなものと干渉しています (大きなオンはミニマップの背景のように機能しています)。 大きなビューポートが小さなビューポートを覆ってしまうことがあります。

両方のビューポート カメラがキャラクターを追跡しています。1 つは第三者の視点から、もう 1 つは上から見たものです。見にくいかもしれませんが、ミニマップ ビューポートの背景が大きなものと干渉しています (大きなオンはミニマップの背景のように機能しています)。大きなビューポートが小さなビューポートを覆ってしまうことがあります。

4

1 に答える 1

10

ビューポートはミニ ウィンドウではありません。ビューポートは、レンダリングが行われるメイン ウィンドウ内の場所にすぎません。すべてのレンダリングは引き続き同じフレーム バッファで行われます。この問題は、両方のビューポートが同じ深度バッファーを使用しているために発生します。OpenGL は、大きなシーンの深度が小さなシーンのレンダリングに影響することを認識していません。OpenGL にとっては、すべて 1 つのシーン、1 つのフレームバッファです。

これを修正するには多くの方法がありますが、すべてパフォーマンスへの影響や OpenGL の要件が異なります。

  1. で 2 つのシーンをレンダリングする間に深度バッファをクリアしglClear(GL_DEPTH_BUFFER_BIT);ます。これは最も単純ですが、パフォーマンスの点で最もコストがかかります。完全を期すためにここにリストするだけです。代わりに次を使用する必要があります。

  2. 最初に大きなシーンを描きます。次に、ビューポートを小さいシーンに設定します。深度テストをオフにして、glDepthMaskオンのままにします。次に、Z が -1 で、クワッドのエクステントが X および Y で [-1, 1] である、画面に位置合わせされたクワッドを描画します。行列は、射影行列とモデルビュー行列の両方で同一である必要があります。これにより、シーンの一部の深度が効果的にクリアされます。

    四角形を描画した後、深度テストをオンにすることを忘れないでください。また、必要に応じてマトリックスを修復することを忘れないでください。これは、新しいビューポートのすべてのピクセルに描画している場合にのみ機能します (クワッドの色を意図した背景色に設定しない限り)。

  3. 最初に大きなシーンを描きます。次に、 を使用glScissorしてシザー ボックスを小さいシーンに設定し、 を使用glEnable(GL_SCISSOR_TEST)してシザリングを有効にします。その後、 で深度バッファをクリアしglClear(GL_DEPTH_BUFFER_BIT)ます。次に、シザー テストを無効にして、小さいシーンをレンダリングします。

    これは #2 に似ていますが、画面に合わせてクワッドを描画する必要はありません。glClearは、シザー テストが有効になっている場合はシザー ボックスを尊重するため、シザー領域のみをクリアします。

    glClearOpenGL の実装ではとのglScissor動作が間違っている可能性があるため、提案されたメカニズムの代わりにこれを提供します。これは、推奨されるメカニズムです。

  4. 深度範囲を使用します。これはシーンの品質に影響を与える可能性がありますが、おそらく最も高速です (注: 気にする本当の理由がない限り、気にする必要はありません。つまり、プロファイリングでパフォーマンスに問題があることが示された場合にのみこれを行ってください)。メイン シーンではglDepthRange(0.1, 1.0)、 ;を使用します。小さなシーンの場合は、 を使用しますglDepthRange(0.0, 0.1)

    これは事実上、小さなシーンのすべての深度値が、大きなシーンのすべての深度値よりも前にあることを意味します。ただし、これは大規模なシーンの深度精度が低下することも意味するため、Z ファイティングが明らかになる可能性があります。

    必要に応じて移動でき0.1ます。範囲を 0.5 で半分に分割できますが、個人的にはお勧めしません。小さなシーンはそれほど重要ではなく、解像度が小さいほど Z ファイティングは重要ではありません。そのため、最も重要なシーンにより多くの精度を与える必要があります。

  5. 小さなシーンを FBO にレンダリングし、画面にブリットします。これは、理由付けが最も簡単です。色用と深度用に 1 つずつ、いくつかのレンダー バッファーを作成するだけです。それらをフレームバッファオブジェクトに貼り付けます。そこに小さなシーンをレンダリングします。を使用glBlitFramebufferして、デフォルトのフレームバッファ内の必要な場所に描画します。

ステンシル テストを使用するなど、他の方法もありますが、これらは信頼できる方法です。

于 2012-12-04T20:30:09.677 に答える