ShaderEffect QML Type
将自定义着色器应用于矩形。更多...
| Import Statement: | import QtQuick |
| Inherits: |
属性
- blending : bool
- cullMode : enumeration
- fragmentShader : url
- log : string
- mesh : variant
- status : enumeration
- supportsAtlasTextures : bool
(since QtQuick 2.4) - vertexShader : url
详细说明
ShaderEffect 类型将自定义的vertex 和fragment (pixel) 着色器应用于矩形。它允许在 QML 场景中添加阴影、模糊、着色和卷边等效果。
注意:根据 所使用的Qt Quick 场景图后端不同,ShaderEffect类型可能不受支持。例如,使用software 后端时,效果将完全无法渲染。
着色器
在 Qt 5 中,效果以 GLSL(OpenGL 着色语言)源代码的形式提供,通常作为字符串嵌入到 Qt Qml 中。从 Qt 5.8 开始,也可以引用文件,无论是本地文件还是 Qt 资源系统中的文件。
在 Qt 6 中,Qt Quick 还支持 Vulkan、Metal 和 Direct3D 11 等图形 API。 因此,使用 GLSL 源代码字符串的方法已不再可行。取而代之的是,新的着色器管道基于将兼容 Vulkan 的 GLSL 代码编译为SPIR-V,随后收集反射信息并将其转换为其他着色语言,例如 HLSL、Metal 着色语言以及各种 GLSL 版本。 生成的资源会被打包到一个单一的包中,通常存储在扩展名为.qsb 的文件中。此过程在离线状态下进行,或最迟在应用程序构建时完成。 在运行时,场景图和底层图形抽象层会调用这些.qsb 文件。因此,ShaderEffect 期望在 Qt 6 中使用文件(本地或 qrc)引用来替代内联着色器代码。
在 Qt 6 中,vertexShader 和fragmentShader 属性是 URL,其工作原理与Image.source 等非常相似。不过,ShaderEffect 仅支持file 和qrc 方案。此外,还可以省略file 方案,从而以便捷的方式指定相对路径。此类路径将相对于组件(即.qml 文件)的位置进行解析。
着色器输入与资源
vertexShader 有两种类型的输入:uniforms和顶点输入。
以下输入是预定义的:
- vec4 qt_Vertex,位置为 0——顶点位置,左上角顶点的位置为 (0, 0),右下角为 (width,height)。
- vec2 qt_MultiTexCoord0(位置 1)——纹理坐标,左上角坐标为 (0, 0),右下角为 (supportsAtlasTextures, )。如果 为 true,则坐标将基于图集中的位置。
注意: 实际上只有顶点输入的位置才 重要。 名称可以自由更改,但位置必须始终为:顶点位置使用 `0 `,纹理坐标使用 `1 `。但请注意,这仅适用于顶点输入,对于顶点着色器输出的变量(随后作为片段着色器的输入,通常是插值后的纹理坐标)则未必成立。
以下统一变量已预定义:
- mat4 qt_Matrix - 组合变换矩阵,由从根项到此 ShaderEffect 的各矩阵与正交投影矩阵的乘积构成。
- float qt_Opacity - 组合不透明度,即从根项到此 ShaderEffect 的各不透明度值的乘积。
注意:Vulkan 风格的 GLSL 没有独立的 uniform 变量。相反,着色器必须始终使用绑定点为 `0` 的 uniform 块。
注意: uniform 块的 布局限定符必须始终为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。若要包含 fillMode,请使用ShaderEffectSource 或 Image::layer::enabled。
- ShaderEffectSource -> sampler2D - 原点位于左上角,且颜色值已预乘。
采样器在着色器代码中仍被声明为独立的uniform变量。着色器可以自由选择这些变量的任何绑定点,但0 除外,因为该绑定点被保留用于uniform块。
某些着色语言和 API 具有图像对象与采样器对象分离的概念。Qt Quick 在着色器中始终与组合式的图像采样器对象配合使用,这得到了 SPIR-V 的支持。因此,为 ShaderEffect 提供的着色器应始终使用layout(binding = 1) uniform sampler2D tex; 风格的采样器声明。 底层抽象层和着色器管道会自动处理这一机制,使其在所有受支持的 API 和着色语言中正常运行,且对应用程序完全透明。
QML 场景图后端可能会选择将纹理分配到纹理图集中。 如果将纹理图集中分配的纹理传递给 ShaderEffect,系统会默认将其从纹理图集复制到独立纹理中,以便纹理坐标范围为 0 到 1,并获得预期的环绕模式。但是,这会增加内存使用量。 要避免纹理复制,对于使用 qt_MultiTexCoord0 的简单着色器,请设置supportsAtlasTextures ;或者对于每个“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 ,则使用源覆盖混合模式。不过,通过在alpha通道中输出零值,也可以实现加法混合。
| |
本示例假设myeffect.vert 和myeffect.frag 包含Vulkan风格的GLSL代码,这些代码由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;
}注意:场景图(Scene Graph)中的纹理原点位于左上角,而非 OpenGL 中常见的左下角。
仅使用一个着色器
同时指定vertexShader 和fragmentShader 并非强制要求。实际上,许多 ShaderEffect 实现仅需提供片段着色器,同时依赖默认的内置顶点着色器。
默认顶点着色器会将纹理坐标作为vec2 qt_TexCoord0 ,在0 位置传递给片段着色器。
默认片段着色器预期纹理坐标由顶点着色器作为vec2 qt_TexCoord0 传递至位置0 ,并从绑定点1 处的名为source 的sampler2D中进行采样。
警告:当 仅指定其中一个着色器时 ,着色器编写者必须了解默认着色器所期望的统一变量块布局:qt_Matrix 必须始终位于偏移量 0 处,随后是位于偏移量 64 处的 qt_Opacity。任何自定义统一变量都必须放置在这两个之后。 即使应用程序提供的着色器未使用矩阵或不透明度,此规则也是强制性的,因为在运行时,顶点着色器和片段着色器共享同一个统一缓冲区。
警告: 与顶点输入不同, 顶点着色器与片段着色器之间的数据传递可能(取决于底层图形 API)需要使用相同的名称,仅位置匹配并不总是足够的。 最明显的是,当指定片段着色器而依赖默认的内置顶点着色器时,纹理坐标会作为qt_TexCoord0 传递到位置0 ,因此强烈建议片段着色器声明名称相同的输入(qt_TexCoord0)。 如果不这样做,可能会在某些平台上导致问题,例如在非核心配置文件的 OpenGL 上下文中运行时,底层 GLSL 着色器源代码中没有位置限定符,而在着色器链接过程中,匹配是基于变量名称进行的。
ShaderEffect 和 Item Layers
ShaderEffect 类型可与layered items 结合使用。
禁用效果的图层 ![]() | 启用了效果的图层 ![]() |
|
还可以组合多个分层项:
![]() |
|
其他注意事项
默认情况下,ShaderEffect 由四个顶点组成,每个顶点对应一个角。对于非线性顶点变换(如页面卷曲效果),您可以通过指定 `mesh ` 的分辨率来设置精细的顶点网格。
从 Qt 5 迁移
对于包含 ShaderEffect 项的 Qt 5 应用程序,迁移到 Qt 6 需要:
- 将着色器代码移至独立的
.vert和.frag文件中, - 将着色器更新为与 Vulkan 兼容的 GLSL,
- 对这些着色器运行
qsb工具, - 通过 Qt 资源系统将生成的
.qsb文件包含到可执行文件中, - 并在vertexShader 和fragmentShader 属性中引用该文件。
如QtShader Tools模块所述,其中部分步骤可通过让 CMake 在构建时调用qsb 工具来实现自动化。有关更多信息和示例,请参阅qt_add_shaders()。
关于着色器代码的更新,以下是对常见修改内容的概述。
| Qt 5 中的顶点着色器 | Qt 6 中的顶点着色器 |
|---|---|
| |
转换过程主要涉及更新代码以兼容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)。 - 顶点着色器输出和片段着色器输入由着色器代码自行定义。片段着色器必须在位置 0 处有一个
vec4输出(通常称为fragColor)。 为了实现最大的可移植性,顶点输出和片段输入应同时使用相同的索引号和相同的名称。当仅指定片段着色器时,纹理坐标将从内置顶点着色器作为vec2 qt_TexCoord0从位置0传递进来,如上面的示例代码片段所示。 - 统一块外的统一变量是不合法的。相反,统一数据必须在绑定点为
0的统一块中声明。 - uniform 块应使用 std140 限定符。
- 在运行时,顶点着色器和片段着色器将获得绑定到绑定点 0 的相同统一缓冲区。因此,一般而言,两个着色器之间的统一块声明必须完全一致。这还包括在其中一个着色器中未使用的成员。 成员名称必须一致,因为某些图形 API 会将 uniform 块转换为传统的 struct uniform,且该转换对应用程序是透明的。
- 当仅提供其中一个着色器时,请注意:内置着色器期望在统一块的开头看到
qt_Matrix和qt_Opacity。(更准确地说,分别位于偏移量0和64处)一般而言,应始终将它们作为该块的第一个和第二个成员包含在内。 - 在示例中,uniform 块指定了块名
buf。该名称可以自由更改,但必须在各个着色器之间保持一致。使用实例名(如layout(...) uniform buf { ... } instance_name;)是可选的。如果指定了实例名,则所有对成员的访问都必须通过 instance_name 进行限定。
| Qt 5 中的片段着色器 | Qt 6 中的片段着色器 |
|---|---|
| |
- 精度限定符(
lowp、mediump、highp)目前尚未使用。 - 调用内置 GLSL 函数时必须遵循现代 GLSL 命名规范,最显著的区别是使用
texture()代替texture2D()。 - 采样器必须使用从 1 开始的绑定点。
- 当Qt Quick 在启用
multiview的情况下进行渲染时(例如,因为它是 VR/AR 环境中 3D 场景渲染的一部分,其中左右眼的內容在单次渲染中生成),ShaderEffect 的着色器编写时必须考虑到这一点。 例如,当视图数为 2 时,将有2个矩阵(其中 qt_Matrix 是一个包含两个元素的 mat4 数组)。顶点着色器应考虑gl_ViewIndex的影响。有关创建支持多视图着色器的通用信息,请参阅QSB 手册中的“Multiview”章节。
另请参阅 Item Layers 、QSB 手册以及qt_add_shaders。
属性文档
blending : bool
如果此属性为 true,则“fragmentShader ”的输出将使用“source-over”混合模式与背景进行混合。如果为 false,则忽略背景。混合操作会降低性能,因此当不需要混合时,应将此属性设置为 false。默认值为 true。
cullMode : enumeration
此属性用于定义该项的哪些侧面应显示出来。
| 常量 | 描述 |
|---|---|
ShaderEffect.NoCulling | 两面均可见 |
ShaderEffect.BackFaceCulling | 仅正面可见 |
ShaderEffect.FrontFaceCulling | 仅背面可见 |
默认值为 NoCulling。
fragmentShader : url
该属性包含对包含预处理后片段着色器包的文件的引用,该文件的扩展名通常为.qsb 。该值被视为URL ,这与其他QML类型(如Image)类似。它必须是本地文件,或者使用qrc方案访问通过Qt资源系统嵌入的文件。 URL 可以是绝对路径,也可以是相对于组件 URL 的相对路径。
警告:着色器 (包括.qsb 文件)被视为受信任的内容。建议应用程序开发者在允许加载不属于应用程序本身的用户提供内容之前,仔细考虑其潜在影响。
另请参阅 vertexShader 。
log : string [read-only]
该属性记录了最近一次编译着色器时产生的警告和错误日志。当status 被设置为“已编译”或“错误”时,该属性会同时更新。
注意:在 Qt 6中 ,着色器管道会优先在离线状态下(或最迟在构建时)编译和转换 Vulkan 风格的 GLSL 着色器。 这并不一定意味着运行时不会发生着色器编译,但即使发生,ShaderEffect 也不会参与其中,且该阶段不应再出现语法错误及类似错误。因此,该属性的值通常为空。
另请参阅 status 。
mesh : variant
该属性定义了用于绘制ShaderEffect 的网格。它可以存储任何GridMesh 对象。如果为该属性赋值了一个尺寸值,则ShaderEffect 会隐式地使用一个GridMesh ,其值为mesh resolution 。默认情况下,该属性的尺寸为1x1。
另请参阅 GridMesh 。
status : enumeration [read-only]
该属性反映着着色器的当前状态。
| 常量 | 描述 |
|---|---|
ShaderEffect.Compiled | 着色器程序已成功编译并链接。 |
ShaderEffect.Uncompiled | 着色器程序尚未编译。 |
ShaderEffect.Error | 着色器程序编译或链接失败。 |
设置片段着色器或顶点着色器源代码时,状态将变为“未编译”。首次使用新着色器源代码渲染ShaderEffect 时,系统会编译并链接着色器,状态将更新为“已编译”或“错误”。
当未使用运行时编译,且着色器属性引用了包含字节码的文件时,状态始终为“已编译”。 在渲染管道的后期阶段之前,渲染器不会检查着色器的内容(除了用于发现顶点输入元素和常量缓冲区数据的基本反射之外),因此潜在的错误(如布局或根签名不匹配)只会在稍后阶段被检测到。
另请参阅 log 。
supportsAtlasTextures : bool [since QtQuick 2.4]
将此属性设置为 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 的相对路径。
警告:着色器 (包括.qsb 文件)被视为可信内容。建议应用程序开发人员在允许加载不属于应用程序本身的用户提供的内容之前,仔细考虑其潜在影响。
另请参阅 fragmentShader 。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.



