QSGMaterialShader 类
QSGMaterialShader 类表示一个与图形 API 无关的着色器程序。 更多...
头文件 | #include <QSGMaterialShader> |
CMake | find_package(Qt6 REQUIRED COMPONENTS Quick) target_link_libraries(mytarget PRIVATE Qt6::Quick) |
qmake | QT += quick |
- 所有成员的列表,包括继承的成员
- QSGMaterialShader 是 Qt Quick Scene Graph Material 类 的一部分。
公共类型
struct | GraphicsPipelineState |
class | RenderState |
enum | Flag { UpdatesGraphicsPipelineState } |
flags | Flags |
公共函数
QSGMaterialShader() | |
(自 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) |
详细描述
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
文件是在线生成的,或在最迟应用程序构建时,使用 Qt Shader Tools 模块中的 qsb
工具从 Vulkan 风格的 GLSL 源代码生成的。
有三种可重写的虚拟函数。这些提供均匀缓冲区、纹理和管道状态更改的数据或生成数据的逻辑。
updateUniformData() 是最受子类重新实现的函数。这个函数预计将更新一个 QByteArray 的内容,然后将其暴露给着色器作为均匀缓冲区。任何具有其顶点或片段着色器中的均匀块的 QSGMaterialShader 都必须实现 updateUniformData。
updateSampledImage() 与着色器代码采样纹理相关。该函数将在每个采样器上调用(或相关的图像采样器,在相关的 API 中),允许指定哪个 QSGTexture 应该暴露给着色器。
着色器管道状态更改使用得较少。一个用例是希望使用特定混合模式的材质。相关函数是 updateGraphicsPipelineState。除非 QSGMaterialShader 通过设置标志 UpdatesGraphicsPipelineState 来同意接受,否则这个函数不会被调用。该函数的任务是用期望的更改更新它接收到的 GraphicsPipelineState 结构实例。目前只提供了混合和剔除相关的功能,其它状态无法由材质控制。
一个包含纹理支持的最小示例可能如下。在此,我们假设材料(Material)是创建Shader实例的 QSGMaterial,它在createShader()方法中调用Shader,并且它持有我们希望在片段着色器中采样的 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
标志 QSGMaterialShader::Flags
标志值,用于指示特殊材料属性。
常量 | 值 | 描述 |
---|---|---|
QSGMaterialShader::UpdatesGraphicsPipelineState | 0x0001 | 设置此标志可启用调用 updateGraphicsPipelineState。 |
Flags类型是QFlags<Flag>的typedef。它存储了标志值的或组合。
成员函数文档
QSGMaterialShader::QSGMaterialShader()
构造一个新的QSGMaterialShader。
[自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为真,则在此材质着色器上设置flags;否则清除指定的标志。
void QSGMaterialShader::setFlags(QSGMaterialShader::Flags flags)
为此材质着色器设置flags。
另请参阅 flags。
[受保护]
void QSGMaterialShader::setShader(QSGMaterialShader::Stage stage, const QShader &shader)
为指定的 阶段 设置 着色器。
[受保护]
void QSGMaterialShader::setShaderFileName(QSGMaterialShader::Stage stage, const QString &filename)
为指定 阶段 的着色器设置 文件名。
文件应包含序列化的 QShader。
[虚函数]
bool QSGMaterialShader::updateGraphicsPipelineState(QSGMaterialShader::RenderState &state, QSGMaterialShader::GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
此函数由场景图调用,允许材质提供一组自定义的图形状态。材质可以自定义的状态集限于混合和相关设置。
注意:此函数仅在通过 UpdatesGraphicsPipelineState 标志通过 setFlags() 启用时被调用。默认情况下,它未被设置,因此此函数永远不会被调用。
每当修改了 ps 中任何成员时,必须返回值 true
。
注意:ps 的内容在此函数调用之间不是持久的。
当前渲染 状态 从场景图中传递。
可以从 newMaterial 中提取子类特定的状态。当 oldMaterial 为 null 时,此着色器刚刚被激活。
[虚函数]
void QSGMaterialShader::updateSampledImage(QSGMaterialShader::RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
此函数由场景图调用,用于在着色器中使用采样图像,通常以组合图像采样器的形式。
binding 是采样器的绑定编号。对于与 QSGMaterialShader 相关的着色器代码中的每个组合图像采样器变量,都会调用该函数。
texture 是 QSGTexture 指针数组。数组中的元素数量与着色器代码中指定的图像采样器变量的数量匹配。此变量可能是一个数组,可能具有超过一个维度。可以通过 QSGMaterialShader::combinedImageSamplerCount 找到数组中的元素数量。
当纹理元素为null
时,必须在返回前将其设置为一个有效的QSGTexture
指针。当其为非空时,是否将新的QSGTexture *
存储到它,还是更新已知的QSGTexture
的某些参数,由材质自行决定。不会转移QSGTexture
的所有权。
当前渲染状态是从场景图传递过来的。在有相关性的情况下,由材质决定是否通过QSGTexture::commitTextureOperations
()进行纹理数据的上传队列。
可以从newMaterial
中提取特定子类的状态。
可以使用oldMaterial
来最小化更改。当oldMaterial
为空时,这个着色器刚刚被激活。
另请参阅:QSGMaterialShader::combinedImageSamplerCount。
[虚函数]
bool QSGMaterialShader::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
此函数被场景图调用以获取着色器程序 uniform 缓冲区的内容更新。实现不期望执行任何真正的图形操作,它仅负责将数据复制到从RenderState::uniformData
返回的QByteArray中。场景图负责使该缓冲区在着色器中可见。
当前渲染状态从场景图传递过来。如果状态指示任何相关状态已变脏,实现必须更新通过RenderState::uniformData
可访问的缓冲区数据中的相应区域。如果一个状态,如矩阵或不透明度,未变脏,则不需要触摸相应的区域,因为数据是持久的。
每当对 uniform 数据进行任何更改时,返回值都必须是true
。
从newMaterial
中提取特定子类的状态,如平面颜色材质的颜色,以相应地更新缓冲区的相关区域。
可以使用oldMaterial
来最小化更新材质状态时的缓冲区更改(通常是memcpy调用)。当oldMaterial
为空时,这个着色器刚刚被激活。
© 2024 The Qt Company Ltd。文档中的贡献是各自所有者的版权。提供的文档受GNU Free Documentation License version 1.3
的条款许可,由自由软件基金会发布。Qt及其相关标志是The Qt Company Ltd.在芬兰以及全球其他国家的商标。所有其他商标均为其各自所有者的财产。