交错的 VBO 导致 glDrawArrays() 错误

发布于 2024-11-02 09:49:23 字数 2921 浏览 4 评论 0原文

我最近将我的应用程序从使用 OpenGL ES 1.1 更改为 2.0,在此过程中我决定使用 VBO 进一步优化我的代码。我认为我已经掌握了与 ES 2.0 的主要区别,并且结果表明我在没有 VBO 的情况下正确地做事,但是我被一个只有当我尝试使用 VBO 时才会出现的问题所困扰。

我使用包含顶点位置、颜色和大小(加上一点填充来对齐数据)的自定义结构,然后在 VBO 中交错此顶点数据。该数据用于渲染点精灵。问题是我在 glDrawArrays() 调用上收到 EXC_BAD_ACCESS 。此错误的回溯如下:

#0  0x31fc7358 in gleRunVertexSubmitARM ()
#1  0x31fc87b2 in gleLLVMArrayFunc ()
#2  0x31fc872a in gleSetVertexArrayFunc ()
#3  0x31fbefcc in gleDrawArraysOrElements_ExecCore ()
#4  0x31fc4608 in glDrawArrays_IMM_Exec ()
#5  0x36ddaee2 in glDrawArrays ()
#6  0x0001cab8 in -[Renderer renderDrawingVertexBuffer:withSize:usingTexture:] (self=0x1783b0, _cmd=0x50fec, vboID=0, size=3584, drawTexture=5) at /Users/Stu/Documents/...
#7  0x000202f4 in -[EAGLView drawSmoothCurveFromPoints:endOfLine:] (self=0x195be0, _cmd=0x50d34, points=0x1956f0, endOfLine=1 '\001') at /Users/Stu/Documents/...
#8  0x0001e50c in -[EAGLView drawView:] (self=0x195be0, _cmd=0x50d8a, sender=0x0) at /Users/Stu/Documents/...
#9  0x0001e174 in -[EAGLView layoutSubviews] (self=0x195be0, _cmd=0x3297d4ac) at /Users/Stu/Documents/...
#10 0x326805fa in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#11 0x35efbf02 in -[NSObject(NSObject) performSelector:withObject:] ()
#12 0x333fbbb4 in -[CALayer layoutSublayers] ()
#13 0x333fb96c in CALayerLayoutIfNeeded ()

这是用于存储顶点数据的结构:

typedef struct {
    ISVertex2D vertex;     // Made up of 2 GLfloats.
    ISColor    color;      // Made up of 4 GLfloats.
    GLfloat    size;
    GLfloat    padding;
} ISPointSpriteData;

将一组数据存储在这些结构的数组中后,数据被发送到 VBO 并使用 glDrawArrays() 进行渲染:

[renderer prepareScene];
[renderer renderBackground];

glBindBuffer(GL_ARRAY_BUFFER, penVbo);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(ISPointSpriteData) * penVboSize, sizeof(ISPointSpriteData) * vertexCount, &vertexBuffer[0].vertex);

glBindTexture(GL_TEXTURE_2D, drawTexture);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_COLOR);
glEnableVertexAttribArray(ATTRIB_SIZE);
glDisableVertexAttribArray(ATTRIB_TEXTURE_COORD);
glUniform1i(uniforms[UNIFORM_IS_SPRITE], GL_TRUE);

glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, vertex));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, color));
glVertexAttribPointer(ATTRIB_SIZE, 1, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, size));

glDrawArrays(GL_POINTS, 0, vertexCount);     // <--- EXC_BAD_ACCESS

glDisableVertexAttribArray(ATTRIB_VERTEX);
glDisableVertexAttribArray(ATTRIB_COLOR);
glDisableVertexAttribArray(ATTRIB_SIZE);


[renderer presentScene];

此代码工作正常在我放入 VBO 之前,唯一的改变是 glVertexAttribPointer() 调用的最后一个参数显然指向数据而不是偏移量。我缺少什么?我不认为这段代码特别复杂,所以我只能认为我在某个地方犯了一个愚蠢的错误。

谢谢

I recently changed my app from using OpenGL ES 1.1 to 2.0, and in the process I decided to optimise my code further by using VBOs. I think I've got to grips with the main differences with ES 2.0, and have results to show that I'm doing things correctly without VBOs, however I've been stumped by a problem that only presents itself when I try to use VBOs.

I use a custom struct containing vertex position, color and size (plus a little padding to align data), and then interleave this vertex data in a VBO. This data is used to render point sprites. The problem is that I get an EXC_BAD_ACCESS on the glDrawArrays() call. The backtrace at this error is as follows:

#0  0x31fc7358 in gleRunVertexSubmitARM ()
#1  0x31fc87b2 in gleLLVMArrayFunc ()
#2  0x31fc872a in gleSetVertexArrayFunc ()
#3  0x31fbefcc in gleDrawArraysOrElements_ExecCore ()
#4  0x31fc4608 in glDrawArrays_IMM_Exec ()
#5  0x36ddaee2 in glDrawArrays ()
#6  0x0001cab8 in -[Renderer renderDrawingVertexBuffer:withSize:usingTexture:] (self=0x1783b0, _cmd=0x50fec, vboID=0, size=3584, drawTexture=5) at /Users/Stu/Documents/...
#7  0x000202f4 in -[EAGLView drawSmoothCurveFromPoints:endOfLine:] (self=0x195be0, _cmd=0x50d34, points=0x1956f0, endOfLine=1 '\001') at /Users/Stu/Documents/...
#8  0x0001e50c in -[EAGLView drawView:] (self=0x195be0, _cmd=0x50d8a, sender=0x0) at /Users/Stu/Documents/...
#9  0x0001e174 in -[EAGLView layoutSubviews] (self=0x195be0, _cmd=0x3297d4ac) at /Users/Stu/Documents/...
#10 0x326805fa in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#11 0x35efbf02 in -[NSObject(NSObject) performSelector:withObject:] ()
#12 0x333fbbb4 in -[CALayer layoutSublayers] ()
#13 0x333fb96c in CALayerLayoutIfNeeded ()

This is the struct for storing vertex data:

typedef struct {
    ISVertex2D vertex;     // Made up of 2 GLfloats.
    ISColor    color;      // Made up of 4 GLfloats.
    GLfloat    size;
    GLfloat    padding;
} ISPointSpriteData;

After a set of data is stored in an array of these structs, the data is sent to the VBO and rendered using glDrawArrays():

[renderer prepareScene];
[renderer renderBackground];

glBindBuffer(GL_ARRAY_BUFFER, penVbo);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(ISPointSpriteData) * penVboSize, sizeof(ISPointSpriteData) * vertexCount, &vertexBuffer[0].vertex);

glBindTexture(GL_TEXTURE_2D, drawTexture);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_COLOR);
glEnableVertexAttribArray(ATTRIB_SIZE);
glDisableVertexAttribArray(ATTRIB_TEXTURE_COORD);
glUniform1i(uniforms[UNIFORM_IS_SPRITE], GL_TRUE);

glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, vertex));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, color));
glVertexAttribPointer(ATTRIB_SIZE, 1, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, size));

glDrawArrays(GL_POINTS, 0, vertexCount);     // <--- EXC_BAD_ACCESS

glDisableVertexAttribArray(ATTRIB_VERTEX);
glDisableVertexAttribArray(ATTRIB_COLOR);
glDisableVertexAttribArray(ATTRIB_SIZE);


[renderer presentScene];

This code worked right before I put the VBO in, with the only alteration being that the last parameter of the glVertexAttribPointer() calls would obviously point to the data rather than an offset. What am I missing? I don't think this code is particularly complicated so I can only think that I've made a stupid mistake somewhere.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

随梦而飞# 2024-11-09 09:49:23

问题已解决:

我的代码存在一些问题,并非所有问题都可以从问题的列表中明显看出。我将概述主要问题:

  • 在未列出的代码中,我正在创建
    效用函数中的 VBO。在
    这个函数我错了
    传递 GLuint 句柄
    缓冲区(我试图通过它
    通过在函数中引用
    返回无效)。为了
    使这更具可读性我改变了
    简单地初始化它的函数
    自己的句柄并返回它。这
    停止了程序崩溃
    glDrawArrays() 行(大概是
    未初始化的值必须已经存在
    已分配给另一个缓冲区
    某处)。

一个新问题出现了 - 屏幕被绘制为黑色,并且绘制调用之间存在很大的延迟。这是由于...

  • 之后没有解绑VBO 造成的
    每次绘图调用。对于每一帧
    首先绘制背景纹理,
    接下来是 VBO 的内容。
    通过将 VBO 留给
    下一个背景渲染,我是
    显然导致OGL有点
    很合身!这不仅仅是原因
    黑屏,还有大
    绘制调用之间的延迟。

希望这对其处于类似情况的其他人有所帮助!

Problem solved:

There were a few things wrong with my code, not all of which would have been apparent from the listings in the question. I'll outline the major issues:

  • In code not listed, I was creating
    the VBOs in a utility function. In
    this function I was incorrectly
    passing the GLuint handle for the
    buffer (I was attempting to pass it
    by reference in a function that
    returns void). In the interests of
    making this more readable I changed
    the function to simply initialise its
    own handle and return it. This
    stopped the program crashing at the
    glDrawArrays() line (presumably the
    uninitialised value must already have
    been assigned to another buffer
    somewhere).

A new problem presented itself - the screen was being drawn to black and there were BIG delays between draw calls. This was caused by...

  • Not unbinding the VBOs after
    each draw call. For each frame a
    background texture is first drawn,
    followed by the contents of the VBOs.
    By leaving the VBOs bound for the
    next background render, I was
    obviously causing OGL to have a bit
    of a fit! This was not only the cause
    of the black screen, but also the big
    delays between draw calls.

Hope this is helpful to somebody else in a similar situation!

终止放荡 2024-11-09 09:49:23

您可能必须使用 glDrawElements 而不是 glDrawArrays。因为 glDrawArrays 不允许跳跃或跳过。它从一组连续的顶点读取。

“glDrawArrays() 通过直接在数组中行进而不跳过或跳跃来从启用的数组中读取顶点数据。因为 glDrawArrays() 不允许在顶点数组中跳跃,所以您仍然必须每个面重复共享顶点一次。”

http://www.songho.ca/opengl/gl_vertexarray.html

You might have to use glDrawElements instead of glDrawArrays. Because glDrawArrays does not allow hopping or skipping. It reads from a contiguous set of vertices.

"glDrawArrays() reads vertex data from the enabled arrays by marching straight through the array without skipping or hopping. Because glDrawArrays() does not allows hopping around the vertex arrays, you still have to repeat the shared vertices once per face."

http://www.songho.ca/opengl/gl_vertexarray.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文