Кроме того, у нас есть предопределенный 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 не требует такого поведения, поэтому вы не должны зависеть от него. либо.
Теперь, чтобы быть справедливым, ваша программа должна иметь сбой для связи, когда вы использовали два выхода, которые не получили разных выходных местоположений. Вероятно, произошло то, что ваш компилятор оптимизировал тот, который вы не записывали, поэтому он забыл об этом, когда пришло время проверять ошибки компоновщика.