PainKiller: Технологии рендера
Автор: Роман Марченко
Как-то давно, я уже реверсил рендер пейнкиллера, но только очень поверхностно. А так как о моем мини-исследовании рендера FlatOut'а я неожиданно получил очень положительные отзывы, то решил серьезно заняться этой, несоменно, великолепной игрой.
Итак, почему же PainKiller. Причины схожи с причинами, которые меня побудили взглянуть на FlatOut. Хоть и игра уже немного старая, картиночка, выдаваемая игрой, мне очень нравится. Учитывая великолепную скорость отрисовки, рендер заслуживает всяческих похвал.
Итак, реверсил я на максимальных настройках графики ("insane" в параметрах конфиграции) , на видеокарте GF6600.
Рендер игрового кадра состоит из следующих этапов:

Текстура монстрика (оригинальный размер 1024x1024):

Пример маски блендинга для земли:
Пример лайтмапы для земли:
При отрисовке всех остальных объектов используется лайтмапа и 1 диффузная текстура.
Для ближней геометрии используется также текстура с деталями.
Лайтмапа для объектов (оригинальный размер 1024x1024):
Большое количество входных параметров. Vs - 56 инструкций, ps - 31 инструкция. В этом проходе накладываем reflections, анимируя её используя 2 dudv карты. Волнение геометрии создаем анимацией вершин в vs. Я вообще обнаружил повертексную анимацию, только после того, как шейдер проанализировал, и увидел, что там меняется позиция вершины. Так думал, что вода плоская.
В арсенале PainKiller'а есть еще один тип воды. Без честных отражений, с использованием лайтмап. Такой тип используется на уровнях, где воды много.
Например в локации C5L1_City_On_Water. Первый же тип используется на первом уровне аддона Battle Out Of Hell: C6L1_Orphanage. Думаю, что мощный редактор позволяет по-разному варьировать параметры воды, чтобы получить нужный визуальный стиль.
полусфера, внутри чашечка в зените, потом опять полусфера. Эти слои блендятся стандартным альфаблендом (srcalpha, invsrcalpha), и используют шейдеры точно такие же как при рендеринге земли. Неиспользованные слои (вспомним, что при рендеринге земли используется 2 текстуры для комбинирования) заменяются dummy текстурой.
Пример текстур неба:
Оригинальный размер 2048х512
Оригинальный размер 1024x1024
Оригинальный размер 1024x1024

В вертексном шейдере мы вычисляем расстояние от источника света до вершины. Поделив полученное расстояние на дистанцию влияния источника, мы пакуем вектор так, что все расстояния на которые влияет источник попадают в диапазон [-1,1]. Скейлим дальше в [0,1]. Получили текстурные координаты для лукапа в текстуру аттенюации (так как address mode установлен в clamp, то все лукапы за пределами текстуры будут происходить по ее границе). В нашем примере используется простой кружочек, что означает простое постепенное ослабление освещения с расстоянием. Но задав, например тот же кружочек, но инвертировав его цвет, мы получим освещёнными дальние объекты, но неосвещённые ближние. В общем вариантов масса.
Основные стетйты тендера установлены в:
Depth write = false
Srcblend = one
Dstblend = one
Т.е. получаем блендинг pixel color + incoming color

Specular mask хранится в альфа канале normal map'ы (оригинальный размер 1024х1024)
Диффузная карта (оригинальный размер 1024х1024):





3 раза перетиреть почти весь экран, причем такими маленькими квадратиками, это надо уметь :) 2000 дипов.
Рисуем сцену нормально в RTT. Затем из нее делаем ч.б. картинку (способ стандартный: dp3 pixel, float3(0.3, 0.59, 0.11). Потом рисуем монстров специальным шейдером, который используя нормали и градиентную текстуру выделяет границу объекта красным цветом. И, напоследок, используя dudv bump map, вносим в картинку искажения. Для получения motion blur эффекта блендим предыдущий и текущий кадр используя весовые коэффициенты.
Demon mode shader
Градиентная текстура:
Получаем вот такую картинку:
16 ноября 2006