class QSGMaterialShader#

QSGMaterialShader 类表示一个与图形 API 无关的着色器程序。更多...

摘要#

方法#

虚方法#

注意

此文档可能包含从 C++ 自动转换到 Python 的片段。我们始终欢迎对片段翻译的贡献。如果您发现翻译有误,也可以通过在 https:/bugreports.qt.io/projects/PYSIDE 上创建工单来告知我们。

详细说明#

QSGMaterialShader 代表了一个由顶点和片段着色器组成的组合,定义了图形管线状态的变化数据,以及更新图形资源(如统一缓冲区和纹理)的逻辑。

注意

应仅在场景图渲染线程中使用带有 QSG 前缀的所有类。有关更多信息,请参阅 场景图和渲染

《QSGMaterial》和《QSGMaterialShader》之间有一个紧密的关系。对于场景图(包括嵌套图),有一个唯一的《QSGMaterialShader》实例,它封装了场景图使用该材料渲染对象所需的所有着色器和数据。每个《QSGGeometryNode》都可以有一个唯一的《QSGMaterial》,它定义了绘图节点时必须如何配置图形管线。用户不会显式创建《QSGMaterialShader》的实例,它将通过《createShader()`》方法在场景图需要时创建。场景图通过调用`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 文件是在线生成或最晚在应用程序构建时生成,从使用Qt Shader 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 前缀的所有类。有关更多信息,请参阅 场景图和渲染

Flag#

(继承自 enum.Flag) 表示特殊材质属性的 Flag 值。

常量

描述

QSGMaterialShader.UpdatesGraphicsPipelineState

设置此 Flag 将启用调用 updateGraphicsPipelineState() .

Stage#
__init__()#

构建一个新的 QSGMaterialShader .

combinedImageSamplerCount(binding)#
参数:

binding - int

返回类型:

int

返回在 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];

此计数是 QSGTexture 指针在 updateSampledImage 的纹理参数中的数量。

另请参阅

updateSampledImage

flags()#
返回类型:

Flag 的组合

返回此材质着色器目前设置的 Flag。

另请参阅

setFlags()

setFlag(flags[, on=true])#
参数:
  • flags - Flag 的组合

  • on - bool

on为真时,设置此材质着色器上的flags;否则清除指定的标志。

setFlags(flags)#
参数:

flags - Flag 的组合

设置此材质着色器的flags

另请参阅

flags()

setShaderFileName(stage, filename)#
参数:
  • stageStage

  • filename – 字符串

设置特定stage的着色器的filename

该文件预计包含一个序列化的 QShader。

updateUniformData(state, newMaterial, oldMaterial)#
参数:
返回类型:

布尔值

当场景图调用此函数以获取着色程序均匀缓冲区的内容更新时,该函数被调用。实现不需要执行任何真实图形操作,它仅仅负责将数据复制到从 uniformData() 返回的 QByteArray 中。场景图会确保该缓冲区在着色器中可见。

当前渲染state从场景图传递。如果状态指示任何相关的状态是脏的,实现必须在可通过 uniformData() 访问的缓冲数据中的相应区域进行更新。当一个状态,例如,矩阵或不透明度,不是脏的时候,没有必要触摸相应的区域,因为数据是持久的。

如果任何均匀数据发生变化,则返回值必须为 true

应从 newMaterial 中提取子类特定的状态,例如平面颜色材质的颜色,以相应地更新缓冲区中的相关区域。

oldMaterial 可以用来在更新材质状态时最小化缓冲区更改(通常是 memcpy 调用)。当 oldMaterial 为空时,表示此着色器刚刚激活。