Spec-Zone.ru › Qt 6.1

Тип QML ShaderEffect

Применяет пользовательские шейдеры к прямоугольнику. Подробнее...

Заявление об импорте: import QtQuick 2.1
Наследует:

Item

  • Список всех членов, включая унаследованные

Свойства

  • blending : bool
  • cullMode : перечисление
  • fragmentShader : url
  • log : строка
  • mesh : вариант
  • status : перечисление
  • supportsAtlasTextures : bool
  • vertexShader : url

Подробное описание

Тип ShaderEffect применяет пользовательский шейдер вершин и фрагмента (пикселя) к прямоугольнику. Он позволяет добавлять эффекты, такие как тень, размытие, изменение цвета и перелистывание страницы, в сцену QML.

Примечание: В зависимости от используемого бэкенда Qt Quick, тип ShaderEffect может быть не поддерживается. Например, с бэкендом software эффекты вообще не будут отображаться.

Шейдеры

В Qt 5 эффекты предоставлялись в виде исходного кода GLSL (OpenGL Shading Language), часто встроенного в QML в виде строк. Начиная с Qt 5.8, стало возможным также ссылаться на файлы, как локальные, так и в системе ресурсов Qt.

В Qt 6 Qt Quick поддерживает графические API, такие как Vulkan, Metal и Direct3D 11. Поэтому работа со строками исходного кода GLSL больше невозможна. Вместо этого новая конвейерная обработка шейдеров основана на компиляции совместимого с Vulkan кода GLSL в SPIR-V, за которым следует сбор информации о рефлексии и перевод на другие языки шейдеров, такие как HLSL, язык шейдеров Metal и различные версии GLSL. Результирующие ресурсы упаковываются в единый пакет, обычно хранящийся в файлах с расширением .qsb. Этот процесс выполняется автономно или во время сборки приложения.

Свойства vertexShader и fragmentShader в Qt 6 представляют собой URL-адреса и работают очень похоже на Image.source, например. Однако поддерживаются только схемы file и qrc. Также можно опустить схему file, что позволяет удобно указывать относительный путь. Такой путь разрешается относительно расположения компонента (файла .qml).

Входные данные и ресурсы шейдера

Существует два типа входных данных для vertexShader: униформы и входные данные вершин.

Определены следующие входные данные:

  • vec4 qt_Vertex с местоположением 0 — позиция вершины; верхняя левая вершина имеет координаты (0, 0), нижняя правая — (ширина, высота).
  • vec2 qt_MultiTexCoord0 с местоположением 1 — координаты текстуры; верхняя левая координата — (0, 0), нижняя правая — (1, 1). Если supportsAtlasTextures имеет значение true, координаты будут основаны на позиции в атласе.

Примечание: На практике имеет значение только местоположение входных данных вершины. Имена можно изменять произвольно, а местоположение должно всегда быть 0 для позиции вершины и 1 для координат текстуры. Однако имейте в виду, что это относится только к входным данным вершин и не обязательно справедливо для выходных переменных из шейдера вершин, используемых в качестве входных данных в шейдере фрагмента (как правило, интерполированные координаты текстуры).

Определены следующие униформы:

  • mat4 qt_Matrix — комбинированная матрица преобразования, произведение матриц от корневого элемента до данного ShaderEffect и ортогональной проекции.
  • float qt_Opacity — комбинированная непрозрачность, произведение непрозрачностей от корневого элемента до данного ShaderEffect.

Примечание: GLSL в стиле Vulkan не имеет отдельных переменных униформы. Вместо этого шейдеры должны всегда использовать блок униформы с точкой привязки 0.

Примечание: Квалификатор макета блока униформы должен всегда быть std140.

Примечание: В отличие от входных данных вершин, предопределенные имена (qt_Matrix, qt_Opacity) менять нельзя.

Кроме того, любые свойства, которые можно сопоставить с типом GLSL, могут быть доступны шейдерам. Следующий список показывает, как сопоставляются свойства:

  • bool, int, qreal -> bool, int, float — Если тип в шейдере отличается от типа в QML, значение преобразуется автоматически.
  • QColor -> vec4 — Когда цвета передаются шейдеру, они предварительно умножаются. Таким образом, Qt.rgba(0.2, 0.6, 1.0, 0.5) превращается в vec4(0.1, 0.3, 0.5, 0.5) в шейдере, например.
  • QRect, QRectF -> vec4 — Qt.rect(x, y, w, h) превращается в vec4(x, y, w, h) в шейдере.
  • QPoint, QPointF, QSize, QSizeF -> vec2
  • QVector3D -> vec3
  • QVector4D -> vec4
  • QTransform -> mat3
  • QMatrix4x4 -> mat4
  • QQuaternion -> vec4, скалярное значение равно w.
  • Image -> sampler2D — Начало в верхнем левом углу, а значения цвета предварительно умножаются. Текстура предоставляется как есть, исключая режим заполнения Image. Для включения fillMode используйте ShaderEffectSource или Image::layer::enabled.
  • ShaderEffectSource -> sampler2D — Начало в верхнем левом углу, и значения цвета предварительно умножены.

Самплер по-прежнему объявляется как отдельная переменная униформы в коде шейдера. Шейдеры могут выбрать любую точку привязки для них, кроме 0 , потому что она зарезервирована для блока униформы.

Некоторые языки и API шейдеров имеют концепцию отдельных объектов изображения и самплера. Qt Quick всегда работает с объединенными объектами самплера изображения в шейдерах, как поддерживается SPIR-V. Следовательно, шейдеры, предоставляемые для ShaderEffect, должны всегда использовать декларации самплеров в стиле layout(binding = 1) uniform sampler2D tex;. Базовая абстракция и конвейер шейдера заботятся о том, чтобы это работало для всех поддерживаемых API и языков шейдеров, прозрачно для приложений.

Бэкенд QML-сцены может выбирать выделение текстур в атласах текстур. Если текстура, выделенная в атласе, передается ShaderEffect, по умолчанию она копируется из атласа текстур в отдельную текстуру, так что координаты текстуры охватывают диапазон от 0 до 1, и вы получите ожидаемые режимы обрезки. Однако это увеличит использование памяти. Чтобы избежать копирования текстуры, установите supportsAtlasTextures для простых шейдеров, использующих qt_MultiTexCoord0, или для каждого «uniform sampler2D <имя>» объявите «uniform vec4 qt_SubRect_<имя>», который будет назначать нормализованный прямоугольник источника текстуры. Для автономных текстур прямоугольник источника — [0, 1]x[0, 1]. Для текстур в атласе прямоугольник источника соответствует части атласа текстур, где хранится текстура. Правильный способ вычисления координаты текстуры для текстуры с именем «source» в атласе текстур — «qt_SubRect_source.xy + qt_SubRect_source.zw * qt_MultiTexCoord0».

Вывод из fragmentShader должен быть предварительно умножен. Если blending включен, используется смешивание «source-over». Однако аддитивное смешивание можно получить, выдав нулевое значение в альфа-канале.

import QtQuick 2.0

Rectangle {
    width: 200; height: 100
    Row {
        Image { id: img;
                sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
        ShaderEffect {
            width: 100; height: 100
            property variant src: img
            vertexShader: "myeffect.vert.qsb"
            fragmentShader: "myeffect.frag.qsb"
        }
    }
}

Пример предполагает, что myeffect.vert и myeffect.frag содержат код GLSL в стиле Vulkan, обработанный инструментом qsb для генерации файлов .qsb.

#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(location = 0) out vec2 coord;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}
#version 440
layout(location = 0) in vec2 coord;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D src;
void main() {
    vec4 tex = texture(src, coord);
    fragColor = vec4(vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156))), tex.a) * qt_Opacity;
}

Примечание: Текстуры графического узла имеют начало в верхнем левом углу, а не в нижнем левом, что обычно используется в OpenGL.

Использование только одного шейдера

Указание как vertexShader, так и fragmentShader необязательно. Многие реализации ShaderEffect на практике будут предоставлять только шейдер фрагмента, полагаясь на стандартный встроенный шейдер вершин.

Стандартный шейдер вершин передает координату текстуры в шейдер фрагмента как vec2 qt_TexCoord0 в местоположении 0.

Стандартный шейдер фрагмента ожидает, что координаты текстуры будут переданы шейдером вершин как vec2 qt_TexCoord0 в местоположении 0, и он сэмплирует из sampler2D с именем source в точке привязки 1.

Предупреждение: Когда указан только один из шейдеров, разработчик шейдера должен учитывать ожидаемый макет блока униформы стандартными шейдерами: qt_Matrix всегда должен находиться по смещению 0, за которым следует qt_Opacity по смещению 64. Любые пользовательские униформы должны располагаться после этих двух. Это обязательно даже в том случае, если приложение-шейдер не использует матрицу или непрозрачность, поскольку во время выполнения доступен один единственный буфер униформ для шейдеров вершин и фрагмента.

Предупреждение: В отличие от вершинных входных данных, передача данных между вершинным и фрагментным шейдерами может, в зависимости от базового графического API, потребовать использования одинаковых имён; совпадение местоположения не всегда достаточно. В частности, при указании фрагментного шейдера, используя по умолчанию встроенный вершинный шейдер, координаты текстуры передаются как qt_TexCoord0 в местоположении 0, и поэтому настоятельно рекомендуется, чтобы фрагментный шейдер объявлял входной параметр с тем же именем (qt_TexCoord0). Отсутствие этого может привести к проблемам на некоторых платформах, например, при работе с контекстом OpenGL без ядра, где исходный код шейдера GLSL не имеет квалификаторов местоположения, а соответствие основано на именах переменных во время процесса линковки шейдеров.

Эффект шейдера и слои элементов

Тип ShaderEffect можно комбинировать с слоистыми элементами.

Слой с отключённым эффектом Слой с включённым эффектом
Item {
    id: layerRoot
    layer.enabled: true
    layer.effect: ShaderEffect {
       fragmentShader: "effect.frag.qsb"
    }
}
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D source;
void main() {
    vec4 p = texture(source, qt_TexCoord0);
    float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
    fragColor = vec4(g, g, g, p.a) * qt_Opacity;
}

Также можно комбинировать несколько слоистых элементов:

Rectangle {
    id: gradientRect;
    width: 10
    height: 10
    gradient: Gradient {
        GradientStop { position: 0; color: "white" }
        GradientStop { position: 1; color: "steelblue" }
    }
    visible: false; // should not be visible on screen.
    layer.enabled: true;
    layer.smooth: true
 }
 Text {
    id: textItem
    font.pixelSize: 48
    text: "Gradient Text"
    anchors.centerIn: parent
    layer.enabled: true
    // This item should be used as the 'mask'
    layer.samplerName: "maskSource"
    layer.effect: ShaderEffect {
        property var colorSource: gradientRect;
        fragmentShader: "mask.frag.qsb"
    }
}
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D colorSource;
layout(binding = 2) uniform sampler2D maskSource;
void main() {
    fragColor = texture(colorSource, qt_TexCoord0)
                    * texture(maskSource, qt_TexCoord0).a
                    * qt_Opacity;
}

Другие замечания

По умолчанию ShaderEffect состоит из четырёх вершин, по одной для каждого угла. Для нелинейных преобразований вершин, таких как скручивание страницы, можно указать тонкую сетку вершин, задав разрешение сетки сетки.

Миграция с Qt 5

Для приложений Qt 5 с элементами ShaderEffect миграция в Qt 6 включает:

  • Перемещение кода шейдера в отдельные .vert и .frag файлы,
  • обновление шейдеров до совместимых с Vulkan GLSL,
  • запуск инструмента qsb на них,
  • включение полученных .qsb файлов в исполняемый файл с помощью системы ресурсов Qt,
  • и ссылку на файл в свойствах vertexShader и fragmentShader.

Как описано в модуле Qt Shader Tools, некоторые из этих шагов можно автоматизировать, разрешив CMake вызывать инструмент qsb во время сборки. Дополнительную информацию и примеры см. в Интеграция системы сборки Qt Shader Tools.

Что касается обновления кода шейдера, ниже приведён обзор обычно необходимых изменений.

Вершинный шейдер в Qt 5 Вершинный шейдер в Qt 6
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
uniform highp mat4 qt_Matrix;
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}
#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(location = 0) out vec2 coord;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}

Процесс преобразования в основном заключается в обновлении кода для обеспечения совместимости с GL_KHR_vulkan_glsl. Следует отметить, что Qt Quick использует подмножество функций, предоставляемых GLSL и Vulkan, и поэтому процесс преобразования для типичных шейдеров ShaderEffect обычно является простым.

  • Директива version должна указывать 440 или 450, хотя указание других версий GLSL тоже может работать, так как расширение GL_KHR_vulkan_glsl предназначено для GLSL 140 и выше.
  • Входы и выходы должны использовать современные ключевые слова GLSL in и out. Кроме того, необходимо указать местоположение. Пространства имён местоположений для входов и выходов разделены, поэтому назначение местоположений, начиная с 0 для обоих, является безопасным.
  • Что касается входных данных вершинного шейдера, единственными возможностями с ShaderEffect являются местоположение 0 для позиции вершины (традиционно называемой qt_Vertex) и местоположение 1 для координат текстуры (традиционно называемой qt_MultiTexCoord0).
  • Выходы вершинного шейдера и входные данные фрагментного шейдера определяются кодом шейдера. Фрагментный шейдер должен иметь вывод vec4 в местоположении 0 (обычно называемый fragColor). Для максимальной переносимости выходы вершины и входные данные фрагмента должны использовать как один и тот же номер местоположения, так и то же имя. При указании только фрагментного шейдера координаты текстуры передаются встроенным вершинным шейдером как vec2 qt_TexCoord0 в местоположении 0, как показано в приведённых выше фрагментах примеров.
  • Переменные униформы за пределами блока униформы недопустимы. Вместо этого данные униформы должны быть объявлены в блоке униформы с точкой связывания 0.
  • Ожидается, что блок униформы будет использовать квалификатор std140.
  • Во время выполнения вершинный и фрагментный шейдеры получат один и тот же буфер униформы, привязанный к точке связывания 0. Поэтому, как общее правило, объявления блока униформы должны быть идентичны между шейдерами. Это также включает члены, которые не используются в одном из шейдеров. Имена членов должны совпадать, потому что с некоторыми графическими API блок униформы преобразуется в традиционную структуру uniform, прозрачно для приложения.
  • При предоставлении одного из шейдеров следует учитывать тот факт, что встроенные шейдеры ожидают qt_Matrix и qt_Opacity в начале блока униформы. (точнее, в смещении 0 и 64 соответственно) Как общее правило, всегда включайте эти значения как первый и второй члены в блоке.
  • В примере блок униформы определяет имя блока buf. Это имя можно свободно изменять, но оно должно совпадать между шейдерами. Использование имени экземпляра, такого как layout(...) uniform buf { ... } instance_name; является необязательным. При указании все обращения к членам должны быть квалифицированы с помощью instance_name.
Фрагментный шейдер в Qt 5 Фрагментный шейдер в Qt 6
varying highp vec2 coord;
uniform lowp float qt_Opacity;
uniform sampler2D src;
void main() {
    lowp vec4 tex = texture2D(src, coord);
    gl_FragColor = vec4(vec3(dot(tex.rgb,
                        vec3(0.344, 0.5, 0.156))),
                             tex.a) * qt_Opacity;
}
#version 440
layout(location = 0) in vec2 coord;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D src;
void main() {
    vec4 tex = texture(src, coord);
    fragColor = vec4(vec3(dot(tex.rgb,
                     vec3(0.344, 0.5, 0.156))),
                          tex.a) * qt_Opacity;
}
  • Квалификаторы точности (lowp, mediump, highp) в настоящее время не используются.
  • Вызовы встроенных функций GLSL должны следовать современным именам GLSL, в частности, texture() вместо texture2D().
  • Сэмплеры должны использовать точки связывания, начиная с 1.

См. также Слои элементов, Руководство по QSB и Интеграция системы сборки Qt Shader Tools.

Документация свойств

blending : bool

Если это свойство равно true, вывод из fragmentShader смешивается с фоном с помощью режима смешивания source-over. Если false, фон игнорируется. Смешивание снижает производительность, поэтому вы должны установить это свойство в false, когда смешивание не требуется. Значение по умолчанию — true.

cullMode : перечисление

Это свойство определяет, какие стороны элемента должны быть видимы.

  • ShaderEffect.NoCulling - Обе стороны видны
  • ShaderEffect.BackFaceCulling - видима только лицевая сторона
  • ShaderEffect.FrontFaceCulling - видима только задняя сторона

Значение по умолчанию — NoCulling.

fragmentShader : url

Это свойство содержит ссылку на файл с предварительно обработанным пакетом фрагментного шейдера, обычно с расширением .qsb. Значение обрабатывается как URL, аналогично другим типам QML, таким как Image. Оно должно быть либо локальным файлом, либо использовать схему qrc для доступа к файлам, встроенным через систему ресурсов Qt. URL может быть абсолютным или относительным к URL компонента.

См. также vertexShader.

log : строка

Это свойство содержит журнал предупреждений и ошибок последней попытки компиляции шейдеров. Оно обновляется одновременно с status для установления значений Compiled или Error.

Примечание: В Qt 6, конвейер шейдеров способствует компиляции и трансляции шейдеров GLSL в стиле Vulkan автономно или на этапе сборки как минимум. Это не обязательно означает, что компиляция шейдеров не происходит во время выполнения, но даже если это происходит, ShaderEffect в этом не участвует, и синтаксические и подобные ошибки больше не должны возникать на этом этапе. Поэтому значение этого свойства обычно пустое.

См. также status.

mesh : variant

Это свойство определяет сетку, используемую для отрисовки ShaderEffect. Оно может содержать любой объект GridMesh. Если свойству присвоено значение размера, ShaderEffect неявно использует GridMesh с указанным значением в качестве разрешения сетки. По умолчанию это свойство имеет размер 1x1.

См. также GridMesh.

status : перечисление

Это свойство указывает текущий статус шейдеров.

  • ShaderEffect.Compiled - программа шейдера была успешно скомпилирована и связана.
  • ShaderEffect.Uncompiled - программа шейдера ещё не скомпилирована.
  • ShaderEffect.Error - программа шейдера не смогла быть скомпилирована или связана.

При установке кода источника фрагментного или вершинного шейдера статус станет Uncompiled. В первый раз, когда ShaderEffect отображается с новым кодом источника шейдера, шейдеры компилируются и связываются, и статус обновляется до Compiled или Error.

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

См. также log.

END_OF_DOCUMENT_MARKER

[since QtQuick 2.4] supportsAtlasTextures : bool

Установите это свойство в значение true, чтобы подтвердить, что ваш код шейдера не полагается на qt_MultiTexCoord0, изменяющийся в пределах от (0,0) до (1,1) относительно сетки. В этом случае диапазон qt_MultiTexCoord0 будет определяться положением текстуры в атласе. В настоящее время это свойство не оказывает никакого влияния, если в качестве входных данных для вашего шейдера используется меньше или больше одного униформа-сэмплера.

Это отличается от предоставления униформ qt_SubRect_<name>, так как последнее позволяет рисовать одну или несколько текстур из атласа в одном элементе ShaderEffect, тогда как supportsAtlasTextures позволяет группировать несколько экземпляров компонента ShaderEffect, использующих различные изображения из атласа в одной операции отрисовки. Оба свойства предотвращают копирование текстуры из атласа при ссылке на неё элементом ShaderEffect.

Значение по умолчанию – false.

Это свойство было введено в QtQuick 2.4.

vertexShader : url

Это свойство содержит ссылку на файл с предварительно обработанным пакетом шейдера вершин, как правило, с расширением .qsb. Значение обрабатывается как URL, аналогично другим типам QML, таким как Image. Оно должно быть либо локальным файлом, либо использовать схему qrc для доступа к файлам, встроенным через систему ресурсов Qt. URL может быть абсолютным или относительным к URL-адресу компонента.

См. также fragmentShader.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qml-qtquick-shadereffect.html

Spec-Zone.ru

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