在 GLSL 顶点着色器中,您可以访问索引缓冲区中的顶点索引,而不仅仅是顶点缓冲区吗?

In a GLSL vertex shader can you access the index of a vertex in the index buffer, not just the vertex buffer?

我正在 Vulkan 中渲染一个基元,它具有重复的顶点,顶点着色器根据它们在顶点缓冲区中的索引对其进行不同的处理。所有重复的顶点都是连续的,所以如果 a、b、c 是顶点,缓冲区可能看起来像 [a,a,a,b,b,b,c,c,c],我需要能够在我的顶点着色器中判断这是第一次、第二次还是第三次看到相同的顶点。

如果我简单地将同一个顶点多次提交到顶点缓冲区,我可以使用 gl_VertexIndex(或 OpenGL 中的 gl_VertexID)来确定同一个顶点的重复次数,然后根据需要以不同方式处理每个重复。

但是,我想使用索引缓冲区来避免重复内存中的顶点。当使用索引缓冲区时,每次出现相同的索引时,gl_VertexIndex 都是相同的值,因为它是顶点缓冲区的索引,对于索引缓冲区来说,每个顶点只有一个副本是值得的。这意味着在顶点着色器中我无法区分顶点的第一次、第二次或第三次重复。

是否有像 gl_VertexIndex 这样的内置变量我可以使用,例如 gl_IndexBufferIndex 它告诉我这个顶点来自索引缓冲区中的哪个索引?或者,这个顶点在索引缓冲区中已经遇到了多少次?如果没有,是否有一种有效的方法可以将此信息逐个顶点发送到顶点着色器?

根据 Vulkan Specification 1.2.146 §8.7.1,必须对同一索引重复顶点着色,除非保证得到相同的结果,因此这应该是可能的:

If the same vertex is specified multiple times in a draw command (e.g. by including the same index value multiple times in an index buffer) the implementation may reuse the results of vertex shading if it can statically determine that the vertex shader invocations will produce identical results.

I need to be able to tell in my vertex shader whether this is the first, second or third time it's seeing the same vertex.

你不能。 Vulkan(以及所有其他渲染 API)定义“相同顶点”的方式是 通过顶点索引 (或者更具体地说,通过 vertex/instance 索引对,但这与这个问题无关)。如果系统在绘制调用中获得相同的顶点索引,则允许假设顶点着色器 从该顶点产生相同的输出值,因此可以跳过 VS 调用感谢 post-T&L 缓存。

这就是您引用的文字所说的内容。

如果您真的需要做您所说的事情,那么您将不得不自己进行顶点获取。也就是说,您将“真实”顶点索引数组设为属性,并在 VS 中使用该索引从 SSBO 读取实际属性数据。这允许您获取相同的数据,尽管顶点索引不同。