Почему цвета не являются непрерывными (слоями) в моем примере игры с освещением?

#graphics #glsl #lighting

Вопрос:

Я тестирую библиотеку «Сокол» (https://github.com/floooh/sokol) для создания простого игрового образца с подсветкой в OpenGL, D3D11 и Metal. Я использую шейдеры, аналогичные учебникам LearnOpenGL (https://learnopengl.com/Lighting/Light-casters).

Это часть моего фрагментарного шейдера:

 vec3 lightDir = normalize(light.position - v_position);
float diff = max(dot(normal, lightDir), 0.0);
diffuse = vec3(1.0,1.0,1.0) * diff * vec3(texture(u_diffuse, v_uv)); 
 

Цвета в земле не являются непрерывными, вы можете видеть цветовые слои (посмотрите красные линии).

Красный свет в цветовых слоях

Вот еще один пример использования шейдеров PBR. Опять же, цвет в земле не является непрерывным.

Снова красный свет в цветовых слоях

Почему это происходит? Как я могу создать идеальную плоскую площадку?

Ответ №1:

«Полосы», которые вы видите, просто отличаются на 1 в одном из цветовых каналов. Вы только что достигли фактического предела точности цвета 8 бит на канал, между этими двумя полосами просто нет другого презентабельного цвета. В зависимости от используемого дисплея и настроек дисплея он будет более или менее заметен. Существует 3 возможных решения:

  • Эффекты особенно заметны, потому что ваш пол окрашен в один сплошной цвет. Человеческий глаз будет наиболее чувствителен к таким изменениям (см. Также эффект полосы Маха). Добавив к нему некоторую структуру / текстуру, он больше не будет восприниматься.
  • Используйте дисплей с точностью цветопередачи более 8 бит на канал. В настоящее время HDR-дисплеи допускают 10 или более бит.
  • Нанесите на изображение некоторое размытие, чтобы скрыть видимые полосы. Упорядоченное смешение с некоторым шаблоном байера может быть легко реализовано в шейдере GLSL.

Комментарии:

1. Спасибо за помощь, теперь я понимаю. Вы сказали использовать дисплей с 10 или более битами на chanel, но нужно ли мне также изменять свойство цвета буфера кадров? От RGB8 до чего-то вроде RGB16?

2. Что ж, это довольно сложная тема. Для включения вывода HDR обычно требуются некоторые API-интерфейсы для конкретной платформы (и, возможно, даже для конкретного драйвера), и, как правило, для буфера кадров вашего окна необходимо использовать формат с плавающей запятой, драйвер преобразует его в фактическую точность для конкретного используемого дисплея. Посмотрите, например, на эту презентацию nvidia