3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenGL マルチビューレンダリング

Last updated at Posted at 2024-12-16

マルチビューレンダリング

xR用に両眼描画するとき、モデルの状態は一緒なのでマルチビューレンダリングを使って両目分の絵を同時に描きます
マルチビューレンダリングを利用するために必要な設定を記載します
NVIDIAだとTuring以降のアーキテクチャで有効です

サンプル

バーテックスシェーダー

#version 430						
#extension GL_OVR_multiview : require
layout(num_views = 2) in;

#define MVR_VIEWS 2
uniform mat4 projMatrix[MVR_VIEWS];	
uniform mat4 modelMatrix;

in vec4 position;

void main()
{
    int viewID = int(gl_ViewID_OVR);
    gl_Position = projMatrix[viewID] * position;
}

GL_OVR_multiview拡張機能をrequireします
"layout(num_views = 2) in" を記載します

フラグメントシェーダ

赤色を出力しているだけです。

#version 430
out vec4 fragment;
void main()
{
    fragment = vec4(0.8, 0.0, 0.0, 1.0);
}

Main

struct MultiViewRendering_FrameBuffer
{
	GLuint m_nDepthBufferId = 0;
	GLuint m_nRenderTextureId = 0;
	GLuint m_nRenderFramebufferId = 0;
	GLuint m_nLogicalFramebufferId = 0;
};

main()
{

/// 省略 ///

    GlShader shader;
    glUseProgram(shader.GetShaderID());

    MultiViewRendering_FrameBuffer multiviewFrameBuffer;
    CreateMultiViewFrameBuffer(multiviewFrameBuffer, nRenderWidth, nRenderHeight);

/// 省略 ///

     while(glfwWindowShouldClose(window.GetGlfwWindowPtr()) == GL_FALSE)
	{
		float a = nRenderWidth / nRenderHeight;
		
		glBindFramebuffer(GL_FRAMEBUFFER, multiviewFrameBuffer.m_nRenderFramebufferId);
		glViewport(0, 0, nRenderWidth, nRenderHeight);

		glClear(GL_COLOR_BUFFER_BIT);

		float proj[2][16];
		StaticFunc::GetProjectionMatrix(-5, 5, a, -5, 5, proj[0]);
		StaticFunc::GetProjectionMatrix(-5, 5, a, -5, 5, proj[1]);
		glUniformMatrix4fv(shader.GetProjectionMatrixLocation(), 2, false, (float*)proj);

		plate.Render(); //3Dモデルを1回だけ描画

		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
		glViewport(0, 0, window.GetWindowWidth(), window.GetWindowHeight());

		glBindFramebuffer(GL_READ_FRAMEBUFFER, multiviewFrameBuffer.m_nLogicalFramebufferId);
		glNamedFramebufferTextureLayer(multiviewFrameBuffer.m_nLogicalFramebufferId, GL_COLOR_ATTACHMENT0, multiviewFrameBuffer.m_nRenderTextureId, 0, 0);
		glBlitFramebuffer(0, 0, nRenderWidth, nRenderHeight, 0, 0, nRenderWidth, nRenderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);

		glNamedFramebufferTextureLayer(multiviewFrameBuffer.m_nLogicalFramebufferId, GL_COLOR_ATTACHMENT0, multiviewFrameBuffer.m_nRenderTextureId, 0, 1);
		glBlitFramebuffer(0, 0, nRenderWidth, nRenderHeight, nRenderWidth, 0, nRenderWidth * 2, nRenderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);

		glfwSwapBuffers(window.GetGlfwWindowPtr());
		glfwWaitEvents();
	}
 
/// 省略 ///

 }
bool CreateMultiViewFrameBuffer(MultiViewRendering_FrameBuffer &multiviewFrameBuffer, unsigned int nRenderWidth, unsigned int nRenderHeight)
{
	const int MAX_VIEWS = 2;
	const int nMultiViewCount = 2;

	glGenFramebuffers(1, &multiviewFrameBuffer.m_nRenderFramebufferId);
	glBindFramebuffer(GL_FRAMEBUFFER, multiviewFrameBuffer.m_nRenderFramebufferId);

	glGenTextures(1, &multiviewFrameBuffer.m_nDepthBufferId);

	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, multiviewFrameBuffer.m_nDepthBufferId);
	glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, GL_DEPTH_COMPONENT24, nRenderWidth, nRenderHeight, MAX_VIEWS, GL_FALSE);
	glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, multiviewFrameBuffer.m_nDepthBufferId, 0, 1, nMultiViewCount);

	glGenTextures(1, &multiviewFrameBuffer.m_nRenderTextureId);

	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, multiviewFrameBuffer.m_nRenderTextureId);
	glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, GL_RGBA8, nRenderWidth, nRenderHeight, MAX_VIEWS, GL_FALSE);

	glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, multiviewFrameBuffer.m_nRenderTextureId, 0, 1, nMultiViewCount);

	// check FBO status
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		return false;
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glGenFramebuffers(1, &multiviewFrameBuffer.m_nLogicalFramebufferId);

	return true;
}

void glFramebufferTextureMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);

フレームバッファオブジェクトとしてマルチテクスチャオブジェクトを指定する

  • target : テクスチャオブジェクトをバインドするフレームバッファオブジェクト
  • attachment : フレームバッファのアタッチメントポイント
  • texture : テクスチャオブジェクト
  • level : テクスチャ画像のミップマップレベル
  • baseViewIndex : マルチテクスチャオブジェクトの何番目のバッファに書き込むか
  • numViews : マルチレンダリングを行うビューの数

結果

”plate.Render”で、平面を1つ描画します。1回の呼び出しで2つの画像が作成されます
res.png

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?