Quad-engine. Свой 2д движок. Когда приперло со всех сторон

Предисловие. Было начало 2010 года, когда я расстроился при просмотре очередного фреймворка с поддержкой Delphi. В тот момент я искал замену уже сильно устаревшему и заброшенному PowerDraw. Как говорится, тоже самое, только с перламутровыми пуговицами. Пересмотрев всё, что было из 2Д, я так и не нашел искомого. То не было шейдеров, то черезчур нагроможденный с точки зрения кода, то вообще какой-то убогий. А душа просила простоты использования и шейдеров.Поэтому я сел, и начал изобретать свой велосипед. Первое собранное приложение выглядело, конечно, не сильно впечатляюще: 5cb132aed06d4f7e93afd71e6e821318.PNG

Под катом прилично картинок.

В Марте был забронирован домен quad-engine.com, было нарисовано лого моим хорошим знакомым Weilard’ом и началась работа. На тот момент «движок» писался под игру типа собери-три, и одним из условий было обязательное наличие красивого бамп-меппинга с цветным спекуляром. В первых интерпретациях попытка сделать его была предпринята через мультитекстурирование, но результат оставлял желать лучшего. Так я лишний раз удостоверился что мне нужен мощный 2Д фреймворк с поддержкой шейдеров.

Как только с текстурированием, загрузкой и отрисовкой было покончено, сразу же все силы были брошены на прикручивание шейдеров (и пробы деллались с бамп-меппингом и спекуляром): 20d9447ef1994460ad94c0a95ee515f6.PNGПо завершению реализации шейдеров (пока еще не в том виде, что сейчас), сразу стало понятно, что без поддержки вывода текста движком это будет назвать ну вообще никак невозможно. Поэтому я написал утилиту для генерации текустур и служебной информации из шрифтов. А с полученным результатом уже и поддержку вывода текста в движке.Кстати, вот она эта утилита: 1a73f8dae03647949fd84737d4ae9862.png

Со шрифтами вышла история долгая, так как качество буковок, рендерящееся через DrawText на канву меня разочаровало быстро. В связи с этим было решено отказаться от такого подхода и рисовать каждую буковку самостоятельно, сглаживая грани так, как хотелось бы мне. Поэтому тут пришлось углубиться в получение векторного представления буковок от системы и растеризовать самостоятельно, получая в итоге карту символов: 4a87756f01af471a90a314b45373f532.PNG

В реальном приложении выглядело на тот момент это так: e399c14ee51b434f82642dbbb5920891.jpg

С игрой три-в-ряд довольно быстро всё не сложилось и решили от проекта отказаться, но «движок» потихоньку рос и обзаводился новым функционалом. Мыслей было больше чем реализованных фич, а ядро пришлось пару раз серьезно переписать.

Шейдеры Под то, чтобы сделать их использование удобным и достаточно гибким ушло времени много, а еще больше ушло на то, чтобы разбираться и «играться» с шейдерами, писать свои. Например реализация вот такого эффекта была ограничена только умением писать шейдеры и фантазией. Обращу внимание, что это всё 2Д, как я и говорил. Однако, шейдеры, делают всё объемным, хотя в кадре только 2 треугольника: Шаг 1: Рисуем диффузную текстуруb358d85ac600456b9077f9dd5ae2bc6d.jpg

Шаг 2: Рисуем тени на диффузной текстуре: fe863ca2fb1044148c83d9a0c3a1277a.jpg

Шаг 3: Рисуем в рендертаргет карту высот, соотвествующую месту: 3a57ac23075a479dafac9e4e10e42403.jpg

Шаг 4: Рисуем в другой рендертаргет карту нормалей: 8698d384e0d243b88be82233f1ff0c11.jpg

Шаг 5: Накладываем parallax oclussion mapping шейдер: 15923945d03144d9b5876cb0a70db977.jpg

Шаг 6: Увеличиваем и обрезаем картинку, чтобы избавиться от артефактов на краях: 5e7b70251e7c4a09af36e97d820820b6.jpg

Симпатично, правда? Но на этом можно не останавливаться и сделать всё еще интереснее (используя при этом всё еще один только шейдер). Добавим еще немного шагов?

Шаг 7: Добавим воду, с корректировкой цвета по глубине (из карты высот)fca88166aea24178ad61cc6ce66944c0.jpg

Шаг 8: Добавим текстурку с облаками и отражения на воде, а воде добавим рябь: c7dbe35e7d4846008722b1a6c96ab5c0.jpg

Шаг 9: Сделаем воде отражающую способность пропорциональную глубине: 3a936c7bfcfd4aa29d2c8418c402df6c.jpg

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

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

Псевдовекторные шрифты Суть псевдовекторных шрифтов в том, что все данные хранятся в текстуре особым образом. А рендер букв происходит с помощью шейдера. Настолько простого, что он практически не замедляет отрисовку сцены. Однако шейдер позволяет делать антиалиасинг, обводку и свечение у букв, а также масштабировать буквы не теряя при этом четкости и не размыливая изображение.Да, они есть. И о них очень хочется рассказать, но тема настолько большая, что тянет на отдельную статью, как я, пожалуй, и поступлю. Поэтому прошу меня извинить, но этот раздел мы откладываем до следующей статьи.Крик души А давайте чтобы избежать непонимания и холиваров, я попрошу просто принять тот факт, что движок писался и продолжает писаться на Delphi. Начинал писаться на Delphi 2007, сейчас поддерживается на XE5. API выбрано DirectX и никакие OpenGL мне не нужны, я с ним работал и знаю что это. На момент начала меня интересовала только платформа Windows.Так о чем же, собственно речь? Многие скажут, мол что же, надо брать С++ или C# и писать на нем. Здраво, но цель статьи не холивары, поэтому примем за должное. Движок начал писать для Delphi, позже адаптировав и под другие языки. Именно под Delphi недоставало такого инструмента, коим всё стало сейчас. Просто, удобно и прозрачно. И позвольте называть мои наработки «движком», это слово более русское, нежели фреймворк и мне нравится больше, хотя я и понимаю, что это только фреймворк.Движок стоился на DirectX9 таким образом, чтобы не тащить за собой никаких *d3dx* библиотек. Иными словами — кроме dll самого движка ничего не надо больше. ООП, да, всё определенно хотелось на объектах. Слабые машины, а именно поддержка интегрированного видео. Что ёще? Шейдеры, без них вообще бесполезно было и начинать.

На кроссплатформенность мне откровенно было наплевать, потому что я уверен, что нет ничего лучше, чем хороший инструмент, а сделать хороший, да еще и кроссплатформенный несколько сложнее и требует больше времени, а его у меня нет, разработка идет 4fun, для удовольствия, то есть.

Что мне помогло? Помогли, совершенно однозначно, игры, которые я или мои друзья писали с использованием quad-engine. Каждый раз выползала какая-то необходимость, которая не была тем или иным образом учтена в движке. На текущий момент на нем пишется один большой игровой проект (разумеется большой в понятиях и рамках инди-разработчиков), и он также помогает развивать мне движок вширь, править ошибки и всячески улучшать.Когда с шейдерами было покончено встал вопрос куда же развиваться дальше. А дальше развиваться было и остаётся куда. Я решил делать те вещи, на которые обычно закрывают глаза другие разработчики. А именно — мелочи. Мелочи пошли уже немного за грань фреймворка для рисования. Появился функционал создания окна, автоматической обработки потери Direct3D устройства и его восстановления, вместе со всеми потерянными рендертаргетами (этой проблемы уже нет в более старших версиях DirectX). Были добавлены такие вещи, как определение разрешений, аппаратные курсоры. Даже такой маленький нюанс, как убирание рамки вокруг окна, если оконное разрешение совпадает с экранным (так называемый borderless window). Иными словами всё, чтобы было удобно и просто. Все эти удобства как раз и рождались в процессе разработке игр. В частности последний вал обновлений связан с разработкой моей игры долгостроя Blast-off. Но о ней я раскажу в другой раз.

IGDC IGDC, или если писать полностью Independent Games Developers Contests помог мне в развитии моего движка. Участники ни раз и ни два использовали разные версии движка для конкурсных работ, писали на разных языках, в том числе помогли отточить заголовочные файлы для C#. Многие из этих работ, кстати, доступны для скачивания у меня с сайта с полными исходными кодами и указанием версии библиотеки, которая была использована.Немного видео Лучше один раз увидеть, чем сто раз услышать, верно? http://www.youtube.com/embed/nt_eM88ZNHk[embedded content]Зачем это всё? Зачем же я написал этот пост? Рассказать как всё было, возможно кому-то окажется полезным моё творение, а кто-то может быть поможет и подскажет что сделать еще. В любом случае я буду рад любым комментариям и готов написать статью на любую заинтересовавшую вас из этого повествования тему. Раскрыть её, так сказать, полнее.

© Habrahabr.ru