我无法弄清楚如何使用索引VBO,恕我直言,缺乏相关信息(例如,索引的vbo页面缺少ATM的lwjgl站点)。
我在顶点缓冲区中使用的结构是{pos.x,pos.y pos.z},{tex.u,tex.v tex.W}和{norm.x,norm.y norm.z},我的索引缓冲区结构是{posIndex,texIndex,normIndex} 我从.obj文件中读取所有这些数据,如果缺少tex或norm,我将其设置为{-1,-1,-1}。
这是我将数据发送到GPU缓冲区的代码部分:
this.VBOSize = Vertices.size();
FloatBuffer vbo = BufferUtils.createFloatBuffer(this.VBOSize);
for (int i = 0; i < this.VBOSize; i++) {
vbo.put(Vertices.get(i));
}
vbo.flip();
glBindBuffer(GL_ARRAY_BUFFER, VBOHandle);
glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
this.IBOSize = Indices.size();
IntBuffer ibo = BufferUtils.createIntBuffer(this.IBOSize);
for (int i = 0; i < this.IBOSize; i++) {
ibo.put(Indices.get(i));
}
ibo.flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
以及我[错误地]渲染它的方式:
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, Object3D.getVBOHandle());
glVertexAttribPointer(0, 3, GL_FLOAT, true, 12, 0);//3 floats * 4 sizeof(float)
glVertexAttribPointer(1, 3, GL_FLOAT, true, 12, 13);
glVertexAttribPointer(2, 3, GL_FLOAT, true, 12, 25);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Object3D.getIBOHandle());
glDrawElements(GL_TRIANGLES, Object3D.getIBOSize(), GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
答案 0 :(得分:0)
这不是opengl的工作方式。在openGL中,顶点是属性的集,如position,normal,color,textcoord等等。索引渲染仅引用顶点。您不能为各种属性指定不同的索引,而只能为整个集合指定一个索引。如果您有两个顶点共享其位置的情况,但不是texcoords,就GL而言,它们完全 _different_顶点。你不能直接使用lightwave .obj文件中的数据,但必须预处理数据以生成顶点数组,OpenGL可以使用它。
有GL_AMD_interleaved_elements扩展名,它有点实现了您要使用的功能。它仍然使用32位索引,但允许一个将它们分成2个16位或4个8位索引,以便为不同的属性使用不同的索引,但是这个扩展远不是核心GL,没有广泛支持和仍然非常有限。
现在有了可编程管道,人们也可以在着色器中手动进行索引解除引用,基本上(误)使用顶点属性并通过纹理缓冲区对象访问真实属性数组,但这是非常先进的和性能影响不清楚。