本页内容

QSGMaterial Class

QSGMaterial 类封装了着色器程序的渲染状态。更多内容...

头文件: #include <QSGMaterial>
CMake: find_package(Qt6 REQUIRED COMPONENTS Quick)
target_link_libraries(mytarget PRIVATE Qt6::Quick)
qmake: QT += quick
继承自:

QSGFlatColorMaterial、QSGOpaqueTextureMaterial 以及QSGVertexColorMaterial

公共类型

enum Flag { Blending, RequiresDeterminant, RequiresFullMatrixExceptTranslate, RequiresFullMatrix, NoBatching, CustomCompileStep }
flags Flags

公共函数

virtual int compare(const QSGMaterial *other) const
virtual QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const = 0
QSGMaterial::Flags flags() const
void setFlag(QSGMaterial::Flags flags, bool on = true)
virtual QSGMaterialType *type() const = 0
(since 6.8) int viewCount() const

详细说明

QSGMaterial 与QSGMaterialShader 的子类之间有着紧密的联系。对于一个场景图(包括嵌套的场景图),存在一个唯一的QSGMaterialShader 实例,它封装了场景图用于渲染该材质的着色器,例如用于对几何体进行平涂着色的着色器。 每个QSGGeometryNode 都可以拥有一个唯一的QSGMaterial,其中包含在绘制该节点时着色器的配置方式,例如用于渲染几何体的实际颜色。

QSGMaterial 拥有两个虚拟函数,二者均需实现。函数type() 应返回特定子类的所有实例的唯一实例。函数createShader() 应返回QSGMaterialShader 的新实例,该实例专属于该 QSGMaterial 子类。

一个最简的 QSGMaterial 实现示例如下:

class Material : public QSGMaterial
{
public:
    QSGMaterialType *type() const override { static QSGMaterialType type; return &type; }
    QSGMaterialShader *createShader(QSGRendererInterface::RenderMode) const override { return new Shader; }
};

请参阅“自定义材质”示例,了解如何实现由QSGGeometryNode 和自定义材质支持的QQuickItem 子类。

注意: createShader() 对于每个QSGMaterialType 仅被调用一次,以减少着色器准备过程中的冗余工作。如果一个 QSGMaterial 由多组顶点着色器和片段着色器的组合支持,则type() 的实现必须针对每组着色器组合返回一个不同的、唯一的QSGMaterialType 指针。

注意:所有 以 QSG 为前缀的类应仅在场景图的渲染线程上使用。有关更多信息,请参阅“场景图与渲染”。

另请参阅《 QSGMaterialShader》 、《场景图 - 自定义材质》、《场景图 - 两个纹理提供程序》以及《场景图 - 图》。

成员类型文档

enum QSGMaterial::Flag
flags QSGMaterial::Flags

常数值描述
QSGMaterial::Blending0x0001如果材质在渲染时需要启用混合,请将此标志设置为 true。
QSGMaterial::RequiresDeterminant0x0002如果材质在渲染时依赖几何节点矩阵的行列式,请将此标志设置为 true。
QSGMaterial::RequiresFullMatrixExceptTranslate0x0004 | RequiresDeterminant如果材质在渲染时依赖几何节点矩阵的完整矩阵(平移部分除外),请将此标志设置为 true。
QSGMaterial::RequiresFullMatrix0x0008 | RequiresFullMatrixExceptTranslate如果材质在渲染时依赖几何节点的完整矩阵,请将此标志设置为 true。
QSGMaterial::NoBatching0x0010如果材质使用的着色器与场景图的批处理机制不兼容,请将此标志设置为 true。这在某些高级用法中很重要,例如在顶点着色器中直接操作 `gl_Position.z `。此类解决方案通常与特定的场景结构相关联,且在场景中包含任意内容时使用起来可能不安全。 因此,仅应在充分调查后设置此标志,且对于绝大多数材质而言,该标志绝非必要。设置此标志可能会因需要发出更多绘制调用而导致性能下降。该标志于 Qt 6.3 中引入。
QSGMaterial::CustomCompileStepNoBatching在 Qt 6 中,此标志与 NoBatching 完全相同。建议改用 NoBatching。

Flags 类型是QFlags<Flag> 的 typedef。它存储 Flag 值的按“或”运算组合。

成员函数文档

[virtual] int QSGMaterial::compare(const QSGMaterial *other) const

将该材质与other 进行比较,若两者相等则返回0;若该材质应在other 之前排序,则返回-1;若other 应在该材质之前排序,则返回1。

场景图可以重新排列几何节点以尽量减少状态变化。在排序过程中会调用该比较函数,以便对材质进行排序,从而在每次调用 QSGMaterialShader::updateState() 时尽量减少状态变化。

保证 this 指针和other 调用的type() 返回值相同。

[pure virtual] QSGMaterialShader *QSGMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const

该函数返回一个QSGMaterialShader 实现的新实例,该实例用于为QSGMaterial 的特定实现渲染几何体。

对于每种材质类型与renderMode 的组合,该函数仅会被调用一次,并在内部进行缓存。

对于大多数材质而言,renderMode 可以忽略。少数材质可能需要针对特定的渲染模式进行自定义处理。例如,如果材质实现抗锯齿的方式在使用 RenderMode3D 时需要考虑透视变换。

QSGMaterial::Flags QSGMaterial::flags() const

返回材质的标志。

void QSGMaterial::setFlag(QSGMaterial::Flags flags, bool on = true)

如果on 为真,则在此材质上设置标志flags ;否则清除该属性。

[pure virtual] QSGMaterialType *QSGMaterial::type() const

该函数由场景图调用,用于查询由createShader() 实例化的QSGMaterialShader 所拥有的唯一标识符。

对于许多材质而言,通常的做法是返回一个指向静态(因此可在全局范围内访问)的QSGMaterialType 实例的指针。QSGMaterialType 是一个不透明对象,其唯一目的是作为一种类型安全且简单的方式来生成唯一的材质标识符。

QSGMaterialType *type() const override
{
    static QSGMaterialType type;
    return &type;
}

[since 6.8] int QSGMaterial::viewCount() const

返回值:当该材质用于多视图渲染时,其视图数量。

注意:该 返回值仅在从createShader()调用后才有效。在场景图调用createShader()之前,该值未必是最新的。

通常,返回值为1 。视图计数大于 2 表示进行了多视图渲染。 支持多视图的材质应在createShader() 中或其QSGMaterialShader 构造函数中查询 viewCount(),并确保选择适当的光栅化着色器。随后,顶点着色器应使用gl_ViewIndex 来索引模型-视图-投影矩阵数组,因为多视图模式下存在多个矩阵(每个视图一个)。

以下是一个简单的顶点着色器示例:

#version 440

layout(location = 0) in vec4 vertexCoord;
layout(location = 1) in vec4 vertexColor;

layout(location = 0) out vec4 color;

layout(std140, binding = 0) uniform buf {
    mat4 matrix[2];
    float opacity;
};

void main()
{
    gl_Position = matrix[gl_ViewIndex] * vertexCoord;
    color = vertexColor * opacity;
}

该着色器仅准备处理 2 个视图,且仅限 2 个视图。它与其他视图数量不兼容。在设置着色器条件时,必须通过--view-count 2 调用qsb 工具;或者,如果使用 CMake 集成,则必须在qt_add_shaders() 命令中指定VIEW_COUNT 2 。

注意: 每当设置视图数量为 2 或更大时,qsb 会自动注入包含#extension GL_EXT_multiview : require 的代码行 。

建议开发者使用自动注入的预处理变量QSHADER_VIEW_COUNT ,以简化对不同视图数量的处理。例如,如果需要在同一个源文件中同时支持非多视图和视图数为 2 的多视图,可以这样做:

#version 440

layout(location = 0) in vec4 vertexCoord;
layout(location = 1) in vec4 vertexColor;

layout(location = 0) out vec4 color;

layout(std140, binding = 0) uniform buf {
#if QSHADER_VIEW_COUNT >= 2
    mat4 matrix[QSHADER_VIEW_COUNT];
#else
    mat4 matrix;
#endif
    float opacity;
};

void main()
{
#if QSHADER_VIEW_COUNT >= 2
    gl_Position = matrix[gl_ViewIndex] * vertexCoord;
#else
    gl_Position = matrix * vertexCoord;
#endif
    color = vertexColor * opacity;
}

现在,同一个源文件可以通过qsb 或qt_add_shaders() 运行两次:一次不指定视图数,一次将视图数设置为 2。随后,Material 可以在运行时根据 viewCount() 选择相应的 .qsb 文件。

使用 CMake 时,代码可能类似于以下示例。在此示例中,相应的QSGMaterialShader 应根据 viewCount() 的值在:/shaders/example.vert.qsb 和:/shaders/multiview/example.vert.qsb 之间进行选择。(片段着色器亦同)

qt_add_shaders(application "application_shaders"
    PREFIX
        /
    FILES
        shaders/example.vert
        shaders/example.frag
)

qt_add_shaders(application "application_multiview_shaders"
    GLSL
        330,300es
    HLSL
        61
    MSL
        12
    VIEW_COUNT
        2
    PREFIX
        /
    FILES
        shaders/example.vert
        shaders/example.frag
    OUTPUTS
        shaders/multiview/example.vert
        shaders/multiview/example.frag
)

注意: 为了实现最大的可移植性,片段着色器 应与 顶点着色器采用相同的方式处理,尽管片段着色器代码本身不能依赖于视图计数(gl_ViewIndex )。 将片段着色器也纳入多视图集有两个原因。其一是,根据底层图形 API 的不同,在同一图形管道中混合使用不同版本的着色器可能会引发问题:例如,在 D3D12 中,混合使用针对着色器模型 5.0 和 6.1 的 HLSL 着色器会引发错误。 另一个原因是,在片段着色器中定义 `QSHADER_VIEW_COUNT ` 非常有用,例如在顶点和片段阶段之间共享统一缓冲区布局时。

注意:对于 OpenGL,依赖于 `gl_ViewIndex ` 的顶点着色器的最低 GLSL 版本为 `330`。较低版本在构建时可能被接受,但根据 OpenGL 实现的不同,运行时可能会导致错误。

为方便起见,qt_add_shaders() 还提供了一个MULTIVIEW 选项。该选项首先正常运行qsb 工具,然后将VIEW_COUNT 覆盖为2 ,并将GLSL 、HLSL 、MSL 设置为一些合适的默认值,最后再次运行qsb ,此时生成的 .qsb 文件会附加后缀。 随后,材质实现可以使用接受viewCount 参数的QSGMaterialShader::setShaderFileName() 重载方法,该方法会自动选择正确的 .qsb 文件。

因此,以下代码与上文所示的示例调用基本等效,区别仅在于无需指定任何手动管理的输出文件。请注意,在某些情况下,自动选择的着色语言版本可能不够用,此时应用程序应继续显式指定所有内容。

qt_add_shaders(application "application_multiview_shaders"
    MULTIVIEW
    PREFIX
        /
    FILES
        shaders/example.vert
        shaders/example.frag
)

有关 Qt 中多视图支持的更多低级细节,请参阅QRhi::MultiView 、QRhiColorAttachment::setMultiViewCount() 和QRhiGraphicsPipeline::setMultiViewCount()。Qt Quick 场景图渲染器已准备好识别多视图渲染目标,当通过QQuickRenderTarget::fromRhiRenderTarget() 或 3D API 特定函数(例如将arraySize 参数设为大于 1 的fromVulkanImage())进行指定时。 随后,渲染器将把视图计数传播到图形管道和材质中。

该函数在 Qt 6.8 中引入。

© 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.