Спойлер: собаку пришлось перерисовать с нуля. Но обо всём по порядку. А больше всего времени занял скульптинг груди ;-)
В прошлый раз Claude за полтора часа перевёл досовскую демку Quake на нативный DirectX 12, пока я ходил на кухню. Демка Alone in the Dark лежала в соседней папке, в той же самой папке Heroes 2 и просто дх12 порта мне показлось мало…
апд: обновил футажик. теперь видно в сравнении работу длсс
Задумка
Сначала всё было скромно. Сделай как с Quake: рекомпил, нативный DX12, никаких врапперов, векторы движения для DLSS 5.
Потом я посмотрел на результат и понял, что хочу больше. Он понял. Вот это, наверное, и есть вайбкодинг в чистом виде: ТЗ без единой запятой там, где она нужна, и с «кк?» в конце.
Часть 1. Просто порт
Исходников самой игры 1992 года, понятно, нет. Зато есть FITD (Free in the Dark) от yaz0r, открытая реимплементация движка под GPL, которая работает с оригинальными файлами. Только рисует она через bgfx, окно делает через SDL, а звук играет через SoLoud.
Всё это Claude выкинул и написал на замену своё: рендер на DirectX 12, окно на Win32, звук на XAudio2. Музыка AdLib никуда не делась, эмулятор чипа YM3812 сидит внутри движка и кормит XAudio2 буферами. Окно 1600x1200, как я люблю.
Демка, кстати, сразу упала. Дважды. Первый раз потому, что в ней меньше спрайтов, чем ждёт движок от полной версии, второй раз потому, что движок после вступления пытался загрузить седьмой этаж особняка, которого в демке просто нет. Обе ямы он залатал.
С DLSS тут вышла забавная штука. Alone in the Dark считает 3D-модели на процессоре, каждую вершину, вручную. Поэтому прошлое положение каждой вершины известно точно, и векторы движения у Эмили и у монстров получаются настоящие, без угадывания. А вот фон в этой игре... это картинка. Нарисованная. Глубины у неё нет, векторов тоже, камера в каждой комнате стоит неподвижно.
Запомните это, к фону мы ещё вернёмся.
На порт ушло 40 минут: папку проекта он создал в 13:38, первую рабочую сборку закоммитил в 14:18.
Часть 2. Numpad 5
Полигоны. Модели в AITD собраны из отдельных кусков: лицо, грудь, рукава, всё отдельно, с дублированными вершинами на стыках. Он их склеил в одну сетку и дважды прогнал через сабдивижн Loop. Каждый треугольник превращается в 16. Острые сгибы (воротник, края книги) остаются острыми, всё остальное округляется.
Первая версия округлила вообще всё. Окна стали овальными, бумажки на полу тоже. Пришлось учить его отличать угол прямоугольника от изгиба.
Текстуры. Вот тут мне понравилось больше всего. Он взял палитру, которой рисовал художник в 1992-м, и по цвету каждого полигона определил материал: зелёное и синее у Эмили это ткань, коричневое на мебели это дерево, тёплое светлое это кожа, тёмное тёплое у людей это обувь и ремни. Дальше я сказал ему зайти через Chrome-аддон, и он сам зашёл на Poly Haven и скачал пять материалов под CC0: шерсть ёлочкой, дерево, металл, кожу и штукатурку. Каждый с картой нормалей и шероховатостью. Цвет художника остаётся основой, фотка даёт только фактуру.
Я в этом процессе нажал одну кнопку «Разрешить загрузку нескольких файлов».
Тени и блум. Тени героев на полу через стенсил-буфер, блум только в финальной картинке, чтобы DLSS получал чистый кадр.
Фоны. Real-ESRGAN, увеличение в 4 раза. Видеокарты у него в облаке нет, так что нейросеть крутилась на процессоре, по 3-5 минут на картинку 320x200. Подменяет фон он попиксельно: где на экране меню или текст, остаётся оригинал, а затемнения палитры между сценами продолжают работать.

Баги. Их было много, и они были смешные
Сеточка на лице. Я прислал скрин: у Эмили всё лицо в мелкую клетку. Оказалось, материал определялся в момент, когда палитра была затемнена до чёрного (игра так делает при смене сцены). Почти чёрный цвет он принял за ткань, и Эмили целиком, вместе с лицом, получила текстуру шерсти ёлочкой.
Чёрные квадраты на ногах. Появлялись во время анимации, на долю секунды, я даже заскринить не успевал. В паре вырожденных треугольников нормаль считалась как деление на ноль, получался NaN, а блум радостно размазывал этот NaN в аккуратные чёрные квадраты.
Пианино. Real-ESRGAN решил, что клавиши должны быть чёрными, и нарисовал на их месте жирные пятна. Теперь шейдер сравнивает HD-фон с размытым оригиналом, и там, где нейросеть насочиняла лишнего или замазала мелкие детали, берёт рисунок художника.

Грудь. Тут цитирую себя же: «грудь пожалуйста все таки сделай более округлой... но чтоб у нас не получился tomb raider». Сделал. Потом, когда чинил прямоугольные окна, случайно сделал её обратно угловатой. Я заметил. Он вернул, а заодно поправил лицо: художник покрасил каждый полигон лица своим оттенком, и с нормальным светом это читалось как грани. Теперь у кожи один тон, а объём рисует свет.

Собака
Монстр на чердаке собран из 17 шаров: живот, голова, суставы, позвонки на шее. В оригинале это плоские кружки, и выглядит нормально. А вот когда шары стали честно освещёнными сферами, его запузырило. Реально, гроздь пузырей с зубами.
Я написал: «просто перерисуй собаку с нуля... ты понял? подвигай полигоны... и пр. чтоб она не была таким пузырем».
Он сначала вытащил из модели скелет: 114 вершин, 24 группы анимации, кто к кому крепится. Потом построил новое тело из 39 капсул: худой сгорбленный торс, бицепсы, длинный череп, толстая шея, тонкий хвост и шипы вдоль спины. Капсулы сплавил в одну поверхность (это через поле расстояний и surface nets, я загуглил, ничего не понял) и получил около 19 тысяч треугольников. Каждая вершина привязана к костям оригинальной анимации, так что монстр двигается ровно так же, как в 1992-м. Зубы, когти, глаза и ступни остались родные.

Первая версия, кстати, получилась вывернутой наизнанку. Видеокарта рисовала внутреннюю сторону тела, и на бедре зияли круглые дыры. Он это поймал на своих же скриншотах.

Самое смешное, что вживую он монстра так и не увидел. Его тестовая Эмили каждый раз уходила к столу и находила масляную лампу, а игра вставала на диалоге «You Find An Oil Lamp». Два длинных прогона, три десятка скриншотов, и на всех лампа.
Монстра увидел уже я, у себя:


Как он это всё тестировал
Как и с Quake: Linux в облаке, Wine, vkd3d и программный Vulkan на процессоре. Никакой видеокарты. Игра там бегает примерно на 7 FPS, а он гоняет её скриптами: нажать Enter, подождать, пройти вперёд, снять скриншот, переключить Numpad 5, снять ещё один.
Мою RTX 5090 он в этот раз не трогал вообще. Всё проверялось в облаке, а на настоящем железе уже смотрел я.
Кстати, оверлей NVIDIA игру не захватывал. Это не баг рендера: оверлей цепляется только к играм из своего списка, и exe надо добавить в NVIDIA App руками. А для роликов я попросил надпись ON/OFF в углу, теперь она есть, прячется на F8.
DLSS 5 сверху
Подключал через RenoDX. Ноутбук с RTX 5090 Laptop и Core Ultra 9 275HX. Без DLSS игра держит 60 FPS при загрузке видеокарты около 45%. С DLSS 5 видеокарта уходит в 100%, а FPS падает до 18, на одном из скринов до 33.
Результат? Зависит от того, что подать на вход.
Оригинал (OFF). Дизеринг фона 320x200 нейросеть воспринимает как фактуру, и весь пол превращается в мозаику из плиточек. Смотреть на это больно.

Ремастер (ON). Получается фото кукольного домика. Местами красиво, местами... ну, вы видите сами. Деревянные столбы превратились в красные шторы, бочки стали жестяными банками, а лицо Эмили размыло в призрака.

На других скринах цвета гуляют: всё уходит в жёлто-синий, ковёр становится серой плитой, а монстр в окне превращается в кучу тряпья.


Самый спокойный кадр из всех, на 33 FPS. Галлюцинаций меньше, картинка ближе к оригиналу, только Эмили поседела, а монстр стал тёмным пятном.

Отдельно смешно с надписью ON в углу. DLSS 5 её тоже перерисовал, стилизовал и сделал полупрозрачной. Значит, через RenoDX нейросеть обрабатывает весь готовый кадр, вместе с интерфейсом поверх. И, судя по всему, на мои честные векторы движения и глубину она даже не смотрит.
Так зачем всё это?
Главный вывод для меня такой: DLSS 5 очень сильно зависит от того, что ему дают. Пиксельный оригинал он превращает в мозаику, гладкий ремастер в кукольный домик. Нарисованный фон без глубины для него просто фотография, которую можно перерисовать как угодно, отсюда и шторы вместо столбов.
По цифрам. Около 5 500 новых строк кода: рендер, ремастер-режим, шейдеры, окно и звук. Экзешник весит 3 МБ. С 13:38 до 17:43, четыре часа, считая собаку.

