Использовать типы матриц в качестве выходных данных фрагментарного шейдера в OpenGL

#opengl #glsl #shader

#opengl #glsl #шейдер

Вопрос:

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

Мне интересно, возможно ли сделать что-то подобное для типов матриц в качестве выходных данных в фрагментном шейдере при рендеринге в несколько фреймбуферов. То есть у меня было бы 4 разные текстуры в буфере кадров, привязанные к цветным вложениям с 0 по 3, и тогда у меня могла бы быть layout(location = 0) out matrix4 out_mat , в которую я мог бы записывать с помощью фрагментного шейдера.

Прав ли я, предполагая, что это сработает?

Комментарии:

1.Вы можете преобразовать столбец матрицы в другую цель (плоскость) буфера. out0 = m[0]; out1 = m[1];

2. Значит ли это, что это не работает?

3. @InformationAether: » В OpenGL матрица занимает несколько местоположений в шейдере » Матрицы занимают более одного местоположения только при использовании в качестве входных данных вершинного шейдера . Во всех других случаях, когда они могут быть использованы (переменные ввода / вывода внутри шейдера, униформы), они занимают только одно местоположение.

Ответ №1:

Для выходных данных фрагментного шейдера матричный тип данных недопустим :

Смотрите Спецификацию OpenGL Shading Language 4.60 — 4.3.6. Выходные переменные, стр. 54:

Fragment выводит данные для каждого фрагмента и объявляется с использованием out спецификатора хранилища. Использование вспомогательных квалификаторов хранилища или квалификаторов интерполяции в объявлении выходных данных фрагментного шейдера является ошибкой времени компиляции. Объявление выходных данных фрагментного шейдера с любым из следующих типов или содержащего их является ошибкой времени компиляции:

  • Логический тип
  • Скаляр или вектор двойной точности (double, dvec2, dvec3, dvec4)
  • Непрозрачный тип
  • Тип матрицы
  • Структура

Но выходные данные фрагментного шейдера могут быть массивом:

например

 layout (location = 0) out vec4 fragOut[4];

void main()
{
    mat4 m = [...];

    fragOut[0] = m[0];
    fragOut[1] = m[1];
    [...]
}
  

Матрица может быть назначена массиву конструктором массива (см. 4.1.13. Массивы, страница 36):

 layout (location = 0) out vec4 fragOut[4];

void main()
{
    mat4 m = [...];

    fragOut = vec4[4](m[0], m[1], m[2], m[3]);
}
  

Комментарии:

1. Вы знаете, разрешены ли массивы векторов? Не удалось найти это в спецификации.

2. @ybungalobill Это явно не запрещено. В общем случае выходной переменной может быть массив. Я только что попробовал это, и это работает.

Ответ №2:

В спецификации GLSL указано (выходные переменные версии 4.5, 4.3.6):

Объявление выходных данных фрагментного шейдера, содержащих любое из следующего, является ошибкой времени компиляции:

  • Любой тип матрицы

Поэтому

 layout(location = 0) out mat4 out_mat;
  

является незаконным.

Вместо этого вы должны выводить элементы матрицы в четыре отдельных вывода:

  layout(location = 0) out vec4 out_mat0;
 layout(location = 1) out vec4 out_mat1;
 layout(location = 2) out vec4 out_mat2;
 layout(location = 3) out vec4 out_mat3;

 void main() {
     mat4 M = ...;
     out_mat0 = M[0]; // column 0
     out_mat1 = M[1]; // column 1
     out_mat2 = M[2]; // column 2
     out_mat3 = M[3]; // column 3
 }