Учитывает ли блики кадрового буфера OpenGL гамма-коррекцию при включении?

Вот моя проблема, когда я загружаю текстуры, я загружаю их как SRGB, чтобы преобразовать их в линейное пространство. Когда я выполнял запись в буфер кадров по умолчанию, предоставляемый системой управления окнами, я включил GL_FRAMEBUFFER_SRGB, чтобы при записи в буфер кадров преобразовывались цвета из линейного пространства в пространство SRGB.

Проблема сейчас в том, что я рендерил в FBO вне экрана, а затем вставлял его в стандартный кадровый буфер. При этом включение или отключение GL_FRAMEBUFFER_SRGB не имеет никакого эффекта. Я попытался включить GL_FRAMEBUFFER_SRGB как с привязкой кадрового буфера по умолчанию, так и с привязкой закадрового FBO, они не работают.

Что работает, однако, если я указываю GL_SRGB в качестве внутреннего формата текстуры, которую я связываю как буфер цвета внеэкранного FBO. Я предполагаю, что в этом случае, когда GL_FRAMEBUFFER_SRGB включен, записи из фрагментного шейдера в текстуру преобразуют его из линейного пространства в пространство SRGB.

Мне было интересно, кажется, что переход от FBO к кадровому буферу по умолчанию преобразования GL_FRAMEBUFFER_SRGB не применяется. Поскольку я хотел бы работать в линейном пространстве до окончательной передачи в буферный буфер стандартного кадрового буфера, как я могу применить преобразование при перетаскивании внеэкранного FBO в стандартный кадровый буфер? Я предполагаю, что выборка закадрового FBO в качестве текстуры и рендеринг четырехугольника в кадровом буфере по умолчанию применили бы преобразование SRGB, но нет ли способа сделать это преобразование с помощью кадрового буфера?

1

Решение

Делая этот поворот GL_FRAMEBUFFER_SRGB вкл или выкл не имеет никакого эффекта. Я пытался включить GL_FRAMEBUFFER_SRGBкак с привязанным по умолчанию кадровым буфером, так и с закадровым ограничением FBO, они не работают.

GL_FRAMEBUFFER_SRGB не то, что вы думаете, что делает: не превратить любого мошенника формат от RGB до sRGB.
GL_FRAMEBUFFER_SRGB будет иметь эффект только тогда, когда формат кадрового буфера уже указан sRGBнапример, прикрепив текстуру с internalFormat из GL_SRGB8 или же GL_SRGB8_ALPHA8 в качестве цветного буфера для FBO. Если вы хотите преобразование sRGB для буфера кадров по умолчанию, вы должны использовать специальные API оконной системы, чтобы явно создать PixelFormat / Visual / FBConfig / что угодно с поддержкой sRGB. Посмотрите на GL / GLX / WGL _ARB_FRAMEBUFFER_SRGB расширение спецификации о том, как это сделать.

Что работает, однако, если я укажу GL_SRGB в качестве внутреннего формата текстуры, которую я связываю как буфер цвета внеэкранного FBO. Я предполагаю в этом случае, когда GL_FRAMEBUFFER_SRGB включается запись из фрагмента шейдера в текстуру, преобразование его из линейного пространства в пространство SRGB.

Да, именно так и должно работать. GL_FRAMEBUFFER_SRGB включить бит это только средство запрещать преобразования SRGB в форматах, которые обычно делают их, а не наоборот.

Мне было интересно, кажется, что переход от FBO к кадровому буферу по умолчанию преобразования GL_FRAMEBUFFER_SRGB не применяется.

Давайте посмотрим на самую последнюю спецификацию OpenGL на сегодняшний день: Спецификация профиля ядра OpenGL 4.6, раздел 18.3.1 «Прямоугольники блицующих пикселей» (выделено мной):

Когда значения взяты из буфера чтения, если
FRAMEBUFFER_SRGB включен и значение
FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING для вложения кадрового буфера, соответствующего буферу чтения
SRGB (см. раздел 9.2.3), красный, зеленый и синий компоненты преобразованы из нелинейного цвета sRGB
пространство в соответствии с уравнением 8.17.

Когда значения записываются в буферы рисования, блиц-операции обходят большинство
фрагмент трубопровода. Единственные операции фрагмента, которые влияют на блиц, являются пикселем
тест собственности, тест ножниц, и преобразование sRGB (см. раздел 17.3.7). Цвет,
глубина и трафаретные маски (см. раздел 17.4.2) игнорируются

с разделом 17.3.7 «Преобразование sRGB» с указанием:

Если FRAMEBUFFER_SRGB включен и значение
FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING для вложения кадрового буфера, соответствующего буферу назначения
SRGB (см. раздел 9.2.3), значения R, G и B после
смешивание преобразуется в нелинейное цветовое пространство sRGB [формула следует …]

Обратите внимание, что в разделе 17.3.7 будет ясно, что при записи в цветной буфер преобразование линейного в sRGB будет применяться только в том случае, если GL_FRAMEBUFFER_SRGB включен.

Так что это оставляет нам следующие возможности:

  1. И исходный, и целевой цветовой буфер имеют стандартный формат NON-sRGB: блиц будет копировать значения пикселей, преобразования sRGB не могут произойти, независимо от того, как GL_FRAMEBUFFER_SRGB установлено.

  2. Исходный буфер имеет формат sRGB, пункт назначения имеет формат NON-sRGB. Преобразование из sRGB в линейное будет сделано если и только если GL_FRAMEBUFFER_SRGB включен.

  3. Исходный буфер имеет формат NON-sRGB, пункт назначения имеет формат sRGB. Преобразование из линейного в sRGB будет сделано если и только если GL_FRAMEBUFFER_SRGB включен.

  4. И источник, и пункт назначения имеют форматы sRGB. Будет выполнено преобразование из sRGB в линейный И линейный в sRGB если и только если GL_FRAMEBUFFER_SRGB включен. Обратите внимание, что преобразование может сводиться к неработоспособности здесь. Это относится и к случаям с билинейной фильтрацией: спецификация GL не требует применения билинейной фильтрации к источникам sRGB в линейном пространстве после преобразования, ее также можно применять и раньше.

Теперь история может быть здесь. Но это не так. Поведение кадровых буферов в форматах sRGB претерпело ряд изменений в истории GL.

Раздел 18.3.1 Спецификация профиля ядра OpenGL 4.3 заявляет:

Когда значения взяты из буфера чтения, если значение
FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING для вложения кадрового буфера, соответствующего буферу чтения
SRGB (см. раздел 9.2.3), красный, зеленый и синий компоненты преобразуются из нелинейного цветового пространства sRGB в соответствии с уравнением

[Второй абзац такой же, как предыдущий цитата из 4.6]

Это означает, что до GL 4.3, преобразование источник буфер всегда выполнялся, когда он имел формат sRGB, независимо от того, GL_FRAMEBUFFER_SRGB включить. Однако для буфера назначения этот параметр все еще актуален.

Сейчас в OpenGL 3.3, нет никакого упоминания о поведении при блиттинге с форматами sRGB. Соответствующий раздел 4.3.2 «Копирование пикселей» и только утверждает:

Блит-операции обходят фрагмент конвейера. Единственный фрагмент операции
на блиц влияют тест владения пикселем и ножницы.

Это означает, что он также будет обходить линейное преобразование в sRGB для целевого буфера и не будет делать никаких заявлений об исходном преобразовании вообще.

Кроме того, исторически сложилось так, что драйверы также игнорировали спецификации и делали то, что, по их мнению, лучше всего, когда дело доходит до преобразований sRGB. Смотри например статья «Состояние драйверов OpenGL за март 2015 года и конверсии FB sRGB». Существует также этот хороший патч к тестовому пакету OpenGL для поросят говорить о проблемах и выдвигать несколько печальные выводы:

Я думаю, что краткая сводка такова: sRGB в OpenGL настолько сломан, насколько это возможно. 🙁 По крайней мере, каждый разработчик игр, с которым я когда-либо общался, говорит мне об этом. Тьфу.

Однако, по моему опыту, большинство современных драйверов GL> = 4.4 выполняют преобразования в соответствии с указаниями, поэтому ситуация уже не так уж и плоха. Но я бы не стал ставить на это свою жизнь.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]