-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
120 lines (102 loc) · 3.29 KB
/
main.cpp
File metadata and controls
120 lines (102 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <QApplication>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQuickGraphicsDevice>
#include <QQuickItem>
#include <QQuickRenderControl>
#include <QQuickRenderTarget>
#include <QQuickWindow>
#include <QSurfaceFormat>
int main(int argc, char **argv) {
QGuiApplication app(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription("Offscreen Qt Quick Renderer");
parser.addHelpOption();
QCommandLineOption outputOption({"o", "output"}, "Path to output image",
"output");
parser.addOption(outputOption);
parser.process(app);
QString outputPath = parser.value(outputOption);
if (outputPath.isEmpty()) {
qCritical() << "No output path specified. Use --output <path> or -o <path>";
return 1;
}
QSurfaceFormat format;
format.setMajorVersion(4);
format.setMinorVersion(6);
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setRenderableType(QSurfaceFormat::OpenGL);
} else {
format.setRenderableType(QSurfaceFormat::OpenGLES);
}
QOpenGLContext gl_ctx;
gl_ctx.setFormat(format);
gl_ctx.create();
if (!gl_ctx.isValid()) {
return 1;
}
QOffscreenSurface surface;
surface.setFormat(format);
surface.create();
if (!surface.isValid()) {
return 1;
}
gl_ctx.makeCurrent(&surface);
QQmlEngine engine;
QQmlComponent component{&engine};
// Create a QQuickWindow that will render the scene to a custom fb
QQuickRenderControl control;
QQuickWindow window{&control};
window.setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(&gl_ctx));
if (!control.initialize()) {
qDebug() << "Failed to initialize QQuickRenderControl";
return 0;
}
// Viewport size
QSize fb_size{400, 300};
// A custom framebuffer for rendering.
QOpenGLFramebufferObject fb{fb_size,
QOpenGLFramebufferObject::CombinedDepthStencil};
// Set the custom framebuffer's texture as the render target for the
// Qt Quick window.
auto tg = QQuickRenderTarget::fromOpenGLTexture(fb.texture(), fb.size());
window.setRenderTarget(tg);
QObject::connect(
&control, &QQuickRenderControl::sceneChanged, &control,
[&] {
control.polishItems();
control.beginFrame();
control.sync();
control.render();
control.endFrame();
// To simplify, just save the image.
fb.toImage().save(outputPath);
},
Qt::QueuedConnection);
// Reparent the loaded component to the quick window.
QObject::connect(&component, &QQmlComponent::statusChanged, [&] {
QObject *rootObject = component.create();
if (component.isError()) {
QList<QQmlError> errorList = component.errors();
foreach (const QQmlError &error, errorList)
qWarning() << error.url() << error.line() << error;
return;
}
auto rootItem = qobject_cast<QQuickItem *>(rootObject);
if (!rootItem) {
qWarning("run: Not a QQuickItem");
delete rootObject;
return;
}
rootItem->setParentItem(window.contentItem());
});
// Load qml.
component.loadUrl(QUrl::fromLocalFile("main.qml"));
return app.exec();
}