Я пытаюсь добавить пользовательский интерфейс в качестве плагина к существующему приложению, используя OpenGL.
Для этого я визуализирую пользовательский интерфейс в текстуру и рисую эту текстуру поверх трехмерной сцены после того, как сцена нарисована.
Текстура генерируется следующим образом:
if (context_ == nullptr)
{
QSurfaceFormat format;
format.setDepthBufferSize( 16 );
format.setStencilBufferSize( 8 );
format.setMajorVersion(3);
format.setMinorVersion(3);
native_context_ = new QOpenGLContext;
native_context_->setNativeHandle( QVariant::fromValue(
QGLXNativeContext( native_context_information_->context, native_context_information_->display )));
if ( !native_context_->create())
{
ROS_ERROR( "OverlayManager: Fatal! Failed to create context!" );
}
context_ = new QOpenGLContext;
context_->setFormat( format );
context_->setShareContext( native_context_ );
if ( !context_->create())
{
ROS_ERROR( "OverlayManager: Fatal! Failed to create context!" );
}
surface_ = new QOffscreenSurface;
surface_->setFormat( format );
surface_->create();
if ( !surface_->isValid()) ROS_ERROR( "Surface invalid!" );
context_->makeCurrent( surface_ );
paint_device_ = new QOpenGLPaintDevice( 1920, 1080 );
{
QOpenGLFramebufferObjectFormat format;
format.setSamples(16);
format.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
fbo_ = new QOpenGLFramebufferObject( 1920, 1080, format );
texture_fbo_ = new QOpenGLFramebufferObject( 1920, 1080 );
}
fbo_->bind();
}
else
{
context_->makeCurrent( surface_ );
fbo_->bind();
}
context_->functions()->glClear(GL_COLOR_BUFFER_BIT);
QPainter painter(paint_device_);
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
painter.setBrush(QBrush(Qt::green));
painter.drawRect(0, 0, 400, 300);
// painter.setPen(Qt::red);
painter.setPen(QPen(QBrush(Qt::red), 4));
painter.setFont(QFont("Arial", 20));
painter.drawText(100, 120, "Hello");
painter.drawText( 10, 80, QString( "Rendertime (ms): %1" ).arg( timer_average_ / 15.0 ));
painter.end();
fbo_->release();
QOpenGLFramebufferObject::blitFramebuffer(texture_fbo_, fbo_);
context_->functions()->glFinish();
// Texture looks fine
context_->doneCurrent();
glXMakeCurrent( native_context_information_->display, native_context_information_->drawable, native_context_information_->context );
// Now it is messed up
Вероятно, более интересной частью является рисунок текстуры:
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glOrtho(0, 1920, 0, 1080, -1, 1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_fbo_->texture());
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(0, 1); glVertex2f(0, 1080);
glTexCoord2f(1, 1); glVertex2f(1920, 1080);
glTexCoord2f(1, 0); glVertex2f(1920, 0);
// glClear(GL_DEPTH_BUFFER_BIT); // Wrong but not the issue, see second edit
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glMatrixMode(GL_MODELVIEW);
В основном я нашел этот метод рисования текстур вместе с некоторыми комментариями, в которых говорилось, что это устарело, но я не смог найти что-то особенное для полноэкранных наложенных текстур, используя более современные методы. Если у вас есть краткий ресурс / руководство по этому вопросу, я был бы признателен за это, но, поскольку это далеко от моей области знаний, я не хочу вкладывать в это больше пары часов, чтобы избежать использования устаревшего кода.
Надеюсь, у вас есть достаточно четкое представление о том, чего я пытаюсь достичь.
Это на самом деле хорошо работает на моем рабочем столе, используя NVidia Geforce GTX 1080 с Ubuntu 16.04, Qt 5.5.1, OGRE 1.9.0 и OpenGL 4.6 (GLSL 4.6) и виртуальную машину на моем рабочем столе с использованием Ubuntu 18.04, Qt 5.9.5, OGRE 1.9 .0 и OpenGL 2.1 (GLSL 1.2).
Однако на моем ноутбуке с Ubuntu 16.04, Qt 5.5.1, OGRE 1.9.0 и OpenGL 3 (GLSL 1.3) он вообще не работает.
Теперь очевидный вопрос: почему это так и как я могу это исправить?
Вот так выглядит мой рабочий стол и виртуальная машина:
Вот как это выглядит на моем ноутбуке:
Весь исходный код можно найти здесь .
Редактировать :
В случае, если это важно, если я перемещу камеру в нижнем примере, белые области также изменятся. Из-за этого я думаю, что они могут быть остатками от рендеринга сцены.
Второе редактирование :
Я сделал больше отладки, и это не рисунок не так, как я изначально думал, а переключение контекста.
Я сохранил текстуру в файл перед переключателем и после него, и текстура выглядит так, как задумано, до того, как испорчена после переключения.
Теперь мне просто нужно выяснить, почему.