基于VTS Browser C++的QOpenGLWidget仅显示黑屏问题求助
基于VTS Browser C++库的QOpenGLWidget黑屏问题排查
我正在基于VTS Browser C++库开发Qt的QOpenGLWidget,所有函数看似运行正常,但Widget仅显示黑屏。已调试OpenGL上下文状态正常,排查过VTS相关函数仍未找到原因,Qt开发经验不足,寻求帮助。测试环境为Ubuntu 20.04。
Widget实现代码(.cpp)
#include "vtswidget.h" #include <QGuiApplication> #include <QMouseEvent> #include <QWheelEvent> #include <vts-browser/log.hpp> #include <vts-browser/map.hpp> #include <vts-browser/mapOptions.hpp> #include <vts-browser/camera.hpp> #include <vts-browser/navigation.hpp> #include <vts-renderer/renderer.hpp> #include <stdexcept> #include <QSurface> #include <QDebug> #include <QTimer> static Gl *openglFunctionPointerInstance; void *openglFunctionPointerProc(const char *name) { return (void*)openglFunctionPointerInstance->getProcAddress(name); } Gl::Gl(QSurface *surface) : surface(surface) {} void Gl::current(bool bind) { if (bind) makeCurrent(surface); else doneCurrent(); } void Gl::initialize() { setFormat(surface->format()); create(); if (!isValid()) throw std::runtime_error("unable to create opengl context"); } void DataThread::run() { vts::setLogThreadName("data"); gl->current(); vts::renderer::installGlDebugCallback(); map->dataAllRun(); } VtsWidget::VtsWidget(QWidget *parent) : QOpenGLWidget(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&VtsWidget::update)); timer->start(1000); QSurfaceFormat format; format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); #ifndef NDEBUG format.setOption(QSurfaceFormat::DebugContext); #endif format.setDepthBufferSize(0); format.setStencilBufferSize(0); setFormat(format); } void VtsWidget::initializeGL() { setWindowTitle(tr("VTS Widget")); resize(QSize(800, 600)); if (!this->context()) { qWarning("Failed to get current OpenGL context"); return; } // Initialize the OpenGL functions for the current context if (!this->context()->isValid() || !this->context()->functions()) { qWarning("Failed to initialize OpenGL functions for the current context"); return; } this->context()->functions()->initializeOpenGLFunctions(); if (this->context() != nullptr) { if (this->context()->isValid()) { if (!this->context()->surface()) { qWarning("Failed to get OpenGL surface for the current context"); return; } } else { qDebug() << "Invalid QSurfaceFormat"; return;// Handle the case where the QSurfaceFormat is invalid. } } else { qDebug() << "surfacecontext is null"; return; // Handle the case where surfacecontext is null. } dataThread.gl = std::make_shared<Gl>(this->context()->surface()); dataThread.gl->initialize(); dataThread.gl->current(false); gl = std::make_shared<Gl>(this->context()->surface()); gl->setShareContext(dataThread.gl.get()); gl->initialize(); gl->current(); gl->makeCurrent(this->context()->surface()); openglFunctionPointerInstance = gl.get(); vts::renderer::loadGlFunctions(&openglFunctionPointerProc); vts::MapCreateOptions mapopts; mapopts.clientId = "vts-browser-qt"; map = dataThread.map = std::make_shared<vts::Map>(mapopts); map->setMapconfigPath( "http://192.168.4.104:9000/store/vts/gebco_global/mapConfig.json", ""); camera = map->createCamera(); navigation = camera->createNavigation(); vtscontext = std::make_shared<vts::renderer::RenderContext>(); vtscontext->bindLoadFunctions(map.get()); view = vtscontext->createView(camera.get()); dataThread.gl->moveToThread(&dataThread); dataThread.start(); lastTime = std::chrono::high_resolution_clock::now(); } VtsWidget::~VtsWidget() { view.reset(); navigation.reset(); camera.reset(); if (map) map->renderFinalize(); dataThread.wait(); } void VtsWidget::mouseMove(QMouseEvent *event) { QPoint diff = event->globalPos() - lastMousePosition; lastMousePosition = event->globalPos(); double n[3] = { (double)diff.x(), (double)diff.y(), 0 }; if (event->buttons() & Qt::LeftButton) navigation->pan(n); if ((event->buttons() & Qt::RightButton) || (event->buttons() & Qt::MiddleButton)) navigation->rotate(n); } void VtsWidget::mousePress(QMouseEvent *) {} void VtsWidget::mouseRelease(QMouseEvent *) {} void VtsWidget::mouseWheel(QWheelEvent *event) { navigation->zoom(event->angleDelta().y() / 120.0); } bool VtsWidget::event(QEvent *event) { switch (event->type()) { case QEvent::MouseMove: mouseMove(dynamic_cast<QMouseEvent*>(event)); return true; case QEvent::MouseButtonPress: mousePress(dynamic_cast<QMouseEvent*>(event)); return true; case QEvent::MouseButtonRelease: mouseRelease(dynamic_cast<QMouseEvent*>(event)); return true; case QEvent::Wheel: mouseWheel(dynamic_cast<QWheelEvent*>(event)); return true; default: return QWidget::event(event); } } void VtsWidget::paintGL() { auto currentTime = std::chrono::high_resolution_clock::now(); double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>( currentTime - lastTime).count() * 1e-6; lastTime = currentTime; if (!isVisible()) return; if (!gl->isValid()) throw std::runtime_error("invalid gl context"); gl->makeCurrent(this->context()->surface()); QSize size = QWidget::size(); // release build -> catch exceptions and close the window // debug build -> let the debugger handle the exceptions #ifdef NDEBUG try { #endif map->renderUpdate(elapsedTime); camera->setViewportSize(size.width(), size.height()); camera->renderUpdate(); view->options().targetFrameBuffer = gl->defaultFramebufferObject(); view->options().width = size.width(); view->options().height = size.height(); view->render(); #ifdef NDEBUG } catch(...) { this->close(); return; } #endif // finish the frame gl->swapBuffers(this->context()->surface()); }
Widget头文件(.hpp)
#ifndef VTSWIDGET_H #define VTSWIDGET_H #include <QOpenGLWidget> #include <memory> #include <chrono> #include <QWindow> #include <QThread> #include <QOpenGLContext> #include <QSurface> #include <QOpenGLFunctions> namespace vts { class Map; class Camera; class Navigation; namespace renderer { class RenderContext; class RenderView; } } class Gl : public QOpenGLContext { public: explicit Gl(QSurface *surface); void initialize(); void current(bool bind = true); QSurface *surface; }; class DataThread : public QThread { public: std::shared_ptr<Gl> gl; std::shared_ptr<vts::Map> map; void run() override; }; class VtsWidget : public QOpenGLWidget, protected QOpenGLFunctions { public: explicit VtsWidget(QWidget *parent = nullptr); ~VtsWidget(); void initializeGL() override; bool event(QEvent *event); void paintGL() override; void mouseMove(class QMouseEvent *event); void mousePress(class QMouseEvent *event); void mouseRelease(class QMouseEvent *event); void mouseWheel(class QWheelEvent *event); std::shared_ptr<Gl> gl; std::shared_ptr<vts::renderer::RenderContext> vtscontext; std::shared_ptr<vts::Map> map; std::shared_ptr<vts::Camera> camera; std::shared_ptr<vts::Navigation> navigation; std::shared_ptr<vts::renderer::RenderView> view; QPoint lastMousePosition; std::chrono::high_resolution_clock::time_point lastTime; DataThread dataThread; private: }; #endif // VTSWIDGET_H
主函数代码(main.cpp)
#include <QApplication> #include "vtswidget.h" int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_UseDesktopOpenGL); QApplication app(argc, argv); std::setlocale(LC_ALL, "C"); VtsWidget glWidget; glWidget.show(); // Clean up the global context // globalContext->doneCurrent(); // delete globalContext; return app.exec(); }
内容的提问来源于stack exchange,提问作者biscuitvanille
相关产品推荐
相关产品推荐

