Давайте напишем ... MMO! Часть 12: Приключения в стране OpenGL

Опубликовано NowhereMan -

10 февраля 2011

В последней части я пытался ускорить код рендеринга, чтобы отобразить больший мир. Вот мои последние показатели:

Непрозрачные: 1,87 мс Прозрачные: 16,49 мс Всего: 18,36 мс Частота кадров: 54 fps

Чтобы сделать еще быстрее, мне были нужны массивы текстур. Я подумал, что это ускорит рендер прозрачных деталей еще на 5 мс, что было бы неплохо, но несущественно. Чтобы получить эту возможность, я мог либо перейти на DX 10, либо переключиться на OpenGL, либо посмотреть, смогу ли я сделать все сам в шейдерах с DX 9.

Так как использование OpenGL потенциально могло бы дать мне пользователей MacOS и Linux без потери пользователей Windows XP, я решил изучить его последнюю версию (я игрался с версией 1.1 много лет назад). Я купил электронную копию OpenGL SuperBible и начал работать с ней. Это заняло почти всю неделю.

К сожалению, теперь, когда у меня есть демо-версия, работающая под OpenGL, я получил такие результаты:

Непрозрачные: 1,95 мс Прозрачные: 27.19 мс Всего: 29,14 мс Частота кадров: 34 fps

Как видите, время отрисовки прозрачных элементов гораздо хуже, чем при реализации DirectX. Так как задействовано всего несколько вызовов API, я не знаю, что и попробовать. Мне все равно придется изменить код, чтобы использовать массивы текстур, что сэкономит мне хотя бы немного времени. Если все вызовы OpenGL API будут связаны с большими накладными расходами, это может сэкономить много времени. Я буду продолжать экспериментировать.

Я попробовал код на своей старой машине с Windows XP, и он отлично работал. Это подтолкнуло меня к тому, что я не потеряю ни одного пользователя XP. Но затем я попробовал его на своем ноутбуке, с Windows 7 и видеокартой ATI Radeon HD 3450. Он пожаловался, что драйвер поддерживает только OpenGL 2.1 или что-то в этом роде.

Я обновил драйверы с сайта ATI (на сайте Dell ничего не было), а в новой версии сказано, что она поддерживает OpenGL 3.3, которая работает на моем десктопе. К сожалению, компилятор шейдеров испортил все шейдеры, которые отлично работали с двумя видеокартами Nvidia. После некоторой чистки я заставил три из четырех шейдеров скомпилироваться и запуститься. Последний из них использует "Rectangle Textures " (для курсора), и, видимо, эта возможность не поддерживается ATI.

Это реальная проблема, так как это означает, что я не могу рассчитывать на определенный набор возможностей при разработке кода. Я не уверен, чего ожидать под MacOS и Linux, или на другом оборудовании. Ох. Я действительно считаю непростительным, что ATI и NVidia поддерживают немного разный синтаксис для языка шейдеров. Разве комитет OpenGL не написал точную грамматику для этой штуки?

Я установил xcode на свой Hackintosh и скомпилировал один из их примеров OpenGL. Чтобы перенести демоверсию, мне нужно лишь пролистать всю документацию по разработке для MacOS. Не уверен, буду ли я делать это прямо сейчас, или еще немного поработаю над версией для Windows.

Если мой интерес к OpenGL сохранится достаточно долго, я намерен перенести его и на Linux. Можете ли вы, пользователи Linux, показать мне вашу любимую IDE и инструменты для разработки на C++/OpenGL?

Та еще куча...

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

  • Код написан на С++, и вы должны его знать. Но также необходимо знать обычный C и быть хорошо знакомым с препроцессором. Это потому, что программируя на C++, довольно часто отладчик бросает вас в какую-нибудь библиотеку, написанную на C. Библиотеки "glew" и "freeglut", поставляемые вместе с SuperBible, обе написаны на C. Обе имеют секции, которые представляют собой лабиринт ссылок на макросы, и #ifdef'ы для работы с несколькими платформами. Если вы не можете прочитать этот код, вам будет сложно понять, почему ваша программа упала в библиотеке.
  • Нужно знать хотя бы программирование для Windows/MacOS/Linux, чтобы не только правильно инициализировать, но и работать с входом, звуком, несколькими потоками, критическими секциями и т.д. Такой код не тривиален для отладки.
  • Для работы с координатными пространствами в 3D необходимо знать хотя бы основы алгебры и тригонометрии, а также знать, что делают все эти dot product-ы и умножения матриц.
  • Интерфейс OpenGL проще, чем когда-либо, так как они перешли на шейдеры для всего, но там еще есть что изучить.
  • И наконец, нужно знать, как работают шейдеры, чему я еще учусь.

Помимо сложности изучения, весь этот стек программного обеспечения, снизу вверх, известен своей хрупкостью и беспощадностью. Даже после десятилетий опыта работы с Си++, все еще бывают моменты, когда я получаю сообщение об ошибке от компилятора и думаю: "На что, черт возьми, ты жалуешься сейчас?". Сделайте что-нибудь не так в Windows или OpenGL API и ваша программа падает без объяснения причин.

Самые банальные ошибки в коде могут отбросить вас на несколько часов назад. Когда я закончил свой первый проход в демо-версии OpenGL, я запустил его и получил ... черное окно. Это раздражало, так как я отлаживал весь графический код в меньшей автономной демо-версии, а остальная часть была такой же, как и моя DirectX-версия. Я знал, что генерирую правильный список вершин и индексов, устанавливаю правильную проекцию и просматриваю матрицы. Так почему же никакого вывода?

Я перешагнул через огромное количество кода, вставлял все больше отладочных операторов, проверял коды возврата OpenGL в большем количестве мест, и не нашел никаких проблем. Насколько я мог судить, он все делал правильно. После того, как я не спал всю ночь, я, наконец, бросил все в 5 утра. И как только моя голова коснулась подушки, я подумал "Mipmapping!" и снова встал с кровати. Оказалось, что в этом и была проблема.

"Mipmapping" - это когда библиотека производит несколько версий текстуры с более низким разрешением для использования на больших расстояниях. Так что для текстуры 128 на 128 она также будет генерировать 64 на 64, 32 на 32 и т.д. версии. Я забыл поставить вызов на генерацию этих версий, а это значит, что все версии с более низким разрешением черные. Так что мой код все делал правильно, но рисовал черные треугольники поверх других черных треугольников, на черном фоне! Ох...

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

Детские игрушки?

Я делаю успехи в проекте, но все еще сравниваю все это с тем, с чем я имел дело в младшей школе, когда учился программированию, еще в 1971 году. Это было очень необычно для любого ребенка в то время иметь доступ к компьютеру, а тем более учиться программированию. Но программировать этот старый мейнфрейм было легко по сравнению с этим. Все, с чем мне приходилось иметь дело - это один язык программирования (не Си, не Си++ и не шейдер), практически не имеющий API. Вы просто писали текст на терминале типа пишущей машинки.

Моими первыми программами были игры. Карточная игра, "звездный путь" и очень, очень плохие шахматы. Я думаю, что ребенок сегодня тоже захочет написать игру. Поскольку он играл в игры с тех пор, как мог нажимать кнопки на консоли, он, наверное, захочет написать 3D-игру. Но он больше не может просто написать простую программу на Basic. Эта огромная стопка ПО, пара тысяч страниц учебника и немного математики - вот с чем ему приходится иметь дело!

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

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

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

В-третьих, есть и другие языки, на которых можно писать. Может быть, кто-то из вас работает в игровой индустрии и может сказать, пишут ли до сих пор люди на Си++? Большинство игр делают художники/дизайнеры, которые используют движок, написанный несколькими хардкорными программистами на Си++? Игры "indie" сделаны таким же образом?

Учитывая мои навыки, мне нравится выбранный здесь подход - большое приложение на C++, занимающееся графикой на самом низком уровне. Но, работая с OpenGL, я задался вопросом, не выбрал ли я, туристическую тропу через горы, когда внизу отличное шоссе...

Я также подумал, может быть, какой-нибудь ребенок где-нибудь еще берет книгу по программированию и пишет что-нибудь замечательное, или мы сделали это невозможным?