【问题标题】:why does binding a GL_ELEMENT_ARRAY_BUFFER to 0 produce a memmove error?为什么将 GL_ELEMENT_ARRAY_BUFFER 绑定到 0 会产生 memmove 错误?
【发布时间】:2012-05-11 04:31:32
【问题描述】:

我有一个错误,我花了很长时间才修复。 我不断收到 EXC_BAD_ACCESS 和对 memmove 错误的引用,没有任何进一步的描述,直到我评论了以下行:

[自加载着色器];

glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);

// Vertex Buffer
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

glEnableVertexAttribArray(ATTRIB_TEXTURE);
glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));

// Index Buffer
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER,0);  

////////// COMMENTED THIS ONE //////////////
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);//
////////////////////////////////////////////

glBindVertexArrayOES(0);

我认为将缓冲区绑定到 0 意味着解除绑定,所以我真的无法理解这会如何导致我的应用崩溃。

感谢您的信息!我只是不关心这个问题......

我的结构:

const Vertex Vertices[4] = {
    {{0.75, -1, 0}, {1, 0, 0, 1},     {0.125, 0.833496}},
    {{0.75, 1, 0}, {0, 1, 0, 1},      {0.125, 1}},
    {{-0.75, 1, 0}, {0, 0, 1, 1},     {0,     1}},
    {{-0.75, -1, 0}, {0, 0, 0, 1},    {0,     0.833496}},
};

const GLushort Indices[6] =
{
    0, 1, 2,
    2, 3, 0
};

【问题讨论】:

  • 最有可能的问题出在代码的其他地方。评论这个呼吁只会使问题以不同的方式表现出来。但是查看您发布的代码 - 您确定 Vertices 结构至少有 9 个浮动成员吗?因为我看到你只使用了其中的 5 个,但给 ATTRIB_TEXURE 提供了偏移量 7(其数据为 +2)。
  • 是的,我也认为它在其他地方,但仅这一行就解决了问题,我真的不明白为什么,我已经用我的结构发布了更新。谢谢
  • 我知道这是一个旧的 Q,但正如 Christian Rau 的示例所解释的,对 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...) 的调用直接影响当前绑定的 VAO。 即使 glBindBuffer(GL_ARRAY_BUFFER, ...) 也是如此。 不是。这个 WebGL 演示确实帮助消除了我对 OpenGL 状态绑定的大量困惑:webgl2fundamentals.org/webgl/lessons/resources/…

标签: ios opengl-es-2.0


【解决方案1】:

从你的代码来看,这个函数看起来好像在一些初始化例程中,你初始化你的属性数据,这些数据存储在绑定的 VAO 中,所以在绘图时你只需要绑定 VAO。

VAO 反过来封装了绘制 VBO 所需的所有状态,即属性的启用标志(由gl(En/Dis)ableVertexAttribArray 设置)、属性源和属性(由glVertexAttribPointer 设置)、和 当前绑定的索引缓冲区(使用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...) 设置)。请注意,它不存储当前绑定的顶点缓冲区,因为此信息存储在属性状态中。

所以发生的情况是,您创建并绑定索引缓冲区,设置其数据,然后解除绑定,此时 VAO 仍处于活动状态。因此,VAO 状态将存储0GL_ELEMENT_ARRAY_BUFFER 绑定。当你现在用

绘制一些东西时
glBindVertexArrayOES(_vao);
glDrawElements(...);

没有缓冲区绑定,glDrawElements 失败,因为 VAO 不适用于客户端阵列。您要么必须对索引数据使用 VBO,要么绘制非索引图元(使用 glDrawArrays)。

也不会

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBindVertexArrayOES(_vao);
glDrawElements(...);

工作,因为绑定的索引缓冲区在绑定时被 VAO 覆盖(其索引缓冲区为0)。如果您先绑定 VAO,然后绑定索引缓冲区,它会起作用,但这只会规避问题。

从概念上讲,绑定GL_ELEMENT_ARRAY_BUFFER 是VAO 状态的一部分,因此您不应在VAO 初始化例程中将其绑定到0(仅当您不需要任何索引数据时)。在使用 VAO 时,您也不允许将客户端数组用于索引或顶点数据。如果您不想绘制索引几何图形,只需使用glDrawArrays 而不是glDrawElements,但无论如何索引缓冲区已过时。

【讨论】:

  • 哦,我明白了,我不知道 VAO 也会将其存储为配置的一部分。谢谢!
  • 我什至没有想过它,我从那时起就开始编码 gl ......很好的解释。非常有帮助的问题/答案
猜你喜欢
  • 2013-09-04
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
相关资源
最近更新 更多