SegFault после вызова glDrawArrays - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь написать дозатор спрайтов.Первоначально я загружал следующие данные в openGL, чтобы посмотреть, смогу ли я получить что-либо на экран:

static GLfloat const vertexData[] = {
        //Position                  //Color                 //UV Coords
        0.5f, 0.5f,             1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 1.0f,
        -0.5f, 0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 1.0f,
        0.5f, -0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 0.0f,

        -0.5f, -0.5f,           1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 0.0f,
        -0.5f, 0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 1.0f,
        0.5f, -0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 0.0f
};

Это мои вершинные и фрагментные шейдеры:

const char* vert = "#version 330 core\n"
                   "layout (location = 0) in vec2 vPos;\n"
                   "layout (location = 1) in vec4 vColor;\n"
                   "layout (location = 2) in vec2 vTexPos;\n"
                   "\n"
                   "out vec4 fColor;\n"
                   "out vec2 fTexPos;\n"
                   "\n"
                   "void main() {\n"
                   "    gl_Position = vec4(vPos.xy, 0.0, 1.0);\n"
                   "    fColor = vColor;\n"
                   "    fTexPos = vec2(vTexPos.s, 1.0 - vTexPos.t);\n"
                   "}";




const char* frag = "#version 330 core\n"
                   "in vec4 fColor;\n"
                   "in vec2 fTexPos;\n"
                   "out vec4 finalColor;\n"
                   "\n"
                   "uniform sampler2D textureUniform;\n"
                   "\n"
                   "void main() {\n"
                   "  vec4 textureColor = texture(textureUniform, fTexPos);"
                   "  finalColor = fColor * textureColor;\n"
                   "}";

Iнастроить VAO и VBO следующим образом:

auto vaoID_ = 0;
auto vboID_ = 0;
glGenVertexArrays(1, &vaoID_);
glGenBuffers(1, &vboID_);

glBindVertexArray(vaoID_);
glBindBuffer(GL_ARRAY_BUFFER, vboID_);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV

И, наконец, в каждом цикле я бы терял буфер и затем помещал данные в.

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexData), vertexData);
glDrawArrays(GL_TRIANGLES, 0, 6);

Это работало нормально!Итак, я попытался начать писать основной пакет спрайтов.Я сгруппировал свои данные вершин в структуру POD:

   struct VertexData {
        struct {
            GLfloat screenx;
            GLfloat screeny;
        } position;

        struct {
            GLfloat r;
            GLfloat g;
            GLfloat b;
            GLfloat a;
        } color;

        struct {
            GLfloat texu;
            GLfloat texv;
        } uv;
    }

И использовал вектор для пакетирования всего вместе: std::vector<VertexData> spritebatch_

Я изменил вызовы на glVertexAttribPointer, чтобы соответствовать этой структуре (хотя я думаю, что это изменение было ненужным?)

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV

Чтобы проверить это, в каждом цикле я бы передавал те же данные, что и в статическом массиве GLfloat:

spritebatch_.push_back({0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,   1.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
spritebatch_.push_back({-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});

А затем попытайтесь разорвать буфер и передать данные в:

glBufferData(GL_VERTEX_ARRAY, spritebatch_.size() * sizeof(VertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_VERTEX_ARRAY, 0, spritebatch_.size() * sizeof(VertexData), spritebatch_.data());
glDrawArrays(GL_TRIANGLES, 0, spritebatch_.size());

Наконец, я бы сбросил spritebatch_: spritebatch_.clear();

Однако, это segfaults.Я делаю что-то неправильно, когда я иду, чтобы осиротить буфер и передать данные в?Форматы данных по-прежнему совпадают (все члены VertexData POD по-прежнему GLfloat с), размер spritebatch_ по-прежнему равен 6 (6 вершин, образующих квадрат), и расположение этих данных остается неизменным в каждомвершина.

1 Ответ

0 голосов
/ 04 января 2019

5-й параметр glVertexAttribPointer - это "шаг", смещение байта между последовательными общими атрибутами вершин.

Таким образом, изменение с

 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV

на

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV

важно, потому что sizeof(VertexData) не является8, но это 8*sizeof(GL_FLOAT).


Первый параметр glBufferData соответственно glBufferSubData должен быть константой перечислителя для цели, который является одним из GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, ....
GL_VERTEX_ARRAY идентифицирует массив вершин для фиксированной функции на стороне клиента - см. glEnableClientState.

Изменение:

glBufferData(GL_VERTEX_ARRAY, ...);
glBufferData(GL_ARRAY_BUFFER, ...);

glBufferSubData(GL_VERTEX_ARRAY, ...);
glBufferSubData(GL_ARRAY_BUFFER, ...);

Обратите внимание: если вы проверите ошибки OpenGL (glGetError или Отладочный вывод ), вы получите ошибку GL_INVALID_ENUM.
Хранилище данных длябуфер массива не создается, это вызывает ошибку сегмента.

...