У меня проблема при использовании нескольких однородных буферов.
Вот мой код GLSL:
layout(std140) uniform MaterialInfo {
vec3 Ka;
vec3 Ks;
vec3 Kd;
};layout(std140) uniform LightInfo {
vec3 La;
vec3 Ls;
vec3 Ld;
};
И вот как я создаю и заполняю свои буферы:
blockIndex = glGetUniformBlockIndex(program, "MaterialInfo");
if (blockIndex == -1) {
fprintf(stderr, "Could not bind uniform block\n");
}
glGenBuffers(1, &materialUbo);
glBindBuffer(GL_UNIFORM_BUFFER, materialUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialBlock), &mesh->material, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, materialUbo);blockIndex = glGetUniformBlockIndex(program, "LightInfo");
if (blockIndex == -1) {
fprintf(stderr, "Could not bind uniform block\n");
}
glGenBuffers(1, &lightUbo);
glBindBuffer(GL_UNIFORM_BUFFER, lightUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), &light->lightBlock, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, lightUbo);
Когда структуры определены следующим образом:
struct LightBlock {
glm::vec4 La;
glm::vec4 Ld;
glm::vec4 Ls;
};
struct MaterialBlock {
glm::vec4 Ka;
glm::vec4 Ks;
glm::vec4 Kd;
};
Этот код работает нормально, если я использую только один унифицированный буфер. Это МатериалИнфо. Если я включаю второй буфер для lightInfo, я получаю сбой, когда в конце рендеринга я получаю glDrawElements ().
Есть ли проблема с использованием нескольких одинаковых буферов, как это? Могу ли я сделать это в 1 UBO?
glGetUniformBlockIndex
не работает таким образом. Он извлекает число, которое идентифицирует этот конкретный унифицированный блок. это не унифицированный индекс привязки буфера для передачи glBindBufferRange/Base
,
Связывание UBO во многом похоже на связывание текстур. Вы сообщаете программе, в каком слоте искать. С текстурами вы получаете единое местоположение текстуры, а затем устанавливаете значение этой униформы в индекс единицы текстуры. С помощью UBO вы получаете индекс блока для блока, устанавливая значение привязки этого индекса блока равным точке привязки единого буфера, где он будет выглядеть.
Таким образом, вы должны взять индекс из glGetUniformBlockIndex
и использовать glUniformBlockBinding
назначить ему точку привязки буфера. Затем привяжите свой буфер к точке привязки, которую вы назначили для единого блока.
Просто чтобы расширить на ответ Николь. Большинство примеров связывают назначение и использование, и они жестко кодируют слот использования, так что поддерживается только один буфер, это действительно сбивает с толку, просто потерял для него день.
Настройка инициализации шейдера:
m_ubo_transform_block_index = glGetUniformBlockIndex(m_gl_program_object, "transform_uniforms");
if (m_ubo_transform_block_index != -1)
{
glUniformBlockBinding(m_gl_program_object, m_ubo_transform_block_index, UBO_TRANSFORM_INDEX);
}
UBO_TRANSFORM_INDEX — это слот, как и текстурный блок.
Использование во время розыгрыша:
if(m_ubo_transform_block_index != -1)
{
glBindBufferBase(GL_UNIFORM_BUFFER, UBO_TRANSFORM_INDEX, uniform_buffer->m_uniform_transform_buffer_object);
}