QSGMaterialShader Class
QSGMaterialShader 类表示一个与图形 API 无关的着色器程序。更多内容...
| 头文件: | #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 ` 构建,并拥有诸如 `updateState() ` 之类的函数,可发出任意的 OpenGL 命令。 在 Qt 6 中情况已发生改变。QSGMaterialShader 并非严格的数据导向型,这意味着它不仅提供数据(着色器和所需的管道状态更改),还提供用于更新统一缓冲区中数据的逻辑。 不提供图形 API 访问接口。这意味着 QSGMaterialShader 无法自行调用 OpenGL、Vulkan、Metal 或 Direct 3D。结合统一的着色器管理机制,这使得 QSGMaterialShader 只需编写一次,即可在运行时与任何受支持的图形 API 兼容。
通过调用受保护的setShaderFileName()函数设置的着色器,控制材质如何处理几何体的顶点数据,以及片段如何进行着色。通常,QSGMaterialShader会在构造时设置顶点着色器和片段着色器。此后更改着色器可能无法达到预期效果,因此必须避免。
在 Qt 6 中,默认做法是将.qsb 文件与应用程序一同发布,通常通过资源系统嵌入,并在调用setShaderFileName() 时进行引用。.qsb 文件是在脱机状态下(或最迟在应用程序构建时)通过 QtShader Tools 模块中的qsb 工具,从 Vulkan 风格的 GLSL 源代码生成的。
有三个虚拟方法可以被重写。它们为统一缓冲区、纹理以及管道状态更改提供数据,或提供生成这些数据的逻辑。
updateUniformData() 是子类中最常被重写的函数。该函数负责更新QByteArray 的内容,该内容随后将作为统一缓冲区提供给着色器。任何在顶点着色器或片段着色器中包含统一块的 QSGMaterialShader 都必须重写updateUniformData()。
updateSampledImage() 适用于着色器代码对纹理进行采样的情况。该函数将针对每个采样器(或在相关 API 中,针对组合图像采样器)被调用,并允许指定应向着色器暴露哪个QSGTexture 。
着色器管道状态的更改使用频率较低。一种用例是希望使用特定混合模式的材质。相关函数是updateGraphicsPipelineState()。除非 QSGMaterialShader 通过设置标志UpdatesGraphicsPipelineState 选择了启用该功能,否则不会调用此函数。该函数的任务是根据所需的更改更新传递给它的GraphicsPipelineState 结构实例。 目前仅提供与混合和剔除相关的功能,其他状态无法通过材质进行控制。
一个包含纹理支持的简易示例如下。此处假设 Material 是通过createShader() 方法创建 Shader 实例的QSGMaterial ,且其持有我们在片段着色器中需要采样的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 、场景图 - 自定义材质、场景图 - 两个纹理提供程序以及场景图 - 图。
成员类型文档
enum QSGMaterialShader::Flag
flags QSGMaterialShader::Flags
用于指示特殊材料属性的标志值。
| 常量 | 值 | 描述 |
|---|---|---|
QSGMaterialShader::UpdatesGraphicsPipelineState | 0x0001 | 设置此标志可启用对updateGraphicsPipelineState()的调用。 |
Flags 类型是QFlags<Flag> 的 typedef。它存储了 Flag 值的按“或”运算组合。
成员函数文档
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)
为指定stage 的着色器设置filename 。
该文件应包含一个序列化的QShader 。
警告:着色器 (包括.qsb 文件)被视为可信内容。建议应用程序开发人员在允许加载不属于应用程序的用户提供的内容之前,仔细考虑其潜在影响。
[protected, since 6.8] void QSGMaterialShader::setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename, int viewCount)
为指定stage 的着色器设置filename 。
该文件应包含一个序列化的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 为 null 时,表示该着色器刚刚被激活。
[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 为 null 时,表示该着色器刚刚被激活。
另请参阅 QSGMaterialShader::combinedImageSamplerCount 。
[virtual] bool QSGMaterialShader::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
该函数由场景图调用,用于更新着色器程序中uniform缓冲区的内容。该实现不应执行任何实际的图形操作,其职责仅限于将数据复制到由RenderState::uniformData()返回的QByteArray 中。场景图负责确保该缓冲区在着色器中可见。
当前的渲染state 由场景图传递而来。如果状态指示任何相关状态为“脏”状态,实现必须更新通过RenderState::uniformData()访问的缓冲区数据中的相应区域。当某个状态(例如矩阵或不透明度)不是“脏”状态时,由于数据是持久的,因此无需修改相应的区域。
只要对统一数据进行了任何更改,返回值必须为true 。
子类特有的状态(例如纯色材质的颜色)应从newMaterial 中提取,以便相应地更新缓冲区中的相关区域。
oldMaterial 可用于在更新材质状态时最大限度地减少缓冲区更改(通常是 memcpy 调用)。当 `oldMaterial ` 为空时,表示该着色器刚刚被激活。
© 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.