Spec-Zone.ru › Qt 5.13

Тип QML ShaderEffect

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

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

Item

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

Свойства

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

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

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

Примечание: В зависимости от используемого бэкэнда Qt Quick, тип ShaderEffect может быть не поддерживается (например, с программным бэкэндом) или может использовать другой язык шейдеров с правилами и ожиданиями, отличными от OpenGL и GLSL.

OpenGL и GLSL

Существует два типа ввода для vertexShader: переменные униформы и атрибуты. Некоторые из них предварительно определены:

  • uniform mat4 qt_Matrix - комбинированная матрица преобразования, произведение матриц от корневого элемента до этого ShaderEffect, а также ортогональная проекция.
  • uniform float qt_Opacity - комбинированная непрозрачность, произведение непрозрачностей от корневого элемента до этого ShaderEffect.
  • attribute vec4 qt_Vertex - положение вершины, верхняя левая вершина имеет координаты (0, 0), нижняя правая (ширина, высота).
  • attribute vec2 qt_MultiTexCoord0 - координаты текстуры, верхняя левая координата (0, 0), нижняя правая (1, 1). Если supportsAtlasTextures истинно, координаты будут основаны на положении в атласе.

Кроме того, любые свойства, которые можно отобразить в типе OpenGL Shading Language (GLSL), доступны в качестве переменной униформы. Следующий список показывает, как свойства отображаются в переменных униформы 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 - Начало в верхнем левом углу, и значения цвета предварительно умножаются. Текстура предоставляется как есть, за исключением fillMode элемента Image. Чтобы включить fillMode, используйте ShaderEffectSource или Image::layer::enabled.
  • ShaderEffectSource -> sampler2D - Начало в верхнем левом углу, и значения цвета предварительно умножаются.

Бэкэнд QML-сцена не может выбрать выделение текстур в атласах текстур. Если текстура, выделенная в атласе, передаётся в ShaderEffect, она по умолчанию копируется из атласа текстур в автономную текстуру, чтобы координаты текстуры охватывали диапазон от 0 до 1, и вы получите ожидаемые режимы перекрытия. Однако это увеличит использование памяти. Чтобы избежать копирования текстуры, установите supportsAtlasTextures для простых шейдеров, использующих qt_MultiTexCoord0, или для каждой "uniform sampler2D <name>" объявите "uniform vec4 qt_SubRect_<name>", которые будут назначены нормализованному прямоугольнику источника текстуры. Для автономных текстур прямоугольник источника равен [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: "
                uniform highp mat4 qt_Matrix;
                attribute highp vec4 qt_Vertex;
                attribute highp vec2 qt_MultiTexCoord0;
                varying highp vec2 coord;
                void main() {
                    coord = qt_MultiTexCoord0;
                    gl_Position = qt_Matrix * qt_Vertex;
                }"
            fragmentShader: "
                varying highp vec2 coord;
                uniform sampler2D src;
                uniform lowp float qt_Opacity;
                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;
                }"
        }
    }
}

Примечание: Текстуры сцены имеют начало в верхнем левом углу, а не в нижнем левом, что является общим для OpenGL.

Сведения о используемой версии GLSL см. в QtQuick::GraphicsInfo.

Начиная с Qt 5.8, ShaderEffect также поддерживает чтение исходного кода GLSL из файлов. Всякий раз, когда значение свойства fragmentShader или vertexShader является URL с схемой file или qrc, это рассматривается как ссылка на файл, и исходный код читается из указанного файла.

Direct3D и HLSL

Бэкэнды Direct3D предоставляют поддержку ShaderEffect с HLSL. Бэкэнд Direct3D 12 требует использования как минимум Shader Model 5.0 для шейдеров вершин и фрагментов. При необходимости, GraphicsInfo.shaderType может использоваться для определения в ходе выполнения, какой тип значения назначить fragmentShader или vertexShader.

Все описанные выше концепции для OpenGL и GLSL применяются к Direct3D и HLSL, однако существуют некоторые заметные практические различия:

Вместо униформ, шейдеры HLSL ожидают использования одного буфера констант, назначенного в регистр b0. Специальные имена qt_Matrix, qt_Opacity, и qt_SubRect_<name> работают аналогично GLSL. Все остальные члены буфера ожидают сопоставления с свойствами в элементе ShaderEffect.

Примечание: Структура буфера должна быть совместима для обоих шейдеров. Это означает, что шейдеры, предоставляемые приложением, должны убедиться, что qt_Matrix и qt_Opacity включены в буфер, начиная с смещения 0, когда предоставляется только кастомный код для одного типа шейдера, что приводит к тому, что ShaderEffect предоставляет другой шейдер. Это вызвано встроенным кодом шейдера ShaderEffect, объявляющим буфер констант, содержащий float4x4 qt_Matrix; float qt_Opacity;.

В отличие от атрибутов GLSL, для элементов ввода вершин не используются имена. Поэтому qt_Vertex и qt_MultiTexCoord0 не имеют значения. Вместо этого используются стандартные семантики Direct3D, POSITION и TEXCOORD (или TEXCOORD0). Они используются для определения правильной структуры входных данных.

В отличие от сапплеров GLSL, объекты текстуры и сапплера отделены в HLSL. Шейдеры ожидают 2D-текстуры без массивов и без сэмплирования. Оба связывающие точки текстуры и сапплера ожидаются последовательными и начинаются с 0 (т.е. регистры t0, t1, ..., и s0, s1, ..., соответственно). В отличие от OpenGL, сапплеры не сопоставляются со свойствами элементов Qt Quick, поэтому имя сапплера не имеет значения. Вместо этого текстуры сопоставляются со свойствами, ссылающимися на элементы Image или ShaderEffectSource.

В отличие от OpenGL, бэкэнды для современных API обычно предпочитают отложенную компиляцию и поставляют предварительно скомпилированный байткод с приложениями вместо встроенных строк исходного кода шейдера. В этом случае строковые свойства для вершинных и фрагментных шейдеров интерпретируются как URL-адреса, ссылающиеся на локальные файлы или файлы, предоставленные через систему ресурсов Qt.

Для проверки поддержки во время выполнения используйте свойства GraphicsInfo.shaderSourceType и GraphicsInfo.shaderCompilationType. Обратите внимание, что это битовые маски, так как некоторые бэкэнды могут поддерживать несколько подходов.

В случае Direct3D 12 поддерживаются все комбинации. Если свойства vertexShader и fragmentShader образуют допустимый URL со схемой file или qrc, байткод или исходный код HLSL читается из указанного файла. Тип содержимого файла определяется автоматически. В противном случае строка рассматривается как исходный код HLSL и компилируется во время выполнения, предполагая Shader Model 5.0 и точку входа "main". Это позволяет динамически создавать строки шейдера. Однако, когда исходный код шейдера статичен, настоятельно рекомендуется предварительно скомпилировать его в байткод с помощью инструмента fxc и ссылаться на эти файлы из QML. Это значительно повысит производительность во время выполнения и позволит обнаруживать синтаксические ошибки в шейдерах при компиляции.

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

END_OF_DOCUMENT_MARKER

Использование файлов с байткодом обеспечивает большую гибкость, особенно в отношении имени точки входа (оно может быть любым, не ограничиваясь main) и модели шейдера (например, может быть новее, чем 5.0, например 5.1).

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
            fragmentShader: "qrc:/effect_ps.cso"
        }
    }
}
где effect_ps.cso — скомпилированный байткод для следующего шейдера HLSL:
cbuffer ConstantBuffer : register(b0)
{
    float4x4 qt_Matrix;
    float qt_Opacity;
};
Texture2D src : register(t0);
SamplerState srcSampler : register(s0);
float4 ExamplePixelShader(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET
{
    float4 tex = src.Sample(srcSampler, coord);
    float3 col = dot(tex.rgb, float3(0.344, 0.5, 0.156));
    return float4(col, tex.a) * qt_Opacity;
}

Вышеприведенный пример эквивалентен представленному ранее примеру для OpenGL. Вершинный шейдер предоставляется неявно объектом ShaderEffect. Обратите внимание, что вывод фрагментного шейдера использует предварительно умноженный альфа-канал, и qt_Matrix присутствует в буфере констант со смещением 0, даже если фрагментный шейдер не использует это значение.

При желании исходный код HLSL можно разместить непосредственно в исходном коде QML, аналогично тому, как это делается с GLSL. Единственное различие в этом случае — имя точки входа, которое должно быть main при использовании встроенных исходных строк.

В качестве альтернативы, мы также могли бы сослаться на файл, содержащий исходный код эффекта, вместо скомпилированной версии байткода.

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

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
            property variant color: Qt.vector3d(0.344, 0.5, 0.156)
            vertexShader: "qrc:/effect_vs.cso"
            fragmentShader: "qrc:/effect_ps.cso"
        }
    }
}
где effect_vs.cso и effect_ps.cso — скомпилированный байткод для ExampleVertexShader и ExamplePixelShader. Исходный код представлен здесь как один фрагмент, но шейдеры также могут быть размещены в отдельных исходных файлах.
cbuffer ConstantBuffer : register(b0)
{
    float4x4 qt_Matrix;
    float qt_Opacity;
    float3 color;
};
Texture2D src : register(t0);
SamplerState srcSampler : register(s0);
struct PSInput
{
    float4 position : SV_POSITION;
    float2 coord : TEXCOORD0;
};
PSInput ExampleVertexShader(float4 position : POSITION, float2 coord : TEXCOORD0)
{
    PSInput result;
    result.position = mul(qt_Matrix, position);
    result.coord = coord;
    return result;
}
float4 ExamplePixelShader(PSInput input) : SV_TARGET
{
    float4 tex = src.Sample(srcSampler, coord);
    float3 col = dot(tex.rgb, color);
    return float4(col, tex.a) * qt_Opacity;
}

Примечание: При использовании OpenGL координата y изменяется снизу вверх, в то время как в Direct3D она изменяется сверху вниз. Для источников шейдерных эффектов Qt Quick скрывает это различие, обрабатывая QtQuick::ShaderEffectSource::textureMirroring соответствующим образом, что означает, что координаты текстуры в версии шейдеров HLSL не потребуют никаких корректировок по сравнению с эквивалентным кодом GLSL.

Элементы ShaderEffect кроссплатформенные и кросс-API

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

Существует два подхода к решению этой проблемы: либо писать условные значения свойств на основе GraphicsInfo.shaderType, либо использовать селекторы файлов. На практике второй подход настоятельно рекомендуется, поскольку он приводит к более лаконичному и чистому коду приложения. Единственный случай, когда он не подходит, — это когда исходные строки генерируются динамически.

import QtQuick 2.8 // for GraphicsInfo

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
            property variant color: Qt.vector3d(0.344, 0.5, 0.156)
            fragmentShader: GraphicsInfo.shaderType === GraphicsInfo.GLSL ?
                "varying highp vec2 coord;
                uniform sampler2D src;
                uniform lowp float qt_Opacity;
                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;"
            : GraphicsInfo.shaderType === GraphicsInfo.HLSL ?
                "cbuffer ConstantBuffer : register(b0)
                {
                    float4x4 qt_Matrix;
                    float qt_Opacity;
                };
                Texture2D src : register(t0);
                SamplerState srcSampler : register(s0);
                float4 ExamplePixelShader(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET
                {
                    float4 tex = src.Sample(srcSampler, coord);
                    float3 col = dot(tex.rgb, float3(0.344, 0.5, 0.156));
                    return float4(col, tex.a) * qt_Opacity;
                }"
            : ""
        }
    }
}
Это первый подход, основанный на GraphicsInfo.shaderType. Обратите внимание, что значение, сообщаемое GraphicsInfo, не обновляется до тех пор, пока элемент ShaderEffect не будет связан с элементом QQuickWindow. До этого сообщаемое значение равно GraphicsInfo.UnknownShadingLanguage. Альтернативой является размещение исходного кода GLSL и скомпилированного байткода D3D в файлы shaders/effect.frag и shaders/+hlsl/effect.frag, включение их в систему ресурсов Qt и предоставление внутренней функции ShaderEffect — QFileSelector выполнить свою работу. Бесселекторная версия — это исходный код GLSL, а селектор hlsl используется при работе с бэкендом D3D12. Файл в +hlsl может содержать либо исходный код HLSL, либо скомпилированный байткод из инструмента fxc. Кроме того, при использовании контекста ядра профиля версии 3.2 или более поздней версии с OpenGL, исходные коды GLSL с синтаксисом, совместимым с ядром профиля, могут быть размещены в +glslcore.
import QtQuick 2.8 // for GraphicsInfo

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
            property variant color: Qt.vector3d(0.344, 0.5, 0.156)
            fragmentShader: "qrc:shaders/effect.frag" // selects the correct variant automatically
        }
    }
}

Эффекты ShaderEffect и слои элементов

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

Слой с отключенным эффектом Слой с включенным эффектом
Item {
    id: layerRoot
    layer.enabled: true
    layer.effect: ShaderEffect {
        fragmentShader: "
            uniform lowp sampler2D source; // this item
            uniform lowp float qt_Opacity; // inherited opacity of this item
            varying highp vec2 qt_TexCoord0;
            void main() {
                lowp vec4 p = texture2D(source, qt_TexCoord0);
                lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
                gl_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: "
                uniform lowp sampler2D colorSource;
                uniform lowp sampler2D maskSource;
                uniform lowp float qt_Opacity;
                varying highp vec2 qt_TexCoord0;
                void main() {
                    gl_FragColor =
                        texture2D(colorSource, qt_TexCoord0)
                        * texture2D(maskSource, qt_TexCoord0).a
                        * qt_Opacity;
                }
            "
        }
    }

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

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

Модуль Qt Graphical Effects содержит несколько готовых эффектов для использования с приложениями Qt Quick.

См. также Слои элементов.

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

blending : bool

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

cullMode : enumeration

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

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

По умолчанию — NoCulling.

fragmentShader : string

Это свойство содержит исходный код фрагментного (пиксельного) шейдера или ссылку на предварительно скомпилированный байткод. Некоторые API, такие как OpenGL, всегда поддерживают компиляцию во время выполнения, и поэтому традиционный способ Qt Quick встраивания строк исходного кода шейдера функционален. Однако бэкэнды Qt Quick для других API могут ограничить поддержку предварительно скомпилированным байткодом, таким как SPIR-V или байткод шейдеров D3D. В этом случае строка просто имя файла, которое может быть файлом в файловой системе или встроено в исполняемый файл через систему ресурсов Qt.

В GLSL по умолчанию шейдер ожидает, что координата текстуры будет передана из вершинного шейдера как varying highp vec2 qt_TexCoord0, и он выбирает образец из сапплера2D под именем source. В HLSL текстура имеет имя source, а вершинный шейдер ожидается, что он предоставит float2 coord : TEXCOORD0 в своем выходе дополнительно к float4 position : SV_POSITION (имена могут отличаться, так как связывание выполняется на основе семантики).

См. также vertexShader и GraphicsInfo.

log : string

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

См. также status.

mesh : variant

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

См. также GridMesh.

status : enumeration

Это свойство сообщает о текущем статусе программы шейдеров OpenGL.

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

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

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

См. также log.

supportsAtlasTextures : bool

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

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

END_OF_DOCUMENT_MARKER

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

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

vertexShader : string

Это свойство содержит исходный код шейдера вершины или ссылку на предварительно скомпилированный байткод. Некоторые API, такие как OpenGL, всегда поддерживают компиляцию во время выполнения, поэтому традиционный способ Qt Quick встраивания строк исходного кода шейдеров работает. Однако бэкэнды Qt Quick для других API могут ограничивать поддержку предварительно скомпилированным байткодом, например, SPIR-V или байткодом шейдеров D3D. В этом случае строка просто представляет собой имя файла, который может находиться в файловой системе или быть встроен в исполняемый файл с помощью системы ресурсов Qt.

При использовании GLSL по умолчанию шейдер передает координаты текстуры фрагмент-шейдеру как varying highp vec2 qt_TexCoord0. При использовании HLSL достаточно использовать стандартную TEXCOORD0 семантику, например float2 coord : TEXCOORD0.

См. также fragmentShader и GraphicsInfo.

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

Spec-Zone.ru

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