7

我目前正在用 OpenGL 编写一个 .obj 加载器。我将顶点数据存储在 VBO 中,然后使用 Vertex Attribs 绑定它。法线也一样。问题是,法线数据和顶点数据的存储顺序不同。

我想,我给 glDrawElements 渲染网格的索引被 OpenGL 用来获取顶点 VBO 中的顶点并获取法线 VBO 中的法线。

除了使用 glBegin/glVertex/glNormal/glEnd 来告诉 glDrawElements 使用顶点索引和法线索引之外,还有 opengl 方式吗?谢谢

4

3 回答 3

7

没有直接的方法可以做到这一点,尽管您可以通过索引到着色器内的缓冲区纹理(OpenGL 3.1 功能)来模拟它。

但是,通常不建议这样做。OBJ 格式允许一次法线被多个(原则上任意数量)顶点引用,因此通常要做的事情是构造一个“完整”顶点,包括每个顶点的坐标和法线和 texcoords(复制相应的数据)。

这可确保
a) 正确渲染平滑的阴影表面
b) 正确渲染硬边

(两者之间的区别只是几个顶点共享相同,相同的法线)

于 2011-06-28T17:03:33.123 回答
2

OpenGL 将顶点视为单个长向量

(position, normal, texcoord[0]…texcoord[n], attrib[0]…attrib[n])

并且这些长向量被索引。您的问题属于同一类别,例如如何使用具有多个法线的共享顶点。规范的答案是,这些顶点实际上是不共享的,因为从长远来看它们并不相同。

因此,您需要做的是遍历面的索引数组并构造“长”顶点,将它们添加到具有唯一性约束的(新)列表中;来自顶点→索引的(散列)映射服务于这项工作。像这样的东西

next_uniq_index = 0
for f in faces:
    for i in f.indices:
        vpos = vertices[i.vertex]
        norm = normals[i.normal]
        texc = texcoords[i.texcoord]
        vert = tuple(vpos, norm, texc)
        key
        if uniq_vertices.has_key(key):
             uniq_faces_indices.append(uniq_vertices[key].index)
        else:
             uniq_vertices[key] = {vertex = key, index = next_uniq_index}
             next_uniq_index = next_uniq_index + 1
于 2011-06-29T07:25:07.873 回答
2

您必须对位置/法线/纹理坐标等使用相同的索引。这意味着在加载 .obj 时,您必须插入唯一的顶点并将您的面指向它们。

于 2011-06-28T17:03:13.027 回答