【问题标题】:QOpenGLWidget with custom framebuffer and multiple render targets具有自定义帧缓冲区和多个渲染目标的 QOpenGLWidget
【发布时间】:2018-11-30 13:12:37
【问题描述】:

my other question 相关,我正在尝试渲染分割蒙版以启用对象拾取。但我无法达到预期的效果。

选项 1 根本不起作用。我无法检索颜色附件 1 的内容,或者检查它是否存在(我只使用原生 OpenGL 调用创建了附件)。

使用this 帖子,我能够通过创建带有第二个颜色附件的自定义帧缓冲区来重现green.pngred.png 图像,然后绑定并绘制到(全部在paintGL() 中)。

不知何故,我不得不使用这个人的帧缓冲区创建代码,因为当我自己创建帧缓冲区时,总是有一个警告说 toImage called for missing color attachment,尽管我附加了颜色附件并且在帧缓冲区上调用 textures() 返回了两个对象.然后我尝试在

之后插入我的渲染代码
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);

但这仍然导致红色和绿色图像。但是当使用正常的默认帧缓冲区时,代码渲染得很好。我将着色器调整为(用于测试目的的简短版本):

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

由于我能够生成红色和绿色图像,我假设必须有一种方法可以使用此自定义帧缓冲区检索片段数据。我现在拥有的解决方案是程序的完整(!)副本和另一个专用的片段着色器,其唯一目的是渲染分段,并第二次执行所有 OpenGL 绘制调用。你可以猜到,这是一个有点丑陋的解决方案,虽然风景不是那么大,我的电脑可以轻松处理。有人有想法/链接吗?

【问题讨论】:

    标签: qt opengl framebuffer rendertarget


    【解决方案1】:

    如果你想在Fragment shader 中写入多个渲染目标,那么你必须声明多个output 变量:

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

    从 GLSL 1.1 版(#version 110,OpenGL 2.0)到 GLSL 1.5 版(#version 150,OpenGL 3.2),同样可以通过写入内置片段着色器输出变量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);
    }
    

    另见Fragment Shader Outputs - Through The Ages


    要在 Qt 中使用多个渲染目标,必须将第二个颜色附件添加到帧缓冲区,并且颜色缓冲区列表必须由 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();
    

    可以访问附加到帧缓冲区的OpenGL纹理对象:

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

    【讨论】:

    • 好吧,我使用 gl_FragData 尝试了第二部分。但是在两个清晰的颜色调用之后插入我已经工作的渲染代码只渲染了清晰的颜色。
    • 你写的正是我尝试过的,但我一定犯了一些错误,因为我再次尝试并且它有效。感谢您的所有时间和答案!
    • 如果其他人遇到此问题:您必须像这样调用 toImage(): fbo.toImage(false, 1);而不是 fbo.toImage(false, GL_COLOR_ATTACHMENT1);。我还在学习...
    猜你喜欢
    • 2018-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    相关资源
    最近更新 更多