我们公司需要捕捉一个Qt3d场景的渲染。为此,我创建了一个小示例应用程序,它说明了我们捕获的用法。
在左侧,您将找到 3D 场景,在右侧有QLabel
一个QPixmap
显示捕获屏幕的 3D 场景。
现在,由于某种原因,我真的不明白捕获的屏幕截图与左侧的 3D 场景相比看起来确实不同。QLabel
与右侧相比,保存的 PNG 图像看起来更令人困惑,但实际上我对我的用例中的 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();
}