渲染到FBO会破坏另一个FBO

时间:2018-07-31 08:59:17

标签: qt opengl

我正在使用Qt构建可渲染点云的应用程序。我的点云是在QQuickFrameBufferObject(包裹OpenGL帧缓冲区对象并在屏幕上直接显示结果的Qt对象)中呈现的。

我还有另一个帧缓冲区对象(QOpenGLFrameBufferObject),可用来进行屏幕外渲染,其大小是第一个的一半。

我正在使用相同的函数(称为render)来渲染这两者。

如果仅在大型FBO中渲染,则没有问题,一切看起来都应该正常。

但是当我同时渲染这两者时,大FBO的内容会随机损坏(这些点在正确的位置渲染,但是全都是黑色的)。它并非在所有框架上都发生,但是在发生时,所有点都是黑色的(在所有VBO上)。哪一帧变暗是随机的。

我的VBO包含3个属性:vec3 positionfloat intensityfloat time。当点为黑色时,似乎第一个顶点属性(vec3 position)通过,但是未设置所有其他属性,而我依赖于这些属性的颜色为黑色(因为这些属性等于0) ;

顶点着色器:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in float intensity; // randomly equals to 0
layout (location = 2) in float time;

uniform mat4 viewProjectionMatrix;

flat out vec4 f_color;

vec4 getIntensityColor() {
    return vec4(vec3(intensity / 65535.0), 1.0);
}

void main() {   
    gl_PointSize = properties.pointSize;
    gl_Position = viewProjectionMatrix * vec4(position.x, position.y, position.z, 1.0);


    f_color = getIntensityColor();
}

我的渲染函数如下:

void render() {

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ZERO);
    glBlendEquation(GL_FUNC_ADD);

    // the big FBO is bound before the call to this function. Hence why I do not bind it here
    if(_manager.renderToBigFbo()) { 

        glClearColor(_properties.clearColor.redF(), _properties.clearColor.greenF(), _properties.clearColor.blueF(), _properties.clearColor.alphaF());

        glEnable(GL_PROGRAM_POINT_SIZE);
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        QMatrix4x4 viewProjectionMatrix = _properties.camera.viewProjectionMatrix();

        _renderer->beforeRendering(viewProjectionMatrix, _properties, boundingBox, datasetMetadata);
        _renderer->bindVao();

        for(auto const& vbo : _vbos) {
            _renderer->render(vbo.second->data.get());
        }

        _renderer->afterRendering();
        _renderer->unbindVao();

    }

    if(_manager.renderToSmallFbo()) {
        static constexpr int boxSize = 20.0 * _fboFactor + 1; // box of NxNxN.
        QSize fboSize = _size * _fboFactor;

        _smallFbo->bind(); // FBO is bound here

        glViewport(0, 0, fboSize.width(), fboSize.height());

        glClearColor(0, 0, 0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_PROGRAM_POINT_SIZE);
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glEnable(GL_SCISSOR_TEST);
        glScissor(_manager.getMousePosition().x() * _fboFactor - (boxSize / 2.0), 
            _manager.getMousePosition().y() * _fboFactor - (boxSize / 2.0), boxSize, boxSize);

        QMatrix4x4 viewProjectionMatrix = _properties.camera.viewProjectionMatrix();

        // change some properties. Will cause the vertex shader to be recompiled
        auto colorMode = _properties.colorMode;
        auto pointSize = _properties.pointSize;
        _properties.colorMode = ColorModeItem::ColorMode::INDEX;
        _properties.pointSize = pointSize / 2;


        _renderer->beforeRendering(viewProjectionMatrix, _properties, boundingBox, datasetMetadata);
        _renderer->bindVao();

        for(auto const& vbo : _vbos) {
            _renderer->render(vbo.second->data.get());
        }

        _renderer->afterRendering();
        _renderer->unbindVao();

        }

        // reset the old color mode
        _properties.colorMode = colorMode;
        _properties.pointSize = pointSize;

        glDisable(GL_SCISSOR_TEST);

        // do stuff with the FBO's content
        QImage img (_smallFbo->toImage(false));
        QImage image(img.constBits(), img.width(), img.height(), QImage::Format_ARGB32);

        _smallFbo->release();           
    }

    // needed by Qt
    if(_window != nullptr) {
        _window->resetOpenGLState();
    }
}

vbos对象的render成员函数绑定缓冲区,设置顶点attrib指针并调用glDrawArrays

我正在渲染完全相同的VBO,并在两个FBO中绑定了完全相同的VAO,但是在两个渲染器之间重新编译了顶点着色器,以显示不同的颜色集。

如果我没有在小型FBO渲染部分中绑定VAO,问题就会消失(当然,小型FBO不再包含我想要的内容,但是它将停止破坏其他FBO)。这很奇怪,因为VAO已在较早的FBO大段中成功绑定。

我完全不知道是什么原因造成的。

1 个答案:

答案 0 :(得分:0)

我发现了问题。我仍在重新绑定着色器程序并使用它时重新对其进行编译。因此出现了问题。我重构了着色器的编译步骤,问题消失了