【问题标题】:OpenGL buffer woesOpenGL缓冲区问题
【发布时间】:2019-12-12 23:44:01
【问题描述】:

在过渡到 linux 后,我最近又回到了 OpenGL。出于某种原因,glGenBuffersglBindBuffer 等内容在正常的 GL 标头中不存在,并导致我的程序在使用 GLEW 时崩溃。为了解决这个问题,我一直在使用 GLES2。

现在的问题是:

#include <SFML/Graphics.hpp>
#include <GLES2/gl2.h>
#include <GL/gl.h>

int main() {
  sf::RenderWindow window(sf::VideoMode(640, 480), "OpenGL Tests");

  glOrtho(0, 640, 0, 480, -1, 1);
  glEnable(GL_TEXTURE_2D);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glClearColor(0, 0, 0, 0);

  //x, y, r, g, b
  GLfloat triangleVertices[15] = {
    10, 10, 1, 0, 0,
    110, 10, 0, 1, 0,
    60, 96.6f, 0, 0, 1
  };
  GLuint triangleBuf;

  glGenBuffers(1, &triangleBuf);
  glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
  glBufferData(GL_VERTEX_ARRAY, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
  glBindBuffer(GL_VERTEX_ARRAY, 0);

  while(window.isOpen()) {
    sf::Event event;

    while(window.pollEvent(event)) {
      if(event.type == sf::Event::Closed) window.close();
    }

    glClear(GL_COLOR_BUFFER_BIT);

    glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 3, 0);
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(3, GL_FLOAT, 2, (GLfloat*) 2);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    window.display();
    sf::sleep(sf::milliseconds(50));
  }

  glDeleteBuffers(1, &triangleBuf);
}

这就是我记忆中使用缓冲区的方式,但老实说,我不相信自己的记忆。似乎有充分的理由,因为它在窗口打开后立即崩溃。

我尝试将glDrawArrays 的最后一个参数更改为 1 而不是 3。我还尝试绑定缓冲区两次,首先是 GL_VERTEX_ARRAY,然后是 glVertexPointer,其次是 GL_COLOR_ARRAY,然后是通过glColorPointer。没有骰子。

【问题讨论】:

  • 我认为您只是在这里混淆了一些常量。 glBindBuffer 不能与 GL_VERTEX_ARRAY 一起使用。见here。你的意思是GL_ARRAY_BUFFER

标签: c++ opengl-es buffer


【解决方案1】:

glVertexPointerglColorPointer 的第三个参数是连续(stride)之间的字节偏移量。如果绑定了命名缓冲区对象,则第 4 个参数也被视为字节偏移量。
stride 参数必须是 5 * sizeof(GLfloat),因为每个属性元组由 5 个 (GLfloat) 组件(X、Y、R、G、B)组成。顶点坐标的偏移量为 0,因为它们位于开头。颜色的偏移量是2 * sizeof(GLfloat),因为颜色位于顶点坐标的两个分量之后。

还有更多GL_VERTEX_ARRAY 不是有效的缓冲区目标。顶点属性的缓冲区目标是GL_ARRAY_BUFFERGL_VERTEX_ARRAY 的错误使用会导致 INVALID_ENUM 错误。错误信息可以通过glGetError获取。

进行以下更改:

glGenBuffers(1, &triangleBuf);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 5*sizeof(GLfloat), 0);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 5*sizeof(GLfloat), (GLfloat*)(2*sizeof(GLfloat)));

由于您没有绑定纹理,而且您甚至有指定的纹理坐标,所以不要启用 2 维纹理:

glEnable(GL_TEXTURE_2D);

【讨论】:

  • 谢谢!在 glVertexPointer 的 Khronos 页面上看到“如果步幅为 0,则顶点被认为是紧密排列的”,这让我认为它指的是一个顶点的结尾和另一个顶点的开头之间的空间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
相关资源
最近更新 更多