繁体   English   中英

在 OpenGL 3.x 中使用索引顶点数组时如何指定每个面的颜色?

[英]How can I specify per-face colors when using indexed vertex arrays in OpenGL 3.x?

我正在尝试使用一个包含 8 个顶点的数组和一个包含 24 个(4 * 6)个索引的索引数组到顶点数组中来渲染一个立方体。 但是如何在不使用弃用函数的情况下指定每个面的变量,例如颜色和法线? 为此,我需要一组单独的索引,但是当我指定两个索引数组( GL_ELEMENT_ARRAY_BUFFERs )并将它们指向不同的着色器变量(两次调用 glVertexAttribPointer)时,出现了问题,并且它不呈现任何东西(但不会也不报告任何错误 - 使用 glGetError 检查)。 我是否必须对每个面使用不同的 glDrawElements 调用,并将颜色和法线加载到统一变量中?

澄清一下,当 8 个顶点中的每一个都是不同面的一部分并且需要不同的颜色和法线值时,就会出现问题。

对是否使用数组索引感兴趣的人可能会在我创建的图表中找到一些实用程序来以图形方式总结不同 OpenGL 调用的行为,以便您可以看到,例如,哪些绘制了连续的顶点数据块,哪些绘制了连续的顶点数据块使用索引“跳过”。

OpenGL 绘制调用 .

如此来源所述,我在 Creative Commons BY-SA 下发布了此图像

先说实际答案:
请参阅 Goz 的回答。 保留 24 个独立的顶点。

一些命名法第二:
顶点是一组顶点属性。 请在阅读以下内容时记住这种区别:

您有一种误解,认为使用已弃用的 API 可以帮助您解决问题。 不是这种情况。 OpenGL 处理(并且一直处理)每个顶点作为一组唯一的属性。 如果您仔细阅读原始规范,您会注意到在执行以下操作时:

glNormal()
glVertex()
glVertex()
glVertex()

规范明确指出glNormal设置current normal state ,并且glVertex激发一个新顶点,复制传递所有current state ,包括current normal state 也就是说,即使您只通过了一个 Normal,GL 仍然会看到 3。

因此,GL 没有“per-face”属性。

此外,您正在混合使用glDrawElements(..., pointer)索引数组GL_ELEMENT_ARRAY_BUFFER ,其中pointer是索引数组内的偏移量,以及从glVertexAttribPointer使用的顶点属性数组GL_ARRAY_BUFFER (以及所有已弃用的glVertexPointer/glNormalPointer ...

索引缓冲区中的每个索引都将用作每个属性的索引,但您只能为每个顶点指定一个索引。 所以,设置GL_ELEMENT_ARRAY_BUFFER然后调用glVertexAttribPointer ,根本不会做你认为的那样。 它要么使用您设置为GL_ARRAY_BUFFER的最后一个数组来定义顶点属性,或者如果您没有保持一个界限,则将您的偏移量解释为一个指针(并且可能会崩溃)。

GL 不支持您尝试执行的操作,即为每个顶点属性设置索引数组。 让我重申一下:每次 draw 只有 1 个索引数组

关于历史的一些额外花絮包括:

glVertex 有点用词不当。 它仅指定顶点位置 但是,这就是它的名字的由来,它还引发了一个要传递给 GL 的顶点。 为了使 API 完全干净,您可以想象必须执行 2 次调用:

// not valid code
glPosition(1,2,3); // specifies the current vertex position
glProvoke(); // pass the current vertex to GL

然而,当第一次指定 GL 时,Position 总是需要的,所以将这 2 个融合来激发一个顶点是有意义的(如果只是为了减少 API 调用次数)。

快进到vertex_program_arb :试图摆脱固定功能模型同时仍然保持兼容意味着必须继承 glVertex 的特殊性质。 这是通过使vertex attribute 0挑衅性和 glVertex 的同义词来实现的。

快进到 GL3.2:开始/结束模型消失了,所有这些激发顶点的规范终于可以消失了,以及current state的管理。 所有语义 API(glVertex*、glNormal*...)也是如此,因为现在所有输入都只是顶点属性。

您需要超过 8 个顶点。 顶点可以共享位置,但除非顶点中的其他所有内容都是唯一的,否则它不是唯一的顶点。 法线是在立方体定义中需要超过 8 个顶点的另一个经典原因。

有趣的解释,但它们似乎掩盖了原始问题包含自己的答案这一事实:“我是否必须对每个面使用不同的 glDrawElements 调用,并将颜色和法线加载到统一变量中?” - 如果不得不在一次应该足够的情况下将相同的顶点位置数据提供给图形处理器三次会冒犯一个人的美感(并且应该这样做),那么这是可以的。

最初的提问者不想知道 OpenGL 不能做他想做的事,他需要为一个立方体维护 24 个顶点,而标准数学和常识告诉我们应该只需要 8 个。 他已经知道他可以做他想做的事,他甚至知道该怎么做。 他只是想确认他提出的方法确实有意义,并且没有更好的方法来做到这一点,而他却忽略了这一点。

对每个面进行调用确实会增加其自身的开销,但这在仅绘制一个立方体时并不重要。 当绘制很多时,所有相同属性的面可以一起批处理,例如所有朝南然后所有西方,或所有红色然后所有绿色,或其他。

在 OpenGL 3.x 中,您可以访问类型插值限定符 使用flat限定符,您将强制使用仅由激发顶点传递的变量。 在某些情况下,这应该足以完成您想要的操作,但缺点是您需要非常注意绘制顶点的顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM