OpenGL Uniform Buffer Object (Array), пропускающий все остальные Vec2

0

Изображение 174551

проблема

Между этими белыми линиями не должно быть пробелов. Эти линии состоят из квадратов (в конечном итоге я не буду генерировать только один гигантский квадрат, это для отладки). По какой-то причине, когда я отправляю данные через свой Uniform Buffer Object (пример ниже), я получаю пробелы. Это почти так, как если бы он пропускал все другие значения y. На каждом месте на самом деле есть два квадрата, а не один (y) и один на (y + 1).

Фрагменты кода

Создание массива указателей данных

blockData = new glm::vec2[24*24];
for (int x = 0; x < 24; x++) {
    for (int y = 0; y < 24; y++) {
        int i = x * 24 + y;
        blockData[i] = glm::vec2(x, y);
    }
}

В классе рендеринга

glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::vec2) * blocksActive, blockData);
glBindBufferRange(GL_UNIFORM_BUFFER, uniBlockData, ubo, 0, sizeof(glm::vec2) * blocksActive);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

glBindVertexArray(vao);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0, blocksActive);
glBindVertexArray(0);

Vertex Shader (GLSL)

layout (std140) uniform blockData {
    vec2 blockDataPosition[5184];
};

тестирование

  • Когда я меняю blockData[i] = glm::vec2(x, y); to blockData[i] = glm::vec2(y, x); (переключение y и x), промежутки перемещаются к оси x.
  • Я попытался переключить x и y в цикле for, но это не влияет на него. Эта проблема каким-то образом связана с переменной y.
  • Что влияет на это, если я переключаю x и y вокруг в int я = x * 24 + y;
  • Установка vec2 в (x, x) приводит к правильно заданной диагонали.
  • Установка vec2 в (y, y) приводит к странно расположенной диагонали (ниже)
  • Прежде чем переключиться на UBO, я просто использовал форму в шейдере, и он работал нормально. Вот почему я считаю, что это имеет какое-то отношение к моей отправке данных через UBO. Изображение 174551
  • 0
    Можете ли вы включить соответствующую часть шейдера GLSL? Похоже, проблема выравнивания в вашем UBO.
  • 0
    Спасибо за предложение, я забыл его включить. Я понимаю, что с std140 vec3 занимает столько же места, сколько и vec4, но я использую vec2, поэтому я не уверен, что может происходить.
Теги:
opengl
debugging

1 ответ

2
Лучший ответ

Ну, так что происходит, скорее всего, проблема выравнивания. Используя std140, вы должны выровнять по 4 поплавкам. Однако, не видя всего вашего кода, я не буду полностью уверен в том, как вы буферизируете свои данные. Однако я могу предложить вам запросить смещения блока с помощью glGetActiveUniformsiv, а затем выровнять ваши объекты на основе этого. Таким образом, типичным примером может быть следующее:

    char* bufferNames[] = [generate the values with a for loop, this should be pretty easy with string and sprintf e.g "blockData.blockDataPosition[0]" to "block.Data.blockDataPosition[5184]"];

    GLuint uniformBlockIndex = glGetUniformBlockIndex(yourprogram, "block name");

    GLuint uniformIndices[number of names in bufferNames];

    glGetUniformIndices(yourprogram, the number of names in bufferNames, bufferNames, indices);

    GLint uniformOffsets[the number of names in bufferNames];

    glGetActiveUniformsiv(yourprogram, 1, &uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);

Смещения расскажут вам все, что вам нужно знать. Это число смещений в байтах для каждого имени. И вы можете использовать цикл for для заполнения каждого смещения или просто распечатать его, чтобы увидеть, как все выровнено. Это не должно выполняться в цикле, но один раз для инициализации и т.д. Скажите мне, есть ли у вас какие-либо вопросы или вам нужен более конкретный пример.

  • 0
    Отличается ли это от переменного выравнивания (то есть vec2 требует 2 числа с плавающей запятой, vec3 и vec4 требуют 4)?
  • 1
    @badcc Нет, он ничего не делает с самим выравниванием, которое обозначено std140, упакованным или совместно используемым. Тем не менее, это позволяет вам увидеть, как все выровнено в блоке, и вы можете заполнить свой буфер на основе этого или просто прочитать его, чтобы увидеть, является ли запрошенный вами макет тем, что вы получаете. Это один из способов использовать более быстрые спецификации компоновки, такие как упакованные, и при этом гарантировать правильное поведение разных поставщиков. В вашем случае это больше для отладки и для проверки правильности представления запрошенной унифицированной схемы.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню