You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 11:07:01