QSGMaterialShader Class
QSGMaterialShader 类代表独立于图形 API 的着色器程序。更多
Header: | #include <QSGMaterialShader> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Quick) target_link_libraries(mytarget PRIVATE Qt6::Quick) |
qmake: | QT += quick |
- 所有成员(包括继承成员)的列表
- QSGMaterialShader 是Qt Quick 场景图材质类的一部分。
公共类型
struct | GraphicsPipelineState |
class | RenderState |
enum | Flag { UpdatesGraphicsPipelineState } |
flags | Flags |
公共函数
QSGMaterialShader() | |
(since 6.4) int | combinedImageSamplerCount(int binding) const |
QSGMaterialShader::Flags | flags() const |
void | setFlag(QSGMaterialShader::Flags flags, bool on = true) |
void | setFlags(QSGMaterialShader::Flags flags) |
virtual bool | updateGraphicsPipelineState(QSGMaterialShader::RenderState &state, QSGMaterialShader::GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
virtual void | updateSampledImage(QSGMaterialShader::RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
virtual bool | updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
保护函数
void | setShader(QSGMaterialShader::Stage stage, const QShader &shader) |
void | setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename) |
(since 6.8) void | setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename, int viewCount) |
详细说明
QSGMaterialShader 表示顶点和片段着色器、定义图形管道状态变化的数据以及更新统一缓冲区和纹理等图形资源的逻辑的组合。
注意: 所有带有 QSG 前缀的类都只能在场景图的渲染线程中使用。更多信息请参见场景图和渲染。
QSGMaterial 和 QSGMaterialShader 关系密切。对于一个场景图(包括嵌套图),有一个唯一的 QSGMaterialShader 实例,该实例封装了场景图用于使用该材质渲染对象的着色器和其他数据。每个QSGGeometryNode 都可以有一个唯一的QSGMaterial ,用于定义在绘制节点时必须如何配置图形管道。用户永远不会明确创建 QSGMaterialShader 实例,它会由场景图通过QSGMaterial::createShader() 按需创建。场景图通过调用QSGMaterial::createShader() 方法创建 QSGMaterialShader 实例,确保每个着色器实现只有一个实例。
在 Qt 5 中,QSGMaterialShader 与 OpenGL 绑定。它直接建立在QOpenGLShaderProgram 上,并拥有可发出任意 OpenGL 命令的updateState()
等函数。Qt 6 不再是这种情况。QSGMaterialShader 严格来说不是面向数据的,这意味着它提供数据(着色器和所需的流水线状态变化)以及在统一缓冲区中更新数据的逻辑。不提供图形 API 访问。这意味着 QSGMaterialShader 自身无法进行 OpenGL、Vulkan、Metal 或 Direct 3D 调用。加上统一的着色器管理,这使得 QSGMaterialShader 只需编写一次,就能在运行时与任何受支持的图形 API 配合使用。
通过调用受保护的setShaderFileName() 函数设置的着色器可控制材质如何处理来自几何体的顶点数据,以及片段如何着色。QSGMaterialShader 通常会在构建过程中设置顶点和片段着色器。事后更改着色器可能达不到预期效果,因此必须避免。
在 Qt XML 6 中,默认方法是随应用程序一起发送.qsb
文件,通常通过资源系统嵌入,并在调用setShaderFileName() 时引用。.qsb
文件是使用 QtShader Tools 模块中的qsb
工具从 Vulkan 风格的 GLSL 源代码离线生成的,或最迟在应用程序构建时生成。
有三个虚函数可以被重写。它们为统一缓冲区、纹理和流水线状态变化提供数据或生成数据的逻辑。
updateUniformData() 是子类中最常重新实现的函数。该函数用于更新QByteArray 的内容,然后将该内容作为统一缓冲区暴露给着色器。任何在顶点或片段着色器中使用 uniform 块的 QSGMaterialShader 都必须重新实现updateUniformData()。
updateSampledImage() 在着色器代码对纹理进行采样时非常重要。每个采样器(或相关 API 中的组合图像采样器)都将调用该函数,并可选择指定哪些QSGTexture 应暴露给着色器。
着色器流水线状态更改较少使用。一种用例是希望使用特定混合模式的材质。相关函数是updateGraphicsPipelineState() 。除非 QSGMaterialShader 通过设置标志UpdatesGraphicsPipelineState 选择了混合模式,否则不会调用此函数。该函数的任务是根据所需的更改更新传递给它的GraphicsPipelineState 结构实例。目前只有混合和剔除相关功能可用,其他状态无法由材质控制。
下面是一个包含纹理支持的最小示例。在这里,我们假定材质是QSGMaterial ,它在createShader() 中创建了一个着色器实例,并保存了我们希望在片段着色器中采样的QSGTexture 。顶点着色器只依赖模型视图-投影矩阵。
class Shader : public QSGMaterialShader { public: Shader() { setShaderFileName(VertexStage, QLatin1String(":/materialshader.vert.qsb")); setShaderFileName(FragmentStage, QLatin1String(":/materialshader.frag.qsb")); } bool updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *) { bool changed = false; QByteArray *buf = state.uniformData(); if (state.isMatrixDirty()) { const QMatrix4x4 m = state.combinedMatrix(); memcpy(buf->data(), m.constData(), 64); changed = true; } return changed; } void updateSampledImage(RenderState &, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *) { Material *mat = static_cast<Material *>(newMaterial); if (binding == 1) *texture = mat->texture(); } };
着色器的 Vulkan 风格 GLSL 源代码如下所示。这些代码有望使用qsb
工具进行离线预处理,生成 Shader() 构造函数中引用的.qsb
文件。
#version 440 layout(location = 0) in vec4 aVertex; layout(location = 1) in vec2 aTexCoord; layout(location = 0) out vec2 vTexCoord; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; } ubuf; out gl_PerVertex { vec4 gl_Position; }; void main() { gl_Position = ubuf.qt_Matrix * aVertex; vTexCoord = aTexCoord; }
#version 440 layout(location = 0) in vec2 vTexCoord; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D srcTex; void main() { vec4 c = texture(srcTex, vTexCoord); fragColor = vec4(c.rgb * 0.5, 1.0); }
注意: 所有带有 QSG 前缀的类都只能在场景图的渲染线程中使用。更多信息请参见场景图和渲染。
另请参阅 QSGMaterial 、场景图 - 自定义材质、场景图 - 两个纹理提供程序和场景图 - 图形。
成员类型文档
枚举 QSGMaterialShader::Flag
flags QSGMaterialShader::Flags
用于指示特殊材质属性的标志值。
常量 | 值 | 说明 |
---|---|---|
QSGMaterialShader::UpdatesGraphicsPipelineState | 0x0001 | 设置此标志可调用updateGraphicsPipelineState(). |
Flags 类型是QFlags<Flag> 的类型定义。它存储 Flag 值的 OR 组合。
成员函数文档
QSGMaterialShader::QSGMaterialShader()
构建新的 QSGMaterialShader。
[since 6.4]
int QSGMaterialShader::combinedImageSamplerCount(int binding) const
返回位于binding 的组合图像采样器变量中的元素个数。该值来自着色器代码。变量可以是一个数组,也可以有多个维度。
计数反映了变量中组合图像采样器项的总数。在下面的示例中,srcA
的计数为 1,srcB
的计数为 4,srcC
的计数为 6。
layout (binding = 0) uniform sampler2D srcA; layout (binding = 1) uniform sampler2D srcB[4]; layout (binding = 2) uniform sampler2D srcC[2][3];
该计数是QSGMaterialShader::updateSampledImage 的纹理参数中QSGTexture 指针的数量。
此函数在 Qt 6.4 中引入。
另请参阅 QSGMaterialShader::updateSampledImage 。
QSGMaterialShader::Flags QSGMaterialShader::flags() const
返回此材质着色器当前设置的标记。
另请参阅 setFlags()。
void QSGMaterialShader::setFlag(QSGMaterialShader::Flags flags, bool on = true)
如果on 为 true,则设置此材质着色器的flags ;否则清除指定标记。
void QSGMaterialShader::setFlags(QSGMaterialShader::Flags flags)
设置此材质着色器的flags 。
另请参阅 flags().
[protected]
void QSGMaterialShader::setShader(QSGMaterialShader::Stage stage, const QShader &shader)
为指定的stage 设置shader 。
[protected]
void QSGMaterialShader::setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename)
为指定的着色器设置filename stage 。
该文件预计包含序列化的QShader 。
警告: 着色器(包括.qsb
文件)被假定为可信内容。建议应用程序开发人员在允许加载非应用程序一部分的用户提供内容之前,仔细考虑其潜在影响。
[protected, since 6.8]
void QSGMaterialShader::setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename, int viewCount)
为指定的着色器设置filename stage 。
预计该文件将包含序列化的QShader 。
此重载用于启用multiview 渲染时,尤其是使用联编系统的 MULTIVIEW 便捷选项时。
viewCount 应为 2、3 或 4。 将据此自动调整。filename
警告: 着色器(包括.qsb
文件)被假定为可信内容。建议应用程序开发人员在允许加载非应用程序一部分的用户提供内容之前,仔细考虑其潜在影响。
此功能在 Qt 6.8 中引入。
[virtual]
bool QSGMaterialShader::updateGraphicsPipelineState(QSGMaterialShader::RenderState &state, QSGMaterialShader::GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
该函数由场景图调用,使材质能够提供一组自定义的图形状态。材质可自定义的状态集仅限于混合和相关设置。
注意: 只有通过setFlags() 启用UpdatesGraphicsPipelineState 标志时,才会调用此函数。默认情况下未设置该标志,因此从未调用过该函数。
每当对ps 中的任何成员进行更改时,返回值必须为true
。
注意: 在调用此函数期间,ps 中的内容不会持久存在。
当前渲染state 由场景图传递。
子类的具体状态可从newMaterial 中提取。当oldMaterial 为空时,该着色器刚刚被激活。
[virtual]
void QSGMaterialShader::updateSampledImage(QSGMaterialShader::RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
该函数由场景图调用,以准备在着色器中使用采样图像,通常采用组合图像采样器的形式。
binding 是采样器的绑定编号。与 相关联的着色器代码中的每个组合图像采样器变量都会调用此函数。QSGMaterialShader
texture 是 指针数组。数组中的元素个数与着色器代码中指定的图像采样器变量中的元素个数一致。该变量可以是一个数组,也可以有多个维度。数组中的元素个数可通过以下方式查找QSGTexture QSGMaterialShader::combinedImageSamplerCount
当texture 中的元素为空时,必须在返回前将其设置为有效的QSGTexture 指针。非空时,由材料决定是否向其存储一个新的QSGTexture *
,或者是否更新已知QSGTexture 上的某些参数。QSGTexture 的所有权不会转移。
当前渲染state 由场景图传递。在相关情况下,材质可通过QSGTexture::commitTextureOperations() 触发纹理数据的上传。
子类的具体状态可从newMaterial 中提取。
oldMaterial 可用于尽量减少更改。当 为空时,该着色器刚刚被激活。oldMaterial
另请参见 QSGMaterialShader::combinedImageSamplerCount 。
[virtual]
bool QSGMaterialShader::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
该函数由场景图调用,用于更新着色器程序统一缓冲区的内容。该函数的实现不需要执行任何真正的图形操作,它只负责将数据复制到从RenderState::uniformData() 返回的QByteArray 。场景图负责在着色器中显示该缓冲区。
当前的渲染state 由场景图传递。如果状态显示任何相关状态为脏状态,执行程序必须更新可通过RenderState::uniformData() 访问的缓冲区数据中的相应区域。如果矩阵或不透明度等状态没有变脏,则无需接触相应区域,因为数据是持久的。
每当统一数据发生变化时,返回值必须是true
。
子类的特定状态(如平面颜色材料的颜色)应从newMaterial 中提取,以便相应地更新缓冲区中的相关区域。
oldMaterial 在更新材质状态时,可以使用 来尽量减少缓冲区的变化(通常是调用 memcpy)。当 为空时,该着色器刚刚被激活。oldMaterial
© 2025 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.