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 после вашей проекции.