OpenGL 4.5 - хранение шейдеров: запись в вершинный шейдер, чтение во фрагментный шейдер

И мои фрагментные и вершинные шейдеры содержат следующие два парня:

struct Light {
  mat4 view;
  mat4 proj;
  vec4 fragPos;
};

layout (std430, binding = 0) buffer Lights {
  Light lights[];
};

Моя проблема в том, что это последнее поле, fragPos, вычисляется вершинным шейдером следующим образом, но фрагментный шейдер не видит изменений, внесенных вершинным шейдером в fragPos (или любые изменения вообще):

aLight.fragPos = bias * aLight.proj * aLight.view * vec4(vs_frag_pos, 1.0);

... где aLight является lights[i] в петле. Как вы можете себе представить, я вычисляю положение вершины в системах координат каждого источника света, который будет использоваться в картографировании теней. Есть идеи, что здесь не так? Я делаю принципиально неправильную вещь?

Вот как я инициализирую свое хранилище:

struct LightData {
  glm::mat4 view;
  glm::mat4 proj;
  glm::vec4 fragPos;
};

glGenBuffers(1, &BBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, BBO);

glNamedBufferStorage(BBO, lights.size() * sizeof(LightData), NULL, GL_DYNAMIC_STORAGE_BIT);

// lights is a vector of a wrapper class for LightData.
for (unsigned int i = 0; i < lights.size(); i++) {
  glNamedBufferSubData(BBO, i * sizeof(LightData), sizeof(LightData), &(lights[i]->data));
}

Стоит отметить, что если я перееду fragPos в массив фиксированного размера out переменная в вершинном шейдере out fragPos[2], оставьте результаты тут же, а затем добавьте аналог шейдера фрагмента in fragPos[2] и использовать это для остальных моих вещей, тогда все в порядке. Поэтому я хочу узнать больше о том, почему мой фрагментный шейдер не видит числа, сжатые вершинным шейдером.

1 ответ

Я не буду очень точным, но я попытаюсь объяснить вам, почему ваш фрагментный шейдер не видит, что пишет ваш вершинный шейдер:

Когда ваш вершинный шейдер записывает некоторую информацию в ваш буфер, записываемое вами значение не обязательно записывается в видеопамять, но может храниться в виде кеша. Та же идея возникает, когда ваш фрагментный шейдер будет читать ваш буфер, он может считывать значение в кеше (это не то же самое, что вершинный шейдер).

Чтобы избежать этой проблемы, вы должны сделать две вещи: во-первых, вы должны объявить свой буфер как связный (внутри glsl): layout(std430) coherent buffer ...

Как только вы это сделаете, после ваших записей вы должны создать барьер (глобально он говорит: будьте осторожны, я записываю значение в буфер, значения, которые вы прочитаете, могут быть недействительными, пожалуйста, примите новые значения, которые я написал).

Как это сделать? Используя функцию memoryBarrierBuffer после твоих пишет. https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/memoryBarrierBuffer.xhtml

Кстати: не забудьте разделить на w после вашей проекции.

Другие вопросы по тегам