Я в процессе преобразования моего отложенного рендерера webgl в тот, который использует расширенный динамический диапазон. Я много читал на эту тему из различных источников в Интернете, и у меня есть несколько вопросов, которые, надеюсь, можно прояснить. Большая часть прочитанного мною касается рендеринга изображений HDR, но мои вопросы касаются того, как рендерер, возможно, придется изменить для поддержки HDR.
Насколько я понимаю, HDR, по сути, пытается захватить более высокие световые диапазоны, чтобы мы могли видеть детали как в очень освещенных, так и в темных сценах. Обычно в играх мы используем интенсивность 1 для представления белого света и 0 для черного. Но в HDR / реальном мире диапазоны гораздо более разнообразны. Т.е. Солнце в двигателе может быть в 10000 раз ярче, чем лампочка в 10 раз.
Чтобы справиться с этими большими диапазонами, вам необходимо преобразовать средство визуализации для использования целей визуализации с плавающей запятой (или, в идеале, половинных чисел с плавающей запятой, поскольку они используют меньше памяти) для его проходов света.
Мой первый вопрос по освещению. Помимо целей рендеринга с плавающей запятой, означает ли это, что если раньше у меня был свет, представляющий солнце с интенсивностью 1, то теперь он мог бы / должен быть представлен как 10000? Т.е.
float spec = calcSpec();
vec4 diff = texture2D( sampler, uv );
vec4 color = diff * max(0.0, dot( N, L )) * lightIntensity + spec; //Where lightIntensity is now 10000?
return color;
Есть ли какие-либо другие фундаментальные изменения в системе освещения (кроме плавающих текстур и более высоких диапазонов)?
Следуя этому, у нас теперь есть цель рендеринга с плавающей запятой, которая аддитивно накапливала все значения света (в более высоких диапазонах, как описано). На этом этапе я мог бы провести некоторую пост-обработку цели рендеринга с такими вещами, как bloom. После завершения его необходимо преобразовать в тональную карту, прежде чем его можно будет отправить на экран. Это связано с тем, что дальность света должна быть преобразована обратно в дальность действия наших мониторов.
Итак, для фазы тонального отображения я бы предположительно использовал пост-процесс, а затем, используя формулу тонального отображения, преобразовал освещение HDR в низкий динамический диапазон. Я выбрал технику Джона Хейблса из Uncharted 2:
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
const float W = 11.2;
vec3 Uncharted2Tonemap(vec3 x)
{
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
... // in main pixel shader
vec4 texColor = texture2D(lightSample, texCoord );
texColor *= 16; // Hardcoded Exposure Adjustment
float ExposureBias = 2.0;
vec3 curr = Uncharted2Tonemap( ExposureBias * texColor.xyz );
vec3 whiteScale = 1.0 / Uncharted2Tonemap(W);
vec3 color = curr * whiteScale;
// Gama correction
color.x = pow( color.x, 1.0 /2.2 );
color.y = pow( color.y, 1.0 /2.2 );
color.z = pow( color.z, 1.0 /2.2 );
return vec4( color, 1.0 );
Статья о тональном сопоставлении
Мой второй вопрос связан с этой фазой отображения тонов. Есть ли что-то большее, чем просто эта техника? Достаточно ли просто использовать более высокую интенсивность света и настроить экспозицию, чтобы считаться HDR - или это еще не все? Я понимаю, что в некоторых играх есть функция автоэкспозиции для определения средней люминесценции, но нужно ли это на самом базовом уровне? Предположительно можно просто вручную настроить экспозицию?
Во многих документах обсуждается еще кое-что, что касается гамма-коррекции. Кажется, что коррекция гаммы выполняется в двух областях. Сначала при считывании текстур, а затем еще раз, когда они отправляются на экран. Когда текстуры читаются, их нужно просто поменять на что-то вроде этого:
vec4 diff = pow( texture2D( sampler, uv), 2.2 );
Затем в вышеупомянутой технике тонального отображения коррекция вывода выполняется с помощью:
pow(color,1/2.2);
Из презентации Джона Хейблса он говорит, что не все текстуры нужно исправлять подобным образом. Диффузные текстуры должны быть, но такие вещи, как карты нормалей, не обязательно.
Мой третий вопрос касается этой коррекции гаммы. Это необходимо для работы? Означает ли это, что я должен менять свой движок во всех местах, где читаются диффузные карты?
Это мое текущее понимание того, что нужно для этого преобразования. Правильно ли это, и есть ли что-то, что я неправильно понял или ошибся?
GL_RGB10_A2
, если вы можете пожертвовать альфой (что часто имеет место при отложенном затенении). Существует аналогичный небольшой упакованный формат с плавающей запятой (GL_R11F_G11F_B10F
), который даст вам действительно хорошую производительность, если вы пожертвуете точностью в одном цветовом канале и исключите альфа-канал. Они обеспечат вам примерно такую же производительность на современном оборудовании, и обычно предпочтительнее использовать упакованный формат с плавающей запятой (черезGL_APPLE_texture_packed_float
в ES 2.0). - person Andon M. Coleman   schedule 14.01.2015