Как фрагментный шейдер узнает, какую переменную использовать для цвета пикселя? - PullRequest
76 голосов
/ 10 февраля 2012

Я вижу много разных фрагментных шейдеров,

#version 130

out vec4 flatColor;

void main(void)
{
    flatColor = vec4(0.0,1.0,0.0,0.5);
}

И все они используют другую переменную для "out color" (в данном случае flatColor). Так как же OpenGL узнает, что вы пытаетесь сделать?

Я предполагаю, что это работает, потому что flatColor - единственная переменная, определенная как out, но вы можете добавить больше out переменных, не так ли? Или это просто сбой?


На самом деле, в качестве теста я просто запустил это:

#version 330

in vec2 TexCoord0;

uniform sampler2D TexSampler;

out vec4 x;
out vec4 y;

void main()
{
    y = texture2D(TexSampler, TexCoord0.xy);
}

Работало нормально, использовал ли я x или y.


Кроме того, у нас есть предопределенный gl_FragColor. В чем разница, и почему люди обычно настаивают на использовании своих собственных переменных?

Ответы [ 2 ]

134 голосов
/ 10 февраля 2012

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

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

8 голосов
/ 26 января 2016

Я хотел бы указать это для OpenGLES 3.1, который использует GLSL_ES_3.10 ссылка :

§4.4.2

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...