我正在尝试使用8个顶点的数组和24个(4 *
6)索引的索引数组渲染一个立方体到顶点数组中。但是,如何在不使用弃用函数的情况下指定 per-face 变量(如颜色和法线)?为此,我需要一组单独的索引,但是当我指定两个索引数组(GL_ELEMENT_ARRAY_BUFFERs
)并将它们指向不同的着色器变量(两次调用glVertexAttribPointer)时出现问题,并且它不会呈现任何事情(但也没有报告任何错误 - 用glGetError检查)。我是否必须为每个面使用不同的glDrawElements调用,颜色和法线加载到统一变量中?
为了澄清,当8个顶点中的每一个都是不同面的一部分并且需要不同的颜色和法线值时,就会出现问题。
答案 0 :(得分:39)
对是否使用数组索引感兴趣的人可以在我创建的图表中找到一些实用程序,以图形方式总结不同OpenGL调用的行为,以便您可以看到,例如哪些绘制了连续的顶点数据块与那些使用指数“跳过”的人相比。
我在{Commmons BY-SA下发布此图片,如this source.
所述答案 1 :(得分:32)
实际答案首先:
看看Goz的回答。保留24个不同的顶点。
一些命名法第二:
顶点是一组顶点属性。阅读以下内容时请记住这一区别:
您误以为使用已弃用的API可以帮助您解决问题。不是这种情况。 OpenGL处理(并且始终处理)每个顶点作为一组唯一的属性。如果您仔细阅读原始规范,您会注意到:
glNormal()
glVertex()
glVertex()
glVertex()
规范明确规定glNormal
设置current normal state
,glVertex
激发新顶点,复制传递所有current state
,包括current normal state
。也就是说,即使你只通过了一个法线,GL仍然会看到3。
此外,您正在混合使用GL_ELEMENT_ARRAY_BUFFER
的索引数组glDrawElements(..., pointer)
,其中pointer
是索引数组中的偏移量,以及顶点属性数组GL_ARRAY_BUFFER
,用于glVertexAttribPointer
(以及所有已弃用的glVertexPointer/glNormalPointer
...
索引缓冲区中的每个索引都将用作每个属性的索引,但是您只能为每个顶点指定一个索引。因此,设置GL_ELEMENT_ARRAY_BUFFER
然后调用glVertexAttribPointer
,根本不会执行您认为的操作。它使用您设置为GL_ARRAY_BUFFER
的最后一个数组来定义顶点属性,或者如果您没有保留一个边界,则将偏移量解释为指针(并且可能会崩溃)。 / p>
GL不支持您为每个顶点属性设置索引数组的操作。让我重申一下:每次绘制只有1个索引数组。
包含历史的一些额外花絮:
glVertex有点用词不当。它仅指定Vertex 位置。但是,这就是它的名字,它也引发了一个传递给GL的顶点。为了使API完全干净,您可能会想到必须进行2次调用:
// not valid code
glPosition(1,2,3); // specifies the current vertex position
glProvoke(); // pass the current vertex to GL
但是,当首次指定GL时,总是需要位置,因此融合那些2来激发顶点是有意义的(如果只是为了减少API调用次数)。
快进vertex_program_arb
:试图摆脱固定功能模型,同时仍保持兼容意味着必须继续推进glVertex的特殊性。这是通过使vertex attribute 0
激发和glVertex的同义词来实现的。
快进到GL3.2:开始/结束模型消失了,引发顶点的所有这些规范都可以最终消失,同时管理current state
。所有语义API(glVertex *,glNormal * ...)都可以,因为所有输入现在都只是顶点属性。
答案 2 :(得分:6)
您需要超过8个顶点。 Verts可以共享位置,但除非顶点中的其他所有内容都是唯一的,否则它不是唯一的顶点。法线是在多维数据集定义中需要超过8个顶点的另一个经典原因。
答案 3 :(得分:6)
有趣的解释,但它们似乎掩盖了这样一个事实:原始问题包含它自己的答案:“我是否必须对每个面使用不同的glDrawElements调用,颜色和法线加载到均匀变量中?” - 如果必须将相同的顶点位置数据提供给图形处理器三次,而一次应该足以冒犯一个人的审美意识(并且它应该),那么这是肯定的。
原始提问者不想知道OpenGL不能做他想要做的事情,并且他需要为立方体维护二十四个顶点,标准数学和常识告诉我们只需要八个。他已经知道他可以做他想做的事了,他甚至知道如何做。他只是想确认他提出的方法确实有意义,并且没有一些更好的方法去做他忽略的事情。
对每个面孔进行调用会增加其自身的开销,但在绘制一个多维数据集时这几乎不重要。在绘制多个时,所有相同属性的面可以一起批量处理,例如,面向南方的所有西方,或所有的红色,然后是所有的绿色,或其他什么。
答案 4 :(得分:1)
在OpenGL 3.x中,您可以访问类型interpolation qualifiers。使用flat
限定符,您将强制使用仅由provoking vertex传递的变量。在某些情况下,这应该足以做你想做的事情,但是你需要非常小心地注意绘制顶点的顺序。