QOpenGLWidget with custom framebuffer and multiple render targets

人走茶凉 提交于 2020-01-14 19:20:39

问题


Related to my other question, I'm trying to render a segmentation mask to enable object picking. But I am not able to achieve the desired result.

Option 1 did not work at all. I was not able to retrieve the content of color attachment 1, or check if it existed at all (I created the attachment using only native OpenGL calls).

Using this post, I was able to reproduce the green.png and red.png images by creating a custom frame buffer with a second color attachment which is then bound and drawn to (all in paintGL()).

Somehow I had to use the person's frame buffer creation code because when I created the frame buffer myself there was always a warning saying toImage called for missing color attachment, although I attached the color attachment and textures() called on the frame buffer returned two objects. I then tried to insert my rendering code after

GLfloat red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 0, red);

GLfloat green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 1, green);

but this still resulted in the red and green image. But the code renders fine when using the normal default framebuffer. I adapted the shader to (short version for testing purposes):

void main() {
       gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}

Since I was able to produce the red and green image, I'm assuming there must be a way to retrieve the frag data with this custom framebuffer. The solution I have right now is a complete (!) copy of the program and another dedicated fragment shader which's sole purpose is to render the segmentation, and perform all OpenGL draw calls a second time. As you can guess, this is a somewhat ugly solution, although the scenery is not that large and my computer is able to handle it easily. Has anyone got an idea/link?


回答1:


If you want to write to multiple render targets in a Fragment shader, then you have to declare multiple output variables:

#version 330

layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;

void main() 
{
    fragData0 = vec4(1.0, 1.0, 1.0, 1.0);
    fragData1 = vec4(0.0, 0.0, 0.0, 1.0);
}

From GLSL version 1.1 (#version 110, OpenGL 2.0) to GLSL version 1.5 (#version 150, OpenGL 3.2), the same can be achieved by writing to the built in fragment shader output variable gl_FragData.

void main() 
{
    gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
    gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}

See also Fragment Shader Outputs - Through The Ages


To use multiple render targets in Qt, a 2nd color attachment has to be add to the framebuffer and the list of color buffers has to be specified by glDrawBuffers:

QOpenGLShaderProgram *program;
QOpenGLFramebufferObject *fb; 
int fb_width;
int fb_height,

fb = new QOpenGLFramebufferObject( fb_width, fb_height );
fb->addColorAttachment( fb_width, fb_height );

glViewport(0, 0, fb_width, fb_height);
fb->bind();
glClearColor(0, 0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);

program->bind();
// ..... do the drawing    

program->release();
fb->release();

The OpenGL texture objects which are attached to the framebuffer, can be accessed:

QVector<GLuint> fb_textrues = fb->textures();


来源:https://stackoverflow.com/questions/50964539/qopenglwidget-with-custom-framebuffer-and-multiple-render-targets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!