处理具有多种顶点格式的 GLTF 节点
Handling GLTF nodes with multiple vertex formats
我正在使用 Vulkan 和 C++ 在爱好渲染器中实现对 GLTF 2.0 的支持。
https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html
最初,我实现了对一些测试 GLTF 文件的基本支持。然而,在仔细阅读规范后,我发现了一些难以处理的细节。
根据规范,一个节点由一个或多个网格组成,一个网格由一个或多个基元组成。在同一个Node中,每个Primitive可以使用不同的顶点格式,包括:
- 不同数量的属性(即:仅位置与位置+普通)
- 不同的属性排序(即:位置+法线与法线+位置)。
- 指向结构数组的访问器与其他使用元素数组的访问器。
在我看来,这会产生一种情况,为了制作一个可以处理一般 GLTF 模型的强大渲染器,需要创建一堆着色器排列图元可能使用的各种顶点格式。到目前为止,我想到的关于如何避免着色器排列爆炸的唯一想法如下:
- 使用包含所有规范定义属性的顶点格式定义着色器。解析 GLTF 文件时,对任何缺失的属性使用默认值。从文件中读取顶点数据时,如果属性存在但具有不同的数据类型,则将该数据转换为预期类型(即:将 short 提升为 ints)。将属性重新排序为着色器所期望的。此外,当检测到一些众所周知的顶点格式时,还有一些其他专门的着色器(即:如果格式是 Position+Normal+Coord0,则使用着色器 Foo)。
我尝试了上面的变体,加载模型非常慢。此外,这似乎是一种脆弱的方法。
还有什么方法可以减轻对单个节点进行大量管道更改的潜在需求? and/or 需要为所有不同的情况定义许多着色器?
每个图元都旨在成为一个单独的绘制调用,可能带有一个单独的着色器程序。
请注意,图元的不同之处不仅仅在于顶点属性。图元包含自己的 material 引用,因此它可以与同一网格拥有的其他图元完全分开 material。
基元的存在是为了提供一种在单个网格中包含多个 material 的机制,但它们需要单独的绘制调用和单独的着色器来实现。这个在Meshes Overview section.
里面有讲到
我正在使用 Vulkan 和 C++ 在爱好渲染器中实现对 GLTF 2.0 的支持。 https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html
最初,我实现了对一些测试 GLTF 文件的基本支持。然而,在仔细阅读规范后,我发现了一些难以处理的细节。
根据规范,一个节点由一个或多个网格组成,一个网格由一个或多个基元组成。在同一个Node中,每个Primitive可以使用不同的顶点格式,包括:
- 不同数量的属性(即:仅位置与位置+普通)
- 不同的属性排序(即:位置+法线与法线+位置)。
- 指向结构数组的访问器与其他使用元素数组的访问器。
在我看来,这会产生一种情况,为了制作一个可以处理一般 GLTF 模型的强大渲染器,需要创建一堆着色器排列图元可能使用的各种顶点格式。到目前为止,我想到的关于如何避免着色器排列爆炸的唯一想法如下:
- 使用包含所有规范定义属性的顶点格式定义着色器。解析 GLTF 文件时,对任何缺失的属性使用默认值。从文件中读取顶点数据时,如果属性存在但具有不同的数据类型,则将该数据转换为预期类型(即:将 short 提升为 ints)。将属性重新排序为着色器所期望的。此外,当检测到一些众所周知的顶点格式时,还有一些其他专门的着色器(即:如果格式是 Position+Normal+Coord0,则使用着色器 Foo)。
我尝试了上面的变体,加载模型非常慢。此外,这似乎是一种脆弱的方法。
还有什么方法可以减轻对单个节点进行大量管道更改的潜在需求? and/or 需要为所有不同的情况定义许多着色器?
每个图元都旨在成为一个单独的绘制调用,可能带有一个单独的着色器程序。
请注意,图元的不同之处不仅仅在于顶点属性。图元包含自己的 material 引用,因此它可以与同一网格拥有的其他图元完全分开 material。
基元的存在是为了提供一种在单个网格中包含多个 material 的机制,但它们需要单独的绘制调用和单独的着色器来实现。这个在Meshes Overview section.
里面有讲到