在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用
Posted
技术标签:
【中文标题】在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用【英文标题】:Drawing with Vertex Buffer Objects in OpenGL ES 1.1 not working 【发布时间】:2012-01-05 23:32:39 【问题描述】:我的 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
。
【参考方案1】:
使用 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 Upvoting 总是受到赞赏。【参考方案2】:在这一行:
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(如果需要的话)。我会纠正这个。 当然这个尺寸错误也需要在他的更新程序中改变。 @ChristianRau 我不认为这是问题所在。就像你说的,z 总是等于 0(这是我想要的,我只绘制 2D 对象)。 @RossKimes 这是我的观点:如果您不需要除 0 以外的 z,二维坐标就可以了。但是这个答案的第一部分(缓冲区分配和更新代码中的大小错误)仍然适用,并且很可能是您的问题的根源。 我认为这不是问题所在。请注意,我使用的是 TextureTRIANGLE2D,而不是 TextureVertex2D。 TextureTriangle2D 由 3 个 TextureVertex2D 组成,因此其中 3 个已经存在。以上是关于在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在带有 Java 的 Android 的 OpenGL ES 2.0 中使用顶点缓冲区中的对象?
在OpenGL ES(Android)中使用带纹理的索引缓冲区有什么意义吗?