Pull to refresh

Comments 23

E7500, 4Gb DDR2, ATI Radeon 4850 512Mb, Win7 x64 Ult
не запустилась демка
Первый раз увидел саму суть создания карты нормалей.
Еще в таком же изложении про другие виды карт для освещения, можешь написать?
У меня не так много времени, но если оно у меня будет, то я обязательно напишу еще ряд статей.
Спасибо!
В целом графика интересна, в частности на xna, ибо проще чем Dx, но то сил, то времени нету, что бы сесть и разобраться, хотя бы ради интереса, а благодаря таким вот статьям немножко познаю область.

Кстати, еще было бы неплохо написать про bmp карту, глубина цвета в которой потом превращается в высоту ландшафта, если такое есть на xna — не знаю :(
И про постпроцессинги тоже интересно!
Постпроцессинг я описывал в прошлой статье :)
Эта карта называется картой высот. В ней белые области означают возвышенность. Т.е. по сути это карта задает высоты в пределах от 0 до 255. Сэмплируем пиксель, применяем масштаб и на выходе получаем высоту для точки ландшафта. Относительно сложным здесь является как раз сэмплирование. Тут надо масштабировать карту под размеры ландшафта (интерполяция). Это все относится больше к обработке изображений.
Да тут не много вариантов, добавляется еще specular map обычно. Черно-белая текстура (обычно низкого разрешения, а как вариант — хранить в альфа-канале normal map), белые области которой говорят о том, что поверхность хорошо отражает свет, а черные — наоборот. Так можно определить где на текстуре металлические части, которые хорошо отражают свет, а где более матовые.
Не совсем так — спекуляр управляется двумя параметрами — яркость блика и размер блика.
На матовой хорошо отражающей поверхности будет яркий блик большого размера, на темном металле — блик будет тусклый и небольшой. Но на светлом металле блик будет небольшой, но яркий.

Поэтому либо нужны два вспомогательных канала для спекуляра (если мы используем deferred shading с g-буфером из трех текстур — можно использовать альфу диффуза и альфу нормалей), либо, если у нас нет двух «лишних» каналов — строим индекс материалов и храним в свободном канале число, по которому шейдер сможет понять, какой набор параметров использовать. Например, в движке X-Ray (который в S.T.A.L.K.E.R.'е) использовался второй подход.
Интересно очень, а можно по подробней про индекс материала? Как оно реализуется в общем виде?
есть texture lookup, т.е. текстура с определенно подобранным форматом. Я их точно все не помню, но здесь, к примеру, будет достаточно RG. В R будет храниться яркость бликов, а в G — экспонента. Индекс материала — это просто текстурные координаты. С помощью интерполирования можно добиться разных вариантов. Кажется в сталкере именно так и было сделано. Вот, кстати, статья: http.developer.nvidia.com/GPUGems2/gpugems2_chapter09.html
Спасибо, жаль плюсануть не могу ))
Это все, разумеется, интересно и познавательно, но описанная техника не имеет никакого отношения к deferred lighting :)

Суть всех deferred-техник в разделении отрисовки на отрисовку вначале только данных геометрии, а затем — наложении освещения на отрисованную геометрию.

Поясню поподробнее.
1. На первом этапе мы отрисовываем в отдельные текстуры информацию о нормалях в каждой точке экрана и о глубине в каждой точке экрана.
Мы получаем карту глубины:
image
и карту нормалей:
image
2. На втором этапе мы, пользуясь данными из этих текстур, восстанавливаем положение точки пространства в каждом пикселе экрана, а также нормаль. Зная нормаль и координаты точки в мировом пространстве — не составляет труда посчитать освещенность этой точки. Одновременно с этим мы можем наложить теневую карту, если хотим стоить тени. Таким образом, пройдясь по всем источникам света, мы получаем карту освещения:
image
3. Мы объединяем карту освещения с неосвещенной геометрией:
image
И в итоге получаем готовую картинку:
image

Чем хороша такая техника?
Тем, что освещение в каждом пикселе считается единожды. Вся невидимая геометрия отсекается на этапе построения буфера геометрии. Если бы мы использовали обычный forward lighting — пришлось бы для каждого источника света заново отрисовывать каждый объект. Если источников света много — видеокарточка просто захлебнется.
Поэтому, используя deferred-технику, можно отрисовывать в каждом кадре дикое число источников света (тысячи) с человеческой производительностью. А столько источников света позволяют получить сложные визуальные эффекты — как пример, таким образом можно реализовать непрямое освещение.

Чем же плоха такая техника?
1. Повышаются требования к пропускной способности видеопамяти, т.к. нам теперь приходится, в нагрузку к всему прочему, еще и текстуры буфера геометрии, а они достаточно большие, т.к. по размеру равны размеру экрана.
2. Как несложно понять — deferred-техники фактически вычисляют освещение некой сплошной поверхности. Т.е. если у нас некоторые объекты полупрозрачны — мы не сможем их отрисовать, потому что нам потребуется считать в одном и том же пикселе сразу две освещенности: для полупрозрачного объекта, и для того объекта, который находится за ним. А если у нас за одним полупрозрачным объектом находится еще один полупрозрачный… Этот недостаток обходится, но…
3. В реальности карты нормалей и карты глубины не хватает — нужна еще карта материалов. Дело в том, что на соседних пикселях могут находится объекты с совершенно разными материалами — один, к примеру, блестящий металлический, а другой — матовый пластиковый. И чтобы мы могли корректно вычислить освещенность — нам придется хранить дополнительную карту, считывать в шейдере ее значение и в зависимости от него использовать разные формулы.

Приведу примеры игр с deferred shading и deferred lighting: S.T.A.L.K.E.R. (только в режиме динамического освещения), Crysis 2 (в первом Crysis освещение было прямым), Метро 2033. Список, разумеется, неполный :)

А в данной статье, по факту, рассматривается обычный forward shading с простейшей оптимизацией — просчет более одного источника света за проход (кстати говоря, движок Crysis использовал именно такую технику).

Автору: статья-то хорошая, но озаглавлена некорректно :) Ждем новой статьи, тем более что поднятая тема весьма любопытна для многих, я уверен :)
Спасибо за столь развернутый комментарий!
Все правильно, но на самом деле все тоже самое. Только здесь геометрия плоская, а принцип такой же. Рисуем все спрайты в две текстуры (на самом деле можно воспользоваться одной). Т.к. геометрия плоская, то нам не нужна глубина пикселей. В самом примере рисуется какая-то конкретная текстура, но она легко заменяется на то, что получается в первом проходе, когда рисуется сцена и формируется g-buffer.
В том-то и дело. Да, нашу плоскую геометрию можно считать какбы g-буфером, но построение g-буфера — это составная часть deferred-техники. А в статье она не описывается.

А раз g-буфер не строится — то уже не получится описать восстановление мировых координат по g-буферу, а это весьма любопытный момент.

Т.е. у нас тут получается строго 2D-ситуация. Неинтересно же, 3D гораздо веселее :)
согласен, 3д намного интереснее :)
а как собственно обходится рендеринг полупрозрачных поверхностей?
Рисуется поверх непрозрачной, используя один и тот же depth buffer :) траву вообще можно рисовать с альфа-тестом
ссылки на демки с ваших предыдущих статей не рабочие. Везде ERROR 404 — Not Found! А так хотелось поглядеть, эх.
На исходники тоже ссылки битые, сервер падал сильно и на руках у меня этого всего — увы, нет Но я попробую что-нибудь придумать.
Тем, кто еще не видел, советую поглядеть на игрушку NormalTanks. Там как раз-таки такое же 2D с освещением и парой трюков, но выглядит более чем приятно.
А почему на карте нормалей текстуры не обозначены дырки в кирпичах? Я почему-то ожидал увидеть имено их, а не границы самих кирпичей.
Sign up to leave a comment.

Articles