glVertexAttribPointer GL_INVALID_OPERATION неверное использование указателя vao vbo

Я пытаюсь реализовать отложенное затенение с помощью OpenGL 4.4 на NVIDIA GTX 970 с установленными последними драйверами.
Мой код работал с рендерингом прямо на экран. Чтобы добавить второй проход, я создаю FBO, которому я рендерил свою сцену, и квад, к которому я рендерил окончательное изображение. Когда я пытаюсь ничего не рендерить на первом проходе и рисую четырехугольник после второго прохода, четырехугольник виден. Когда я пытаюсь визуализировать сетку (например, куб) во время первого прохода, квад исчезает. Также я получаю следующие сообщения об ошибках:
введите описание изображения здесь

Сетка была загружена с AssImp.
Я использую следующий код для создания VBO / VAO:

void Mesh::genGPUBuffers()
{
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vec3), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(vec2), &uvs[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(vec3), &normals[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glGenBuffers(1, &indexbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

И я рендерил свою сетку так:

void Mesh::render()
{
if (shader != nullptr)
{
shader->use();
shader->setModelMatrix(modelMatrix);
}

for (int i = 0x1; i <= 0xB; i++)
{
if (texture[i] != nullptr)
{
glBindMultiTextureEXT(GL_TEXTURE0 + i, GL_TEXTURE_2D, texture[i]->getTextureID());
}
}

// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,                  // attribute
3,                  // size
GL_FLOAT,           // type
GL_FALSE,           // normalized?
0,                  // stride
(void*)0            // array buffer offset
);

// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1,                                // attribute
2,                                // size
GL_FLOAT,                         // type
GL_FALSE,                         // normalized?
0,                                // stride
(void*)0                          // array buffer offset
);

// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2,                                // attribute
3,                                // size
GL_FLOAT,                         // type
GL_FALSE,                         // normalized?
0,                                // stride
(void*)0                          // array buffer offset
);

// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);

// Draw the triangles
glDrawElements(
GL_TRIANGLES,      // mode
(GLsizei)indexCount,    // count
GL_UNSIGNED_SHORT,   // type
(void*)0           // element array buffer offset
);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}

С помощью gDEBugger я узнал, что сообщения об ошибках приходят от glVertexAttribPointer. Но так как gDEBugger не поддерживает OpenGL 4, он сам выдает много ошибок и на самом деле не работает.

FBO генерируется так:

GLuint depthBuf;
Texture
posTex(this),
normTex(this),
colorTex(this)
;

// Create and bind the FBO
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// The depth buffer
glGenRenderbuffers(1, &depthBuf);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<GLsizei>(resolution.x), static_cast<GLsizei>(resolution.y));

// Create the textures for position, normal and color
posTex.createGBuf(GL_TEXTURE0, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
normTex.createGBuf(GL_TEXTURE1, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
colorTex.createGBuf(GL_TEXTURE2, GL_RGB8, static_cast<int>(resolution.x), static_cast<int>(resolution.y));

// Attach the textures to the framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuf);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, posTex.getTextureID(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normTex.getTextureID(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTex.getTextureID(), 0);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

Функция createGBuf () выглядит так:

void C0::Texture::createGBuf(GLenum texUnit, GLenum format, int width, int height)
{
this->width = width;
this->height = height;
glActiveTexture(texUnit);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}

1

Решение

Ошибка с вашим кодом, вероятно, потому что вы никогда не генерировали VertexArrayObject,
вызовите glGenVertexArray (1, ваш указатель vao); если у вас его нет, современный opengl пометит это как ошибку, что, вероятно, и происходит с вами. Создайте массив вершин, затем свяжите его с glBindVertexArray (ваш vao);

Во-вторых, вы не должны буферизовать свои данные каждый цикл рендеринга. Это невероятно неэффективно. Вы должны создать несколько VAO, привязать к ним данные вершин, а затем отсоединить vao, когда вы рендерите соответствующий меш, просто перепривязайте VAO и glDrawElements.

Так что пример будет такой,

если у вас есть структура Vertex, как так

struct Vertex{
vec3 position;
vec2 uv;
vec3 normal;
};
struct Mesh{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;

GLuint VAO;

void initializeVAO();
void Render();
};

Затем вы инициализируете так.

Mesh::initializeVAO(){
GLuint vertexBuffer, indiceBuffer;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &vertexBuffer);
glGenBuffers(1, &indiceBuffer);

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)sizeof(vec3));

glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(:vec3) + sizeof(glm::vec2)));

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);

glBindVertexArray(0);
glDeleteBuffers(1, &vertexBuffer);
glDeleteBuffers(1, &indiceBuffer);
}

Затем сделать

Mesh::Render()
{
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), 0);
glBindVertexArray(0);
}

Если у вас есть вопросы, не стесняйтесь спросить.

3

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


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