Кроме того, у нас есть предопределенный gl_FragColor.
Начнем с этого. Нет, у вас нет предопределенного gl_FragColor
. Это было удалено из ядра OpenGL 3.1 и выше. Если вы не используете совместимость (в этом случае шейдеры 3.30 должны указывать #version 330 compatibility
вверху), вам никогда не следует ее использовать.
Теперь вернемся к пользовательским выводам фрагментного шейдера. Но сначала небольшая аналогия.
Помните, как в вершинных шейдерах у вас есть входы? И эти входы представляют собой вершину индексов атрибутов, число Проходите glVertexAttribPointer
и glEnableVertexAttribArray
так далее? Вы устанавливаете, какой вход будет извлекаться из какого атрибута. В GLSL 3.30 вы используете этот синтаксис:
layout(location = 2) in color;
Это устанавливает, что color
ввод вершинного шейдера будет поступать из местоположения атрибута 2. До 3.30 (или без ARB_explicit_attrib_location) вам нужно было бы явно установить это с помощью glBindAttrbLocation
перед связыванием или запросить программу для индекса атрибута с glGetAttribLocation
. Если вы явно не укажете местоположение атрибута, GLSL назначит местоположение произвольно (то есть: способом, определяемым реализацией).
Установка его в шейдере почти всегда лучший вариант.
В любом случае выходные данные фрагментного шейдера работают почти так же. Фрагментные шейдеры могут записывать в несколько выходных цветов , которые сами отображаются на несколько буферов в буфере кадра . Следовательно, вам нужно указать, какой вывод идет на какой цвет вывода фрагмента.
Этот процесс начинается со значения местоположения вывода фрагмента. Это очень похоже на расположение входных данных вершинного шейдера:
layout(location = 1) out secColor;
Также существуют функции API glBindFragDataLocation
и glGetFragDataLocation
, аналогичные glBindAttribLocation
и glGetAttribLocation
.
Если вы не выполняете каких-либо явных назначений, реализации обычно присваивают одну из ваших выходных переменных местоположению 0. Однако стандарт OpenGL не требует такого поведения, поэтому вы также не должны зависеть от него.
Теперь , чтобы быть справедливым, ваша программа должна не удалось в связи , когда вы использовали два выхода, которые не получают в разных местах выхода. Вероятно, произошло то, что ваш компилятор оптимизировал тот, для которого вы не писали, поэтому он как бы забыл об этом, когда пришло время проверять ошибки компоновщика.