Как шейдер фрагментов знает, какую переменную использовать для цвета пикселя?
Я вижу много разных шейдеров фрагментов,
#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 ответа:
кроме того, у нас есть предопределенный 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 не требуются такое поведение, так что вы не должны зависеть от этого.
честно говоря, ваша программа должна иметь ошибка чтобы связать, когда вы использовали два выхода, которые не получили разные места вывода. Вероятно, произошло то, что ваш компилятор оптимизировал тот, который вы не писали, поэтому он забыл об этом, когда он пришло время проверить ошибки компоновщика.
Я хотел бы указать это для OpenGLES 3.1, который использует GLSL_ES_3. 10 ссылке:
§4.4.2
Если есть только один выход [в шейдере фрагментов], в расположение не нужно указывать, в этом случае оно по умолчанию равно нуль.