Tone mapping что это
Что такое Tone Mapping и как создать потрясающую фотографию HDR
Последнее обновление 11 ноября 2021 г. by Питер Вуд
Tone Mapping используется для изменения тональных значений пикселей в изображении, чтобы они последовательно переназначались на новые значения. Если вы хотите применить эффекты тонального отображения, набор инструментов HDR должен быть отличным выбором, который вы должны принять во внимание. Узнайте больше об этой концепции и о том, как применить фильтр, в этом посте.
Часть 1: Что такое Tone Mapping HDR
Перед изучением тональной карты вы должны понять некоторые ключевые концепции. Изображение состоит из пикселей, независимо от того, снято ли вы его цифровой камерой или смартфоном. Каждый пиксель имеет свой цвет, в том числе черный и белый. Для определения этих цветов, которые обычно используют систему RGB, например 255, 0, 0. Три значения указывают количество красного, зеленого и синего цветов для получения цвета для пикселя. Эта система также известна как цветовые каналы в фоторедакторах.
Согласно метаданным, тональное отображение адаптирует цифровые сигналы к соответствующим уровням освещенности. Этот процесс не просто применяет функцию электрооптической передачи к изображению, но пытается использовать информацию метаданных для сопоставления данных изображения.
Когда дело доходит до создания изображения HDR, вы выбираете диапазон яркости, выходящий за рамки того, что может захватывать стандартная 16-битная цифровая камера, например 32-битная. Но такой файл нельзя отобразить на обычном дисплее. В таких случаях требуется, чтобы процесс превратил его в файл изображения, который можно отобразить. Вот тут-то и приходит на помощь Tone Mapping.
С другой стороны, сегодня на рынке доступен широкий спектр устройств отображения. У каждого из них своя яркость и цветовая гамма. Это делает правильное отображение тонов необходимым для отличного просмотра.
Часть 2: 2 метода тонального отображения HDR
Вообще говоря, существует два типа алгоритмов тонального отображения:
Местные операторы
Местные операторы обращают внимание на положение пикселя в светлых или темных областях для каждого изображения. Затем пиксели обрабатываются на основе их пространственных характеристик, и в результате из них извлекаются детали. Таким образом, изображение становится более доступным для нашего глаза и имеет больше деталей. Обратной стороной является то, что обработка занимает больше времени.
Для реализации локального алгоритма тонального отображения необходимо выполнить следующие шаги:
Глобальные операторы
Для глобальных операторов каждый пиксель отображается в соответствии с глобальными характеристиками, независимо от того, в какое место на изображении он попадает. Это означает, что пиксели в светлой или темной части будут проигнорированы. По сравнению с местными операторами этот метод более быстрый. Однако стоимость плоского изображения.
Часть 3: Советы по настройке тонов при съемке и редактировании
Советы по настройке тонов при съемке
Советы по наложению тонов для редактирования
Часть 4: Как применить Tone Mapping HDR
Шаг 1. После того, как вы установили WidsMob HDR, вы можете запустить программу на своем компьютере. Перейти к Файл и выберите Импортировать и добавьте серию изображений с разделением на 3 сегмента, чтобы применить эффекты преобразования тонов.
Шаг 2: Он объединит фотографии в фотографию HDR. Вы можете настроить параметры, например Длина тона, Насыщенность тона, яркость, Подавление призраков, и многое другое, чтобы соответственно получить желаемое фото.
Шаг 3: нажмите Сохраните кнопку, чтобы вызвать диалог сохранения. Затем установите имя файла, формат вывода и другие параметры и экспортируйте изображение на жесткий диск. Нажми на Поделиться кнопку, чтобы поделиться изображением напрямую.
Часть 5: Часто задаваемые вопросы о Tone Mapping HDR
Это название
В качестве метода постобработки сжатие тона устанавливает правильный тон по всему изображению. Этот процесс в фотографии HDR создает базовое изображение, из которого вы можете вносить другие изменения. Он применит большую насыщенность к сжатию тона, чтобы яркое изображение было более реалистичным.
Перейдите в Параметры приложение, вы можете нажать на камера значок и включите Авто HDR вариант. После этого вы можете вернуться в приложение «Камера» и найти опцию HDR в верхней части экрана. После этого вы можете делать фотографии с помощью камеры iPhone с эффектами тонального отображения.
Даже самая лучшая цифровая камера будет видеть только в одном динамическом диапазоне. Датчики камеры улучшаются, но они не видят то, что видят глаза. HDR-фотография имитирует то, что вы видите своими глазами. Это достигается путем объединения более чем одной фотографии. Эти фотографии будут иметь разную экспозицию.
Заключение
Основываясь на вышеизложенном, вы должны понимать, что такое Tone Mapping, когда вам нужно изучить фильтр и многое другое. Он связан с двумя сторонами: вашими изображениями и устройством, на котором они отображаются. Чтобы получить идеальные впечатления от просмотра, необходимо использовать тональное отображение. Он позволяет вам регулировать яркость и цвет каждого изображения перед его отображением на целевом устройстве, чтобы вы могли получить наилучшее представление. Более того, вы также можете использовать WidsMob HDR для применения желаемых эффектов.
Learn OpenGL. Урок 5.7 — HDR
При записи во фреймбуфер значения яркости цветов приводятся к интервалу от 0.0 до 1.0. Из-за этой, на первый вгляд безобидной, особенности нам всегда приходится выбирать такие значения для освещения и цветов, чтобы они вписывались в это ограничение. Такой подход работает и даёт достойные результаты, но что случится, если мы встретим особенно яркую область с большим количеством ярких источников света, и суммарная яркость превысит 1.0? В результате все значения, большие чем 1.0, будут приведены к 1.0, что выглядит не очень красиво:
Так как для большого количества фрагментов цветовые значения приведены к 1.0, получаются большие области изображения, залитые одним и тем же белым цветом, теряется значительное количество деталей изображения, и само изображение начинает выглядеть неестественно.
Решением данной проблемы может быть снижение яркости источников света, чтобы на сцене не было фрагментов ярче 1.0: это не лучшее решение, вынуждающее использовать нереалистичные значения освещения. Лучший подход заключается в том, чтобы разрешить значениям яркости временно превышать яркость 1.0 и на финальном шаге изменить цвета так, чтобы яркость вернулась к диапазону от 0.0 до 1.0, но без потери деталей изображения.
Дисплей компьютера способен показывать цвета с яркостью в диапазоне от 0.0 до 1.0, но у нас нет такого ограничения при расчёте освещения. Разрешая цветам фрагмента быть ярче единицы, мы получаем намного более высокий диапазон яркости для работы — HDR (high dynamic range). С использованием hdr яркие вещи выглядят яркими, тёмные вещи могут быть реально тёмными, и при этом мы будем видеть детали.
Часть 2. Базовое освещение
Часть 3. Загрузка 3D-моделей
Часть 4. Продвинутые возможности OpenGL
Часть 5. Продвинутое освещение
Изначально высокий динамический диапазон использовался в фотографии: фотограф делал несколько одинаковых фотографий сцены с различной экспозицией, захватывая цвета почти любой яркости. Комбинация этих фотографий формирует hdr изображение, в котором становится различимым большинство деталей за счёт сведения изображений с разными уронями экспозиции. Например, ниже на левом изображении хорошо видны сильно освещённые фрагменты изображения (посмотрите на окно), но эти детали пропадают при использовании высокой экспозиции. Однако, высокая экспозиция делает различимымидетали на тёмных областях изображения, которые до этого не были видны.
Это похоже на то, как работает человеческий глаз. При недостатке света глаз приспосабливается, так что тёмные детали становятся хорошо различимыми, и аналогично для ярких областей. Можно сказать, что человеческий глаз имеет автоматическу настройку экспозиции, зависящую от яркости сцены.
HDR рендеринг работает примерно так же. Мы разрешаем при рендере использовать большой диапазон значений яркости, чтобы собрать информацию и о ярких, и о тёмных деталях сцены, и в конце мы преобразуем значения из диапазона HDR обратно в LDR (low dynamic range, диапазон от 0 до 1). Это преобразование называется тональной компрессией (tone mapping), существует большое количество алгоритмов, нацеленных на сохранение большинства деталей изображения при конвертации в LDR. Эти алгоритмы часто имеют параметр экспозиции, который позволяет лучше показывать яркие или тёмные области изображения.
Использование HDR при рендеринге позволят нам не только превышать LDR диапазон от 0 до 1 и сохранять больше деталей изображения, но также даёт возможность указывать реальную яркость источников света. Например, солнце имеет намного большую яркость света, чем что-нибудь типа фонарика, так почему бы не настроить солнце таким (например, присвоить ему яркость 10.0)? Это позволит нам лучше настроить освещение сцены с более реалистичными параметрами яркости, что было бы невозможно при LDR рендеринге и диапазоне яркости от 0 до 1.
Так как дисплей показывают яркость только от 0 до 1, мы вынуждены конвертировать используемый HDR диапазон значений обратно к диапазону монитора. Просто отмасштабировать диапазон не будет хорошим решением, так как на изображении начнут преобладать яркие области. Однако мы можем использовать различные уравнения или кривые для преобразования значений HDR в LDR, что даст нам полный контроль над яркостью сцены. Этот преобразование называется тональной компрессией (tone mapping) и являетя финальным шагом HDR рендеринга.
Фреймбуферы с плавающей точкой
Для реализации HDR рендеринга нам нужен способ, чтобы предотвратить приведение значений к диапазону от 0 до 1 результатов работы фрагментного шейдера. Если фреймбуфер использует нормализованный формат с фиксированной точкой (GL_RGB) для буферов цвета, то OpenGL автоматически ограничнивает значения перед сохранением во фреймбуфер. Это ограничние применяется для большинства форматов фреймбуфера, кроме форматов с плавающей точкой.
Создание floating point буфера отличается от обычного буфера только тем, что в нём используется другой внутренний формат:
Если к фреймбуферу присоединён floating point буфер для цвета, мы можем рендерить сцену в него с учётом того, что значения цвета не будут ограничены диапазоном от 0 до 1. В коде к данной статье мы сначала рендерим сцену в floating point фреймбуфер и после этого выводим содержимое буфера цвета на полкоэкранный прямоугольник. Это выглядит примерно так:
Здесь значения цвета, содержащиеся в буфере цвета, могут быть больше 1. Для этой статьи была создана сцена с большим вытянутым кубом, выглядящим как туннель с четырьмя точечными источниками света, один из них расположен в конце туннеля и обладает огромной яркостью.
Рендеринг в floating point буфер точно такой же, как если бы мы рендерили сцену в обычный фреймбуфер. Новым является только фрагментный hdr шейдер, который занимается простой закраской полноэкранного прямоугольника значениями из текстуры, являющейся буфером цвета с плавающей точкой. Для начала напишем простой шейдер, передающий входные данные без изменений:
Мы берём входные данные из floating point буфера цвета и используем их в качестве выходных значений шейдера. Однако, так как 2д прямоугольник рендерится в фреймбуфер по-умолчанию, выходные значения шейдера будут ограничены интервалом от 0 до 1, не смотря на то, что в некоторых местах значения больше 1.
Становится очевидным, что слишком большие значения цвета в конце туннеля ограничены единицей, так как значительная часть изображения полностью белая, и мы теряем детали изображения, которые ярче единицы. Так как мы используем HDR значения напрямую в качестве LDR, это эквивалентно отсутствию HDR. Чтобы исправить это, мы должны отобразить различные значения цветов обратно в диапазон от 0 до 1 без потери каких-либо деталей изображения. Для этого применим тональную компрессию.
Тональная компрессия
Тональная компрессия — преобразование значений цвета, чтобы уместить их в диапазоне от 0 до 1 без потери деталей изображения, часто в сочетании с приданием изображению желаемого баланса белого.
Самый простой алгоритм тональной компрессии известен как алгоритм Рейнхарда (Reinhard tone mapping). Он отображает любые HDR значения в LDR диапазаон. Добавим этот алгоритм в предыдущий фрагментный шейдер, а так же применим гамма-коррекцию (и использование SRGB текстур).
Прим. пер. — при малых значениях х функция x/(1+x) ведёт себя примерно как х, при больших х — стремится к единице. График функции:
С тональной компрессией Рейнхарда мы больше не теряем деталей в ярких областях изображения. Алгоритм отдаёт предпочтение ярким областям, делая тёмные области менее отчётливыми.
Здесь вы снова можете видеть такие детали в конце изображения, как текстура дерева. С этим относительно простым алгоритмом мы хорошо видим любые цвета из HDR диапазона и можем контролировать освещение сцены без потери деталей изображения.
Стоит отметить, что мы можем использовать тональную компрессию напрямую в конце нашего шейдера для рассчёта освещения, и тогда нам вообще не понадобится floating point фреймбуфер. Однако, на более сложных сценах вы часто будете встречаться с необходимостью хранить промежуточные HDR значения в floating point буферах, так что это вам пригодится.
Ещё одной интересной возможностью тоновой компрессии является использование параметра экспозиции. Возможно, вы помните, что на изображениях в начале статьи различные детали были видны при разных значениях экспозиции. Если мы имеем сцену, на которой сменяются день и ночь, имеет смысл использовать низкую экспозицию днём и высокую ночью, что схоже с адаптацией человеческого глаза. С таким параметром экспозиции мы сможем настраивать параметры освещения, которые будут работать и днём и ночью при разных условиях освещения.
Относительно простой алгоритм тональной компрессии с экспозицией выглядит так:
Прим. пер: добавлю график и для этой функции c экспозицией 1 и 2:
Здесь мы определили переменную для экспозиции, которая по умолчанию равна 1 и позволяет нам более точно выбрать баланс между качеством отображения тёмных и ярких областей изображения. Например, с большой экспозицией мы видим значительно больше подробностей на тёмных областях изображения. И наоборот, малая экспозиция делает неразличимыми тёмные области, но позволяет лучше увидеть яркие области изображения. Ниже приведены изображения туннеля с различными уровнями экспозиции.
Эти изображения явно показывают преимущества hdr рендеринга. При изменении уровня экспозиции мы видим больше деталей сцены, которые были бы потеряны при обычном рендеринге. Возьмите для примера конец туннеля — с нормальной экспозицией текстура дерева едва видна, но при низкой экспозиции текстуру превосходно видно. Аналогично, при высокой экспозиции очень хорошо видны детали в тёмных областях.
Исходный код для демо здесь
Больше HDR
Те два алгоритма тоновой компрессии, которые были показаны, являются лишь малой частью среди большого количества более продвинутых алгоритмов, каждый из которых имеет свои сильные и слабые стороны. Некоторые алгоритмы лучше подчёркивают определённые цвета/яркости, некоторые алгоритмы показывают одновременно тёмные и яркие области, выдавая более красочные и детализированные изображения. Так же существует множество способов, известных как автоматичесий выбор экспозиции (automatic exposure adjustment) или адаптация глаз (eye adaptation). В них определяется яркость сцены на предыдущем кадре и (медленно) изменяется параметр экспозиции, так что тёмная сцена потихоньку становится ярче, а яркая — темнее: схоже с привыканием человеческого глаза.
Реальные преимущества HDR становятся лучше всего видны на больших и сложных сценах с серьёзными алгоритмами освещения. В целях обучения в данной статье использовалась максимально простая сцена, так как создание большой сцены может быть сложным. Несмотря на простоту сцены, на ней видны некоторые преимущества hdr рендеринга: в тёмных и светлых областях изображения не теряются детали, так как они сохраняются при помощи тоновой компрессии, добавление множественных источников света не приводит к появлению белых областей, и значения не обязаны умещаться в LDR диапазон.
Более того, HDR рендеринг также делает некоторые интересные эффекты более правдоподобными и реалистичными. Одним из таких эффектов является блум (bloom), который мы обсудим в следующей статье.
HDR vs LDR, реализация HDR Rendering
Как я и обещал – публикую вторую статью о некоторых моментах разработки игр в трех измерениях. Сегодня расскажу об одной технике, которая используется почти любом проекте ААА-класса. Имя ей — HDR Rendering. Если интересно — добро пожаловать под хабракат.
Взять, например, Crysis 2:
В этих двух скриншотах нет никакого DirextX10 и DirectX11. Так отчего люди думают, что делать что-то на XNA — заниматься некрофилией? Да, Microsoft перестала поддерживать XNA, но запаса того, что там есть — хватит на 3 года точно. Более того, сейчас существует monogame, он опенсорсный, кроссплатформенный (win, unix, mac, android, ios, etc) и сохраняет всю ту же архитектуру XNA. Кстати, FeZ из прошлой статьи написан с использованием monogame. Ну и напоследок — статьи направленные в целом то на компьютерную графику в трех измерениях (все эти положения справедливы и для OpenGL, и для DirectX), а не XNA — как можно подумать. XNA в нашем случае всего-лишь инструмент.
Ладно, поехали
Обычно в играх используется LDR (Low Dynamic Range) рендеринг. Это означает, что цвет бэк-буфера ограничен в пределах 0…1. Где на каждый канал уделяется по 8 бит, а это 256 градаций. К примеру: 255, 255, 255 — белый цвет, все три канала (RGB) равны максимальной градации. Понятие LDR несправедливо применять к понятию реалистичного рендеринга, т.к. в реальном мире цвет задается далеко не нулем и единицей. На помощь к нам приходит такая технология, как HDRR. Для начала, что такое HDR? High Dynamic Range Rendering, иногда просто «High Dynamic Range» — графический эффект, применяемый в компьютерных играх для более выразительного рендеринга изображения при контрастном освещении сцены. В чем заключается суть этого подхода? В том, что мы рисуем нашу геометрию (и освещение) не ограничиваясь нулем и единицей: один источник света может дать яркость пикселя в 0.5 единиц, а другой в 100 единиц. Но как можно заметить на первый взгляд, наш экран воспроизводит как раз тот самый LDR формат. И если мы все значения цвета бэк-буфера разделим на максимальную яркость в сцене — получится тот же LDR, а источник света в 0.5 единиц почти не будет виден на фоне второго. И как раз для этого был придуман особый метод называемый Tone Mapping. Суть этого подхода, что мы приводим динамический диапазон к LDR в зависимости от средней яркости сцены. И для того, чтобы понять о чем я, рассмотрим сцену: две комнаты, одна комната indoor, другая outdoor. Первая комната — имеет искусственный источник света, вторая комната — имеет источник света в виде солнца. Яркость солнца на порядок выше, чем яркость искусственного источника света. И в реальном мире, при нахождении в первой комнате — мы адаптируемся к этому освещению, при входе в другую комнату мы адаптируемся к другому уровню освещения. При взгляде из первой комнаты во вторую — она будет казаться нам чрезмерно яркой, а при взгляде из второй в первую — черной.
Еще один пример: одна outdoor комната. В этой комнате — есть само солнце и рассеянный свет от солнца. Яркость солнца на порядок выше, чем его рассеянный свет. В случае LDR значения яркости света были бы равны. Поэтому, используя HDR можно добиться реалистичных бликов с различных поверхностей. Это очень заметно на воде:
Или на бликах с сурфейса:
Ну и контрастность сцены в целом (слева HDR, справа LDR):
Вместе с HDR принято применять и технологию Bloom, яркие области размываются и накладываются поверх основного изображения:
Это делает освещение еще мягче.
Так же, в виде бонуса — расскажу про Color Grading. Этот поход повсеместно применяется в играх ААА-класса.
Color Grading
Очень часто в играх сцена должна иметь свой цветовой тон, этот цветовой тон может быть общим как для всей игры, так и для отдельных участков сцены. И чтобы каждый раз не иметь по сто шейдеров-постпроцессоров — используют подход Color Grading. В чем суть этого подхода?
Знаменитые буквы RGB — цветовое трехмерное пространство, где каждый канал это своеобразная координата. В случае формата R8G8B8: 255 градаций на каждый канал. Так вот, что будет, если мы применим обычные операции обработки (например, кривые или контрастность) к этому пространству? Наше пространство изменится и в будущем мы можем назначить любому пикселю — пиксель из этого пространства.
Создадим простое RGB пространство (хочу заменить, что берем мы каждый 8-ой пиксель, т.к. если будем брать все 256 градаций, то размер текстуры будет очень большим):
Это трехмерная текстура, где на каждую ось — свой канал.
И возьмем какую-нибудь сцену, которую нужно модифицировать (добавив при этом на изображение наше пространство):
Проводим нужные нам трансформации (на глаз):
И извлекаем наше модифицируемое пространство:
Теперь, по этому пространству — мы можем применить все модификации с цветом к любому изображению. Просто сопоставляя оригинальный цвет с измененным пространством цвета.
Реализация
Ну и кратко по реализации HDR в XNA. В XNA формат бэк-буфера задается (в основном) R8G8B8A8, т.к. рендеринг прямо на экран не может поддерживать HDR априори. Для этого обхода — нам нужно создать новый RenderTarget (ранее я описывал работу онных тут) с особым форматом: HalfVector4*. Этот формат поддерживает плавающие значения у RenderTarget.
* — в XNA есть такой формат — как HDRBlendable, это все тот же HalfVector4 — но сам RT занимает меньше места (т.к. на альфа канал нам не нужен floating-point).
Заведем нужный RenderTarget:
Создаем новый RT с размерами бэк-буфера (разрешением экрана) с отключенным mipmap (т.к. эта текстура будет рисоваться на экранном кваде) с форматом сурфейса — HdrBlendable (или HalfVector4) и 24-ех битным буфером глубины / стенсил-буферов 8 бит. Так же отключим multisampling.
У этого RenderTarget важно включить буфер глубины (в отличии от обычного post-process RT), т.к. мы будем рисовать туда нашу геометрию.
Далее — все как в LDR, мы рисуем сцену, только теперь не нужно ограничиваться рисованием яркости [0. 1].
Добавим skybox с номинальной яркостью умноженной на три и классический чайник Юта с DirectionalLight-освещением и Reflective-поверхностью.
Сцена создана и теперь нам нужно как-нибудь формат HDR привести к LDR. Возьмем самый простой ToneMapping — разделим все эти величины на условное значение max.
Покрутим камерой и поймем, что сцена все равно обладает статичностью и подобную картинку можно с легкостью добиться, применив контрастность к изображению.
В реальной же жизни — наш глаз адаптируется к нужному освещению: в плохо освещенной комнате мы все равно видим, но до тех пор, пока перед нашими глазами нет яркого источника света. Это называется световой адаптацией. И самое крутое то, что HDR и цветовая адаптация идеально сочетается друг с другом.
Теперь нам нужно вычислить среднее значение цвета на экране. Это довольно проблематично, т.к. формат с плавающим значением не поддерживает фильтрацию. Поступим следующим образом: создадим N-ое кол-во RT, где каждый следующий меньше предыдущего:
И будем рисовать каждый предыдущий RT в следующий RT применяя некоторое размытие. После этих циклов у нас получится текстура 1×1, которая собственно и будет содержать средний цвет.
Если это все сейчас запустить, то цветовая адаптация действительно будет, но она будет моментальной, а так не бывает. Нам нужно, чтобы при взгляде с резко темной области на резко светлую — сначала чувствовали слепоту (в виде повышенной яркости), а затем все приходило в норму. Для этого достаточно завести еще один RT 1×1, который и будет отвечать за текущее значение адаптации, при этом, каждый кадр мы приближаем текущую адаптацию к рассчитанному в данный момент цвету. Причем, значение этого приближения должно быть завязано на все том же gameTime.ElapsedGameTime, чтобы кол-во FPS не влияло на скорость адаптации.
Ну и теперь в качестве параметра max для _toneSimple можно передавать наш средний цвет.
Существует масса формул ToneMapping‘a, вот некоторые из них:
Я же использую собственную формулу:
Ну и следующий этап это Bloom (частично я его описывал тут) и Color Grading:
Использование Color Grading:
Любое цветовое значение пикселя (RGB) после ToneMapping‘a лежит в пределах от 0 до 1. Наше цветовое пространство Color Grading тоже условно лежит в пределах от 0 до 1. Поэтому, мы можем заменить текущее значение цвета пикселя на цвет пикселя в цветовом пространстве. При этом, фильтрация сэмплера произведет линейное интерполирование между нашими 32 значениями на карте Color Grading. Т.е. мы «как-бы»
подменяем эталонное цветовое пространство — нашим измененным.
Для Color Grading нужно ввести следующую функцию:
где ColorGradingSampler — трехмерный сэмплер.
Ну и LDR/HDR сравнение:
LDR:
HDR:
Заключение
Этот простой подход — одна из фишек 3D AAA-игр. И как видите — реализован он может быть и на старом-добром DirectX9c, причем реализация в DirectX10+ принципиально ничем отличатся. Больше информации вы найдете в исходниках.
Так же стоит отличать друг от друга HDRI (используется в фотографии) и HDRR (используется в рендеринге).