我正在使用Qt构建可渲染点云的应用程序。我的点云是在QQuickFrameBufferObject
(包裹OpenGL帧缓冲区对象并在屏幕上直接显示结果的Qt对象)中呈现的。
我还有另一个帧缓冲区对象(QOpenGLFrameBufferObject
),可用来进行屏幕外渲染,其大小是第一个的一半。
我正在使用相同的函数(称为render
)来渲染这两者。
如果仅在大型FBO中渲染,则没有问题,一切看起来都应该正常。
但是当我同时渲染这两者时,大FBO的内容会随机损坏(这些点在正确的位置渲染,但是全都是黑色的)。它并非在所有框架上都发生,但是在发生时,所有点都是黑色的(在所有VBO上)。哪一帧变暗是随机的。
我的VBO包含3个属性:vec3 position
,float intensity
和float 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大段中成功绑定。
我完全不知道是什么原因造成的。
答案 0 :(得分:0)
我发现了问题。我仍在重新绑定着色器程序并使用它时重新对其进行编译。因此出现了问题。我重构了着色器的编译步骤,问题消失了