Что именно нужно для гамма-коррекции?

У меня есть проблемы, чтобы полностью понять необходимость гамма-коррекции. Я надеюсь, что вы, ребята, можете мне помочь.

Давайте предположим, что мы хотим отобразить 256 соседних пикселей. Эти пиксели должны иметь плавный градиент от черного к белому. Чтобы обозначить их цвета, мы используем линейные значения серого из 0..255. Из-за нелинейности человеческого глаза монитор не должен просто превращать эти значения в линейные значения яркости. Если соседние пиксели имели значения яркости (1/256)*I_max, (2/256)*I_max, et ceteraВ более темной области мы будем воспринимать слишком большие различия в яркости между двумя пикселями (градиент не будет плавным).

К счастью, монитор имеет обратную нелинейность для человеческого глаза. Это означает, что если мы введем линейные значения серого 0..255 в буфер кадров, затем монитор превращает их в нелинейные значения яркости х ^ гамма. Однако, поскольку наш глаз, наоборот, нелинейный, мы воспринимаем плавный линейный градиент. Нелинейность монитора и нашего глаза компенсируют друг друга.

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

Насколько я понимаю, было бы идеально, если бы мы поместили линейные значения серого в буфер кадра. Монитор превращает эти значения в нелинейные значения яркости, и наш глаз снова воспринимает линейные значения яркости, потому что глаз является взаимно нелинейным. Не будет необходимости гамма-коррекции значений серого в буфере кадров и не нужно заставлять монитор выдавать линейные значения яркости.

Что не так с моим взглядом на эти вещи? Спасибо

3 ответа

Позвольте мне "воскресить" этот вопрос, так как я сейчас борюсь с подобными вопросами, и я думаю, что нашел ответ - это может быть полезно для кого-то еще. Или я могу ошибаться, и кто-то может сказать мне:)

Я думаю, что нет ничего плохого в вашем образе мышления. Дело в том, что вам не нужно все время гамма-корректировать, если вы знаете, что делаете. Это зависит от того, чего вы хотите достичь. Давайте посмотрим на два разных случая.

А) Моделирование освещения (рендеринг АКА). У вас есть рассеянная поверхность с направленным на нее светом. Затем интенсивность света удваивается.

Что ж. Посмотрим, что происходит в реальном мире в такой ситуации. Предполагая, что поверхность чисто рассеянная, интенсивность отраженного света будет равна альбедо поверхности, умноженному на интенсивность входящего света и косинус угла приходящего света и нормали. Без разницы. Дело в том, что когда интенсивность входящего света удваивается, интенсивность отраженного света также удваивается. Вот почему перенос света называется линейным процессом. Как ни странно, вы не будете воспринимать поверхность в два раза ярче, потому что наше восприятие нелинейно (это моделируется так называемым степенным законом Стивена). Опять же: в реальном мире отраженный свет удваивается, но вы не воспринимаете его вдвое ярче.

Теперь, как бы мы смоделировали это? Что ж, если у нас есть текстура sRGB с альбедо поверхности, нам нужно ее линеаризовать (путем ее коррекции, что означает применение гаммы 2,2). Теперь, когда он линейный, и у нас есть интенсивность света, мы можем использовать формулу, которую я сказал ранее, чтобы вычислить интенсивность отраженного света. Поскольку мы находимся в линейном пространстве, удваивая интенсивность, мы удваиваем выход, как в реальном мире. Теперь мы гамма-корректируем наши результаты. Из-за этого, когда экран отображает визуализированное изображение, он будет применять гамму, и поэтому он будет иметь линейный отклик, что означает, что интенсивность света, излучаемого экраном, будет в два раза больше, когда мы имитируем удвоенную мощный свет, чем когда мы имитируем первый. Таким образом, свет, который попадает на ваши глаза с экрана, будет иметь удвоенную интенсивность. Точно так же, как это было бы, если бы вы смотрели на реальную поверхность с реальными источниками света, влияющими на нее. Конечно, вы не будете воспринимать второй рендер в два раза ярче, но, опять же, как мы уже говорили ранее, это именно то, что произойдет в реальной ситуации. Такое же поведение в реальном мире и в симуляции означает, что симуляция (рендер) была правильной:)

Б) Другой случай - это именно тот случай, если вы хотите, чтобы градиент выглядел как "линейный".

Поскольку вы хотите, чтобы нелинейный отклик экрана подавлял наше нелинейное визуальное восприятие, вы можете вообще пропустить гамма-коррекцию (как вы предлагаете). Или, точнее, продолжайте работать в линейном пространстве и гамма-коррекции, но создавая свой градиент не с последовательными значениями для пикселей (1,2,3...255), которые будут восприниматься нелинейно (из-за Стивена), а с значениями трансформируется обратной величиной нашего воспринимаемого отклика яркости (то есть применяя показатель степени 1/0,5=2 к нормализованным значениям. Это применяет обратную величину показателя Стивена для яркости).

На самом деле, если вы видите линейный градиент с гамма-коррекцией, такой как тот, что на http://scanline.ca/gradients/ вы вообще не воспринимаете его как линейный: вы видите гораздо больше изменений в более низких интенсивностях, чем в высшие (как и ожидалось).

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

Проблема действительно в том, чтобы делать вычисления цвета. Например, если вы смешиваете два цвета, вам нужно использовать линейные интенсивности для выполнения расчетов. Чтобы действительно отобразить правильный результат, вам необходимо преобразовать линейные интенсивности обратно в гамма-скорректированные интенсивности.

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

На самом деле ответить на вопрос, который неверен с вашей точки зрения на это - в этом нет ничего плохого. Было бы здорово иметь линейный кадровый буфер, но, как вы говорите, определенно нехорошо иметь 8-битный линейный буфер кадров.

Тот факт, что 8 битов так легко обрабатывать, является практически единственным оправданием для гамма-сжатых кадровых буферов и цветовых обозначений (подумайте, что HTML #888 - было бы не круто использовать #333 для среднего серого, а не #888).

О мониторе - вы хотите быть в состоянии предсказать его реакцию на ваш ввод, и вы знаете из sRGB, каким он должен быть. Обычно это все, что вам нужно знать. Некоторые люди думают, что это "правильно" или что-то в этом роде, если монитор выдает "линейный" выход, который можно смоделировать, если вы компенсируете гамму монитора. Я советую держаться подальше от такой установки, которая ломает все приложения, которые (правильно и разумно) принимают стандартную гамму в пользу неразрывных, неубедительных приложений, предполагающих линейность. Не делай этого. Вместо этого исправьте приложения или сбросьте их.

Другие вопросы по тегам