Opengles GL_OVR_multiview2 introduction

Recently, the project needs to study GL_OVR_multiview. The
requirement is to do a secondary rendering of GL_TEXTURE_2D_ARRAY completed by unity, and draw different textures to different layers of GL_TEXTURE_2D_ARRAY through a draw call.

First introduce GL_OVR_multiview, and give a more detailed introduction to GL_OVR_multiview on OpenGL ES SDK for Android .
It can be understood that GL_OVR_multiview is a technology that renders a framebuffer object (framebuffer Object) to a 2D texture array (GL_TEXTURE_2D_ARRAY) through a draw call

First initialize the rendering environment

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;
}

The above method is used in the unity rendering thread, unity will render the frameBufferObjectId to the frameBufferTextureId 2D texture array.
After unity finishes rendering, it will pass the frameBufferTextureId 2D texture array to the SDK, and the SDK will do the secondary rendering.
First, the SDK needs to check whether the currently bound texture is renderTexture2DArrayId, if not, it is necessary to rebind renderTexture2DArrayId and set the GL_OVR_multiview
code as follows:

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);

GL_OVR_multiview feature needs to be turned on in the shader (due to the drawn 2D texture array, if different layers not only have different gl_Position, but also different textures and texture coordinates, GL_OVR_multiview2 feature is required.) The
fixed-point shader is as follows

+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";

The fragment shader code is as follows

+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";

The final effect is that the renderTexture2DArrayId texture is processed twice, and the content in sampler2DArray is drawn to renderTexture2DArrayId. The effect is as follows
Insert picture description here

Guess you like

Origin blog.csdn.net/u010116586/article/details/103148752