Ещё про мой диплом: затухание света и спекуляр

На самом деле, кроме теней, я не проводил такой капитальный ресерч, достойный отдельного поста по другим темам. Поэтому я решил выгрузить все остальные интересные вещи в один пост. Пока выгрузил только одну.

Во-первых, о чём, собственно речь? Это видео с финальной дипломной сцены:

http://www.youtube.com/watch?v=7IolXxg1_q8

И пара скринов:

buildFinal 2013-06-20 00-22-52-35 buildFinal 2013-06-20 00-38-38-52

На самом деле, это далеко от того, что планировалось. Институт обязал нас делать много бумажной работы и, собственно, качество самого диплома мы поднять не успели. Многие из хитрых графических трюков я просто не успел вставить в сцену, которую друг-артист прислал мне в последние 3 (!) дня перед защитой.

Что здесь интересного, и на что я и в будущем планирую обращать внимание:

Спекуляр загораживается тенями от источника, даже если их не видно в дифузе. Это почти никогда не применяется в играх, но это действительно так, можете проверить в вашем любимом рейтрейсере:

Это то, что мы видим обычно в играх:

scanline

Тут есть большая ошибка: затухание источника искусственно ограничено и быстро уходит в ноль на краях. Из-за этого спекуляр обрезается ещё палевнее, чем диффуз. В играх свет часто обрезают так, чтобы можно было вписать источник в сферу и избавить множество фрагментов от вычисления света. В дефереде так можно растеризовывать лоу-поли сферы, в которых семплить глубину с нормалями и быстро шейдить.

Однако это всё идёт мимо реализма.

В реальности, источники затухают обратно квадратично – т.е. 1/(dist^2). Вы можете удивиться, насколько большая разница будет в освещении, если вы попытаетесь сменить привычные range-based лайты на реальные.

Вот ещё неплохой пост на тему: http://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/

У такого затухания есть большой минус для производительности – оно может затухать очень-очень долго, что может быть совсем не практично для десятков реалтайм лайтов, которым придётся покрыть всю сцену. Однако в моём случае свет был статичный и всё что было нужно, можно было запечь.

Так будет выглядеть тот же кадр с обратно-квадратичным затуханием:

scanline2

А теперь давайте посмотрим на более интересные кадры:

vray1

Здесь мы имеем чисто диффузные поверхности, освещённые одним лайтом. Это то, что вы обычно запекаете в лайтмапы.

А теперь:

vray2

То же самое, но с более отражающими поверхностями.

Мы можем хорошо видеть появление длинного блика от лайта на полу, но этот блик никогда не будет заходить в тень от него. Там где в диффузе нам, благодаря затуханию, видится сплошная тьма – оно, на самом деле ещё продолжается, просто нашему глазу сложно отличить черноту затухания от черноты теней. И не только нашему глазу – числовая точность в этих тёмных местах тоже будет очень низка.

Объяснение тут очень простое: диффузный свет имеет значительно меньшую интенсивность, чем отражённый. Отражённый свет фокусируется в более “плотные” узкие пучки, в то время как диффузный рассеивается во все стороны.

Поэтому там, где диффуз на глаз совсем затух, спекуляр ещё жив и продолжает обрезаться тенями.

В обычных лайтмапах для этого недостаточно информации, если только вы не собираетесь их хранить во флоате.

11IMG_8577

На этих убогеньких фото можно увидеть тот же эффект: на левых картинках можно хорошо увидеть тень (от столба, от машины), а на правых её нет. На левых картинках  блик падал на поверхность и отделял тени – на правых нет. Запекание диффузного света даст нам только правые.

Попробуйте и сами погулять ночью по улицам – вы увидите, что из-за множества источников света, эффект усиливается, одни тени будут часто исчезать, другие появляться.

Так это может выглядеть в реалтайме:

specc

(Да, это юнити, но с моими шейдерами).

С разных ракурсов кажется, будто тени с разных сторон – такое же можно увидеть и в реале.

В плане реализации, я не придумал ничего умнее, кроме как просто запечь отдельно тени без затухания. RGBA8 текстура вместила 4 теневых маски, по штуке на канал.

Т.к. тени – это просто чёрно-белые маски,  неплохо прокатывает и 4-битная точность. Я пробовал засунуть 8 масок в ргба8 и оставить одну выборку, но при распаковке ломалась фильтрация.

Таким образом, у меня вышли GI-лайтмап (только индирект) и маски теней без затухания. Распространение света и затухание считалось в шейдере.

Индирект довольно рассеянный и не имеет широкого дипазона обычно – его можно хранить в лоуресе DXT1. Вообще, их было три штуки (radiosity normal mapping).

Маски плохо реагируют на DXT – поэтому их я хранил по паре RGBA4 в финале.

Что-то лень стало дальше писать, так что To be continued.

Penumbra shadows

Тут я начну цикл постов по темам того, чем я занимался в своей дипломной работе. Называлась она незатейливо: “Реалистичные материалы в реалтайм рендеринге”, однако под собой это подразумевало всё что угодно от реалистичных теней до избавления мелкого спекуляра от алиасинга.
В целом, задача была – рендерить красивую сцену в реалтайме.

В этом посте я расскажу, что я делал с динамическими тенями.
Тени должны были иметь вариативный радиус полутени – чтобы вблизи кастера они были чёткими, а вдали – размытыми, степень размытости должна варьироваться от физического размера источника.

Я изначально упростил себе задачу – пусть тени отбрасывают только динамические объекты (которых в демке будет немного), а на статике запечём лайтмапы.

Мучавшись с месяц, я родил вот такую демку:
!iengine 2013-02-13 01-10-23-92

!iengine 2013-02-13 01-10-36-45

iengine 2013-02-13 01-18-55-10

Её можно скачать здесь: http://geom.io/iengineShadows.zip

/*
В ini файлике можно поменять разрешение.
 Если у вас не нвидия - снизьте antialiasing, т.к. по умолчанию там нвидия-специфик CSAA.
 Мышь + WASD - летать
 LMB - задать направление света в соответствнии с направлением камеры.
 Колесо мыши - менять размер источника света (т.е. размер пенумбры теней). Идеально чёткими конечно не сделать, т.к. ограничено разрешением шадоумапы.
 Требуется нормальная видеокарта скорее всего.
*/

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

Короче говоря, как это работает: за основу я взял технику PCSS, суть которой в нахождении для каждого фрагмента некого среднего значения глубины вокруг него в шадоумапе – это значение конвертируется в радиус размытия, который затем юзается в PCF.

Технику юзали не часто, ибо она тормозила. Поиск средней глубины требовал множество выборок, PCF при большом радиусе – не меньше. Чтобы PCF был широким и гладким, его надо сделать совсем тормозящим, и все равно ещё будет присутствовать алиасинг на поверхностях под острым углом (отсутствие мипмаппинга шадоумапы). Альтернативы – мало семплов и жуткий banding или вышеупомянутый шум. В общем то, в играх научились маскировать этот шум не так уж плохо – проходясь по нему скринспейс блюром. Но намётанный глаз все равно спалит =).

Первым делом я решил заменить PCF на другой алгоритм. Чудесность PCSS в том, что PCF в нём совершенно необязателен – даже при не высоком числе выборок в стадии blocker search, мы получаем не самые кривые коэффициенты размытия, которые можем засунуть в любой алгоритм.

Меня заинтересовали summed area tables. Суть их в том, что благодаря простой арифметике, имея картинку, каждый пиксель которой содержит сумму всех пикселей выше и левее его (существуют вариации и с ниже и правее, но не суть), мы можем найти среднее значение всех пикселей в любом прямоугольнике на ней, имея лишь угловые значения. Сперва это может туго пониматься – но атишная дока довольно наглядна. Таким образом, сделав один раз препасс и превратив любую текстуру в SAT, мы можем за 4 выборки и маленькое число инструкций получить блюр любого радиуса. Ух ты!

Ух ты ли? На самом деле далеко не совсем.

Во-первых, суммы пикселей будут иметь чертовски широкий диапазон значений. Если текстура была RGBA8 формата, для SAT в большинстве случаев придётся создавать RGBA32F. И даже в точность флоатов SAT вносит много погрешностей. Если на цветовой текстуре их может быть не заметно, это может сломать шадоумапы. Я бы не стал юзать SAT для больших теней аля открытый мир, но т.к. в моих планах было маленькое число дин. объектов в мире статики – жить было можно.

Во-вторых, препасс очень тяжёлый. “Сложить все пиксели текстуры” звучит несложно на словах, но совсем не дешёво на практике. Лучший известный способ, он же представленный в атишной доке, требует несколько пассов, причём кол-во пассов очень быстро увеличивается при увеличении текстуры. Генерировать SAT больше, чем на 512х512 – дохлый номер. Дешевле делать VSM с широким блюром.

Но, однако, в вышеобозначенной демке я всё же использовал SAT – ещё не успев окончательно в нём разочароваться.

Были применены некоторые дополнительные трюки:

Дело в том, что у PCSS техники есть один знатный баг – невозможно получить несколько полутеней, пересекающих друг друга корректно – blocker search видит только ближайшие к камере данные из шадоумапы. Поэтому “главной” полутенью будет полутень ближайшего к ней объекта – и если какой-нибудь более мелкий объект стоит в тени и кастует свою тень на полутень объекта за ним – она не отобразится. Будет полутень главного, а потом резко начнётся тень мелкого, как только он появится в шадоумапе.

Пока тени не пересекаются, это не заметно, но я хотел это исправить. Для этого я сделал из шадоумапа атлас, в котором выделил отдельно место для каждого объекта – таким образом я ещё и сэкономил пространство текстуры и смог крутить препасс SAT отдельно на каждый блок атласа. Вообще там было хитро – 512х512 атлас с 4мя шадоумапами по 256х256, я смог генерировать SAT атласа за кол-во пассов, необходимое для одной 256х256 текстуры.

Таким образом, у меня были данные всех объектов в шадоумапе не загороженные и можно было избежать этого артефакта – можно заметить его отсутствие на втором скрине.

Тем временем сроки подходили к концу, на меня снова стал сыпаться контент, и такие экспериментальные методы пришлось отбросить. У меня не было времени подготовить к “продакшену” всю эту систему с атласами.

Дело было упрощено до VSM + PCSS. Шадоумапа рисовалась в VSM текстуру без всяких атласов, далее по ней проходился минимальный блюр. PCSS юзал тот же PCF цикл, который вместо бинарных сравнений/hardware pcf’а семплил эту VSM карту. Минимальный блюр в ней был конечно пошире хардварного псфа, это позволяло брать мало семплов (при псфе это выглядело бы как жуткий бандинг). В результате получались тени с широким (много семплов неширокого) блюром вдали от кастера и менее широким вблизи. В идеале хотелось сделать их вблизи чётче – но и так более-менее устраивало:

btest 2013-05-29 16-45-03-04 1dxc btest 2013-06-19 19-52-11-26

Конечно, эффект уже был не такой, но с ними просто было работать. Тут можно посмотреть видео: http://www.youtube.com/watch?v=2jk5TmfKNZA

Остался, правда, косяк, который я не успел исправить – а именно резкие границы у черезчур размытых теней. Для оптимизации у меня в шейдере стоял if, который не считал тени там где их не должно было быть – но работал он не совсем корректно.

Далее подобным образом я сделал и тени от поинтлайтов – для VSM, их пришлось рендерить как dual-paraboloid‘ы.

Прикольная черта теней от поинт лайтов – т.к. мы снимаем шадоумапы с центра лайта с включённой перспективой – у нас автоматически дальние объекты становятся мельче и тени от них размываются сильнее. Получается дополнительный фейк в пользу визуального эффекта корректной полутени =).

btest 2013-06-01 01-33-28-62 btest 2013-06-01 01-34-11-40 btest 2013-06-05 03-43-43-04 btest 2013-06-03 23-13-26-26

Каковы мои дальнейшие планы?

Мне нравятся distance fields и то, что с ними можно сделать. Даже очень лоуресные DF могут трейситься как довольно похожие на оригинальную форму геометрии – в дипломной работе я использовал их для самоотражений объектов (но об этом в другой раз). Много чего можно запечь в маленькие DF. А можно и попытаться генерить их в реалтайме…

Арт

Прежде чем рассказать о своём дипломе, запощу ка я сюда вялую коллекцию своих моделек и картинок.

debris6.jpg1e44cf4d-c1fb-421e-90b7-5427b8c2f090Large fence8.jpg1d41c893-537c-4b35-b019-3d4308049c34Large

Environment: я делал всю геометрию уровней/пропсов в Incident, а друг текстурил её. Сейчас наши самые вменяемые модели тех времён можно купить на турбосквиде.

Модель вертолёта друг так и не затекстурил – а ведь она планировалась быть “главным героем” симулятора:

mi2

mi2_3

А вообще, я люблю моделить лица людей. Я вообще люблю лица людей.

98b1dd2e2bd515daa2bb782b523fa574 96874deebbf298c696ea502e3357ad96 99f30b8f3631ae85d476b9f48fd5bc5f ec749be4dac3f5f02d5fd505480685f7 83a36c55ff2829e2ddcdc836928109a4

Давно планирую заняться, наконец, продолжением сей деятельности.

А пока остаётся показать моё 2D – но оно уж совсем убого:

someI1a copy3c_comp copyLo

fadedsk1 copyBW IMG_3780

Hello world

Привет.

Я – самопровозглашённый программист графики и indie-разработчик игр. Моё желание и цель – разработка хороших и интересных видеоигр.

Помимо графики я также писал физику, геймплей, тулзы, плагины… и чего только не писал. Главное – было бы ради чего.

Что же я сделал и каков мой пройденный путь?

Жили были я и мой друг (я обязательно оставлю его ник/контакты, как только он решит что мне о нём здесь написать). И хотели мы делать игры. И повелось так, что я писал весь код, а он делал арт. Впрочем, я тоже иногда делаю арт – но об этом позже. Ну и мы начали:

– Так и не завершённый (заморожен до далёких времён) шутер Incident. Изначально был модом на игру Mafia: The City of Lost Heaven. Следует упомянуть, что никаких официальных моддинговых тулз к движку не было – и фанаты изощрялись как могли (и, сложно поверить, изощряются до сих пор). Приходилось реверсить форматы, писать самопальные недоредакторы, конвертеры, мучить файлы в хексе… Наибольший вклад в создание вообще возможностей моддинга тогда внесли такие люди, как GOLOD55, zibob32 и Akay, возможно и другие, кого я незаслуженно забыл. Попачкать руки пришлось и мне – отличительной фишкой тогдашнего Инцидента были лайтмапы – до этого моддеры довольствовались повертексным движковым светом.

Счастливые и безмятежные были времена моддинга. Несмотря на кривость наших недоредакторов, мы всё же могли пользоваться готовым, проверенным движком, который скрывал от нас многие сложности и “просто работал”.

Скриншоты с Mafia-версии:

screen_ls3d1

screen_ls3d2

screen_ls3d3

screen_ls3d4 screen_ls3d5

По сравнению с мафийными модами того времени, картинка у нас была самая понтовая, и ЧСВ так и распирало.

Однако этого нам было мало. Прогресс стремительно двигался вперёд, графика Мафии устаревала (дело было в 2007 году, если память не изменяет), и мы хотели сделать круче. Резко прекратив разработку мода, мы объявили Инцидент отдельной игрой. Вероятно, зря – в виде мода мы бы хотя бы смогли бы его довести до конца.

Тут надо сделать небольшое лирическое отсутпление что бы понять причину такого решения. С детства я интересовался программированием. Моя бабушка была программистом, её брат тоже что-то умел – тут и там валялись книжки от “MS-DOS для пользователя” до “Введение в язык С” (названия пишу по памяти, но смысл верен). ПК в семье был с моего 4х-летнего возраста и много раз менялся по мере моего взросления, однако до 2004 года доступные мне ПК всегда были на несколько лет отстающими от современных. Страстными глазами я смотрел на скриншоты современных игр в журналах и мечтал о них. По большей части, все игры, которыми я располагал были очень скучными и сложными. Я не был одним из тех хардкорных игроков, которые проходили HL1 по несколько раз – я не смог пройти его даже один. У меня просто не было мотивации, уровни были однообразны, а атмосфера неизменно угнетающей. И это уже HL1 – чего уж говорить о поколениях более ранних игр.

В общем, мне нравились игры как сама по себе форма – но до 2000х я не встречал конкретных экземпляров, которые бы вызывали у меня большую симпатию. И т.к. в моём распоряжении был компьютер, на котором каким-то чудом стоял qbasic, несколько книжек и англоязычный хелп этого самого бейсика – я (взяв толстый словарь) начал пытаться непременно делать свои игры, в которых бы всё было как я хочу. За кубейсиком последовал Dark Basic – к моему огорчению, 3D-ускорителя у меня не оказалось, и пришлось довольствоваться 2D. Тогда я сделал свои первые спрайтовые гоночки и недостратегии. Dark Basic сменился Blitz Basic’ом – и в него я влюбился надолго, заодно скорешившись с коммьюнити русских блицеров. Блиц казался менее “казуальным”, и к нему писали множество либ и врапперов – можно было даже пожамкать PhysX.

Будучи долгое время на устаревшем железе, жадно смотрящим в сторону современных игр, и судя о них по скриншотам в журналах (ибо больше не по чему было – ютубы ещё не появились, да и на диалапе много не посмотришь), я восхищался их графикой, и даже нередко её переоценивал – кто там разберёт на маленькой картинке – настоящее отражение или в диффуз впечено? Это мотивировало меня и самому пытаться делать что-то “графичное”, пытаясь извратиться на бедном FFP как только можно (вспомнить хотя бы тормозящее попиксельное искажение на ЦПУ).

В то время (конец 90х, начало 2000х) игры развивались очень быстро – как технологически, так и идейно. Мне казалось, что я стою на пороге некой революции – будто ещё немного, и человечество создаст, наконец, Матрицу. Создание игр приняло для меня облик сотворения миров, такой эпичный и захватывающий, что хотелось быть частью этого.

Поворотным моментом для меня стало появление движка Xors3D – который добавлял в блиц DX9 рендер с шейдерами, от самого упоминания которых я с восхищением дрожал. ШЕЙДЕРЫ! Я люблю, как звучит это слово!

Итак, в моём распоряжении был любительский DX9 движок и, благодаря помощи и примерам Моки, я разобрался в основах HLSL. Помимо этого, благодаря моддингу и сопутствующему реверсингу, я худо-бедно понимал как нормальные люди хранят бинарные данные. Это и было причинами, по которым казалось, что разработка качественной игры вполне себе осуществима.

Наш энтузиазм, на удивление, передавался и другим – немало помогли нам тогда художники Сергей Су и SkyGround.

Что же было дальше? Скриншоты:

screen1

screen2

screen3

Можно даже сказать, что получалось не так плохо. Однако тратили мы на это чертовски много времени – да и на что тратили – вместо того, чтобы делать, собственно игру, мы погрязли в создании графики и, в конце концов, поняли, что в наши уровни невозможно играть. Они, выстраданные, пробегались за пару минут, а продумывание геймплея, по большей части, было упрощено до расставления врагов на равномерном расстоянии по пути игрока. Это не было похоже на глубокое атмосферное приключение в пост-апокалиптическом мире – наш энтузиазм начал иссякать. Диздок был многократно переписан с нуля, и, наконец, проект был заморожен – мы просто не могли потянуть его в то время, или были не столь умны, чтобы сделать его уникальным и интересным и в то же время дешёвым в реализации.

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

Результирующим подходом по пайплайну было определение свойств поверхности по её текстуре, причём не только графических но и физических и прочих. К примеру, когда игра загружала модель ящика, она связывала имя его текстуры с одноимённым конфигом, содержащим свойства шейдера ящика (дефайны, константы), физические свойства (трение, масса), звуки (слабый/сильный удар, звук попадания пули), декали (виды дырок от пуль). Вообще, подход был довольно приятен в работе, но, как оказалось, нам периодически хотелось использовать одну и ту же текстуру, но давать объекту разные свойства рендера/физики, и тут система начинала разваливаться – доходило до того, что мы дублировали одинаковые текстуры ради того, чтобы у них были разные имена.

Рендер был сделан в традициях Source – лайтмапы для статики, ambient cubes для динамики; динамические тени от дин. объектов я блюрил в скрин-спейсе и умножал на лайтмапленую картинку. Сцена состояла из множества convex секторов, соединённых порталами – через порталы проводился дополнительный фрустум, который куллил видимый в нём сектор. Шейдеров, кроме постпроцессов, было 2 – для статики и для динамики, но это были толстые убершейдеры, контроллируемые дефайнами.

Впрочем, ФПС все равно не радовал – движок был не слишком оптимизирован, да и за дипами мы плохо следили. Последней каплей стало отсутствие поддержки в движке фоновой загрузки ресурсов – наш контент весил так много, что мы просто обязаны были стримить его по ходу движения игрока, он не влезал в тогдашнюю мелкую видеопамять (у меня было 256 мб).

Ну и тогда я пошёл дальше – надо было непременно перейти на C++ и иметь возможность выбирать разные движки.

Я быстренько поглядел туторы по С++, подключил, для начала, тот же Xors3D и пошёл делать свой игровой движок – по ходу дела допуская все мыслимые и немыслимые ошибки, создавая утечки и рандомные краши. Первый блин – комом!

Движок загружал сцены, сделанные в моём же редакторе, причём большую часть времени я потратил как раз на редактор – теперь мне приходилось не только заботится о работоспобности игры, но и функционале и удобности редактора.

Редактор умел много чего за пределами расставления моделек: создание CSG геометрии и булевые операции с ней, автоматическая развёртка под лайтмапы, интеграция с Beast (не спрашивайте откуда он у нас тогда был), настройка постпроцесса, внутренний скриптовый редактор…

blitzccf3133704

blitzccf3137072

blitzccf3259104

Отдельной гордостью была система партиклов, полностью на GPU:

blitccf3517200

Однако всё это было сильно сырым и глючным. Кроме того, осознав, что в данный момент мы не потянем большой проект, мы решили испытать это всё в чём-нибудь попроще. Таким образом, наш следующий проект был аркадой про лодочки, которые плавают и стреляют друг в друга.

blitzccf3284536

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

Отчаявшись, мы начали делать приложение для вконтакта – но это не только было невесело делать, но и конкурентов было полно, а за серверы надо платить. Слишком мало гарантий, слишком мало интереса в разработки для соц. сетей. Проект был снова заброшен, не успев толком начаться – разве что успел немного вкурить в AS/PHP/mySQL/VK API.

Где-то в параллели, я продолжал помогать моддингу Мафии, периодически выпуская разные тулзы и небольшие моды. На mafiapub.com (в момент написания поста сайт, увы не работает; но упомянутые штуки можно найти и на других фан-сайтах) можно найти мои импортер/экспортер моделей для макса (на MaxScript) а также мод, добавляющий шейдерную воду (Water Shader Mod), сделанный через жестокий прокси длл между игрой и DX8 (шейдеры 1.0, написаны на асме).

Вообще, стоит отметить, после C++ опыта никакой язык уже не выглядел для меня совсем уж “не родным”. Везде, по большому счёту, одинаковые конструкции, всем правит логика. Так что с того времени я сбился с счёту на каких языках я писал. Когда ты понимаешь основные принципы кодинга и работы компьютера, ты видишь их отражение в любом языке или API.

Тем временем, я был студентом института по киношной специальности. В качестве курсовых мы делали ролики, и один стоит отметить и здесь – т.к. времени на него было угрохано не мало. В плане программирования я делал некоторые помогающие пайплайну скрипты и шейдеры (HLSL для вьюпорта и для mental ray’евские для рендера), но по большей части на мне было всё 3D, монтаж и часть компоуза, а друг был “арт директором” и делал всё 2D.

А вот и сам ролик:

http://youtu.be/trHQPw_pzWk

Множество шотов из него было вырезано и так и не дошли до финала из-за того что их просто нельзя было куда-то вставить “в тему”.

Как, например, вот этот кадр с Йоханнесбургом: youtu.be/V3d7PKOejgM

Между тем, Render, автор PhysX враппера для блица и соавтор Xors3D, связал меня с чуваками, занимающимися авиатренажёрами. Перспектива разрабатывать вертолётный симулятор для тренировки пилотов была интересной – с неё можно было получить намного больше опыта (и денег, как предполагалось), чем с клепанья унылых казуалок (чем в большинстве случаев занимаются унылые геймдев стартапы).

Так началась разработка симулятора и самая большая моя прокачка как кодера. Симулятор делался полностью на своём движке (DX9), который переписывался с нуля пару раз. Мой движок наконец поддерживал стриминг. Друг-артист отказался рисовать террейн тайлами и я был вынужден реализовывать мегатекстуры и их стриминг. Мегатекстуры были по началу по заветам Кармака – рисовался специальный пасс, выводящий инфу о необходимых тайлах, анализировался на цпу, и данные подгружались для отрисовки. Однако, гонять текстуру в оперативку было слишком дорого, так же как и позволять лишний пасс при большой геометрической сложности террейна. Т.к. мегатекстуры использовались только для террейна, система была упрощена до квадтри, и определение требуемых тайлов делалось быстро на цпу без участия гпу. Благодаря этому так же и исчезла назойливая черта классических мегатекстур – зависимость от ротации камеры. Можно стало резко поворачиваться во все стороны и не видеть запаздывающих подгрузок.

Движок имел полный набор тулз к нему – экспортер моделей и разные вспомогательные утилиты.

Сама геометрия террейна также была разбита на квадтри с хитрым морфинг в вертексном шейдере для скрытия швов между кусками.

С тенями тоже пришлось повозиться – идея накинуть на всё каскадные провалилась – либо у нас не было теней вдалеке, либо мы теряли качество близких теней, 4х сплитов не хватало чтобы получить хорошее качество везде. Кроме того, флоатовая погрешность не давала нам получить аккуратные тени от мелочей под острым углом (закат) на всей территории. В результате пришлось делать смешанный подход: каскадные тени остались от построек, для террейна – мини гпу рейтрейсер хейтмапы, пересчитывающий лайтмапу террейна только при отклонении солнца на несколько градусов, от вертолёта был отдельный маленький VSM, всегда детальный, а облака рисовались в ещё одну текстуру чёрным по белому без сортировки, которая затем умножающе проецировалась на всё сверху.

Таковые реалии реалтайм рендеринга – или всё выглядит херово и тормозит или ты реализовываешь частные случаи для всего.

Было реализовано ещё до черта всего – от спавна машинок на дорогах и симуляции капель на стекле до динамической смены времени суток и даже года (!).

iengine 2011-08-28 20-21-59-26

iengine 2011-08-28 20-19-52-65

iengine 2011-08-24 19-50-32-32

iengine 2011-08-23 21-33-16-51

iengine 2011-08-16 18-18-48-03

iengine 2011-07-30 20-53-57-40

iengine 2011-07-29 02-03-29-20

iengine 2011-07-10 22-57-10-43

iengine 2011-07-07 22-03-01-93

iengine 2011-03-25 01-19-38-09

iengine 2011-03-04 00-13-26-89

Не трудно догадаться, что при малом опыте и больших амбициях, разработка затянулась на черезчур долгое время. В результате сроки были упущены, но нам было предложено переделать симулятор из вертолётного в парашютный – на него спрос ещё был, а сложность была ниже.

И началась разработка парашютного: было выпилено всё недоделанное и малонужное (поезда, светофоры, песчаные бури), был взят чуть поменьше масштаб мира и всё стало вылизываться.

Для параштного также был сделан интересный процедурный генератор домов – в результате мы имели тысячи разных и более-менее аккуратных построек на карте.

Результат был довольно неплох:

4f0e6b7efc1be5e88ccab060c8cf9bdd 1788f398155afa46f8a70235c2f7e4ce 751a2858f00f31045c9ccc66b8cc439e 2ea48a985a2e492faddd18add590c7e2 29a49096615f6e701aad1bc22670cc31

iengine 2011-11-02 16-32-22-01 iengine 2011-11-02 16-32-19-20 iengine 2011-10-25 22-34-19-79 iengine 2011-10-20 16-56-01-06

И рандомное видео: http://www.youtube.com/watch?v=vsahx8WcU1Y

За это мы даже умудрились получить деньги. И жили бы долго и счастливо, но запланированных массовых продаж не последовало – конкурентные продукты обошли нас в глазах покупателей, и тренажёрные товарищи забили на нас.

Дальше я делал что-то по мелочам.

Например, вот эту реалтайм бутылочку:

iengine 2012-06-28 21-47-41-96

iengine 2012-06-28 21-49-49-67

Тут я в шейдере симулировал движение всех лучей отражённых/искажённых и проходящих сквозь стекло. Целью было приблизить качество к рейтрейсеру. Вроде что-то получилось:

vrayVsMe

Ещё я делал radiosity лайтмаппер на GPU:

iengine 2012-07-09 05-13-04-37

Но он вышел слишком медленным, чтобы его юзать. Зато он считал GI! Это было весело.

Таким образом проведя ещё одно лето, я внезапно столкнулся с тем, что оканчиваю институт – и пора бы мне делать диплом. И решил я делать диплом о том, о чём больше знал – о реалтайм рендеринге.

Но об этом напишу в следующем посте. Сейчас пора спать.

Вот такой я у мамы молодец.