HDR, экспозиция и сохранение ярких деталей
Различия HDR, sRGB и экспозиции; сохранение EXR без потери ярких значений.
HDR-рендеринг сохраняет значения света выше 1 на промежуточных этапах расчёта. Это позволяет различать яркие поверхности до экспозиции и тонального преобразования. HDR не означает бесконечную точность, наличие HDR-монитора или автоматический фотореализм.
Разделяйте три операции
| Операция | Для чего нужна | Чего не делает |
|---|---|---|
| sRGB → linear | Декодирует цвет перед расчётом освещения. Значение sRGB 0.5 соответствует примерно 0.214 в линейном пространстве. | Не сжимает яркие блики в диапазон дисплея. |
| Экспозиция и тональное преобразование | Настраивают яркость сцены и отображают её значения в нужном диапазоне вывода. | Не восстанавливают детали, уже потерянные в текстуре или изображении. |
| Вывод на HDR-дисплей | Передаёт подходящий сигнал через поддерживаемую конфигурацию ОС и графического бэкенда. | Не превращает обычный PNG или 8-битный буфер в исходные HDR-данные. |
Преобразование linear → sRGB само по себе не является тональным преобразованием: входное значение 4 после него остаётся выше 1. Эти операции не добавляют недостающие детали поверхности, правильные нормали, тени и отражения.
Настройте 3D-сцену
- Добавьте Entity
WorldEnvironmentи назначьте ресурсEnvironment. Перед изменением проверьте, не переопределяет ли активнаяCamera3Dокружение собственным ресурсом. - Выберите алгоритм в разделе Tonemap ресурса Environment. Сравнивайте кривые на одной камере и сцене: они меняют контраст и цвет светлых участков, а не только яркость.
- На время настройки источников зафиксируйте экспозицию. В коде
Environment.TonemapExposure— множитель, а не число ступеней EV. Значение2удваивает входную яркость;0.5уменьшает вдвое. - Если назначены атрибуты камеры, проверьте их множитель экспозиции и автоэкспозицию. Для сравнения двух вариантов света отключите автоматическую адаптацию: иначе камера может компенсировать изменение.
- Проверьте кадр на целевом рендерере и с нужным режимом вывода. Эффекты рендерера и поддержка HDR-дисплея — разные возможности; одинаковый результат на всех устройствах не гарантирован.
Управление окружением описано в статье Окружение и постобработка, вывод на дисплей — в HDR-выводе. Общего шага «включите оба переключателя sRGB» в этом процессе нет.
Различайте цветовые текстуры и текстуры данных
Albedo/base color обычно содержит закодированный цвет. В собственном spatial-шейдере помечайте соответствующий цветовой семплер через source_color, чтобы рендерер интерпретировал его как цвет. Карты нормалей, шероховатости, металличности и маски содержат данные: не применяйте цветовое преобразование только потому, что они хранятся в файле изображения. Используйте подходящий слот материала или подсказку шейдера для каждой карты.
Не вызывайте SrgbToLinear() вручную для значения, которое уже декодировал материал или шейдер: повторное преобразование затемняет результат. В свою очередь, CPU-метод Image.GetPixel() читает сохранённые значения пикселя, не выполняя семплирование материала и расчёт света. Float-формат Image определяет точность хранения, но не цветовое пространство содержимого.
Сохраните HDR-данные без незаметного обрезания
Для CPU-изображения со значениями выше 1 используйте float-формат, например Image.Format.Rgbaf. Следующий класс записывает однопиксельное тестовое изображение с RGB (4, 2, 0.25) в EXR. Это пример работы с данными файла, не рендер сцены и не снимок viewport.
using Reckfell;
public static class HdrData
{
// CPU image data, not a viewport capture or a display-ready screenshot.
public static Image CreateSample()
{
var image = Image.CreateEmpty(1, 1, false, Image.Format.Rgbaf);
image.SetPixel(0, 0, new Color(4f, 2f, 0.25f, 1f));
return image;
}
public static Error SaveSample(string path)
{
using var image = CreateSample();
return image.SaveExr(path, grayscale: false,
colorImage: false, maxLinearValue: -1f);
}
}Вызовите HdrData.SaveSample("user://hdr-data.exr") и проверьте возвращённый Error перед использованием файла. Загрузите его через Image.LoadFromFile(), чтобы прочитать значения. На проверенном Windows-runtime EXR сохраняет (4, 2, 0.25), а SavePng() для того же Image обрезает первые два канала до 1. Сохранение PNG не применяет автоматически преобразование sRGB для подготовки произвольных линейных данных к показу на дисплее.
Параметры EXR в 1.0.0 означают следующее:
colorImage: falseсохраняет отрицательные float-значения.trueобрезает отрицательные значения каналов до нуля; это не преобразование sRGB и не тональное преобразование.maxLinearValue: -1fотключает верхнее ограничение. Неотрицательное значение ограничивает записываемые каналы указанным максимумом; это не настройка экспозиции.grayscale: trueобозначает одноканальное изображение как яркостное. RGB-изображение от этого не становится чёрно-белым.
Запись поддерживает несжатые R/RG/RGB/RGBA форматы с 8-битными, half-float и float-каналами. Сохранение 8-битного источника в EXR не возвращает потерянные значения и точность. Сборка без EXR-кодека возвращает Error.Unavailable; ошибки файла и формата тоже требуют проверки результата. Наличие кодека проверяйте в реальной экспортированной сборке.
Осознанно снимайте кадр viewport
Перед чтением Viewport.GetTexture().GetImage() дождитесь RenderingServer.FramePostDraw: в _Ready() кадр может быть старым или пустым. Затем проверьте формат полученного Image и путь рендеринга, который его сформировал. Сам по себе float-формат не доказывает, что перед вами исходный буфер сцены до тонального преобразования.
Переименование снимка в .exr, перевод 8-битного Image во float и вызов SaveExr() после обрезания светлых участков не восстанавливают исходное освещение. Опция HDR 2D относится к собственному линейному HDR-пути viewport, а не служит универсальным переключателем захвата исходного 3D-буфера.
Найдите причину видимого дефекта
| Симптом | Что проверить сначала |
|---|---|
| Светильники или окна белые, детали пропали | Сравните с меньшей фиксированной экспозицией; проверьте обрезание исходной текстуры и тональную кривую. EXR не исправляет уже обрезанный источник. |
| Изображение слишком тёмное или выцветшее | Проверьте назначение цветовых текстур и данных, повторное или пропущенное преобразование цвета. |
| Яркость меняется при движении камеры | Проверьте автоэкспозицию перед изменением всех источников света. |
| Изменение Environment не влияет на кадр | Проверьте активную камеру, её переопределение окружения и WorldEnvironment этого viewport. |
| Снимок чёрный или старый | Дождитесь завершения кадра и убедитесь, что viewport действительно рендерится. |
| Свет проходит через стену или потолок | Проверьте геометрию, нормали, отбрасывание и настройки теней. Тональное преобразование не исправляет отсутствие перекрытия света. |
Сопутствующая проверка выполняет преобразования цвета и CPU-цикл записи/чтения EXR/PNG в установленном Windows-редакторе. Она не подтверждает GPU-кривые, физическую экспозицию, HDR-монитор, кодеки экспортированной игры и визуальное качество на других платформах.