QSGRenderNode Class

Die Klasse QSGRenderNode stellt eine Reihe von benutzerdefinierten Rendering-Befehlen dar, die auf die Grafik-API abzielen, die vom Scenegraph verwendet wird. Mehr...

Kopfzeile: #include <QSGRenderNode>
CMake: find_package(Qt6 REQUIRED COMPONENTS Quick)
target_link_libraries(mytarget PRIVATE Qt6::Quick)
qmake: QT += quick
Vererbungen: QSGNode

Öffentliche Typen

enum RenderingFlag { BoundedRectRendering, DepthAwareRendering, OpaqueRendering, NoExternalRendering }
flags RenderingFlags
enum StateFlag { DepthState, StencilState, ScissorState, ColorState, BlendState, …, RenderTargetState }
flags StateFlags

Öffentliche Funktionen

virtual ~QSGRenderNode() override
virtual QSGRenderNode::StateFlags changedStates() const
const QSGClipNode *clipList() const
(since 6.6) QRhiCommandBuffer *commandBuffer() const
virtual QSGRenderNode::RenderingFlags flags() const
qreal inheritedOpacity() const
const QMatrix4x4 *matrix() const
(since 6.0) virtual void prepare()
(since 6.5) const QMatrix4x4 *projectionMatrix() const
virtual QRectF rect() const
virtual void releaseResources()
virtual void render(const QSGRenderNode::RenderState *state) = 0
(since 6.6) QRhiRenderTarget *renderTarget() const

Detaillierte Beschreibung

QSGRenderNode ermöglicht das Erstellen von Szenengraph-Knoten, die ihr eigenes benutzerdefiniertes Rendering über QRhi (der übliche Ansatz ab Qt 6.6), direkt über eine 3D-Grafik-API wie OpenGL, Vulkan oder Metal, oder, wenn das software Backend verwendet wird, über QPainter durchführen.

QSGRenderNode ist der Enabler für eine der drei Möglichkeiten, benutzerdefiniertes 2D/3D-Rendering in eine Qt Quick Szene zu integrieren. Die anderen beiden Möglichkeiten sind, das Rendering before oder after der Qt Quick Szene selbst durchzuführen, oder einen separaten Renderdurchgang zu erzeugen, der auf ein spezielles Renderziel (eine Textur) abzielt und dann ein Element in der Szene die Textur anzeigen zu lassen. Der QSGRenderNode-basierte Ansatz ähnelt dem ersteren, in dem Sinne, dass keine zusätzlichen Render-Passes oder Render-Ziele involviert sind, und erlaubt es, benutzerdefinierte Rendering-Befehle "inline" mit dem eigenen Rendering der Qt Quick Szene zu injizieren.

Siehe auch Scene Graph - Benutzerdefinierte QSGRenderNode.

Member Typ Dokumentation

enum QSGRenderNode::RenderingFlag
flags QSGRenderNode::RenderingFlags

Mögliche Werte für die von flags() zurückgegebene Bitmaske.

KonstanteWertBeschreibung
QSGRenderNode::BoundedRectRendering0x01Gibt an, dass die Implementierung von render() nicht außerhalb des von rect() in Elementkoordinaten gemeldeten Bereichs rendert. Solche Node-Implementierungen können zu einem effizienteren Rendering führen, abhängig vom Scenegraph-Backend. Zum Beispiel kann das software Backend weiterhin den optimaleren partiellen Aktualisierungspfad verwenden, wenn alle Renderknoten in der Szene dieses Flag gesetzt haben.
QSGRenderNode::DepthAwareRendering0x02Zeigt an, dass die Implementierungen von render() den Erwartungen des Scenegraphs entsprechen, indem sie nur einen Z-Wert von 0 in Szenekoordinaten erzeugen, der dann durch die Matrizen transformiert wird, die von RenderState::projectionMatrix() und matrix() abgerufen werden, wie in den Anmerkungen zu render() beschrieben. Solche Node-Implementierungen können zu einem effizienteren Rendering führen, abhängig vom Scenegraph Backend. Zum Beispiel kann der Batching-OpenGL-Renderer weiterhin einen optimaleren Pfad verwenden, wenn alle Renderknoten in der Szene dieses Flag gesetzt haben.
QSGRenderNode::OpaqueRendering0x04Gibt an, dass die Implementierung von render() undurchsichtige Pixel für den gesamten von rect() gemeldeten Bereich ausgibt. Standardmäßig müssen die Renderer davon ausgehen, dass render() auch halb- oder vollständig transparente Pixel ausgeben kann. Das Setzen dieses Flags kann in einigen Fällen die Leistung verbessern.
QSGRenderNode::NoExternalRendering0x08Zeigt an, dass die Implementierung von prepare() und render() die API-Familie QRhi verwendet, anstatt direkt eine 3D-API wie OpenGL, Vulkan oder Metal aufzurufen.

Der Typ RenderingFlags ist ein Typedef für QFlags<RenderingFlag>. Er speichert eine ODER-Kombination von RenderingFlag-Werten.

Siehe auch render(), prepare(), rect(), und QRhi.

enum QSGRenderNode::StateFlag
flags QSGRenderNode::StateFlags

Diese Aufzählung ist eine Bitmaske, die verschiedene Zustände identifiziert.

KonstanteWertBeschreibung
QSGRenderNode::DepthState0x01Tiefe
QSGRenderNode::StencilState0x02Schablone
QSGRenderNode::ScissorState0x04Schere
QSGRenderNode::ColorState0x08Farbe
QSGRenderNode::BlendState0x10Mischen
QSGRenderNode::CullState0x20Ausschneiden
QSGRenderNode::ViewportState0x40Ansicht poirt
QSGRenderNode::RenderTargetState0x80Ziel rendern

Der Typ StateFlags ist ein Typedef für QFlags<StateFlag>. Er speichert eine ODER-Kombination von StateFlag-Werten.

Dokumentation der Mitgliedsfunktionen

[override virtual noexcept] QSGRenderNode::~QSGRenderNode()

Zerstört den Renderknoten. Von abgeleiteten Klassen wird erwartet, dass sie hier ähnliche Aufräumarbeiten wie releaseResources() durchführen.

Wenn eine Low-Level-Grafik-API verwendet wird, stellt der Scenegraph sicher, dass es eine CPU-seitige Wartezeit für die GPU gibt, um alle an die Grafik-Befehlswarteschlange des Scenegraphs übermittelten Arbeiten abzuschließen, bevor die Knoten des Scenegraphs gelöscht werden. Daher ist es nicht notwendig, hier zusätzliche Wartezeiten einzurichten, es sei denn, die Implementierung von render() verwendet zusätzliche Befehlswarteschlangen.

Bei QRhi und Ressourcen wie QRhiBuffer, QRhiTexture, QRhiGraphicsPipeline, etc. ist es oft eine gute Praxis, intelligente Zeiger wie std::unique_ptr zu verwenden, die oft die Notwendigkeit vermeiden, einen Destruktor zu implementieren, und zu kompakterem Quellcode führen. Beachten Sie jedoch, dass die Implementierung von releaseResources(), die höchstwahrscheinlich eine Reihe von reset()-Aufrufen für die unique_ptrs auslöst, immer noch wichtig ist.

Siehe auch releaseResources().

[virtual] QSGRenderNode::StateFlags QSGRenderNode::changedStates() const

Wenn die zugrundeliegende Rendering-API OpenGL ist, sollte diese Funktion eine Maske zurückgeben, bei der jedes Bit einen durch die Funktion render() geänderten Grafikstatus darstellt:

KonstanteBeschreibung
DepthStatedepth write mask, depth test enabled, depth comparison function
StencilStatestencil write masks, stencil test enabled, stencil operations, stencil comparison functions
ScissorStatescissor aktiviert, scissor test aktiviert
ColorStateFarbe löschen, Farbschreibmaske
BlendStateÜberblenden aktiviert, Überblendfunktion
CullStateFrontfläche, Cull Face aktiviert
ViewportStateAnsichtsfenster
RenderTargetStateRendering-Ziel

Bei anderen APIs als OpenGL sind nur die Werte relevant, die dynamischen Zustandsänderungen entsprechen, die in der Befehlsliste/dem Puffer aufgezeichnet werden. Zum Beispiel RSSetViewports, RSSetScissorRects, OMSetBlendState, OMSetDepthStencilState im Falle von D3D11, oder vkCmdSetViewport, vkCmdSetScissor, vkCmdSetBlendConstants, vkCmdSetStencilRef im Falle von Vulkan, und auch nur dann, wenn solche Befehle zur Befehlsliste des Szenegraphen hinzugefügt wurden, die über das QSGRendererInterface abgefragt wird::CommandList Ressourcen-Enum abgefragt werden. Zustände, die in Pipeline-Zustandsobjekten gesetzt wurden, müssen hier nicht gemeldet werden. Ebenso werden Einstellungen, die sich auf Zeichenaufrufe beziehen (Pipeline-Zustände, Deskriptor-Sets, Vertex- oder Indexpuffer-Bindungen, Root-Signatur, Deskriptor-Heaps, etc.), immer wieder vom Scenegraph gesetzt, so dass render() sie frei ändern kann.

RenderTargetState wird bei APIs wie Vulkan nicht mehr unterstützt. Das liegt in der Natur der Sache. render() wird aufgerufen, während der Haupt-Befehlspuffer des Qt Quick -Szenegraphs einen Renderpass aufzeichnet, so dass es keine Möglichkeit gibt, das Ziel zu ändern und einen weiteren Renderpass zu starten (zumindest nicht in diesem Befehlspuffer). Daher ist die Rückgabe eines Wertes mit RenderTargetState nicht sinnvoll.

Hinweis: Das Backend software stellt seine QPainter zur Verfügung und speichert und stellt vor und nach dem Aufruf von render() wieder her. Daher ist es nicht notwendig, geänderte Zustände von hier aus zu melden.

Die Funktion wird vom Renderer aufgerufen, damit er die Zustände nach dem Rendering dieses Knotens zurücksetzen kann. Dies macht die Implementierung von render() einfacher, da sie diese Zustände nicht abfragen und wiederherstellen muss.

Die Standardimplementierung gibt 0 zurück, was bedeutet, dass kein relevanter Zustand in render() geändert wurde.

Hinweis: Diese Funktion kann vor render() aufgerufen werden.

Hinweis: Bei Qt 6 und QRhi-basiertem Rendering sind die einzigen relevanten Werte ViewportState und ScissorState. Andere Werte können zurückgegeben werden, werden aber in der Praxis ignoriert.

const QSGClipNode *QSGRenderNode::clipList() const

Gibt die aktuelle Clip-Liste zurück.

[since 6.6] QRhiCommandBuffer *QSGRenderNode::commandBuffer() const

Gibt den aktuellen Befehlspuffer zurück.

Diese Funktion wurde in Qt 6.6 eingeführt.

Siehe auch renderTarget().

[virtual] QSGRenderNode::RenderingFlags QSGRenderNode::flags() const

Gibt Flags zurück, die das Verhalten dieses Renderknotens beschreiben.

Die Standardimplementierung gibt 0 zurück.

Siehe auch RenderingFlag und rect().

qreal QSGRenderNode::inheritedOpacity() const

Gibt die aktuelle effektive Deckkraft zurück.

const QMatrix4x4 *QSGRenderNode::matrix() const

Gibt den Zeiger auf die aktuelle Model-View-Matrix zurück.

[virtual, since 6.0] void QSGRenderNode::prepare()

Wird in der Phase der Rahmenvorbereitung aufgerufen. Ein Aufruf dieser Funktion erfolgt vor jedem Aufruf von render().

Im Gegensatz zu render() wird diese Funktion aufgerufen, bevor der Scenegraph mit der Aufzeichnung des Rendering-Passes für das aktuelle Bild im zugrunde liegenden Befehlspuffer beginnt. Dies ist nützlich beim Rendering mit Grafik-APIs wie Vulkan, wo Kopiervorgänge vor dem Rendering-Durchgang aufgezeichnet werden müssen.

Die Standardimplementierung ist leer.

Wenn Sie ein QSGRenderNode implementieren, das QRhi zum Rendern verwendet, fragen Sie das QRhi -Objekt vom QQuickWindow über QQuickWindow::rhi() ab. Um ein QRhiCommandBuffer für die Übermittlung von Arbeit zu erhalten, rufen Sie commandBuffer() auf. Um Informationen über das aktive Rendering-Ziel abzufragen, rufen Sie renderTarget() auf. Siehe das Beispiel {Scene Graph - Custom QSGRenderNode} für Details.

Diese Funktion wurde in Qt 6.0 eingeführt.

[since 6.5] const QMatrix4x4 *QSGRenderNode::projectionMatrix() const

Gibt einen Zeiger auf die aktuelle Projektionsmatrix zurück.

In render() ist dies die gleiche Matrix, die von RenderState::projectionMatrix() zurückgegeben wird. Dieser Getter existiert, damit prepare() auch eine Möglichkeit hat, die Projektionsmatrix abzufragen.

Wenn man mit einer modernen Grafik-API oder der Qt-eigenen Grafikabstraktionsschicht arbeitet, ist es mehr als wahrscheinlich, dass man *projectionMatrix() * *matrix() in einen einheitlichen Puffer laden möchte. Das ist jedoch etwas, das in prepare() gemacht werden muss, also außerhalb der Aufzeichnung eines Renderpasses. Deshalb sind beide Matrizen direkt aus QSGRenderNode abfragbar, sowohl in prepare() als auch in render().

Diese Funktion wurde in Qt 6.5 eingeführt.

[virtual] QRectF QSGRenderNode::rect() const

Liefert das Begrenzungsrechteck in Elementkoordinaten für den Bereich, den render() berührt. Der Wert wird nur verwendet, wenn flags() BoundedRectRendering enthält, ansonsten wird er ignoriert.

Die Angabe des Rechtecks in Kombination mit BoundedRectRendering ist besonders wichtig für das software Backend, da andernfalls ein Rendernode in der Szene Vollbild-Updates auslösen würde, wodurch alle Optimierungen für partielle Updates übersprungen würden.

Für Rendernodes, die den gesamten Bereich eines entsprechenden QQuickItem abdecken, wird der Rückgabewert (0, 0, item->width(), item->height()) sein.

Hinweis: Es steht den Knoten auch frei, außerhalb der durch die Breite und Höhe des Elements festgelegten Grenzen zu rendern, da die Knoten des Szenegraphen nicht durch die Geometrie von QQuickItem begrenzt sind, solange dies von dieser Funktion korrekt gemeldet wird.

Siehe auch flags().

[virtual] void QSGRenderNode::releaseResources()

Diese Funktion wird aufgerufen, wenn alle von diesem Knoten zugewiesenen benutzerdefinierten Grafikressourcen sofort wieder freigegeben werden müssen. Falls der Knoten die Grafikressourcen (Puffer, Texturen, Renderziele, Fences usw.) nicht direkt über die verwendete Grafik-API zuweist, gibt es hier nichts zu tun.

Wenn Sie nicht alle benutzerdefinierten Ressourcen freigeben, kann dies auf einigen Systemen zu einem falschen Verhalten beim Ausfall von Grafikgeräten führen, da die anschließende Neuinitialisierung des Grafiksystems fehlschlagen kann.

Hinweis: Einige Scenegraph-Backends rufen diese Funktion möglicherweise nicht auf. Daher wird erwartet, dass die Implementierungen von QSGRenderNode die Bereinigung sowohl in ihrem Destruktor als auch in releaseResources() durchführen.

Anders als beim Destruktor wird erwartet, dass render() alle benötigten Ressourcen reinitialisieren kann, wenn es nach einem Aufruf von releaseResources() aufgerufen wird.

Bei OpenGL ist der OpenGL-Kontext des Scenegraphs sowohl beim Aufruf des Destruktors als auch dieser Funktion aktuell.

[pure virtual] void QSGRenderNode::render(const QSGRenderNode::RenderState *state)

Diese Funktion wird vom Renderer aufgerufen und sollte diesen Knoten mit direkt aufrufenden Befehlen in der aktuell verwendeten Grafik-API (OpenGL, Direct3D, etc.) zeichnen.

Die effektive Deckkraft kann mit inheritedOpacity() abgefragt werden.

Die Projektionsmatrix ist über state verfügbar, während die Modell-Sicht-Matrix mit matrix() abgerufen werden kann. Die kombinierte Matrix ist dann die Projektionsmatrix mal die Modellansichtsmatrix. Die korrekte Stapelung der Elemente in der Szene wird durch die Projektionsmatrix gewährleistet.

Bei der Verwendung der mitgelieferten Matrizen folgt das Koordinatensystem für Scheitelpunktdaten den üblichen Konventionen von QQuickItem: Oben links ist (0, 0), unten rechts ist die entsprechende QQuickItem's width() und height() minus eins. Geht man beispielsweise von einem Layout mit zwei Float-Koordinaten (x-y) pro Scheitelpunkt aus, kann ein Dreieck, das die Hälfte des Objekts abdeckt, als (Breite - 1, Höhe - 1), (0, 0), (0, Höhe - 1) gegen den Uhrzeigersinn angegeben werden.

Hinweis: QSGRenderNode wird als Mittel zur Implementierung von benutzerdefinierten 2D- oder 2,5D-Elementen bereitgestellt Qt Quick. Es ist nicht dafür gedacht, echte 3D-Inhalte in die Qt Quick Szene zu integrieren. Dieser Anwendungsfall wird besser von QQuickFramebufferObject, QQuickWindow::beforeRendering() oder den Äquivalenten dieser APIs für andere als OpenGL unterstützt.

Hinweis: QSGRenderNode kann eine deutlich bessere Leistung erbringen als texturbasierte Ansätze (z. B. QQuickFramebufferObject), insbesondere auf Systemen, auf denen die Fragmentverarbeitungsleistung begrenzt ist. Dies liegt daran, dass das Rendern auf eine Textur und das anschließende Zeichnen eines texturierten Quad vermieden wird. Stattdessen ermöglicht QSGRenderNode die Aufzeichnung von Zeichenaufrufen im Einklang mit den anderen Befehlen des Szenegraphen, wodurch ein zusätzliches Rendering-Ziel und die potenziell teure Texturierung und Überblendung vermieden werden.

Die Clip-Informationen werden vor dem Aufruf der Funktion berechnet. Implementierungen, die das Clipping berücksichtigen wollen, können Scissoring oder Stencil auf der Grundlage der Informationen in state einrichten. Der Schablonenpuffer wird mit den erforderlichen Clip-Formen gefüllt, aber es liegt an der Implementierung, das Testen von Schablonen zu ermöglichen.

Einige Scenegraph-Backends, insbesondere Software, verwenden weder Scissor noch Stencil. Dort wird die Clip-Region als gewöhnliche QRegion bereitgestellt.

Wenn Sie ein QSGRenderNode implementieren, das QRhi zum Rendern verwendet, fragen Sie das QRhi Objekt vom QQuickWindow über QQuickWindow::rhi() ab. Um ein QRhiCommandBuffer zu erhalten, an das die Arbeit übergeben wird, rufen Sie commandBuffer() auf. Um Informationen über das aktive Rendering-Ziel abzufragen, rufen Sie renderTarget() auf. Siehe das {Scene Graph - Custom QSGRenderNode} Beispiel für Details.

Mit Qt 6 und seinem QRhi-basierten Scene Graph Renderer sollten keine Annahmen über den aktiven (OpenGL) Status gemacht werden, wenn diese Funktion aufgerufen wird, selbst wenn OpenGL verwendet wird. Nehmen Sie nichts über die Pipelines und die dynamischen Zustände an, die in der Befehlsliste/im Puffer gebunden sind, wenn diese Funktion aufgerufen wird.

Hinweis: Es wird erwartet, dass Tiefenschreiboperationen deaktiviert sind. Das Aktivieren von Tiefenschreiboperationen kann zu unerwarteten Ergebnissen führen, abhängig vom verwendeten Scenegraph-Backend und dem Inhalt der Szene, daher ist hier Vorsicht geboten.

Hinweis: In Qt 6 ist changedStates() nur noch eingeschränkt nutzbar. Siehe die Dokumentation für changedStates() für weitere Informationen.

Bei einigen Grafik-APIs, auch bei der direkten Verwendung von QRhi, kann es notwendig sein, zusätzlich prepare() zu reimplementieren oder alternativ eine Verbindung zum Signal QQuickWindow::beforeRendering() herzustellen. Diese werden vor der Aufzeichnung des Beginns eines Renderpasses auf dem Befehlspuffer (vkCmdBeginRenderPass mit Vulkan, oder Beginn der Codierung über MTLRenderCommandEncoder im Falle von Metal) aufgerufen/ausgegeben. Die Aufzeichnung von Kopiervorgängen kann nicht innerhalb von render() mit solchen APIs durchgeführt werden. Stattdessen müssen solche Operationen entweder in prepare() oder in dem mit beforeRendering (mit DirectConnection) verbundenen Slot durchgeführt werden.

Siehe auch QSGRendererInterface und QQuickWindow::rendererInterface().

[since 6.6] QRhiRenderTarget *QSGRenderNode::renderTarget() const

Gibt das aktuelle Rendering-Ziel zurück.

Dies wird hauptsächlich zur Verfügung gestellt, um prepare() und render() Implementierungen zu ermöglichen, die QRhi verwenden und auf die QRhiRenderTarget's renderPassDescriptor oder pixel size zugreifen.

Um ein QRhiGraphicsPipeline zu erstellen, was bedeutet, dass ein QRhiRenderPassDescriptor bereitgestellt werden muss, muss der renderPassDescriptor vom Rendering-Ziel abgefragt werden. Beachten Sie jedoch, dass sich das Rendering-Ziel während der Lebensdauer des benutzerdefinierten QQuickItem und des QSGRenderNode ändern kann. Betrachten Sie zum Beispiel, was passiert, wenn Sie layer.enabled: true dynamisch auf das Element oder einen Vorfahren davon setzen: Dies löst das Rendering in eine Textur aus, nicht direkt in das Fenster, was bedeutet, dass das QSGRenderNode von da an mit einem anderen Rendering-Ziel arbeiten wird. Das neue Rendering-Target kann dann ein anderes Pixelformat haben, was dazu führen kann, dass bereits erstellte Grafikpipelines inkompatibel sind. Dies kann mit einer Logik wie der folgenden gehandhabt werden:

if (m_pipeline && renderTarget()->renderPassDescriptor()->serializedFormat() != m_renderPassFormat) {
    delete m_pipeline;
    m_pipeline = nullptr;
}
if (!m_pipeline) {
    // Build a new QRhiGraphicsPipeline.
    // ...
    // Store the serialized format for fast and simple comparisons later on.
    m_renderPassFormat = renderTarget()->renderPassDescriptor()->serializedFormat();
}

Diese Funktion wurde in Qt 6.6 eingeführt.

Siehe auch commandBuffer().

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.