2

我们公司需要捕捉一个Qt3d场景的渲染。为此,我创建了一个小示例应用程序,它说明了我们捕获的用法。

在左侧,您将找到 3D 场景,在右侧有QLabel一个QPixmap显示捕获屏幕的 3D 场景。

现在,由于某种原因,我真的不明白捕获的屏幕截图与左侧的 3D 场景相比看起来确实不同。QLabel与右侧相比,保存的 PNG 图像看起来更令人困惑,但实际上我对我的用例中的 PNG 更感兴趣。

屏幕截图不同于 3d 场景

它为我节省了以下 PNG 文件:

保存的 PNG 文件

我已经尝试QRenderCapture在框架图的不同位置插入,但没有一个地方给出合理的结果。

这是我的frameGraph->dumpObjectTree输出:

Qt3DExtras::QForwardRenderer::
    Qt3DRender::QRenderSurfaceSelector::
        Qt3DRender::QViewport::
            Qt3DRender::QCameraSelector::
                Qt3DRender::QClearBuffers::
                    Qt3DRender::QFrustumCulling::
                Qt3DRender::QCamera::
                    Qt3DRender::QCameraLens::
                    Qt3DCore::QTransform::
                    Qt3DRender::QRenderCapture:: // Insertion of QRenderCapture
    Qt3DRender::QFilterKey::

看来,我在渲染过程中的某个地方捕获了 3d 场景,因此可能存在一些时间问题。(QEventLoop在这个用例中可能不允许使用 of,但我真的不知道为什么。)

QRenderCapture暗示的文档,这QRenderCapture应该是框架图的最后一个叶子节点,但这就是我所做的。

来自 QRenderCapture 文档:

QRenderCapture 用于在任何渲染阶段将渲染捕获到图像中。捕获必须由用户启动,并且每个捕获请求返回一个图像。用户可以同时发出多个渲染捕获请求,但每个 QRenderCapture 实例每帧只提供一个请求。

并且:

用于请求渲染捕获。即使帧图有多个叶节点,每次 requestCapture 调用也只会产生一个渲染捕获结果。该函数返回一个 QRenderCaptureReply 对象,该对象在完成时接收捕获的图像。用户负责释放返回的对象。

这里有人可以帮我吗?

#include <QApplication>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <Qt3DRender/QRenderCapture>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QSphereMesh>
#include <Qt3DExtras/QDiffuseSpecularMaterial>
#include <Qt3DExtras/QForwardRenderer>
#include <Qt3DExtras/Qt3DWindow>

Qt3DCore::QEntity* transparentSphereEntity() {
    auto entity = new Qt3DCore::QEntity;
    auto meshMaterial = new Qt3DExtras::QDiffuseSpecularMaterial();
    meshMaterial->setAlphaBlendingEnabled(true);
    meshMaterial->setDiffuse(QColor(255, 0, 0, 50));

    auto mesh = new Qt3DExtras::QSphereMesh();
    mesh->setRadius(1.0);
    entity->addComponent(mesh);
    entity->addComponent(meshMaterial);
    return entity;
}

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    auto frame = new QFrame;
    auto view = new Qt3DExtras::Qt3DWindow();

    auto camera = new Qt3DRender::QCamera;
    camera->lens()->setPerspectiveProjection(45.0f, 1., 0.1f, 10000.0f);
    camera->setPosition(QVector3D(0, 0, 10));
    camera->setUpVector(QVector3D(0, 1, 0));
    camera->setViewCenter(QVector3D(0, 0, 0));

    view->defaultFrameGraph()->setCamera(camera);
    auto frameGraph = view->defaultFrameGraph();
    frameGraph->dumpObjectTree();
    auto camSelector = frameGraph->findChild<Qt3DRender::QCamera*>();
    auto renderCapture = new Qt3DRender::QRenderCapture(camSelector);
    frameGraph->dumpObjectTree();

    auto rootEntity = new Qt3DCore::QEntity();
    view->setRootEntity(rootEntity);

    auto sphere = transparentSphereEntity();
    sphere->setParent(rootEntity);

    auto btnScreenshot = new QPushButton("Take Screenshot");
    auto labelPixmap = new QLabel;
    frame->setLayout(new QHBoxLayout);
    frame->layout()->addWidget(QWidget::createWindowContainer(view));
    frame->layout()->addWidget(btnScreenshot);
    frame->layout()->addWidget(labelPixmap);
    frame->setMinimumSize(1000, 1000 / 3);
    frame->show();
    QObject::connect(btnScreenshot, &QPushButton::clicked, [&]() {
        QEventLoop loop;
        auto reply = renderCapture->requestCapture();
        QObject::connect(reply, &Qt3DRender::QRenderCaptureReply::completed, [&] {
            reply->image().save("./data/test.png");
            labelPixmap->setPixmap(QPixmap::fromImage(reply->image()));
            loop.quit();
            });
        loop.exec();
        });

    return a.exec();
}
4

0 回答 0