OpenGL ES 1.1中使用顶点缓冲对象进行绘图无法工作

3
我已经让我的OpenGL代码正常运行,但我想要提高一下它的性能(希望在旧设备上提高帧速率)。我正在尝试使用一个顶点缓冲对象来实现这个目标。
我的所有代码都只是绘制了一系列360个GL_TRIANGLES,并将纹理应用于它们。我将坐标和纹理坐标编织到一个数据结构中。
typedef struct {
    GLfloat vertex[2];
    GLfloat texture[2];
    GLfloat padding[4];
} TextureVertex2D;

typedef struct {
    TextureVertex2D textureVertex[3];
} TextureTriangle2D;

这是我的初始化相关部分:
textureTriangles = (TextureTriangle2D*)malloc(360 * sizeof(TextureTriangle2D));

glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);

// This section is the only new code introduced for the VBOs.
glGenBuffers(1, &buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureTriangle2D)*360, textureTriangles[0].textureVertex[0].vertex, GL_DYNAMIC_DRAW);
// end new code    

glVertexPointer(2, GL_FLOAT, sizeof(TextureVertex2D), textureTriangles[0].textureVertex[0].vertex);
glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex2D), textureTriangles[0].textureVertex[0].texture);

/*
textureTriangles is filled and the texture image is loaded in
*/

对于保存到实际VBO的操作,我尝试了两种方法(这两种方法都得到了相同的结果)

// Option 1
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
memcpy(vbo_buffer, textureTriangles[0].textureVertex[0].vertex, 360 * sizeof(TextureTriangle2D));
glUnmapBufferOES(GL_ARRAY_BUFFER); 

// Option 2
glBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureVertex2D), 360 * sizeof(TextureTriangle2D), textureTriangles[0].textureVertex[0].vertex);

然后我绑定缓冲区。
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);

最后进行绘制。
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glDrawArrays(GL_TRIANGLES, 0, 3*360);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

如果没有使用VBO,绘图可以正常工作。但是当我添加以上的VBO代码后,绘图位置不再正确(偏移几个像素),并且整个应用程序会锁死。有什么想法吗?


在你的 glBufferSubData 中,第二个参数应该是 0 而不是 sizeof(TextureVertex2D)。但是,当更新整个缓冲区时,你应该使用 glBufferData - Christian Rau
2个回答

2
使用VBO时,gl...Pointer的最后一个参数不是指向包含顶点数据的某个数组的指针,而是当前绑定的GL_ARRAY_BUFFER中的字节偏移量。因此,您不需要指定您已经复制到缓冲区中的CPU顶点数据的地址,而是指定属性存储在该缓冲区数据的偏移量:
glVertexPointer(2, GL_FLOAT, sizeof(TextureVertex2D), 
    offsetof(TextureVertex2D,vertex));
glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex2D), 
    offsetof(TextureVertex2D,texture));

@RossKimes 点赞总是受欢迎的。 - Christian Rau

0
在这一行中:
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureTriangle2D)*360, textureTriangles[0].textureVertex[0].vertex, GL_DYNAMIC_DRAW);

我认为你应该指定sizeof(TextureTriangle2D)*360*3,因为每个三角形(使用GL_TRIANGLES在绘制数组请求中)需要3个顶点坐标。

我对仅使用2个坐标传递3D坐标的信息不是很清楚(我猜Z轴固定为零?),但声明本身应该由你方面进行审查。

我本来期望:

typedef struct {
    GLfloat vertex[3];
    GLfloat texture[2];
    GLfloat padding[3];
} TextureVertex2D;

但这在很大程度上取决于您的引擎。


只使用2个坐标就可以了,z坐标将会是0(就像w没有被使用时为1一样)。如果您使用3个坐标,那么填充应该只有3而不是4(如果需要的话)。我会进行更正。 - Christian Rau
当然,在更新程序中也需要更改这个大小错误。 - Christian Rau
@ChristianRau 我不认为这是问题所在。就像你说的那样,z始终等于0(这正是我想要的,我只是绘制2D对象)。 - Ross Kimes
@RossKimes 这就是我的观点:如果你不需要除了0以外的z轴,那么2D坐标就足够了。但是,这个答案的第一部分(缓冲区分配和更新代码中的大小错误)仍然适用,并且很可能是你问题的根源。 - Christian Rau
我不认为那一行是问题所在。请注意,我使用的是TextureTRIANGLE2D而不是TextureVertex2D。TextureTriangle2D由3个TextureVertex2D组成,所以这个3已经在里面了。 - Ross Kimes
@RossKimes 啊,确实,完全忽略了那个。 - Christian Rau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接