opengles GL_OVR_multiview2 使用介绍

最近项目需要对GL_OVR_multiview进行了研究,
需求是对 unity 渲染完成的GL_TEXTURE_2D_ARRAY做二次渲染,通过一次draw call将不同的纹理绘制到GL_TEXTURE_2D_ARRAY不同的layer中。

首先介绍下GL_OVR_multiview,在OpenGL ES SDK for Android上对GL_OVR_multiview做了比较详细的介绍。
可以理解为GL_OVR_multiview是通过一次draw call 实现将帧缓冲对象(framebuffer Object)渲染到2D纹理数组(GL_TEXTURE_2D_ARRAY)的技术

首先初始化渲染环境

bool setupFBO(int width, int height)
{
    
    
	// Create array texture
	GL_CHECK(glGenTextures(1, &frameBufferTextureId));
	GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, frameBufferTextureId));
	GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
	GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
	GL_CHECK(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, 2));
	/* Initialize FBO. */
	GL_CHECK(glGenFramebuffers(1, &frameBufferObjectId));
	/* Bind our framebuffer for rendering. */
	GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferObjectId));
	/* Attach texture to the framebuffer. */
	GL_CHECK(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
	                              frameBufferTextureId, 0, 0, 2));
	/* Create array depth texture */
	GL_CHECK(glGenTextures(1, &frameBufferDepthTextureId));
	GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, frameBufferDepthTextureId));
	GL_CHECK(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH_COMPONENT24, width, height, 2));
	/* Attach depth texture to the framebuffer. */
	GL_CHECK(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
	                              frameBufferDepthTextureId, 0, 0, 2));
	/* Check FBO is OK. */
	GLenum result = GL_CHECK(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
	if (result != GL_FRAMEBUFFER_COMPLETE)
	{
    
    
	LOGE("Framebuffer incomplete at %s:%i\n", __FILE__, __LINE__);
	/* Unbind framebuffer. */
	GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
	return false;
	}
	return true;
}

上述方法是在unity渲染线程使用的,unity会将frameBufferObjectId渲染到frameBufferTextureId 2D纹理数组上。
unity完成渲染后,会将frameBufferTextureId 2D纹理数组传递给SDK,由SDK做二次渲染。
首先SDK需要检查当前绑定的纹理是否为renderTexture2DArrayId,如果不是需要重新绑定renderTexture2DArrayId并设置GL_OVR_multiview
代码如下:

GLint defaultActiveTextureArray = 0;
GL(glGetIntegerv(GL_TEXTURE_BINDING_2D_ARRAY, &defaultActiveTextureArray));

GLint renderTexture2DArrayId = frameBufferTextureId;
glBindTexture(GL_TEXTURE_2D_ARRAY, renderTexture2DArrayId);
//相当于glFramebufferTexture2D
glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,renderTexture2DArrayId, 0, 0, 2);

GLint defaultFbId;
GL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbId));
//postprocess renderTexture2DArrayId only by on draw call
postprocess(renderTexture2DArrayId);
glBindTexture(GL_TEXTURE_2D_ARRAY, defaultActiveTextureArray);

shader 中需要打开GL_OVR_multiview feature(由于绘制的2D纹理数组,如果不同layer不仅gl_Position不同,纹理及纹理坐标都不同,需要GL_OVR_multiview2 feature)
定点着色器如下

+char multiviewVs[] =
+    "#version 300 es\n"
+    "#extension GL_OVR_multiview2 : require\n"
+    "layout(num_views = 2) in;\n"
+    "in  vec2 position[2];\n"
+    "in  vec2 texcoord[2];\n"
+    "out vec3 vTexcoord0;\n"
+    "uniform mat4 mvpMatrix[2];\n"
+    "void main()\n"
+    "{\n"
+    "    vec2 vposition = position[gl_ViewID_OVR];\n"
+    "    vec2 vtexcoord = texcoord[gl_ViewID_OVR];\n"
+    "    mat4 currentmvp= mvpMatrix[gl_ViewID_OVR];\n"
+    "    gl_Position    = currentmvp*vec4(vposition .x, vposition y, 0.0, 1.0);\n"
+    "    vTexcoord0     = vec3(vtexcoord .x,vtexcoord .y,gl_ViewID_OVR);\n"
+    "}\n";

片段着色器代码如下

+char multiviewFs[] =
+    "#version 300 es\n"
+    "in vec3 vTexcoord0;\n"
+    "uniform sampler2DArray srcTex;\n"
+    "//uniform sampler2D srcTex;\n"
+    "out  vec4 outColor;\n"
+    "void main()\n"
+    "{\n"
+    "    outColor = texture(srcTex, vTexcoord0);\n"
+    "}\n";

最终的效果是对renderTexture2DArrayId纹理进行了二次处理,将sampler2DArray中的内容绘制到了renderTexture2DArrayId。效果如下图
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u010116586/article/details/103148752