Я хочу применить гамма-коррекцию к моему освещению OpenGL, но с примененной гамма-коррекцией мои результаты вообще не кажутся линейными.
Я также нашел OpenGL: изображение с гамма-коррекцией не выглядит линейным которая очень похожа на мою проблему, но еще не получила ответа и не обсуждала рассеянный свет.
В качестве иллюстрации у меня есть следующие 4 цвета света, определенные в линейном пространстве:
glm::vec3 lightColors[] = {
glm::vec3(0.25),
glm::vec3(0.50),
glm::vec3(0.75),
glm::vec3(1.00)
};
С каждым отдельным источником света и базовым линейным затуханием, примененным к уравнению рассеянного освещения, я получаю следующие результаты:
Это фрагментный шейдер:
void main()
{
vec3 lighting = vec3(0.0);
for(int i = 0; i < 4; ++i)
lighting += Diffuse(normalize(fs_in.Normal), fs_in.FragPos, lightPositions[i], lightColors[i]);
// lighting = pow(lighting, vec3(1.0/2.2));
FragColor = vec4(lighting, 1.0f);
}
Мало того, что я почти не вижу разницы в яркости с гамма-коррекцией света, затухание также искажается гамма-коррекцией. Насколько я понимаю, все расчеты (включая затухание) выполняются в линейном пространстве, и, исправляя гамму, монитор должен правильно отображать ее (так как он снова корректирует ее как вывод). Исходя только из цветов освещения, крайний правый круг должен быть в 4 раза ярче левого и в два раза ярче второго круга, что на самом деле не так.
Просто я недостаточно чувствителен, чтобы воспринимать правильные различия яркости или что-то не так?
Что-то еще, что я попробовал, просто вывести точные цвета света на стандартный кадровый буфер без и с гамма-коррекцией.
Левый не исправлен, правый — с гамма-коррекцией; с красными числами, указывающими интенсивность RGB из палитры цветов Photoshop. Я знаю, что значения RGB в Photoshop не представляют конечного выходного изображения (поскольку Photoshop не считывает значения RGB в качестве выходных данных монитора). Левое изображение интуитивно кажется лучше, но, основываясь на значениях интенсивности RGB, я бы сказал, что самое правое изображение действительно корректно гамма-коррекцией с помощью моего фрагментного шейдера; поскольку каждая из этих интенсивностей пройдет через монитор и попадет в мой глаз с правильной интенсивностью. Например, интенсивность 0,75 при поправке на 0,88 гаммы становится 0,88 ^ 2,2 = 0,75 в качестве выходного сигнала монитора.
Правильное ли изображение действительно правильно? А также, как получается, что фактическое освещение настолько выключено по сравнению с другими изображениями?
Результаты, которые вы получаете, это то, что и следовало ожидать.
Вы, кажется, путаете физическое радиометрическое излучение, создаваемое дисплеем, с воспринимается яркость человека. Последнее нелинейно, и простая гамма-модель — способ приблизить это. В основном монитор инвертирующий нелинейное преобразование человеческого глаза, так что стандартное (нелинейное) пространство RGB воспринимается линейно — при использовании интенсивности RGB 0,5 воспринимается примерно вдвое ярче, чем 1,0, и так далее.
Если бы вы отображали колориметр или спектрофотометр на дисплее при отображении уровней градации серого с гамма-коррекцией, вы бы фактически увидели, что шаг 0,73 будет показывать примерно 50% яркости уровня белого в канделах / м ^ 2 (при условии, что вы отображаете не слишком сильно отличается от модели sRGB, которая, между прочим, не использует гамму 2.2, но линейный сегмент в сочетании с гаммой 2.4 для остальных, 2.2 — это только другое приближение).
Теперь вопрос: чего именно вы хотите достичь? Работа в линейном цветовом пространстве обычно требуется, если вы хотите выполнять физически точные вычисления. Но тогда, источник света с 50% яркости другого не выглядит настолько наполовину ярким для человека, и результат, который вы получили, в основном, правильный.
Если вы хотите просто иметь цветовое пространство, которое является линейным по воспринимаемой яркости, вы можете полностью пропустить гамма-коррекцию, поскольку sRGB точно пытается это сделать. Вам может потребоваться некоторая калибровка цвета или небольшая гамма-коррекция для корректировки отклонений, вносимых вашим дисплеем, если вы хотите получить точные результаты.