Spec-Zone.ru › Qt 5.11

Тип QML ShaderEffect

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

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

Элемент

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

Свойства

  • 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 — true, координаты будут основаны на позиции в атласе.

Кроме того, любая свойство, которая может быть отображена в тип языка шейдеров OpenGL (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 <имя>", объявите "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: "
                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, саплеры не отображаются на свойства QML элементов, поэтому имя саплера не имеет значения. Вместо этого, к свойствам, ссылающимся на элементы 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/archives/qt-5.11/qml-qtquick-shadereffect.html

Spec-Zone.ru

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