1/****************************************************************************
2**
3** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QGuiApplication>
52
53#include <Qt3DCore/QEntity>
54#include <Qt3DRender/QCamera>
55#include <Qt3DRender/QCameraLens>
56#include <Qt3DCore/QTransform>
57#include <Qt3DCore/QAspectEngine>
58
59#include <Qt3DInput/QInputAspect>
60
61#include <Qt3DRender/QRenderStateSet>
62#include <Qt3DRender/QRenderAspect>
63#include <Qt3DExtras/QForwardRenderer>
64#include <Qt3DExtras/QPerVertexColorMaterial>
65
66#include <Qt3DRender/QGeometryRenderer>
67#include <Qt3DRender/QGeometry>
68#include <Qt3DRender/QAttribute>
69#include <Qt3DRender/QBuffer>
70
71#include <QPropertyAnimation>
72#include <Qt3DExtras/qt3dwindow.h>
73#include <Qt3DExtras/qorbitcameracontroller.h>
74#include <Qt3DRender/QParameter>
75#include <Qt3DRender/QEffect>
76#include <Qt3DRender/QTechnique>
77#include <Qt3DRender/QAbstractTexture>
78#include <Qt3DRender/QShaderProgram>
79#include <Qt3DRender/QRenderPass>
80#include <Qt3DRender/QBlendEquation>
81#include <Qt3DRender/QBlendEquationArguments>
82#include <Qt3DRender/QFilterKey>
83#include <Qt3DRender/QGraphicsApiFilter>
84#include <Qt3DRender/QRenderSurfaceSelector>
85#include <Qt3DRender/QViewport>
86#include <Qt3DRender/QCameraSelector>
87#include <Qt3DRender/QNoDraw>
88#include <QColor>
89#include <QVector2D>
90#include <QUrl>
91#include <QTimer>
92#include <Qt3DRender/QMaterial>
93#include <Qt3DRender/QFilterKey>
94#include <Qt3DRender/QTechnique>
95#include <Qt3DRender/QMaterial>
96#include <Qt3DRender/QTexture>
97#include <qmath.h>
98
99static const constexpr auto vertex_shader = R"_(#version 450
100
101/**
102 * Unicode comment: Ѧ𝙱ƇᗞΣ
103 */
104
105layout(location = 0) in vec3 vertexPosition;
106layout(location = 1) in vec3 vertexColor;
107layout(location = 0) out vec3 color;
108
109layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
110 mat4 viewMatrix;
111 mat4 projectionMatrix;
112 mat4 viewProjectionMatrix;
113 mat4 inverseViewMatrix;
114 mat4 inverseProjectionMatrix;
115 mat4 inverseViewProjectionMatrix;
116 mat4 viewportMatrix;
117 mat4 inverseViewportMatrix;
118 vec4 textureTransformMatrix;
119 vec3 eyePosition;
120 float aspectRatio;
121 float gamma;
122 float exposure;
123 float time;
124};
125layout(std140, binding = 1) uniform qt3d_command_uniforms {
126 mat4 modelMatrix;
127 mat4 inverseModelMatrix;
128 mat4 modelViewMatrix;
129 mat3 modelNormalMatrix;
130 mat4 inverseModelViewMatrix;
131 mat4 mvp;
132 mat4 inverseModelViewProjectionMatrix;
133};
134void main()
135{
136 color = vertexColor;
137 gl_Position = mvp * vec4(vertexPosition, 1.0);
138}
139)_";
140
141static const constexpr auto fragment_shader = R"_(#version 450
142
143/**
144 * Unicode comment: Ѧ𝙱ƇᗞΣ
145 */
146
147layout(location = 0) out vec4 fragColor;
148layout(location = 0) in vec3 color;
149
150layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
151 mat4 viewMatrix;
152 mat4 projectionMatrix;
153 mat4 viewProjectionMatrix;
154 mat4 inverseViewMatrix;
155 mat4 inverseProjectionMatrix;
156 mat4 inverseViewProjectionMatrix;
157 mat4 viewportMatrix;
158 mat4 inverseViewportMatrix;
159 vec4 textureTransformMatrix;
160 vec3 eyePosition;
161 float aspectRatio;
162 float gamma;
163 float exposure;
164 float time;
165};
166layout(std140, binding = 1) uniform qt3d_command_uniforms {
167 mat4 modelMatrix;
168 mat4 inverseModelMatrix;
169 mat4 modelViewMatrix;
170 mat3 modelNormalMatrix;
171 mat4 inverseModelViewMatrix;
172 mat4 mvp;
173 mat4 inverseModelViewProjectionMatrix;
174};
175layout(std140, binding = 2) uniform custom_ubo {
176 vec3 colorFactor;
177};
178
179layout(binding = 3) uniform sampler2D myTexture;
180void main()
181{
182 vec2 texCoord = color.xz;
183 vec2 rhiTexCoord = textureTransformMatrix.xy * texCoord+ textureTransformMatrix.zw;
184 fragColor = vec4(color * colorFactor, 1.0);
185
186 fragColor *= texture(myTexture, rhiTexCoord);
187}
188
189)_";
190
191class Material : public Qt3DRender::QMaterial
192{
193public:
194 explicit Material(Qt3DCore::QNode *parent = nullptr)
195 : QMaterial(parent)
196 , m_effect(new Qt3DRender::QEffect(this))
197{
198 setEffect(m_effect);
199
200 m_testParam = new Qt3DRender::QParameter(QStringLiteral("example"), float(0.5));
201
202 m_effect->addParameter(parameter: m_testParam);
203
204 m_filter = new Qt3DRender::QFilterKey(this);
205 m_filter->setName(QStringLiteral("renderingStyle"));
206 m_filter->setValue(QStringLiteral("forward"));
207
208 m_technique = new Qt3DRender::QTechnique(m_effect);
209 m_technique->addFilterKey(filterKey: m_filter);
210
211 m_effect->addTechnique(t: m_technique);
212
213 m_program = new Qt3DRender::QShaderProgram(m_effect);
214 m_program->setVertexShaderCode(vertex_shader);
215 m_program->setFragmentShaderCode(fragment_shader);
216
217 m_renderPass = new Qt3DRender::QRenderPass(m_effect);
218
219 m_renderPass->setShaderProgram(m_program);
220
221 m_technique->addRenderPass(pass: m_renderPass);
222
223 m_technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::RHI);
224}
225private:
226 Qt3DRender::QEffect *m_effect{};
227 Qt3DRender::QParameter *m_testParam{};
228 Qt3DRender::QFilterKey *m_filter{};
229 Qt3DRender::QTechnique *m_technique{};
230 Qt3DRender::QShaderProgram *m_program{};
231 Qt3DRender::QRenderPass *m_renderPass{};
232};
233
234int main(int argc, char* argv[])
235{
236 qputenv(varName: "QT3D_RENDERER", value: "rhi");
237 QGuiApplication app(argc, argv);
238
239 auto api = Qt3DRender::API::OpenGL;
240 if (argc >= 2) {
241
242#ifdef Q_OS_WIN
243 if (argv[1] == QByteArrayLiteral("--d3d11")) api = Qt3DRender::API::DirectX;
244#endif
245
246#if QT_CONFIG(vulkan)
247 if (argv[1] == QByteArrayLiteral("--vulkan")) api = Qt3DRender::API::Vulkan;
248#endif
249
250#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
251 if (argv[1] == QByteArrayLiteral("--metal")) api = Qt3DRender::API::Metal;
252#endif
253 }
254
255 Qt3DExtras::Qt3DWindow view{nullptr, api};
256
257 // Root entity
258 Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
259
260 // Camera
261 Qt3DRender::QCamera *topViewCamera = new Qt3DRender::QCamera(rootEntity);
262 topViewCamera->setPosition(QVector3D(0, 40, 0));
263 topViewCamera->setViewCenter(QVector3D(0, 0, 0));
264 topViewCamera->setUpVector(QVector3D(0, 0, 1));
265 topViewCamera->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f);
266
267 Qt3DRender::QCamera *cameraEntity = view.camera();
268 cameraEntity->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f);
269 cameraEntity->setPosition(QVector3D(0, 0, 40.0f));
270 cameraEntity->setUpVector(QVector3D(0, 1, 0));
271 cameraEntity->setViewCenter(QVector3D(0, 0, 0));
272
273 {
274 // Custom FG
275 auto *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector();
276 surfaceSelector->setSurface(&view);
277
278 // RV 1
279 auto *clearBuffer = new Qt3DRender::QClearBuffers(surfaceSelector);
280 clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
281 clearBuffer->setClearColor(QColor::fromRgbF(r: 0.1, g: 0.5, b: 0.0, a: 1.0));
282 auto *noDraw = new Qt3DRender::QNoDraw(clearBuffer);
283
284 // RV 2
285 auto *cameraSelector1 = new Qt3DRender::QCameraSelector(surfaceSelector);
286 cameraSelector1->setCamera(view.camera());
287 auto *viewport1 = new Qt3DRender::QViewport(cameraSelector1);
288 viewport1->setNormalizedRect(QRectF(0.0f, 0.0f, 0.5f, 0.5f));
289
290 // RV3
291 auto *cameraSelector2 = new Qt3DRender::QCameraSelector(surfaceSelector);
292 cameraSelector2->setCamera(topViewCamera);
293 auto *viewport2 = new Qt3DRender::QViewport(cameraSelector2);
294 viewport2->setNormalizedRect(QRectF(0.5f, 0.5f, 0.5f, 0.5f));
295
296 view.setActiveFrameGraph(surfaceSelector);
297 }
298
299 QTimer *cameraAnimationTimer = new QTimer(&view);
300 QObject::connect(sender: cameraAnimationTimer, signal: &QTimer::timeout,
301 slot: [cameraEntity] {
302 static int angle = 0;
303 const float radius = 40.0f;
304 const float anglef = qDegreesToRadians(degrees: float(angle));
305 cameraEntity->setPosition(QVector3D(qSin(v: anglef), 0.0f, qCos(v: anglef)) * radius);
306 angle += 1;
307 });
308 cameraAnimationTimer->start(msec: 16);
309
310 // For camera controls
311 Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
312 camController->setCamera(cameraEntity);
313
314 // Material
315 Qt3DRender::QMaterial *material = new Material(rootEntity);
316 Qt3DRender::QParameter *parameter = new Qt3DRender::QParameter(QStringLiteral("colorFactor"), QColor(Qt::white));
317 material->addParameter(parameter);
318
319 Qt3DRender::QTextureLoader *textureLoader = new Qt3DRender::QTextureLoader{};
320 textureLoader->setSource(QUrl{QStringLiteral("qrc:///qtlogo.png")});
321 Qt3DRender::QParameter *texture = new Qt3DRender::QParameter(QStringLiteral("myTexture"), textureLoader);
322 material->addParameter(parameter: texture);
323
324 QTimer *parameterAnimationTimer = new QTimer(&view);
325 QObject::connect(sender: parameterAnimationTimer, signal: &QTimer::timeout,
326 slot: [parameter] {
327 static int angle = 0;
328 const float anglef = qDegreesToRadians(degrees: float(angle));
329 parameter->setValue(QColor::fromRgbF(r: fabs(x: qCos(v: anglef)), g: fabs(x: qSin(v: anglef)), b: 1.0f));
330 angle += 10;
331 });
332 parameterAnimationTimer->start(msec: 16);
333
334 // Torus
335 Qt3DCore::QEntity *customMeshEntity = new Qt3DCore::QEntity(rootEntity);
336
337 // Transform
338 Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
339 transform->setScale(8.0f);
340
341 // Custom Mesh (TetraHedron)
342 Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
343 Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
344
345 Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
346 Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
347
348 // 5 vertices of 3 vertices + 3 colors
349 QByteArray vertexBufferData;
350 vertexBufferData.resize(size: 5 * (3 + 3) * sizeof(float));
351
352 // Vertices
353 QVector3D v0(-1.0f, 0.0f, -1.0f);
354 QVector3D v1(1.0f, 0.0f, -1.0f);
355 QVector3D v2(-1.0f, 0.0f, 1.0f);
356 QVector3D v3(1.0f, 0.0f, 1.0f);
357 QVector3D v4(0.0f, 2.0f, 0.0f);
358
359 QVector3D red(1.0f, 0.0f, 0.0f);
360 QVector3D green(0.0f, 1.0f, 0.0f);
361 QVector3D blue(0.0f, 0.0f, 1.0f);
362 QVector3D white(1.0f, 1.0f, 1.0f);
363 QVector3D grey(0.5f, 0.5f, 0.5f);
364
365 const QVector<QVector3D> vertices = QVector<QVector3D>()
366 << v0 << red
367 << v1 << green
368 << v2 << blue
369 << v3 << grey
370 << v4 << white;
371
372 memcpy(dest: vertexBufferData.data(), src: vertices.constData(), n: vertices.size() * sizeof(QVector3D));
373 vertexDataBuffer->setData(vertexBufferData);
374
375 QByteArray indexBufferData;
376 // 6 triangle faces
377 indexBufferData.resize(size: 6 * 3 * sizeof(ushort));
378 ushort *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data());
379
380 rawIndexArray[0] = 0;
381 rawIndexArray[1] = 1;
382 rawIndexArray[2] = 2;
383
384 rawIndexArray[3] = 2;
385 rawIndexArray[4] = 1;
386 rawIndexArray[5] = 3;
387
388 rawIndexArray[6] = 2;
389 rawIndexArray[7] = 3;
390 rawIndexArray[8] = 4;
391
392 rawIndexArray[9] = 3;
393 rawIndexArray[10] = 1;
394 rawIndexArray[11] = 4;
395
396 rawIndexArray[12] = 1;
397 rawIndexArray[13] = 0;
398 rawIndexArray[14] = 4;
399
400 rawIndexArray[15] = 0;
401 rawIndexArray[16] = 2;
402 rawIndexArray[17] = 4;
403
404 indexDataBuffer->setData(indexBufferData);
405
406 // Attributes
407 Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
408 positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
409 positionAttribute->setBuffer(vertexDataBuffer);
410 positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
411 positionAttribute->setVertexSize(3);
412 positionAttribute->setByteOffset(0);
413 positionAttribute->setByteStride(6 * sizeof(float));
414 positionAttribute->setCount(5);
415 positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
416
417 Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
418 colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
419 colorAttribute->setBuffer(vertexDataBuffer);
420 colorAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
421 colorAttribute->setVertexSize(3);
422 colorAttribute->setByteOffset(3 * sizeof(float));
423 colorAttribute->setByteStride(6 * sizeof(float));
424 colorAttribute->setCount(5);
425 colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName());
426
427 Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute();
428 indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
429 indexAttribute->setBuffer(indexDataBuffer);
430 indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
431 indexAttribute->setVertexSize(1);
432 indexAttribute->setByteOffset(0);
433 indexAttribute->setByteStride(0);
434 indexAttribute->setCount(18);
435
436 customGeometry->addAttribute(attribute: positionAttribute);
437 customGeometry->addAttribute(attribute: colorAttribute);
438 customGeometry->addAttribute(attribute: indexAttribute);
439
440 customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
441 customMeshRenderer->setGeometry(customGeometry);
442
443 customMeshEntity->addComponent(comp: customMeshRenderer);
444 customMeshEntity->addComponent(comp: transform);
445 customMeshEntity->addComponent(comp: material);
446
447 view.setRootEntity(rootEntity);
448 view.show();
449
450 return app.exec();
451}
452

source code of qt3d/tests/manual/rhi/main.cpp