...

пятница, 29 августа 2014 г.

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

Предисловие.




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

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


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


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


Как только с текстурированием, загрузкой и отрисовкой было покончено, сразу же все силы были брошены на прикручивание шейдеров (и пробы деллались с бамп-меппингом и спекуляром):



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

Кстати, вот она эта утилита:


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


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


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


Шейдеры




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

Шаг 1: Рисуем диффузную текстуру


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


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


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


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


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


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


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


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


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


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


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


Псевдовекторные шрифты




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

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

Крик души




А давайте чтобы избежать непонимания и холиваров, я попрошу просто принять тот факт, что движок писался и продолжает писаться на 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://ift.tt/1pp463q


Зачем это всё?




Зачем же я написал этот пост? Рассказать как всё было, возможно кому-то окажется полезным моё творение, а кто-то может быть поможет и подскажет что сделать еще. В любом случае я буду рад любым комментариям и готов написать статью на любую заинтересовавшую вас из этого повествования тему. Раскрыть её, так сказать, полнее.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий