最新のOpenGLを備えた複数のビューポート?


9

私はSDL2を使用しています

現在、私の唯一のシェーダーにはMVPマトリックスがあり、それを使用してポイントを変換します。

GLMを搭載したカメラのビューと投影行列を計算します。

glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);

検索しましたが、複数のビューポートのレガシー実装しか見つかりません。

たとえば、4つのカメラを作成して、すべてのカメラが同じであるとしましょう。ただし、すべてのカメラには、レンダリングする画面の四分の一が異なります。(つまり、同じ内容の4つのビューポートが必要です)

これどうやってするの?十分な情報を提供できなかった場合は、申し訳ありませんが質問してください。


レンダリングを4回実行することを具体的に探していますか、それとも1回だけレンダリングして結果を4つの異なる場所に表示しますか?
trichoplax 2017年

レンダリングを4回実行します。私が書いたのは単純化された例にすぎません。たとえば、メインのカメラで車をフルウィンドウでレンダリングし、別のカメラで車を横から隅の小さな正方形にレンダリングします。
Tudvari 2017年

私はあなたのようなシーンの他の部分のレンダリング例えばに4つの部分を、あなたのウィンドウを分割し、各部分にする必要があるので、これを正しく理解している場合のことを
narthex 2017年

はい、ただし厳密には4つの部分ではありません。柔軟にしてほしい。ビューポート長方形の柔軟なサイズと位置。
Tudvari 2017年

回答:


8

同じ画面の異なるビューポート(パーツ)へのレンダリングは、次のように実行できます。

たとえば、画面を4つの部分に分割し、さまざまなユニフォームとさまざまなビューポートを使用して、同じシーンを各コーナーに4回レンダリングします。

bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene->setConstPerFrameUniforms();

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(1);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(2);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(3);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(4);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

そのため、glViewPort()を使用して、次に描画する場所を定義でき、glBlendFuncを使用して、GPUがオーバーラップエリア(フレームバッファー)を相互にブレンドする方法を定義できます。私は正しいですか?
Tudvari 2017年

1
はい、自由にパラメーター化できます。のパラメーターはviewport、チャンクの左下隅のx、yとチャンクの幅、高さです。ブレンディングを使用すると、実験できます。
narthex 2017年

1
なぜブレンド?それは質問とどのように関連していますか?
Raxvan 2017年

3
ブレンドや複数のフレームバッファは必要ありません。レンダリングは現在のglViewportの四角形の外側のピクセルには書き込みません。そのため、各ビューポートを順番に設定して描画することができます。ところで、ビューポートを重ねたい場合は、はさみテストを使用してクリアを特定の長方形に制限することもできます。
ネイサンリード

2
ブレンドはこれとは何の関係もなく、答えをより混乱させます。必要なのはビューポートの設定だけです
デフォルトの

10

独自のVertex / Fragment Shaderを作成している場合、これを行う別の可能性があります。はるかに複雑ですが、あなたや他の人に役立つかもしれません。さらに、描画コマンドの呼び出しを1つだけ使用するため、描画プロセス全体が高速化されます。ビューポートの最大数はGL_MAX_VIEWPORTSによって定義され、通常は16です。

OpenGL 4.1以降、メソッドglViewportArrayvが存在します。ビューポートの配列を定義できます。このメソッドで作成されたビューポートには、インデックスが割り当てられています。

このインデックスを頂点シェーダーで使用して、シーンがレンダリングされるビューポートを設定できます。(シェーダーコードに「ARB_shader_viewport_layer_array」拡張を含める必要があります)

あなたの場合、私は以下を行うことをお勧めします:


" このインデックスを頂点シェーダーで使用して、シーンのレンダリング先のビューポートを設定できます。 "いいえ、できません。まあ、ARB_shader_viewport_layer_array拡張機能、または同等のAMDなしではありません。これらのどれもGL 4.5の標準ではありません。あなたはおそらくジオメトリシェーダーについて考えています。
Nicol Bolas 2017年

@Nicol、このヒントをありがとう!拡張機能を含める必要があることを言及するのを忘れました。回答を編集します。
Christian_B

5

これは@narthexの回答のコピーですが、必要なのはビューポートだけです。彼の答えにフレームバッファーやブレンドの要素が含まれている理由がわかりません。

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

0

これらはすべて良い答えですが、別の方法もあります(常にあるわけではありませんか?)

バーチャルリアリティの人気が高まっているため、OculusVRの人々は「マルチビュー」拡張機能のトリオを開発しました。

  1. OVR_multiview
  2. OVR_multiview2、&
  3. OVR_multiview_multisampled_render_to_texture

これらの拡張により、同じシーンの複数のビューを1回の描画呼び出しでレンダリングできるため、それぞれの目から見た同じシーンを同じ状態でレンダリングする冗長性がなくなります。VRを目的として作成されていますが、開発者は必ずしも2つのビューに限定されるわけではありません。むしろ、この拡張はMAX_VIEWS_OVRが指定するのと同じ数のビューを許可します。

これらの拡張機能を使用する前に、開発者は次のコードを追加して、ユーザーのグラフィックスドライバーでのサポートを確認する必要があります。

const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );
char * found_extension = strstr( (const char*)extensions, "GL_OVR_multiview" );
if (NULL == found_extension)
{
     exit( EXIT_FAILURE );
}

そこから、この機能を利用するためにフレームバッファを設定するだけです。

glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);

同様にシェーダーで:

#version 300 es
#extension GL_OVR_multiview : enable

layout(num_views = 2) in;
in vec3 vertexPosition;
uniform mat4 MVP[2];

void main(){
    gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);
}

CPUにバインドされたアプリケーションでは、この拡張機能により、特により複雑なシーンでレンダリング時間を大幅に削減できます。

マルチビューと通常のステレオの間の相対CPU時間。 X軸はキューブの数、Y軸は相対時間で、小さいほど良いです。

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