处理具有多种顶点格式的 GLTF 节点
Posted
技术标签:
【中文标题】处理具有多种顶点格式的 GLTF 节点【英文标题】:Handling GLTF nodes with multiple vertex formats 【发布时间】:2021-12-24 22:25:14 【问题描述】:我正在使用 Vulkan 和 C++ 在爱好渲染器中实现对 GLTF 2.0 的支持。 https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html
最初,我实现了对一些测试 GLTF 文件的基本支持。然而,在仔细阅读规范后,我发现了一些难以处理的细节。
根据规范,一个节点由一个或多个网格组成,一个网格由一个或多个基元组成。在同一个 Node 内,每个 Primitive 可以使用不同的顶点格式,包括:
不同数量的属性(即:仅位置与位置+正常) 不同的属性排序(即:Position+Normal vs Normal+Position)。 指向结构数组的访问器与其他使用元素数组的访问器相比。在我看来,这造成了一种情况,为了制作一个可以处理一般 GLTF 模型的强大渲染器,需要创建一堆着色器排列以用于 Primitive 可能使用的各种顶点格式。到目前为止,我想到的关于如何避免着色器排列爆炸的唯一想法如下:
使用包含所有规范定义属性的顶点格式定义着色器。解析 GLTF 文件时,对任何缺失的属性使用默认值。从文件中读取顶点数据时,如果存在属性但具有不同的数据类型,则将该数据转换为预期的类型(即:将 short 提升为 ints)。将属性重新排序为着色器所期望的。此外,当检测到一些众所周知的顶点格式时,还有一些其他专用着色器(即:如果格式为 Position+Normal+Coord0,则使用着色器 Foo)。我尝试了上述方法的变体,但加载模型非常慢。此外,这似乎是一种脆弱的方法。
还有什么方法可以减轻对单个节点进行大量管道更改的需求?和/或需要为所有不同的情况定义许多着色器?
【问题讨论】:
从广义上讲,制作“一切渲染器”并不是一条有趣的路。当您可以对您正在做的事情施加一些基本限制时,作为 API 的 Vulkan 处于最佳状态,您施加的限制越多,您所做的一切就越高效。如果您决心找到一种方法将某些 glTF 文件提供给您的 任何内容 投射到屏幕上,那么您将不得不接受由此带来的一些后果。 【参考方案1】:每个基元都是一个单独的绘图调用,可能带有单独的着色器程序。
请注意,图元的不同不仅仅在于顶点属性。图元包含自己的材质参考,因此它可以是与同一网格拥有的其他图元完全分开的材质。
基元的存在是为了提供一种机制来在单个网格中包含多种材质,但它们需要单独的绘制调用和单独的着色器来实现。这在Meshes Overview section 中有讨论。
【讨论】:
以上是关于处理具有多种顶点格式的 GLTF 节点的主要内容,如果未能解决你的问题,请参考以下文章