Spec-Zone.ru › Qt 5.12

Тип QML ShaderEffect

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

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

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), нижняя правая (width, height).
  • attribute vec2 qt_MultiTexCoord0 - координаты текстуры, верхняя левая координата — (0, 0), нижняя правая (1, 1). Если supportsAtlasTextures — true, координаты будут основаны на позиции в атласе.

Кроме того, все свойства, которые могут быть сопоставлены с типом языка 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, не блокируют отрисовку или другие части приложения до готовности байткода.

Использование файлов с байткодом обеспечивает большую гибкость, особенно в отношении имени точки входа (оно может быть любым, не ограничиваясь 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.12/qml-qtquick-shadereffect.html

Spec-Zone.ru

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