Ответ 1
Прежде всего, вы должны понимать, что нелинейное отображение, применяемое к цветным каналам, часто больше, чем просто простая функция мощности. sRGB нелинейность может быть аппроксимирована примерно на x ^ 2,4, но это не настоящая сделка. В любом случае ваши первичные предположения более или менее правильны.
Если ваши текстуры хранятся в более распространенных форматах файлов изображений, они будут содержать значения, как они представлены в графическом сканировании. Теперь есть два общих аппаратных сценария:
-
Интерфейс сканера выводит линейный сигнал, и устройство отображения затем внутренне применяет нелинейное отображение. Старые ЭЛТ-мониторы были нелинейны из-за своей физики: усилители могли вставлять только столько тока в электронный пучок, насыщение фосфора и т.д. - поэтому вся идея гамма была введена в первую очередь для моделирования нелинейностей ЭЛТ-дисплеев.
-
Современные ЖК-дисплеи и OLED-дисплеи используют либо резисторные лестницы в своих усилителях драйверов, либо имеют таблицы поиска гамма-рампы в своих процессорах изображений.
-
Некоторые устройства, однако, являются линейными, и попросите устройство, производящее изображение, предоставить надлежащее соответствие LUT для требуемого цветового профиля вывода при сканировании.
На большинстве компьютеров эффективное сканирование LUT является линейным! Что это значит? Небольшой объезд:
Для иллюстрации я быстро подключил свой аналоговый дисплей ноутбука (разъем VGA) к своему аналоговому осциллографу: синий канал по каналу видимости 1, зеленый канал - к каналу области 2, внешний запуск по сигналу синхронизации линии (HSync). Быстрая и грязная программа OpenGL, преднамеренно написанная с немедленным режимом, использовалась для создания линейной цветовой рампы:
#include <GL/glut.h>
void display()
{
GLuint win_width = glutGet(GLUT_WINDOW_WIDTH);
GLuint win_height = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0,0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUAD_STRIP);
glColor3f(0., 0., 0.);
glVertex2f(0., 0.);
glVertex2f(0., 1.);
glColor3f(1., 1., 1.);
glVertex2f(1., 0.);
glVertex2f(1., 1.);
glEnd();
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("linear");
glutFullScreen();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Графический выход был настроен с помощью Modeline
"1440x900_60.00" 106.50 1440 1528 1672 1904 900 903 909 934 -HSync +VSync
(потому что в том же режиме работает плоская панель, и я использую режим клонирования)
- gamma = 2 LUT на зеленом канале.
- linear (gamma = 1) LUT на синем канале
Вот как выглядят сигналы одной линии сканирования (верхняя кривая: Ch2 = зеленая, нижняя кривая: Ch1 = синяя):
Вы можете четко видеть сопоставления x⟼x² и x⟼x (парабола и линейные формы кривых).
Теперь после этого небольшого объезда мы знаем, что значения пикселей, которые идут к основному фреймбуферу, идут туда, как они есть: линейный линейный выход OpenGL не претерпел никаких изменений, и только при применении нелинейного сканирования LUT он изменил переданный сигнал на дисплей.
В любом случае значения, которые вы представляете сканированию (что означает экранные фреймбуферы), будут подвергаться нелинейному отображению в некоторой точке цепочки сигналов. И для всех стандартных потребительских устройств это сопоставление будет соответствовать стандарту sRGB, потому что это наименьший общий коэффициент (то есть изображения, представленные в цветовом пространстве sRGB, могут воспроизводиться на большинстве выходных устройств).
Так как большинство программ, таких как веб-браузеры, предполагают, что вывод подвергается sRGB для отображения отображения цветового пространства, они просто копируют значения пикселей стандартных форматов файлов изображений в экранный кадр, как они есть, без выполнения преобразования цветового пространства, тем самым подразумевая, что значения цвета в этих изображениях находятся в цветовом пространстве sRGB (или они часто просто преобразуются в sRGB, если профиль цвета изображения не является sRGB); правильная вещь (если и только если значения цвета, записанные в фреймбуфер, будут отсканированы на дисплее без изменений, считая, что сканирование LUT является частью дисплея), будет преобразование в указанный цветовой профиль, который ожидает ожидание.
Но это означает, что сам экранный фреймбуфер находится в цветовом пространстве sRGB (я не хочу разделить волосы на то, как идиот, что позволяет, просто принять этот факт).
Как это сделать вместе с OpenGL? Прежде всего, OpenGL выполняет все операции по цвету линейно. Однако, поскольку ожидается, что сканирование будет в некотором нелинейном цветовом пространстве, это означает, что конечный результат операций рендеринга OpenGL каким-то образом должен быть включен в экранное пространство экранного фреймбуфера.
Здесь находится расширение ARB_framebuffer_sRGB
(которое входит в основное ядро с OpenGL-3), в котором введены новые флаги, используемые для конфигурация оконных пиксельных форматов:
New Tokens
Accepted by the <attribList> parameter of glXChooseVisual, and by
the <attrib> parameter of glXGetConfig:
GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
Accepted by the <piAttributes> parameter of
wglGetPixelFormatAttribivEXT, wglGetPixelFormatAttribfvEXT, and
the <piAttribIList> and <pfAttribIList> of wglChoosePixelFormatEXT:
WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
Accepted by the <cap> parameter of Enable, Disable, and IsEnabled,
and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
and GetDoublev:
FRAMEBUFFER_SRGB 0x8DB9
Итак, если у вас есть окно, настроенное с таким пиксельным форматом sRGB ивключить режим растрирования sRGB в OpenGL с помощью glEnable(GL_FRAMEBUFFER_SRGB);
результат операций рендеринга линейного цветового пространства будет преобразован в цветовое пространство sRGB.
Другим способом было бы превратить все в внеблочное FBO и преобразование цвета в постобработке.
Но это только выходная сторона цепи сигнала рендеринга. Вы также получили входные сигналы в виде текстур. И это обычно изображения, причем их значения пикселей хранятся нелинейно. Поэтому, прежде чем они могут использоваться в операциях линейного изображения, такие изображения сначала должны быть представлены в линейное цветовое пространство. Пока просто игнорируем, что отображение нелинейных цветовых пространств в линейные цветовые пространства открывает несколько банок червей сам по себе - вот почему цветовое пространство sRGB настолько смехотворно мало, а именно, чтобы избежать этих проблем.
Итак, для решения этого вопроса было добавлено расширение EXT_texture_sRGB
, которое оказалось настолько важным, что оно никогда не проходило через ARB, но пошел прямо в спецификацию OpenGL: вот внутренние форматы текстур GL_SRGB…
.
Текстура, загруженная этим форматом, претерпевает преобразование цветового пространства sRGB в линейное RGB, прежде чем использовать исходные образцы. Это дает линейные значения пикселей, подходящие для линейных операций рендеринга, и результат может быть затем корректно преобразован в sRGB при переходе на основной экранный фреймбуфер.
Личное примечание по всей проблеме: представление изображений на экранном фреймбуфере в цветовом пространстве целевого устройства. ИМХО - огромный недостаток дизайна. Нет никакого способа сделать все правильно в такой установке, не сойдя с ума.
Что действительно нужно, так это иметь экранный фреймбуфер в линейном, контактном цветовом пространстве; естественным выбором будет CIEXYZ. Операции рендеринга будут, естественно, происходить в том же цветовом пространстве контакта. Выполняя все графические операции в контактных цветовых пространствах, избегает открытия вышеупомянутых червяков, связанных с попыткой выталкивать квадратный привязку с именем linear RGB через нелинейное круглое отверстие с именем sRGB.
И хотя мне очень не нравится дизайн Weston/Wayland, по крайней мере, он предлагает возможность реально реализовать такую систему отображения, предоставляя визуализацию клиентов, а композитор работает в цветном пространстве контакта и применяет вывод цветные профили устройства на последнем этапе последующей обработки.
Единственным недостатком контактных цветовых пространств является необходимость использования глубокого цвета (т.е. > 12 бит на цветной канал). На самом деле 8 бит полностью недостаточны даже при нелинейном RGB (нелинейность помогает немного скрыть отсутствие ощутимого разрешения).
Update
Я загрузил несколько изображений (в моем случае как изображения .png, так и .bmp) и проверил необработанные двоичные данные. Мне кажется, что изображения на самом деле находятся в цветовом пространстве RGB, как если бы я сравнивал значения пикселей с программой редактирования изображений с байт-массивом, который я получаю в своей программе, они отлично сочетаются. Поскольку мой редактор изображений дает мне значения RGB, это указывает на изображение, сохраненное в RGB.
Да, действительно. Если где-то в цепочке сигналов применяется нелинейное преобразование, но все значения пикселей не изменяются от изображения к дисплею, то эта нелинейность уже была предварительно применена к значениям пикселей изображения. Это означает, что изображение уже находится в нелинейном цветовом пространстве.
2 - "На большинстве компьютеров эффективный сканирование LUT является линейным! Что это значит?
Я не уверен, что смогу найти, когда эта мысль будет завершена в вашем ответе.
Эта мысль развивается в следующем разделе, где я показываю, как значения, которые вы помещаете в простой (OpenGL) фреймбуфер, идут прямо на монитор, не изменяемый. Идея sRGB заключается в том, чтобы "поместить значения в изображения точно так же, как они отправляются на монитор, и создавать потребительские дисплеи, чтобы следовать этому цветовому пространству sRGB".
Из того, что я могу сказать, поэкспериментировав, все мониторы, которые я тестировал на выходных линейных значениях.
Как вы измерили реакцию сигнала? Использовали ли вы калиброванный измеритель мощности или аналогичное устройство для измерения интенсивности света, излучаемого монитором в ответ на сигнал? Вы не можете доверять своим глазам, потому что, как и все наши чувства, наши глаза имеют логарифмический сигнал.
Обновление 2
Мне единственный способ понять, что вы говорите, чтобы быть правдой, - это то, что редактор изображений давал мне значения в пространстве sRGB.
Это действительно так. Поскольку управление цветом было добавлено ко всем широко распространенным графическим системам в качестве запоздалой мысли, большинство редакторов изображений редактируют значения пикселей в их цветовом пространстве назначения. Обратите внимание, что одним из параметров дизайна sRGB было то, что он должен просто ретроактивно указывать неуправляемые, прямые операции переноса цвета так, как они были (и в основном все еще сделаны), выполненные на потребительских устройствах. Поскольку никакого управления цветом вообще нет, значения, содержащиеся в изображениях и управляемые в редакторах, уже должны быть в sRGB. Это работает так долго, поскольку длинные изображения не синтетически создаются в процессе линейного рендеринга; в случае последующей системы визуализации необходимо учитывать цветовое пространство назначения.
Я беру снимок экрана, а затем использую программу редактирования изображений, чтобы увидеть, что значения пикселей
Это дает вам, конечно, только исходные значения в буфере сканирований без применения гамма-LUT и нелинейности отображения.