简体   繁体   English

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

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

I'm trying to render a cube using an array of 8 vertices and an index-array of 24 (4 * 6) indices into the vertex array.我正在尝试使用一个包含 8 个顶点的数组和一个包含 24 个(4 * 6)个索引的索引数组到顶点数组中来渲染一个立方体。 But how can I specify per-face variables, like colors and normals without using deprecated functions?但是如何在不使用弃用函数的情况下指定每个面的变量,例如颜色和法线? For this I need a separate set of indices, but when I specify two index-arrays ( GL_ELEMENT_ARRAY_BUFFERs ) and point them to different shader-variables (with two calls to glVertexAttribPointer) something goes wrong, and it doesn't render anything (but doesn't report any errors either - checked with glGetError).为此,我需要一组单独的索引,但是当我指定两个索引数组( GL_ELEMENT_ARRAY_BUFFERs )并将它们指向不同的着色器变量(两次调用 glVertexAttribPointer)时,出现了问题,并且它不呈现任何东西(但不会也不报告任何错误 - 使用 glGetError 检查)。 Do I have to use different calls to glDrawElements for each face, with color and normal loaded into uniform variables?我是否必须对每个面使用不同的 glDrawElements 调用,并将颜色和法线加载到统一变量中?

To clarify, the problem arises when each of the 8 vertices are part of different faces and need different values for color and normal.澄清一下,当 8 个顶点中的每一个都是不同面的一部分并且需要不同的颜色和法线值时,就会出现问题。

People interested in whether to use array indices or not may find some utility in a diagram I created to graphically summarise the behaviour of the different OpenGL calls, so that you can see, for example, which ones draw contiguous blocks of vertex data, versus which ones 'skip around' using indices.对是否使用数组索引感兴趣的人可能会在我创建的图表中找到一些实用程序来以图形方式总结不同 OpenGL 调用的行为,以便您可以看到,例如,哪些绘制了连续的顶点数据块,哪些绘制了连续的顶点数据块使用索引“跳过”。

OpenGL 绘制调用. .

I published this image under Creative Commons BY-SA, as noted at this source.如此来源所述,我在 Creative Commons BY-SA 下发布了此图像

The actual answer first:先说实际答案:
See Goz's answer.请参阅 Goz 的回答。 Keep 24 separate vertices.保留 24 个独立的顶点。

Some nomenclature second:一些命名法第二:
A Vertex is a set of vertex attributes.顶点是一组顶点属性。 Please keep that distinction in mind when reading the following:请在阅读以下内容时记住这种区别:

You have a misconception that using deprecated APIs would help you solve the issue.您有一种误解,认为使用已弃用的 API 可以帮助您解决问题。 This is not the case.不是这种情况。 OpenGL handles (and has always handled) each vertex as a unique set of attributes. OpenGL 处理(并且一直处理)每个顶点作为一组唯一的属性。 If you read the original spec carefully, you'll notice that when doing:如果您仔细阅读原始规范,您会注意到在执行以下操作时:

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

The specification clearly states that glNormal sets the current normal state , and that glVertex provokes a new vertex, copying in passing all the current state , including the current normal state .规范明确指出glNormal设置current normal state ,并且glVertex激发一个新顶点,复制传递所有current state ,包括current normal state That is, even though you passed only one Normal, the GL still sees 3.也就是说,即使您只通过了一个 Normal,GL 仍然会看到 3。

The GL, therefore, does not have "per-face" attributes.因此,GL 没有“per-face”属性。

Also, you're mixing index arrays GL_ELEMENT_ARRAY_BUFFER , that are used from glDrawElements(..., pointer) , where pointer is an offset inside the index array, and vertex attribute arrays GL_ARRAY_BUFFER , that are used from glVertexAttribPointer (and all the deprecated glVertexPointer/glNormalPointer ...此外,您正在混合使用glDrawElements(..., pointer)索引数组GL_ELEMENT_ARRAY_BUFFER ,其中pointer是索引数组内的偏移量,以及从glVertexAttribPointer使用的顶点属性数组GL_ARRAY_BUFFER (以及所有已弃用的glVertexPointer/glNormalPointer ...

Each index that is in the index buffer will be used as an index into each of the attributes, but you can only specify a single index for each vertex.索引缓冲区中的每个索引都将用作每个属性的索引,但您只能为每个顶点指定一个索引。 So, setting GL_ELEMENT_ARRAY_BUFFER and then calling glVertexAttribPointer , does not do at all what you think it does.所以,设置GL_ELEMENT_ARRAY_BUFFER然后调用glVertexAttribPointer ,根本不会做你认为的那样。 It either uses the last array you set to GL_ARRAY_BUFFER for defining vertex attributes, or if you did not keep one bound, is interpreting your offset as a pointer (and will likely crash).它要么使用您设置为GL_ARRAY_BUFFER的最后一个数组来定义顶点属性,或者如果您没有保持一个界限,则将您的偏移量解释为一个指针(并且可能会崩溃)。

What you were trying to do, setting an index array for each vertex attribute, is not supported by GL. GL 不支持您尝试执行的操作,即为每个顶点属性设置索引数组。 Let me restate this: you only have 1 index array per draw .让我重申一下:每次 draw 只有 1 个索引数组

Some additional tidbits for the history enclined:关于历史的一些额外花絮包括:

glVertex is a bit of a misnomer. glVertex 有点用词不当。 It specifies only the Vertex position .它仅指定顶点位置 But, and this is what it gets its name from, it also provokes a vertex to be passed to the GL.但是,这就是它的名字的由来,它还引发了一个要传递给 GL 的顶点。 For the API to be completely clean, you could have imagined having to do 2 calls:为了使 API 完全干净,您可以想象必须执行 2 次调用:

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

However, when GL was first specified, Position was always required, so fusing those 2 to provoke a vertex made sense (if only to reduce the API call count).然而,当第一次指定 GL 时,Position 总是需要的,所以将这 2 个融合来激发一个顶点是有意义的(如果只是为了减少 API 调用次数)。

Fast forward to vertex_program_arb : Trying to get away from the fixed-function model while still remaining compatible meant that the special nature of glVertex had to be carried forward.快进到vertex_program_arb :试图摆脱固定功能模型同时仍然保持兼容意味着必须继承 glVertex 的特殊性质。 This was achieved by making the vertex attribute 0 provoking, and a synonym to glVertex.这是通过使vertex attribute 0挑衅性和 glVertex 的同义词来实现的。

Fast forward to GL3.2: the Begin/End model is gone, and all this specification of what provokes a vertex can finally go away, along with the management of the current state .快进到 GL3.2:开始/结束模型消失了,所有这些激发顶点的规范终于可以消失了,以及current state的管理。 So can all the semantic APIs (the glVertex*, glNormal*...), since all inputs are just vertex attributes now.所有语义 API(glVertex*、glNormal*...)也是如此,因为现在所有输入都只是顶点属性。

You need more than 8 vertices.您需要超过 8 个顶点。 Verts may share positions but unless everything else in the vertex is unique it is not a unique vertex.顶点可以共享位置,但除非顶点中的其他所有内容都是唯一的,否则它不是唯一的顶点。 Normals is another classic reason for needing more than 8 verts in a cube definition.法线是在立方体定义中需要超过 8 个顶点的另一个经典原因。

Interesting explanations, but they seem to obscure the fact that the original question contains its own answer: "Do I have to use different calls to glDrawElements for each face, with color and normal loaded into uniform variables?"有趣的解释,但它们似乎掩盖了原始问题包含自己的答案这一事实:“我是否必须对每个面使用不同的 glDrawElements 调用,并将颜色和法线加载到统一变量中?” - If having to feed the same vertex position data to the graphics processor three times when once ought to suffice offends one's aesthetic sense (and it ought to) then it's yes to that. - 如果不得不在一次应该足够的情况下将相同的顶点位置数据提供给图形处理器三次会冒犯一个人的美感(并且应该这样做),那么这是可以的。

The original questioner doesn't want to know that OpenGL can't do what he's trying to do, and that he needs to maintain twenty-four vertices for a cube which both standard math and common sense tell us should only need eight.最初的提问者不想知道 OpenGL 不能做他想做的事,他需要为一个立方体维护 24 个顶点,而标准数学和常识告诉我们应该只需要 8 个。 He already knows that he CAN do what he wants to, and he even knows how.他已经知道他可以做他想做的事,他甚至知道该怎么做。 He just wants confirmation that his proposed approach does actually make sense, and that there isn't some better way to do it which he has overlooked.他只是想确认他提出的方法确实有意义,并且没有更好的方法来做到这一点,而他却忽略了这一点。

Making calls for each face does add an overhead of its own, but that's hardly important when drawing just one cube.对每个面进行调用确实会增加其自身的开销,但这在仅绘制一个立方体时并不重要。 When drawing many, all the same-attribute faces can be batched together, eg all the South-facing then all the West, or all the red then all the green, or whatever.当绘制很多时,所有相同属性的面可以一起批处理,例如所有朝南然后所有西方,或所有红色然后所有绿色,或其他。

In OpenGL 3.x you have access to type interpolation qualifiers .在 OpenGL 3.x 中,您可以访问类型插值限定符 Using the flat qualifier, you would force the use of the variable passed by the provoking vertex only.使用flat限定符,您将强制使用仅由激发顶点传递的变量。 In some cases this should be enough to do what you want, but has the downside that you need to pay very careful attention to the ordering in which you draw the vertexes.在某些情况下,这应该足以完成您想要的操作,但缺点是您需要非常注意绘制顶点的顺序。

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

相关问题 GLSL OpenGL 3.x如何指定通用顶点属性索引和语义之间的映射? - GLSL OpenGL 3.x how to specify the mapping between generic vertex attribute indices and semantics? OpenGL 3.x:使用顶点缓冲区对象和glDrawElements(...)时访问冲突 - OpenGL 3.x: Access violation when using vertex buffer object and glDrawElements(…) 计算简单三角形的每面法线 - Calculating per-face normal for a simple triangle 如何不在OpenGL中使用着色器覆盖顶点颜色? - How not to overwrite vertex colors using shaders in OpenGL? 在OpenGL中使用顶点颜色和纹理? - Using vertex colors and textures in OpenGL? 我如何从wavefront .obj文件获取索引的顶点位置和索引的顶点法线到OpenGL顶点着色器中? - How do I get indexed vertex positions AND indexed vertex normals from wavefront .obj file into an OpenGL vertex shader? OpenGL:每个原语的顶点属性数组? - OpenGL: Vertex attribute arrays per primitive? 我什么时候应该使用OpenGL顶点的索引数组? - When should I use indexed arrays of OpenGL vertices? 我可以在调用glDrawArrays后删除OpenGL顶点数组吗? - Can I delete OpenGL vertex arrays after calling glDrawArrays? 使用顶点数组时OpenGL纹理坐标偏斜 - OpenGL texture coordinates being skewed when using vertex arrays
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM