Получить мусор только из шейдерного хранилища?
Я связал shader storage buffer
к shader storage block
вот так
GLuint index = glGetProgramResourceIndex(myprogram, GL_SHADER_STORAGE_BLOCK, name);
glShaderStorageBlockBinding(myprogram, index, mybindingpoint);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mybuffer)
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, mybindingpoint, mybuffer, 0, 48);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 48, &mydata);
mydata
указывает на std::vector
содержащий 4 glm::vec3
объекты.
Потому что я связан 48 bytes
в качестве диапазона буфера я ожидаю lights[]
держать 48/(4*3) = 4 vec3s
,
layout(std430) buffer light {
vec3 lights[];
};
Элемент в индексе 1
в моем std::vector
содержит данные x=1.0, y=1.0, z=1.0
,
Но просматривая вывод, делая
gl_FragColor = vec4(lights[1], 1.0);
Я вижу желтый (x=1.0, y=1.0, z=0.0
) пикселей. Это не то, что я загрузил в буфер.
Может кто-нибудь сказать мне, что я делаю не так?
РЕДАКТИРОВАТЬ
Я просто изменяю блок хранения шейдера на
layout(std430) buffer light {
float lights[];
};
и вывод
gl_FragColor = vec4(lights[3],lights[4],lights[5],1.0);
и это работает (белые пиксели).
Если кто-то может объяснить это, это все равно будет здорово.
1 ответ
Это потому, что люди не принимают этот простой совет: никогда не используйте vec3
в UBO / SSBO.
Базовое выравнивание vec3
16 байтов. Всегда. Следовательно, при его массиве шаг массива (количество байтов от одного элемента к следующему) всегда равен 16. Точно так же, как vec4
,
Да, std430
макет отличается от std140
, Но это не так уж и отличается. В частности, он только предотвращает округление базового выравнивания и шага элементов массива (и выравнивания базовых структур) до такового у vec4
, Но так как базовое выравнивание vec3
всегда равно тому из vec4
, это ничего не меняет в них. Это влияет только на скаляры и vec2
"S.