когда я внедряю индексы в mesh / face, почему он возвращает ошибку OpenGl? - PullRequest
0 голосов
/ 03 ноября 2019

Итак, у меня есть программа, которая генерирует чан-сетки на основе данных вершин. Он уже работает без индексов, но при попытке включить их в мою программу возвращает ошибку OpenGL 1285.

У меня есть вызовы arraybuffer и vao для разных функций, но они выглядят так:


void Chunk::_loadArrayBuffers()
{
    glGenBuffers(1, &_trianglesID);
    glGenBuffers(1, &_uvsID);
    glGenBuffers(1, &_normalsID);
    glGenBuffers(1, &_IndiceID);

    glBindBuffer(GL_ARRAY_BUFFER, _trianglesID);
    glBufferData(GL_ARRAY_BUFFER,
        _triangles.size() * 3 * sizeof(GLfloat),
        _triangles.data(),
        GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
    glBufferData(GL_ARRAY_BUFFER,
        _uvs.size() * 2 * sizeof(GLfloat),
        _uvs.data(),
        GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
    glBufferData(GL_ARRAY_BUFFER,
        _normals.size() * 3 * sizeof(GLfloat),
        _normals.data(),
        GL_STATIC_DRAW);

    if (_indices.size() * 3 > 0)
    {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
            _indices.size() * 3 * sizeof(GLfloat),
            _indices.data(),
            GL_STATIC_DRAW);
    }


}


void Chunk::_makeVAO()
{
    glGenVertexArrays(1, &_VAO);
    glBindVertexArray(_VAO);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _trianglesID);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);
}



Для каждой сетки я храню данные о вершинах каждого треугольника в нескольких glm :: vec3s, по сути, это вектор размера 3. Моя функция создания прямоугольника / лица выглядит следующим образом:


void Chunk::_addRectangle(glm::vec3 center, glm::vec3 height, glm::vec3 width, unsigned tex_num)
{
    if (glm::length(height) == 0 || glm::length(width) == 0)
        throw std::runtime_error("width or height should not be 0");

    glm::vec3 corner1 = center - (height / 2.0) - (width / 2.0);
    glm::vec3 corner2 = center - (height / 2.0) + (width / 2.0);
    glm::vec3 corner3 = center + (height / 2.0) + (width / 2.0);
    glm::vec3 corner4 = center + (height / 2.0) - (width / 2.0);

    glm::vec3 normal = glm::cross(height, width);

    glm::vec2 uv1;
    glm::vec2 uv2;
    glm::vec2 uv3;
    glm::vec2 uv4;

    if (fabs(normal[1]) == 1.0)
    {
        uv1 = glm::vec2(1.0 / _tex_atlas_width, 1);
        uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
        uv3 = glm::vec2(0, 0);
        uv4 = glm::vec2(0, 1);
    }
    else
    {
        uv1 = glm::vec2(1.0 / _tex_atlas_width, height[1]);
        uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
        uv3 = glm::vec2(0, 0);
        uv4 = glm::vec2(0, height[1]);
    }

    float add = (1.0 / double(_tex_atlas_width)) * tex_num;
    uv1.x += add;
    uv2.x += add;
    uv3.x += add;
    uv4.x += add;

    // triangle 1
    _triangles.push_back(corner3); 
    _triangles.push_back(corner2); 
    _triangles.push_back(corner1); 

    _normals.push_back(normal);
    _normals.push_back(normal);
    _normals.push_back(normal);

    _uvs.push_back(uv1);
    _uvs.push_back(uv2);
    _uvs.push_back(uv3);

    _indices.push_back(glm::vec3(nrOfIndices + 0, nrOfIndices + 1, nrOfIndices + 2));

    // triangle 2 
    //_triangles.push_back(corner1); 
    _triangles.push_back(corner4); 
    //_triangles.push_back(corner3); 

    _normals.push_back(normal);
    _normals.push_back(normal);
    _normals.push_back(normal);

    _uvs.push_back(uv3);
    _uvs.push_back(uv4);
    _uvs.push_back(uv1);

    _indices.push_back(glm::vec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));

    nrOfIndices += 4;

}


все работало отлично, пока я не попытался добавить индексы. Что с этим не так? Я дважды проверил порядок индексов, и они кажутся правильными, поэтому я предполагаю, что это ошибка в том, как я загружаю индексы, но я просто не могу понять это с тем, что я мог найти в learnopengl и другихдокументация opengl. Спасибо!

1 Ответ

1 голос
/ 03 ноября 2019

GL_ELEMENT_ARRAY_BUFFER указано в объекте Vertex Array . См. Индексные буферы .

Инструкция

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID); 

связывает _IndiceID с текущим объектом Vertex Array.

Вам необходимо привязать объект Vertex Array,перед указанием буфера массива элементов:

glGenVertexArrays(1, &_VAO);
glBindVertexArray(_VAO);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
    _indices.size() * 3 * sizeof(GLuint),
    _indices.data(),
    GL_STATIC_DRAW);

Обратите внимание, что в векторе состояния VAO указывается также GL_ARRAY_BUFFER, но это происходит при вызове glVertexAttribPointer.
Когда glVertexAttribPointer вызывается, тогда буфер, который в настоящее время привязан к цели GL_ARRAY_BUFFER, связан с атрибутом вершины с указанным индексом.

Различие в поведении GL_ELEMENT_ARRAY_BUFFER и GL_ARRAY_BUFFER вызвано тем, что VAO может ссылаться только на 1 индексный (элементный) буфер, но может ссылаться на несколько буферов массива. Каждый атрибут (индекс) может быть связан с другим буфером.


Более того, тип данных индексов должен быть целым. Возможные типы данных (unsigned) char, short соответственно int, которые соответствуют константам перечислителя OpenGL GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT или GL_UNSIGNED_INT. См. glDrawElements

Измените индексный вектор и используйте glm::ivec3 вместо glm::vec3

std::vector<glm::ivec3> _indices;
_indices.push_back(glm::ivec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));
glDrawElements(GL_TRIANGLES, _indices.size()*3, GL_UNSIGNED_INT, nullptr);
...