0

问题

OpenGL 4.4、C++11

通过将顶点属性设置为 element_array_buffer 和 array_buffer,我是否有权在 element_array_buffer 中为每个属性使用从 0 开始的索引?

数据布局

VAO      
 Buffer(array_buffer)      
   PositionFloat * n  
   TextureFloat  * n
   NormalFloat   * n
 Buffer(element_array_buffer)      
   PositionIndex * 1
   TextureIndex  * 1
   NormalIndex   * 1

数据使用

//gen
glBindVertexArray(VAO);

glBindBuffer(array_buffer, vbo);
glBufferData(array_buffer, size(vertices), data(vertices), access(vertices));
glVertexAttribPointer(POSITIONS, 3, float, offset(0));
glVertexAttribPointer(UVS,       2, float, offset(positions));
glVertexAttribPointer(NORMALS,   3, float, offset(normals));

glBindBuffer(element_array_buffer, ebo);
glBufferData(element_array_buffer, size(elements), data(elements), access(elements)); 
...?! /*Cannot set element attributes!  
If I could, I would set a strided, offset attribPointer for each attribute, 
so that if 0 appears in the NORMALS attribute, it will look up the first normal, 
and not the first element in the buffer. */

问题

我编写索引以便可以使用 0/0/0 引用第一个顶点、UV 和法线。是否可以将其映射到 element_array_buffer 并照此使用?或者我的解决方案是将 nPositions 添加到我的纹理索引,并将 nPositions+nTextures 添加到我的正常索引?

4

1 回答 1

2

OpenGL 不支持每个顶点属性的单独索引。为顶点属性使用缓冲区时,您需要为顶点属性的每个唯一组合创建一个顶点。

典型的例子是一个以位置和法线作为顶点属性的立方体。立方体有 8 个角,因此它有 8 个不同的位置属性值。它有 6 个面,因此它有 6 个不同的正常属性值。立方体有多少个顶点?在 OpenGL 中,答案是…… 24

至少有两种方法可以推导出为什么在这种情况下顶点数是 24:

  • 立方体有 6 个面。我们不能在边之间共享顶点,因为它们有不同的法线。每边有 4 个角,所以我们需要每边 4 个顶点。6 * 4 = 24。
  • 立方体有 8 个角。在这 8 个角中的每一个角处,有 3 条边相交。由于这 3 条边有不同的法线,我们需要为每条边设置不同的顶点。8 * 3 = 24。

现在,由于您专门询问 OpenGL 4.4,因此可以考虑其他选项。例如,您可以将顶点属性的值指定为索引而不是坐标。因为您当然可以使用多个顶点属性,所以每个顶点可以有多个索引。然后,您的顶点着色器将这些索引作为顶点属性的值。然后它可以从不同的来源检索实际的属性值。这些来源的可能性包括:

  • 统一的缓冲区。
  • 纹理缓冲区。
  • 纹理。

我不相信这些中的任何一个都会像以更传统的方式简单地使用顶点属性一样有效。但如果您想探索所有选项,可能值得一试。

实例化渲染是另一种方法,有时可以帮助渲染顶点属性的不同组合,而无需枚举所有组合。但这仅在您的几何图形重复时才真正有效。例如,如果您想通过一次绘制调用渲染多个立方体,并为每个立方体使用不同的颜色,那么实例化渲染将完美地工作。

于 2014-08-17T18:42:36.660 回答