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

Posted

技术标签:

【中文标题】在 GLSL 顶点着色器中,您可以访问索引缓冲区中顶点的索引,而不仅仅是顶点缓冲区吗?【英文标题】:In a GLSL vertex shader can you access the index of a vertex in the index buffer, not just the vertex buffer? 【发布时间】:2020-07-06 03:03:00 【问题描述】:

我在 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 规范 1.2.146 §8.7.1,顶点着色必须为相同的索引重复,除非它保证相同的结果,所以这应该是可能的:

如果在绘制命令中多次指定相同的顶点(例如,通过在索引缓冲区中多次包含相同的索引值),如果它可以静态确定顶点着色器调用将产生相同的结果。

【问题讨论】:

【参考方案1】:

我需要能够在我的顶点着色器中判断这是第一次、第二次还是第三次看到相同的顶点。

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

这就是你引用的那段文字的意思。

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

【讨论】:

感谢您的解释!我现在可能会坚持在内存中重复顶点,但是如果有机会,我可能会使用 SSBO 或实例渲染,如果结果证明它更有效的话。

以上是关于在 GLSL 顶点着色器中,您可以访问索引缓冲区中顶点的索引,而不仅仅是顶点缓冲区吗?的主要内容,如果未能解决你的问题,请参考以下文章

在顶点着色器中更改顶点的颜色

GLSL索引绘图并设置纹理案例

GLSL:使用片段着色器进行对象翻译

顶点纹理获取(在顶点着色器中读取纹理)

GLSL 每个顶点固定大小的数组

OpenGL重叠顶点属性