マルチビューレンダリング
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 : マルチレンダリングを行うビューの数