// Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const constexpr auto vertex_shader = R"_(#version 450 /** * Unicode comment: Ѧ𝙱ƇᗞΣ */ layout(location = 0) in vec3 vertexPosition; layout(location = 1) in vec3 vertexColor; layout(location = 0) out vec3 color; layout(std140, binding = 0) uniform qt3d_render_view_uniforms { mat4 viewMatrix; mat4 projectionMatrix; mat4 uncorrectedProjectionMatrix; mat4 clipCorrectionMatrix; mat4 viewProjectionMatrix; mat4 inverseViewMatrix; mat4 inverseProjectionMatrix; mat4 inverseViewProjectionMatrix; mat4 viewportMatrix; mat4 inverseViewportMatrix; vec4 textureTransformMatrix; vec3 eyePosition; float aspectRatio; float gamma; float exposure; float time; }; layout(std140, binding = 1) uniform qt3d_command_uniforms { mat4 modelMatrix; mat4 inverseModelMatrix; mat4 modelViewMatrix; mat3 modelNormalMatrix; mat4 inverseModelViewMatrix; mat4 mvp; mat4 inverseModelViewProjectionMatrix; }; void main() { color = vertexColor; gl_Position = mvp * vec4(vertexPosition, 1.0); } )_"; static const constexpr auto fragment_shader = R"_(#version 450 /** * Unicode comment: Ѧ𝙱ƇᗞΣ */ layout(location = 0) out vec4 fragColor; layout(location = 0) in vec3 color; layout(std140, binding = 0) uniform qt3d_render_view_uniforms { mat4 viewMatrix; mat4 projectionMatrix; mat4 uncorrectedProjectionMatrix; mat4 clipCorrectionMatrix; mat4 viewProjectionMatrix; mat4 inverseViewMatrix; mat4 inverseProjectionMatrix; mat4 inverseViewProjectionMatrix; mat4 viewportMatrix; mat4 inverseViewportMatrix; vec4 textureTransformMatrix; vec3 eyePosition; float aspectRatio; float gamma; float exposure; float time; }; layout(std140, binding = 1) uniform qt3d_command_uniforms { mat4 modelMatrix; mat4 inverseModelMatrix; mat4 modelViewMatrix; mat3 modelNormalMatrix; mat4 inverseModelViewMatrix; mat4 mvp; mat4 inverseModelViewProjectionMatrix; }; layout(std140, binding = 2) uniform custom_ubo { vec3 colorFactor; }; layout(binding = 3) uniform sampler2D myTexture; void main() { vec2 texCoord = color.xz; vec2 rhiTexCoord = textureTransformMatrix.xy * texCoord+ textureTransformMatrix.zw; fragColor = vec4(color * colorFactor, 1.0); fragColor *= texture(myTexture, rhiTexCoord); } )_"; class Material : public Qt3DRender::QMaterial { public: explicit Material(Qt3DCore::QNode *parent = nullptr) : QMaterial(parent) , m_effect(new Qt3DRender::QEffect(this)) { setEffect(m_effect); m_testParam = new Qt3DRender::QParameter(QStringLiteral("example"), float(0.5)); m_effect->addParameter(m_testParam); m_filter = new Qt3DRender::QFilterKey(this); m_filter->setName(QStringLiteral("renderingStyle")); m_filter->setValue(QStringLiteral("forward")); m_technique = new Qt3DRender::QTechnique(m_effect); m_technique->addFilterKey(m_filter); m_effect->addTechnique(m_technique); m_program = new Qt3DRender::QShaderProgram(m_effect); m_program->setVertexShaderCode(vertex_shader); m_program->setFragmentShaderCode(fragment_shader); m_renderPass = new Qt3DRender::QRenderPass(m_effect); m_renderPass->setShaderProgram(m_program); m_technique->addRenderPass(m_renderPass); m_technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::RHI); } private: Qt3DRender::QEffect *m_effect{}; Qt3DRender::QParameter *m_testParam{}; Qt3DRender::QFilterKey *m_filter{}; Qt3DRender::QTechnique *m_technique{}; Qt3DRender::QShaderProgram *m_program{}; Qt3DRender::QRenderPass *m_renderPass{}; }; int main(int argc, char* argv[]) { qputenv("QT3D_RENDERER", "rhi"); QGuiApplication app(argc, argv); auto api = Qt3DRender::API::OpenGL; if (argc >= 2) { #ifdef Q_OS_WIN if (argv[1] == QByteArrayLiteral("--d3d11")) api = Qt3DRender::API::DirectX; #endif #if QT_CONFIG(qt3d_vulkan) if (argv[1] == QByteArrayLiteral("--vulkan")) api = Qt3DRender::API::Vulkan; #endif #if defined(Q_OS_MACOS) || defined(Q_OS_IOS) if (argv[1] == QByteArrayLiteral("--metal")) api = Qt3DRender::API::Metal; #endif } Qt3DExtras::Qt3DWindow view{nullptr, api}; // Root entity Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); // Camera Qt3DRender::QCamera *topViewCamera = new Qt3DRender::QCamera(rootEntity); topViewCamera->setPosition(QVector3D(0, 40, 0)); topViewCamera->setViewCenter(QVector3D(0, 0, 0)); topViewCamera->setUpVector(QVector3D(0, 0, 1)); topViewCamera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); Qt3DRender::QCamera *cameraEntity = view.camera(); cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); cameraEntity->setPosition(QVector3D(0, 0, 40.0f)); cameraEntity->setUpVector(QVector3D(0, 1, 0)); cameraEntity->setViewCenter(QVector3D(0, 0, 0)); { // Custom FG auto *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector(); surfaceSelector->setSurface(&view); // RV 1 auto *clearBuffer = new Qt3DRender::QClearBuffers(surfaceSelector); clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer); clearBuffer->setClearColor(QColor::fromRgbF(0.1, 0.5, 0.0, 1.0)); auto *noDraw = new Qt3DRender::QNoDraw(clearBuffer); Q_UNUSED(noDraw); // RV 2 auto *cameraSelector1 = new Qt3DRender::QCameraSelector(surfaceSelector); cameraSelector1->setCamera(view.camera()); auto *viewport1 = new Qt3DRender::QViewport(cameraSelector1); viewport1->setNormalizedRect(QRectF(0.0f, 0.0f, 0.5f, 0.5f)); // RV3 auto *cameraSelector2 = new Qt3DRender::QCameraSelector(surfaceSelector); cameraSelector2->setCamera(topViewCamera); auto *viewport2 = new Qt3DRender::QViewport(cameraSelector2); viewport2->setNormalizedRect(QRectF(0.5f, 0.5f, 0.5f, 0.5f)); view.setActiveFrameGraph(surfaceSelector); } QTimer *cameraAnimationTimer = new QTimer(&view); QObject::connect(cameraAnimationTimer, &QTimer::timeout, [cameraEntity] { static int angle = 0; const float radius = 40.0f; const float anglef = qDegreesToRadians(float(angle)); cameraEntity->setPosition(QVector3D(qSin(anglef), 0.0f, qCos(anglef)) * radius); angle += 1; }); cameraAnimationTimer->start(16); // For camera controls Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity); camController->setCamera(cameraEntity); // Material Qt3DRender::QMaterial *material = new Material(rootEntity); Qt3DRender::QParameter *parameter = new Qt3DRender::QParameter(QStringLiteral("colorFactor"), QColor(Qt::white)); material->addParameter(parameter); Qt3DRender::QTextureLoader *textureLoader = new Qt3DRender::QTextureLoader{}; textureLoader->setSource(QUrl{QStringLiteral("qrc:///qtlogo.png")}); Qt3DRender::QParameter *texture = new Qt3DRender::QParameter(QStringLiteral("myTexture"), textureLoader); material->addParameter(texture); QTimer *parameterAnimationTimer = new QTimer(&view); QObject::connect(parameterAnimationTimer, &QTimer::timeout, [parameter] { static int angle = 0; const float anglef = qDegreesToRadians(float(angle)); parameter->setValue(QColor::fromRgbF(fabs(qCos(anglef)), fabs(qSin(anglef)), 1.0f)); angle += 10; }); parameterAnimationTimer->start(16); // Torus Qt3DCore::QEntity *customMeshEntity = new Qt3DCore::QEntity(rootEntity); // Transform Qt3DCore::QTransform *transform = new Qt3DCore::QTransform; transform->setScale(8.0f); // Custom Mesh (TetraHedron) Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer; Qt3DCore::QGeometryView *customMeshView = new Qt3DCore::QGeometryView; Qt3DCore::QGeometry *customGeometry = new Qt3DCore::QGeometry; Qt3DCore::QBuffer *vertexDataBuffer = new Qt3DCore::QBuffer(customGeometry); Qt3DCore::QBuffer *indexDataBuffer = new Qt3DCore::QBuffer(customGeometry); // 5 vertices of 3 vertices + 3 colors QByteArray vertexBufferData; vertexBufferData.resize(5 * (3 + 3) * sizeof(float)); // Vertices QVector3D v0(-1.0f, 0.0f, -1.0f); QVector3D v1(1.0f, 0.0f, -1.0f); QVector3D v2(-1.0f, 0.0f, 1.0f); QVector3D v3(1.0f, 0.0f, 1.0f); QVector3D v4(0.0f, 2.0f, 0.0f); QVector3D red(1.0f, 0.0f, 0.0f); QVector3D green(0.0f, 1.0f, 0.0f); QVector3D blue(0.0f, 0.0f, 1.0f); QVector3D white(1.0f, 1.0f, 1.0f); QVector3D grey(0.5f, 0.5f, 0.5f); const QList vertices = { v0, red, v1, green, v2, blue, v3, grey, v4, white }; memcpy(vertexBufferData.data(), vertices.constData(), vertices.size() * sizeof(QVector3D)); vertexDataBuffer->setData(vertexBufferData); QByteArray indexBufferData; // 6 triangle faces indexBufferData.resize(6 * 3 * sizeof(ushort)); ushort *rawIndexArray = reinterpret_cast(indexBufferData.data()); rawIndexArray[0] = 0; rawIndexArray[1] = 1; rawIndexArray[2] = 2; rawIndexArray[3] = 2; rawIndexArray[4] = 1; rawIndexArray[5] = 3; rawIndexArray[6] = 2; rawIndexArray[7] = 3; rawIndexArray[8] = 4; rawIndexArray[9] = 3; rawIndexArray[10] = 1; rawIndexArray[11] = 4; rawIndexArray[12] = 1; rawIndexArray[13] = 0; rawIndexArray[14] = 4; rawIndexArray[15] = 0; rawIndexArray[16] = 2; rawIndexArray[17] = 4; indexDataBuffer->setData(indexBufferData); // Attributes Qt3DCore::QAttribute *positionAttribute = new Qt3DCore::QAttribute(); positionAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute); positionAttribute->setBuffer(vertexDataBuffer); positionAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float); positionAttribute->setVertexSize(3); positionAttribute->setByteOffset(0); positionAttribute->setByteStride(6 * sizeof(float)); positionAttribute->setCount(5); positionAttribute->setName(Qt3DCore::QAttribute::defaultPositionAttributeName()); Qt3DCore::QAttribute *colorAttribute = new Qt3DCore::QAttribute(); colorAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute); colorAttribute->setBuffer(vertexDataBuffer); colorAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float); colorAttribute->setVertexSize(3); colorAttribute->setByteOffset(3 * sizeof(float)); colorAttribute->setByteStride(6 * sizeof(float)); colorAttribute->setCount(5); colorAttribute->setName(Qt3DCore::QAttribute::defaultColorAttributeName()); Qt3DCore::QAttribute *indexAttribute = new Qt3DCore::QAttribute(); indexAttribute->setAttributeType(Qt3DCore::QAttribute::IndexAttribute); indexAttribute->setBuffer(indexDataBuffer); indexAttribute->setVertexBaseType(Qt3DCore::QAttribute::UnsignedShort); indexAttribute->setVertexSize(1); indexAttribute->setByteOffset(0); indexAttribute->setByteStride(0); indexAttribute->setCount(18); customGeometry->addAttribute(positionAttribute); customGeometry->addAttribute(colorAttribute); customGeometry->addAttribute(indexAttribute); customMeshView->setPrimitiveType(Qt3DCore::QGeometryView::Triangles); customMeshView->setGeometry(customGeometry); customMeshRenderer->setView(customMeshView); customMeshEntity->addComponent(customMeshRenderer); customMeshEntity->addComponent(transform); customMeshEntity->addComponent(material); view.setRootEntity(rootEntity); view.show(); return app.exec(); }