Shadergen 工具

shadergen 工具是 Qt Quick 3D 资产预处理管道的一部分的命令行应用程序。它可以在每个项目中打开或从命令行手动运行。预先生成材料着色器可以显著影响启动时间或在运行时避免不想要的卡顿,因为在运行时创建材料着色器的过程可能会很昂贵。

注意:此工具处于实验性开发阶段,但大多数常见用例应该已经可行。

离线着色器生成器面临的最大挑战是可能生成的不同材料的数量,这不仅取决于材料属性本身,也取决于剩余场景的设置;例如,光数量、光类型、阴影等都会影响生成的着色器。当我们还考虑动态属性时,材料着色器的排列数量可能会迅速变得在实际构建时无法实现。为了限制工具需要生成的着色器数量,工具试图只生成它认为应用程序需要的着色器。工具中使用的启发式算法可能无法始终检测到应该生成哪些材料,这尤其适用于在运行时更改的属性。要验证材料着色器已成功且正确地生成,工具应生成一个可检查以验证其内容是否匹配应用程序使用的材料的 .qsbc 文件。也可以通过设置环境变量 QT_RHI_SHADER_DEBUG=1 查看调试输出中有关引引擎成功加载 预先生成 着色器的提及,以验证材料是否从预构建缓存中加载。

已知限制

  • 包含多个 View3D 的场景。
  • 使用生成材料时,不支持动态添加或删除灯光。
  • 由于它依赖于渲染器的内部,生成的着色器严格绑定到使用的 Qt 版本。因此,生成的着色器的兼容性无法在版本之间保证。

使用

要启用项目中材料着色器的离线生成,请在项目文件中添加以下内容

CMake

qt6_add_materials(offlineshaders "shaders"
    PREFIX
        "/"
    FILES
        ${qml_resource_files}
)

或者,可以通过命令行手动调用 shadergen 工具,如下所示

shadergen main.qml Material.qml

通常,应从应用程序的项目文件夹中运行 shadergen 工具,但也可以通过 -C 参数指令工具更改其当前工作目录。

如果没有提供输出路径,则工具将把生成的文件写入当前目录。可以用 -o 选项更改输出路径。

请注意,为了工具生成预期的材料,它需要了解整个场景而不是仅仅材料,例如场景中的灯光数量也会影响材料的生成方式,所以所有相关的qml文件都应该添加到工具需要处理的文件列表中。

命令行参数

简短完整说明
-C <PATH>–directory <PATH>将当前目录更改到<PATH>。此参数是可选的。
-o <PATH>–output-dir <PATH>设置输出路径为<PATH>。这是工具生成的文件存放的位置。如果没有指定路径,则使用当前目录。
-r <NAME>–resource-file <NAME>将生成的资源文件名称更改为<NAME>。此参数是可选的。
-l <FILE>–list-qsbc <FILE>列出qsbc文件的内容。

生成的内容

shadergen工具的主要输出文件是一个.qsbc文件。.qsbc文件包含一组.qsb文件以及一些关于各种材料着色器的元数据,如每个材料的唯一属性字符串。

可以通过使用带有-d参数的shadergen工具来检查.qsbc文件。

shadergen -d qtappshaders.qsbc

动态属性

由于工具是在构建时运行的,因此它对在运行时可能会改变哪些属性的能力有限。仅在属性范围内改变值(例如,粗糙度值)的属性,对生成的材料着色器没有影响,但对于被视为开启或关闭的属性(例如,在运行时设置图像地图),则需要生成不同类型的材料。因此,建议将所有可以启用或禁用材料或场景功能的材料变体都声明为单独的组件,这将有助于工具生成正确的材料着色器。

以下示例显示了添加基本颜色图到材料以在运行时进行的虚构示例。请注意,组件MaterialRedExtended在示例中从未使用过,它仅仅定义来帮助shadergen工具生成在运行时动态设置baseColorMap所需的着色器。

MaterialRed.qml

PrincipledMaterial {
    baseColor: "red"
    lighting: PrincipledMaterial.NoLighting
}

MaterialRedExtended.qml

MaterialRed {
    baseColorMap: Texture {
        source: "maps/metallic/basecolor.jpg"
    }
}

main.qml

Model {
    position: Qt.vector3d(0, -30, 0)
    scale: Qt.vector3d(4, 4, 4)
    source: "#Sphere"
    materials: MaterialRed {
        id: redMaterial
    }
MouseArea {
    anchors.fill: parent
    onClicked: {
    if (redMaterial.baseColorMap === null)
        redMaterial.baseColorMap = baseColorMap
    else
        redMaterial.baseColorMap = null
    }
}

另见 QtShaderTools

© 2024 The Qt Company Ltd. 本文档的贡献岸权属于各自的所有者。本文档根据由自由软件基金会发布的GNU自由文档许可1.3版的条款进行许可。Qt和相应的标志是The Qt Company Ltd.在芬兰以及全世界其他国家的商标。所有其他商标均为各自所有者的财产。