Синтаксис унифицированных блоков OpenGL - PullRequest
2 голосов
/ 24 февраля 2020

Я задавал себе вопрос о UBO и способах доступа к ним в GLSL с помощью единообразных блоков.

Следуя официальной документации, если я хочу разработать массив источников света, я, вероятно, напишу:

layout(std140, binding = 0) uniform LightBlock
{
    vec4 position;
    vec4 direction;
    vec4 color;
    ...
} lights[8];

Теперь я вижу много примеров, где унифицированный блок записывается так:

struct LightStruct
{
    vec4 position;
    vec4 direction;
    vec4 color;
    ...
};

layout(std140, binding = 0) uniform LightBlock
{
    LightStruct lights[8];
};

В чем разница между этими двумя способами?

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

1 Ответ

4 голосов
/ 24 февраля 2020

Первый

layout(std140, binding = 0) uniform LightBlock
{
    vec4 position;
    vec4 direction;
    vec4 color;
    ...
} lights[8];

сам объявляет массив буферных блоков UBO. Это означает, что вы можете привязать отдельный буферный объект для каждого индекса в вашем массиве или другой буферный диапазон. Обратите внимание, что в этом примере вы будете использовать индексы привязки UBO от 0 до 7, GLSL spe c явно заявляет:

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

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

Таким образом, вы редко действительно хотите использовать массив однородных блоков. Специально для вашего легкого примера вы должны использовать последний:

layout(std140, binding = 0) uniform LightBlock
{
    LightStruct lights[8]; 
};

просто объявляет один унифицированный блок с aeeay в нем. Это означает, что вы должны предоставить один последовательный диапазон буфера UBO для массива, поэтому вы используете только одну из драгоценных точек привязки UBO, и вы можете иметь массив, равный максимальному размеру UBO вашей реализации.

...