问题
OpenGL 4.4, C++11
我是否有权通过将顶点属性设置为element_array_buffer和array_buffer来为每个属性使用从 0 开始的element_array_buffer索引?
数据布局
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. */
问题
我编写索引,以便我可以引用第一个顶点、UV 和 Normal 的 0/0/0。是否可以将其映射到element_array_buffer中并按此使用?或者我的解决方案是将 nPosition 添加到我的纹理索引中,并将 nPosition+nTextures 添加到我的普通索引中?
OpenGL 不支持每个顶点属性的单独索引。对顶点属性使用缓冲区时,需要为每个唯一的顶点属性组合创建一个顶点。
规范示例是一个多维数据集,其中位置和法线作为顶点属性。立方体有 8 个角,因此它的位置属性有 8 个不同的值。它有 6 个边,因此它有 6 个不同的 normal 属性值。立方体有多少个顶点?在OpenGL中,答案是...24.
至少有两种方法可以推导出为什么在这种情况下顶点数为 24:
- 立方体有 6 个边。我们不能在边之间共享顶点,因为它们具有不同的法线。每边有 4 个角,因此每边需要 4 个顶点。6 * 4 = 24。
- 立方体有 8 个角。在这 8 个角中的每一个,都有 3 个侧面相遇。由于这 3 条边具有不同的法线,因此我们需要为它们中的每个边提供不同的顶点。8 * 3 = 24。
现在,由于您专门询问了OpenGL 4.4,因此可以考虑其他选项。例如,您可以将顶点属性的值指定为索引而不是坐标。由于您当然可以使用多个顶点属性,因此每个顶点可以有多个索引。然后,顶点着色器获取这些索引作为顶点属性的值。然后,它可以从其他源检索实际属性值。这些来源的可能性包括:
- 均匀的缓冲液。
- 纹理缓冲区。
- 纹理。
我不相信其中任何一个会像简单地以更传统的方式使用顶点属性一样有效。但是,如果您想探索所有选择,则值得一试。
实例化渲染是另一种方法,有时可以帮助呈现顶点属性的不同组合,而无需枚举所有组合。但这只有在几何图形重复时才真正有效。例如,如果要使用单个绘制调用渲染多个多维数据集,并为每个立方体使用不同的颜色,则实例化渲染将完美运行。