Когда вызывать glEnable (GL_FRAMEBUFFER_SRGB)?

У меня есть система рендеринга, в которой я рисую FBO с помощью мультисэмплированного рендеринга буфера, а затем blit его в другое FBO с текстурой, чтобы разрешить выборки, чтобы читать текстуру для выполнения затенения после обработки при рисовании на бэкбуффер (индекс FBO 0).

Теперь я хотел бы получить правильный вывод sRGB... Проблема в том, что поведение программы довольно противоречиво между тем, когда я запускаю ее на OS X и Windows, и это также изменяется в зависимости от машины: в Windows с Intel HD 3000 он не будет применять нелинейность sRGB, но на моей другой машине с Nvidia GTX 670. На Intel HD 3000 в OS X он также применит его.

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

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

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

Я не знаю, правильно это или нет. Это, безусловно, применяет нелинейность к цветам, но я не могу сказать, будет ли это применяться дважды (что было бы плохо). Он может применять гамма, как я делаю свой первый FBO. Он мог бы это сделать, когда я запустил первый FBO ко второму FBO. Почему нет?

Я дошел до того, что снял скриншоты моего финального кадра и сравнил исходные значения цвета пикселя с цветами, которые я установил в программе:

Я установил цвет ввода в RGB (1,2,3), а выход - RGB (13,22,28).

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

Я только что прошел через уравнение sRGB, и я могу проверить, что преобразование, кажется, применяется только один раз, когда линейные 1/255, 2/255 и 3/255 действительно отображают sRGB 13/255, 22/255 и 28/255, используя уравнение 1.055*C^(1/2.4)+0.055. Учитывая, что расширение настолько велико для этих низких значений цвета, это действительно должно быть очевидно, если цветовое преобразование sRGB применяется более одного раза.

Итак, я все еще не определил, что правильно делать. glEnable(GL_FRAMEBUFFER_SRGB) применяется только к конечным значениям framebuffer, и в этом случае я могу просто установить это во время моей процедуры GL init и забыть об этом в дальнейшем?

Ответы

Ответ 1

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

Любые записи на изображения, не входящие в формат sRGB, не должны быть затронуты. Поэтому, если вы пишете изображение с плавающей точкой, ничего не должно произойти. Таким образом, вы должны иметь возможность просто включить его и оставить его таким образом; OpenGL будет знать, когда вы передаете фреймбуфер sRGB.

В общем, вы хотите работать в линейном цветовом пространстве как можно дольше. Только ваш окончательный рендер после постобработки должен включать в себя цветовое пространство sRGB. Таким образом, ваш мультисэмплированный фреймбуфер должен, вероятно, оставаться линейным (хотя вы должны дать ему более высокое разрешение для его цветов, чтобы сохранить точность. Используйте GL_RGB10_A2, GL_R11F_G11F_B10F или GL_RGBA16F в качестве крайней меры).

Что касается этого:

В Windows с Intel HD 3000 он не будет применять нелинейность sRGB

Это почти наверняка из-за того, что Intel сосать при написании драйверов OpenGL. Если это не так, когда вы включаете GL_FRAMEBUFFER_SRGB, это из-за Intel, а не из вашего кода.

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