diff options
Diffstat (limited to 'src/quick/doc/snippets/qquickrhiitem/qquickrhiitem_intro.cpp')
-rw-r--r-- | src/quick/doc/snippets/qquickrhiitem/qquickrhiitem_intro.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/quick/doc/snippets/qquickrhiitem/qquickrhiitem_intro.cpp b/src/quick/doc/snippets/qquickrhiitem/qquickrhiitem_intro.cpp new file mode 100644 index 0000000000..3a3d1585bf --- /dev/null +++ b/src/quick/doc/snippets/qquickrhiitem/qquickrhiitem_intro.cpp @@ -0,0 +1,147 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QtQuick/QQuickRhiItem> +#include <rhi/qrhi.h> + +//![0] +class ExampleRhiItemRenderer : public QQuickRhiItemRenderer +{ +public: + void initialize(QRhiCommandBuffer *cb) override; + void synchronize(QQuickRhiItem *item) override; + void render(QRhiCommandBuffer *cb) override; + +private: + QRhi *m_rhi = nullptr; + std::unique_ptr<QRhiBuffer> m_vbuf; + std::unique_ptr<QRhiBuffer> m_ubuf; + std::unique_ptr<QRhiShaderResourceBindings> m_srb; + std::unique_ptr<QRhiGraphicsPipeline> m_pipeline; + QMatrix4x4 m_viewProjection; + float m_angle = 0.0f; +}; + +class ExampleRhiItem : public QQuickRhiItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(ExampleRhiItem) + Q_PROPERTY(float angle READ angle WRITE setAngle NOTIFY angleChanged) + +public: + QQuickRhiItemRenderer *createRenderer() override; + + float angle() const { return m_angle; } + void setAngle(float a); + +signals: + void angleChanged(); + +private: + float m_angle = 0.0f; +}; + +QQuickRhiItemRenderer *ExampleRhiItem::createRenderer() +{ + return new ExampleRhiItemRenderer; +} + +void ExampleRhiItem::setAngle(float a) +{ + if (m_angle == a) + return; + + m_angle = a; + emit angleChanged(); + update(); +} + +void ExampleRhiItemRenderer::synchronize(QQuickRhiItem *rhiItem) +{ + ExampleRhiItem *item = static_cast<ExampleRhiItem *>(rhiItem); + if (item->angle() != m_angle) + m_angle = item->angle(); +} + +static QShader getShader(const QString &name) +{ + QFile f(name); + return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); +} + +static float vertexData[] = { + 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, +}; + +void ExampleRhiItemRenderer::initialize(QRhiCommandBuffer *cb) +{ + if (m_rhi != rhi()) { + m_pipeline.reset(); + m_rhi = rhi(); + } + + if (!m_pipeline) { + m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData))); + m_vbuf->create(); + + m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64)); + m_ubuf->create(); + + m_srb.reset(m_rhi->newShaderResourceBindings()); + m_srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, m_ubuf.get()), + }); + m_srb->create(); + + m_pipeline.reset(m_rhi->newGraphicsPipeline()); + m_pipeline->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String(":/shaders/color.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String(":/shaders/color.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 5 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } + }); + m_pipeline->setVertexInputLayout(inputLayout); + m_pipeline->setShaderResourceBindings(m_srb.get()); + m_pipeline->setRenderPassDescriptor(renderTarget()->renderPassDescriptor()); + m_pipeline->create(); + + QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch(); + resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData); + cb->resourceUpdate(resourceUpdates); + } + + const QSize outputSize = renderTarget()->pixelSize(); + m_viewProjection = m_rhi->clipSpaceCorrMatrix(); + m_viewProjection.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f); + m_viewProjection.translate(0, 0, -4); +} + +void ExampleRhiItemRenderer::render(QRhiCommandBuffer *cb) +{ + QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch(); + QMatrix4x4 modelViewProjection = m_viewProjection; + modelViewProjection.rotate(m_angle, 0, 1, 0); + resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData()); + + const QColor clearColor = QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f); + cb->beginPass(renderTarget(), clearColor, { 1.0f, 0 }, resourceUpdates); + + cb->setGraphicsPipeline(m_pipeline.get()); + const QSize outputSize = renderTarget()->pixelSize(); + cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height())); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(3); + + cb->endPass(); +} +//![0] |