glDrawElements выдает ошибку GL_INVALID_VALUE

Я пытаюсь нарисовать часть моего мозаичного изображения, но я получаю ошибку GL_INVALID_VALUE, когда я вызываю функцию glDrawElements. Нет проблем, когда я изменяю эту функцию с помощью glDrawArrays. Проблема в том, что параметр количества индексов не является отрицательным числом.

Есть код:

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
#define VERTEX_ATTR_PTR(loc, count, member, type) \
glEnableVertexAttribArray(loc); \
glVertexAttribPointer(loc, count, GL_FLOAT, GL_FALSE, sizeof(type),  BUFFER_OFFSET(offsetof(struct type, member)))
// ---------- TextRenderer
void TextRenderer::setText(const string& text) {
vector<Vertex2f> vertex_buffer;
vector<GLuint> index_buffer;

GLfloat cursor = 0.f;
FPoint2D cell_size = font->getCellSize();

for (char c : text) {
TILE_ITER iter = font->getCharacter(c);
{
// UV
for (GLuint i = 0; i < 4; ++i) {
TILE_ITER _v = iter + i;
vertex_buffer.push_back( {
{
_v->pos[0]  + cursor,
_v->pos[1],
_v->pos[2]
},
{ _v->uv[0], _v->uv[1] }
});
}
// Index
for (GLuint i = 0; i < 6; ++i)
index_buffer.push_back(
Tile::indices[i] + vertex_buffer.size() - 4);
}
cursor += cell_size.X;
}

vertices_count = vertex_buffer.size();
indices_count = index_buffer.size();

glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
0,
indices_count * sizeof(GLuint),
&index_buffer[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferSubData(GL_ARRAY_BUFFER,
0,
vertices_count * sizeof(Vertex2f),
&vertex_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
}
void TextRenderer::create() {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
{
indices = genGLBuffer( {
nullptr,
BUFFER_SIZE / 2 * sizeof(GLuint),
GL_ELEMENT_ARRAY_BUFFER
}, true, GL_DYNAMIC_DRAW);

vbo = genGLBuffer( {
nullptr,
BUFFER_SIZE * sizeof(Vertex2f),
GL_ARRAY_BUFFER
}, true, GL_DYNAMIC_DRAW);

VERTEX_ATTR_PTR(0, 3, pos, Vertex2f); // Vertex
VERTEX_ATTR_PTR(1, 2, uv, Vertex2f); // UV
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);

setText("DUPA");
}
void TextRenderer::draw(MatrixStack& matrix, GLint) {
static Shader shader(
getFileContents("shaders/text_frag.glsl"),
getFileContents("shaders/text_vert.glsl"),
"");

shader.begin();
shader.setUniform(GL_TEXTURE_2D, "texture", 0,
font->getHandle());
shader.setUniform("matrix.mvp", matrix.vp_matrix * matrix.model);
shader.setUniform("col", col);
{
glBindVertexArray(vao);
//glDrawArrays(GL_LINE_STRIP, 0, vertices_count);
glDrawElements(GL_LINES, indices_count, GL_UNSIGNED_INT,
nullptr);
glBindVertexArray(0);
showGLErrors();
}
shader.end();
}

2

Решение

Проблема заключается в следующей (сокращенной) последовательности вызовов в вашем setText() метод:

glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

...
}
glBindVertexArray(0);

Привязка GL_ELEMENT_ARRAY_BUFFER является частью государства ВАО. Таким образом, делая этот вызов, пока VAO связан:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

вы устанавливаете состояние VAO, чтобы иметь привязку буфера массива элемента 0, Поэтому, когда вы позже связываете ВАО в своем draw() метод, у вас не будет привязки для GL_ELEMENT_ARRAY_BUFFER,

Чтобы избежать этого, самое простое решение — просто удалить этот вызов. Если вы хотите явно отменить привязку, потому что беспокоитесь, что привязка может иметь нежелательные побочные эффекты для другого кода, вам нужно переместить его после отмены привязки VAO:

glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);

...
}
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3

Другие решения

Не видя весь код и не зная точную версию GL, я попытаюсь дать вам правильный ответ.

Во-первых, если вы используете ES2, то использование типа индекса как GL_UNSIGNED_INT не поддерживается по умолчанию, однако я не думаю, что это ваша проблема.

Ваша настоящая проблема заключается в том, что массивы элементов фактически не хранятся в вашем объекте VAO, а только в конфигурации данных вершин. Поэтому glDrawElements выдаст вам эту ошибку, так как будет думать, что массив элементов не связан, и вы передали NULL в качестве аргумента index для функции.

Чтобы решить эту проблему, привяжите соответствующий массив элементов перед вызовом glDrawElements

1

По вопросам рекламы [email protected]