Spec-Zone.ru › Qt 5.6

Qt Quick Граф сцены

Граф сцены в Qt Quick

Qt Quick 2 использует специализированный граф сцены, основанный на OpenGL ES 2.0 или OpenGL 2.0 для рендеринга. Использование графа сцены для графики вместо традиционных императивных систем рисования (QPainter и аналогичных) означает, что сцена, подлежащая рендерингу, может быть сохранена между кадрами, а весь набор примитивов для рендеринга известен перед началом рендеринга. Это открывает возможности для ряда оптимизаций, таких как пакетный рендеринг для минимизации изменений состояния и отбрасывание скрытых примитивов.

Например, предположим, что пользовательский интерфейс содержит список из десяти элементов, каждый из которых имеет цвет фона, значок и текст. Используя традиционные методы рисования, это приведет к 30 вызовам рисования и аналогичному количеству изменений состояния. Граф сцены, с другой стороны, может переупорядочить примитивы для рендеринга таким образом, чтобы все фоны рисовались одним вызовом, затем все значки, затем весь текст, уменьшая общее количество вызовов рисования всего до 3. Такое объединение и сокращение изменений состояния могут значительно улучшить производительность на некоторых устройствах.

Граф сцены тесно связан с Qt Quick 2.0 и не может быть использован автономно. Граф сцены управляется и рендерится классом QQuickWindow, а пользовательские типы элементов могут добавлять свои графические примитивы в граф сцены с помощью вызова QQuickItem::updatePaintNode().

Граф сцены — это графическое представление сцены элементов, независимой структуры, содержащей достаточную информацию для рендеринга всех элементов. После его настройки его можно изменять и рендерить независимо от состояния элементов. На многих платформах граф сцены будет даже рендериться в отдельной потоке рендеринга, в то время как поток GUI готовит состояние следующего кадра.

Структура графа сцены Qt Quick

Граф сцены состоит из ряда предопределенных типов узлов, каждый из которых выполняет конкретную задачу. Хотя мы называем это графом сцены, более точное определение — дерево узлов. Дерево строится из типов QQuickItem в сцене QML, а затем внутренне обрабатывается рендерером, который рисует сцену. Сами узлы не содержат активный код рисования ни виртуальную paint() функцию.

Несмотря на то, что дерево узлов в основном строится внутренними типами Qt Quick QML, пользователи также могут добавлять полные поддеревья со своим содержимым, включая поддеревья, представляющие 3D-модели.

Узлы

Наиболее важным узлом для пользователей является QSGGeometryNode. Он используется для определения пользовательской графики путем определения ее геометрии и материала. Геометрия определяется с помощью QSGGeometry и описывает форму или сетку графического примитива. Это может быть линия, прямоугольник, многоугольник, множество разрозненных прямоугольников или сложная 3D-сетка. Материал определяет, как заполняются пиксели в этой форме.

Узел может иметь любое количество дочерних элементов, и узлы геометрии будут рендериться так, чтобы они появлялись в порядке следования дочерних элементов, с родителями позади своих дочерних элементов.

Примечание: Это ничего не говорит о фактическом порядке рендеринга в рендерере. Гарантируется только визуальный вывод.

Доступные узлы:

QSGClipNode

Реализует функцию обрезки в графике сцены

QSGGeometryNode

Используется для всего рендерного содержимого в графике сцены

QSGNode

Базовый класс для всех узлов в графе сцены

QSGOpacityNode

Используется для изменения непрозрачности узлов

QSGTransformNode

Реализует преобразования в графике сцены

Пользовательские узлы добавляются в граф сцены путем наследования QQuickItem::updatePaintNode() и установки флага QQuickItem::ItemHasContents.

Предупреждение: Крайне важно, чтобы операции OpenGL и взаимодействие с графом сцены происходили исключительно в потоке рендеринга, в первую очередь во время вызова updatePaintNode(). Правило — использовать только классы с префиксом «QSG» внутри функции QQuickItem::updatePaintNode().

Дополнительную информацию см. в разделе Граф сцены — настройка геометрии.

Предварительная обработка

Узлы имеют виртуальную функцию QSGNode::preprocess(), которая вызывается перед рендерингом графа сцены. Подклассы узлов могут установить флаг QSGNode::UsePreprocess и переопределить функцию QSGNode::preprocess(), чтобы выполнить окончательную подготовку своего узла. Например, деление кривой Безье на правильный уровень детализации для текущего коэффициента масштаба или обновление части текстуры.

Владение узлами

Владение узлами выполняется явно создателем или графом сцены путем установки флага QSGNode::OwnedByParent. Назначение владения графу сцены часто предпочтительнее, так как упрощает очистку, когда граф сцены существует вне потока GUI.

Материалы

Материал описывает, как заполняется внутренняя часть геометрии в QSGGeometryNode. Он инкапсулирует программу шейдера OpenGL и обеспечивает достаточную гибкость в достижении целей, хотя большинство элементов Qt Quick сами используют только очень простые материалы, такие как сплошной цвет и заполнение текстурой.

Пользователям, которые просто хотят применить пользовательскую тонировку к типу элемента QML, можно сделать это непосредственно в QML с помощью типа ShaderEffect.

Ниже приведен полный список классов материалов:

QSGMaterial

Инкапсулирует состояние рендеринга для программы шейдера

QSGMaterialShader

Представляет программу шейдера OpenGL в рендерере

QSGMaterialType

Используется в качестве уникального маркера типа в сочетании с QSGMaterial

QSGFlatColorMaterial

Удобный способ рендеринга геометрии сплошного цвета в графе сцены

QSGSimpleMaterial

Класс, сгенерированный шаблоном, используемый для хранения состояния, используемого с QSGSimpleMateralShader

QSGSimpleMaterialShader

Удобный способ создания пользовательских материалов для графа сцены

QSGOpaqueTextureMaterial

Удобный способ рендеринга текстурированной геометрии в графе сцены

QSGTextureMaterial

Удобный способ рендеринга текстурированной геометрии в графе сцены

QSGVertexColorMaterial

Удобный способ рендеринга геометрии с цветом на вершине в графе сцены

Дополнительную информацию см. в разделе Граф сцены — простой материал

Узлы для удобства работы

API графа сцены очень низкого уровня и фокусируется на производительности, а не на удобстве. Написание пользовательской геометрии и материалов с нуля, даже самых базовых, требует немало кода. По этой причине API включает несколько вспомогательных классов, чтобы сделать наиболее распространенные пользовательские узлы легкодоступными.

  • QSGSimpleRectNode — подкласс QSGGeometryNode, который определяет прямоугольную геометрию с материалом сплошного цвета.
  • QSGSimpleTextureNode — подкласс QSGGeometryNode, который определяет прямоугольную геометрию с текстурным материалом.

Граф сцены и рендеринг

Рендеринг графа сцены происходит внутри класса QQuickWindow и не имеет публичного API для доступа. Однако есть несколько мест в конвейере рендеринга, где пользователь может присоединить код приложения. Это можно использовать для добавления пользовательского содержимого графа сцены или рендеринга исходного содержимого OpenGL. Точки интеграции определяются циклом рендеринга.

Подробное описание работы рендеринг графа сцены см. в разделе Qt Quick рендеринг графа сцены.

Доступны три варианта цикла рендеринга: basic, windows, и threaded. Из них basic и windows являются однопоточными, а threaded выполняет рендеринг графа сцены в отдельном потоке. Qt пытается выбрать подходящий цикл в зависимости от платформы и, возможно, графических драйверов. Если это неудовлетворительно или для целей тестирования, переменная среды QSG_RENDER_LOOP может использоваться для принудительного использования заданного цикла. Чтобы проверить, какой цикл рендеринга используется, включите qt.scenegraph.general категорию регистрации.

Примечание: Циклы рендеринга threaded и windows полагаются на реализацию OpenGL для регулирования скорости, запрашивая интервал переключения в 1. Некоторые графические драйверы позволяют пользователям переопределить это значение и отключить его, игнорируя запрос Qt. Без блокировки в операции обмена буферами (или в другом месте) цикл рендеринга будет запускать анимации слишком быстро и перегружать ЦП на 100%. Если известно, что система не может обеспечить регулирование скорости с помощью vsync, используйте цикл рендеринга basic вместо этого, установив QSG_RENDER_LOOP=basic в среде.

Многопоточный цикл рендеринга ("threaded")

На многих конфигурациях рендеринг графа сцены будет выполняться в отдельном потоке рендеринга. Это делается для повышения параллелизма многоядерных процессоров и лучшего использования временных задержек, таких как ожидание блокирующего вызова буферов обмена. Это обеспечивает значительное повышение производительности, но накладывает определенные ограничения на то, где и когда можно взаимодействовать с графом сцены.

Ниже приведено простое описание того, как создается кадр с многопоточным циклом рендеринга.

  1. В сцене QML происходит изменение, вызывая QQuickItem::update(). Это может быть результатом, например, анимации или ввода пользователя. В поток отрисовки отправляется событие для начала нового кадра.
  2. Поток отрисовки готовится к отрисовке нового кадра, делает контекст OpenGL текущим и инициирует блокировку в потоке GUI.
  3. Пока поток отрисовки готовит новый кадр, поток GUI вызывает QQuickItem::updatePolish(), чтобы выполнить окончательную настройку элементов перед их отрисовкой.
  4. Поток GUI заблокирован.
  5. Выпускается сигнал QQuickWindow::beforeSynchronizing(). Приложения могут установить прямые соединения (используя Qt::DirectConnection) с этим сигналом, чтобы выполнить необходимые подготовительные действия перед вызовами QQuickItem::updatePaintNode().
  6. Синхронизация состояния QML в граф сцены. Это выполняется путем вызова функции QQuickItem::updatePaintNode() для всех элементов, которые изменились с момента предыдущего кадра. Это единственный момент взаимодействия элементов QML и узлов в графе сцены.
  7. Блокировка потока GUI снимается.
  8. Граф сцены отрисовывается:
    1. Выпускается сигнал QQuickWindow::beforeRendering(). Приложения могут установить прямые соединения (используя Qt::DirectConnection) с этим сигналом, чтобы использовать пользовательские вызовы OpenGL, которые затем будут накладываться визуально под сценой QML.
    2. Элементы, для которых задан флаг QSGNode::UsePreprocess, получат вызов функции QSGNode::preprocess().
    3. Отрисовщик обрабатывает узлы и вызывает функции OpenGL.
    4. Выпускается сигнал QQuickWindow::afterRendering(). Приложения могут установить прямые соединения (используя Qt::DirectConnection) с этим сигналом, чтобы использовать пользовательские вызовы OpenGL, которые затем будут накладываться визуально над сценой QML.
    5. Отрисованный кадр меняется, и выпускается QQuickWindow::frameSwapped().
  9. Пока поток отрисовки выполняет отрисовку, GUI свободен для продвижения анимаций, обработки событий и т. д.

По умолчанию потоковая отрисовка используется на Windows с opengl32.dll, Linux с драйверами, не основанными на Mesa, macOS, мобильных платформах и Embedded Linux с EGLFS, но это может измениться. Можно принудительно использовать потоковую отрисовку, установив QSG_RENDER_LOOP=threaded в среде.

Циклы отрисовки без потоков ("basic" и "windows")

В настоящее время цикл отрисовки без потоков используется по умолчанию на Windows с ANGLE или нестандартной реализацией opengl32 и Linux с драйверами Mesa. В последнем случае это в основном мера предосторожности, так как не все комбинации драйверов OpenGL и систем окон были протестированы. В то же время такие реализации, как ANGLE или Mesa llvmpipe, вообще не могут корректно функционировать с потоковой отрисовкой, поэтому отключение потоковой отрисовки для них необходимо.

По умолчанию windows используется для отрисовки без потоков на Windows с ANGLE, а basic используется для всех остальных платформ, когда требуется отрисовка без потоков.

Даже при использовании цикла отрисовки без потоков вы должны писать код так, как будто вы используете потоковую отрисовку, так как несоблюдение этого приведет к тому, что код будет непереносимым.

Следующее является упрощенной иллюстрацией последовательности отрисовки кадра в отрисовщике без потоков.

Настройка отрисовки с помощью QQuickRenderControl

При использовании QQuickRenderControl ответственность за управление циклом отрисовки передается приложению. В этом случае встроенный цикл отрисовки не используется. Вместо этого приложение должно вызывать шаги полировки, синхронизации и отрисовки в соответствующее время. Можно реализовать как поточное, так и непоточное поведение, аналогичное показанному выше.

Смешивание графа сцены и OpenGL

Граф сцены предлагает два метода интеграции контента OpenGL: путем вызова команд OpenGL напрямую и путем создания текстурированного узла в графе сцены.

Подключив обработчики сигналов QQuickWindow::beforeRendering() и QQuickWindow::afterRendering(), приложения могут непосредственно вызывать OpenGL-функции в том же контексте, в котором отрисовывается граф сцены. Как показывают названия сигналов, пользователь может отрисовывать контент OpenGL как под сценой Qt Quick, так и над ней. Преимущество интеграции таким образом заключается в том, что для выполнения отрисовки не требуется дополнительный буфер фреймбуфера или памяти. Недостаток заключается в том, что Qt Quick решает, когда вызывать сигналы, и это единственный момент, когда приложение OpenGL разрешено рисовать.

Пример Граф сцены - OpenGL под QML приводит пример использования этих сигналов.

Другой вариант — создать QQuickFramebufferObject, выполнить отрисовку в него и отобразить его в графе сцены в качестве текстуры. Пример Граф сцены - Отрисовка FBO показывает, как это можно сделать. Также возможно объединение нескольких контекстов отрисовки и нескольких потоков для создания контента, отображаемого в графе сцены. Примеры Граф сцены - Отрисовка FBO в потоке показывают, как это можно сделать.

Предупреждение: При смешивании контента OpenGL с отрисовкой графа сцены важно, чтобы приложение не оставляло контекст OpenGL в состоянии, когда привязаны буферы, включены атрибуты, заданы специальные значения в буфере z или буфере трафарета или аналогичные. В противном случае может произойти непредсказуемое поведение.

Предупреждение: Код отрисовки OpenGL должен быть потокобезопасным, так как отрисовка может происходить вне потока GUI.

Пользовательские элементы с помощью QPainter

В QQuickItem есть подкласс QQuickPaintedItem, который позволяет пользователям отрисовывать контент с помощью QPainter.

Предупреждение: Использование QQuickPaintedItem использует косвенную 2D-поверхность для отрисовки содержимого, используя либо программную растризацию, либо буфер фреймбуфера OpenGL (FBO), поэтому отрисовка — это двухэтапный процесс. Сначала растрируйте поверхность, затем нарисуйте поверхность. Использование API графа сцены напрямую всегда значительно быстрее.

Поддержка ведения журнала

Граф сцены поддерживает ряд категорий ведения журналов. Они могут быть полезны для поиска проблем с производительностью и ошибок, а также полезны для разработчиков Qt.

  • qt.scenegraph.time.texture - записывает время, затраченное на загрузку текстур
  • qt.scenegraph.time.compilation - записывает время, затраченное на компиляцию шейдеров
  • qt.scenegraph.time.renderer - записывает время, затраченное на различные этапы отрисовщика
  • qt.scenegraph.time.renderloop - записывает время, затраченное на различные этапы цикла отрисовки
  • qt.scenegraph.time.glyph - записывает время, затраченное на подготовку глифов поля расстояния
  • qt.scenegraph.general - записывает общую информацию о различных частях графа сцены и стека графики
  • qt.scenegraph.renderloop - создает подробный журнал различных этапов, связанных с отрисовкой. Этот режим журнала в первую очередь полезен для разработчиков Qt.

Бэкенд графа сцены

В дополнение к публичному API, граф сцены имеет адаптивный слой, который открывает реализацию для адаптации к конкретному оборудованию. Это недокументированный, внутренний и закрытый API плагина, который позволяет командам адаптации оборудования максимально использовать возможности своего оборудования. Он включает:

  • Пользовательские текстуры; в частности, реализация QQuickWindow::createTextureFromImage и внутреннее представление текстуры, используемое типами Image и BorderImage.
  • Пользовательский отрисовщик; адаптивный слой позволяет плагину решить, как проходить по графу сцены и выполнять отрисовку, позволяя оптимизировать алгоритм отрисовки для определенного оборудования или использовать расширения, которые улучшают производительность.
  • Пользовательская реализация графа сцены для многих стандартных типов QML, включая рендеринг текста и шрифтов.
  • Пользовательский драйвер анимации; позволяет системе анимации подключиться к вертикальной частоте обновления дисплея низкого уровня, чтобы обеспечить плавную отрисовку.
  • Пользовательский цикл отрисовки; позволяет лучше управлять тем, как QML взаимодействует с несколькими окнами.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/qtquick-visualcanvas-scenegraph.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API