DirectX для начинающих.

== Введение ==
Фанаты игр часто встречаются с аббревиатурой "DirectX". На упаковках игр для Windows 95 она появилась в конце 1995 года примерно одновременно с выходом самой операционной системы. С тех пор качество игр резко ушло вверх, достигнув небывалых высот. Что же такое DirectX? Это набор специальных API, которые предоставляют работающей программе прямой доступ к аппаратной части компьютера, обеспечивая наивысшее быстродействие при выводе графики, звука, получения данных от устройств ввода и т. д. Сразу надо сказать, что библиотека создавалась исключительно для игр, т. к. именно они требуют от аппаратных средств все 100% производительности. Позднее, с выходом новых версий, DirectX нашёл применение и в мультимедиа-области.
Компоненты DirectX обеспечивают не только прямой доступ к устройствам компьютера: они избавляют программиста от тяжелого труда программирования на языке Assembler, решают проблему с драйверами устройств, незаменимы при создании трёхмерных и сетевых игр. До появления DirectX хороших сетевых игр было не так уж много по причине трудности их программирования.
На сегодняшний день последняя версия DirectX носит порядковый номер 8.1, что позволяет задуматься, сколько утекло времени. Библиотека полностью обеспечивает разработчика всем необходимым инструментарием для разработки качественных игр, поддерживает все современные аппаратные средства и стала де-факто стандартом в игровой индустрии игр для персонального компьютера IBM PC.
DirectX 8 состоит из следующих компонентов:
* Direct3D - содержит высокоуровневый интерфейс Retained Mode позволяющий легко выводить 3-хмерные графические объекты, и низкоуровневый интерфейс Immediate Mode, предоставляющий полный контроль над рендерингом. В восьмой версии реализована новая технология вершинных шейдеров, позволяющая поднять уровень реалистичности изображения в новых играх. По своей функциональности вплотную приближается к OpenGL 1.2.
* DirectDraw - предназначен для отображения двумерной анимации на экране монитора. Обеспечивает прямой доступ к видеоадаптеру, за счёт чего достигается быстрый вывод графики, по скорости на порядок превышающий GDI. Эти два компонента в восьмой версии объединены в один - DirectXGraphics. Однако, лично я не почувствовал сколь-нибудь характерных изменений (в DirectDraw API). Всё это скорее похоже на маркетинговый ход.
* DirectSound - создан для прямого доступа к аппаратной части звуковых плат, чтобы избавить воспроизведение звука от "тормозов", которые возникают при работе с Win32 API.
* DirectMusic - работает с музыкальными командами, посылаемыми звуковой карте. DirectMusic и DirectSound восьмой версии объединены в один компонент - DirectXAudio.
* DirectInput - эта компонента отвечает за любые устройства ввода, например, аналоговые или цифровые джойстики, рули и педали, ручку управления полётом, световой карандаш или Touch-Screen. Некоторые возможности компоненты можно реализовать средствами Win32 API, получив такой же быстрый доступ, но в некоторых областях DirectInput незаменим (поддерживает технологию force-feedback и нестандартные устройства ввода).
* DirectPlay - упрощает жизнь программиста, решившегося добавить в своей программе возможность совместной работы (игры) по сети или по модему (это наверняка хорошо знакомо любому геймеру). В восьмой версии эта компонента значительно переработана и улучшена.
* DirectSetup - предназначен для установки DirectX.
* DirectShow - используется в мультимедиа-технологиях - можно выполнить высококачественное воспроизведение или захват видео и звука. Распространённость использования компоненты не слишком велика
Все компоненты реализованы как внутрипроцессные серверы, т.е. размещаются в DLL. Архитектура доступа базируется на технологии COM. Значит, для использования DirectX нам понадобится среда программирования, поддерживающая обращение к функциям DLL из готовых программ и поддержка COM. Delphi легко реализует всё это, а значит, можно создавать такие же качественные программы, как и в Visual C++: понадобятся только файлы заголовков для DirectX 8.
== Как я изучал компьютерную графику ==
Когда я только начинал заниматься графикой в Delphi, я применял всякие компоненты VCL вроде TBitmap и TImage. Надо сказать, дело шло: я самостоятельно разобрался с методами Canvas, догадался об необходимости буферизации при графическом выводе, сделал полноэкранную игру (правда, недоделал до конца :-(( ). Меня удивляло только то, что фигурки двигались довольно порывисто (разрешение составляло 800*600), и избавиться я от этого не мог. Постепенно я понял, что это не жизнь и начал изучать GDI. Через некоторое время я полностью закинул TBitmap'ы и мои программы работали исключительно через функции GDI. Но и здесь вывод был слишком медленнен и пригоден разве что при разрешении 400*300 и менее. Также большой проблемой было осуществление вывода нерегулярных спрайтов (картинок с прозрачными областями), т.к. в GDI для этого нужно подготовить маску и сам спрайт. Как ни странно, впервые с DirectX (DirectDraw) я познакомился в книге Михаила Краснова "OpenGL.Графика в проектах Delphi". На дискете с книгой поставлялся пример для изменения экранного разрешения с помощью DirectDraw и заголовочный файл. Начинал я с того, что просто заново набирал исходный текст в своих проектах, "заучивая" особенности DirectDraw API. Тогда всё это выглядело довольно странным и непонятным, даже QueryInterface() был полной загадкой. На самом деле всё становится достаточно прозрачно, но только после практики соответствующего объёма. DirectDraw решил проблемы медленного вывода, а также помог при выводе прозрачных спрайтов. Теперь мои программы работают максимально быстро, а уровень программирования достиг "профессионального", ведь я использую те же самые способы, что и разработчики серьёзных игровых программ.
Когда я ещё не имел доступа в Сеть, работать пришлось с заголовочными файлами от Hiroyuki Hori для DirectX 6 - их я достал на CD-ROM. Но теперь я использую DirectX 8. Вообще, надо приучить себя двигаться в ногу со временем и использовать новейшие технологии, даже если не хочется "слезать" с насиженной старой. И хотя никаких скоростных преимуществ при использовании методов DirectDraw из SDK 8 по сравнению c SDK 5 или 6 уже, наверное, не получить, предпосылок к использованию старых версий нет. Тем более что Microsoft стремится сделать отличия между API разных версий минимальными, а новейшая runtime-часть DirectX установлена уже наверняка у 99% игроманов.
== На кого рассчитаны примеры ==
Все примеры рассчитаны на новичков. Даже если вы переиграли во все мыслимые игры, они не сделали из вас гуру в DirectX. Мне очень не хотелось перегружать программные примеры необязательными подробностями, поэтому все они (за исключением Sound), максимально упрощены. Мне хорошо известно, насколько трудно разбирать программы, написанные кем-то другим, если они ещё и большие по размеру. Все возможности игрового комплекса не используются, в частности, не показано, как корректно выводить в DirectDraw спрайты, выходящие за границы экрана, как плавно гасить экран и т. д. Всё это только усложняет программу - суть, сердце механизма работы компоненты теряется в дебрях кода, обеспечивающего примеру лишь красочность.
Здесь вы не найдёте примеров для Direct3D и DirectMusic - я ещё сам только начинаю изучать трёхмерную графику (в основном пока OpenGL), а с MIDI-звуками связываться отказываюсь из-за примитивности технологии. DirectPlay тоже остался без внимания - это не мои интересы.
Всегда начинайте рассмотрение программы с самого начала - процедуры FormCreate() главной формы, это поможет начать изучение структуры алгоритма.
Я не ставил своей целью переписать главы книг по DirectX при составлении сопроводительных лекций - поэтому дал только самые общие разъяснения, которые, надеюсь, помогут ответить на немые вопросы новичков.
Предполагается, что читатель владеет Delphi и умеет программировать на Object Pascal. Если вы до сих пор программировали только с использованием VCL, переход на API-подобный код может оказаться болезненным - забудьте про размещение компонент на форме подобно набору DelphiX и т. п. - сразу скажу, всё это глупости.
Иногда я говорю "необходимо передать адрес переменной" - но в некоторых случаях символ @ перед переменной не ставится, а иногда он есть. Смотрите интерфейсы функций в заголовочных файлах - вы встретите зарезервированные слова var, out и const, которые указывают на необходимость работы с адресами.
== Что вам понадобится ==
Все проекты строились в IDE Delphi 5. В версии 3 ошибки будут возникать уже на этапе компиляции, хотя бы из-за того, что в модуле DirectXGraphics.pas повсеместно используется тип LongWord, в третьей версии неопределённый. В версии 4 компилировать не пробовал, её у меня нет, возможно (не знаю точно), в среде не будут отображаться формы проектов. Также необходимы файлы заголовков для DirectX. Хотя существует множество различных файлов, для того, чтобы следовать хоть какому-то стандарту, я использовал файлы заголовков, загруженные с сайта www.delphi-jedi.org/delphigraphics. Эти файлы разработаны энтузиастами и представляют собой переложение файлов DirectX SDK фирмы Microsoft на язык Object Pascal. И, конечно же, нужны runtime-библиотеки DirectX 8. Их можно установить с компакт-диска DirectX SDK фирмы Microsoft. В крайнем случае возьмите какую-нибудь новую игру.
Если вы всё же решите изучать DirectX по моим примерам, то сперва прочитайте файлы readme.txt и BUGS.txt - в нём я описал некоторые возникшие проблемы и недоработки.
Скачать примеры: DirectX_Smpl.zip (125 K)
Описания примеров:
* Enum
Иногда необходимо узнать, какое оборудование установлено в компьютере, удовлетворяет ли оно предъявленным требованиям и т. д. Например, к компьютеру может быть подключено несколько игровых контроллеров, и нужно дать возможность игроку выбрать для управления одно из них, а не первое попавшееся. К тому же, их вообще может не быть, и об этом тоже надо знать. Если установлены две звуковые карты, то одна из них може иметь аппаратную поддержку DirectX, а другая - нет. Одним словом, нужно иметь список наличествующего оборудования. DirectX и его компоненты могут обеспечить такое перечисление разных устройств для их выбора.
В этом проекте в простой форме осуществляется перечисление установленных видеоадаптеров, звуковых карт и устройств ввода. Надеюсь, вы разберётесь с этими возможностями DirectX самостоятельно.
* DirectInput API
Прежде чем начать знакомиться с примерами по DirectInput, желательно изучить общий механизм работы этого API, т .к. он одинаков в общих чертах для всех устройств ввода. Впоследствии я не буду останавливаться на повторяющихся приёмах, т. к. объясню их суть здесь.
* Sprite
Этот пример демонстрирует вывод изображения средствами DirectDraw. Он построен без использования VCL, но я надеюсь это не помешает вам.
* Sound
Одним из достоинств компоненты DirectSound является то, что она имеет прямой (ну, почти прямой) доступ к аппаратному обеспечению звуковой карты. Среди интересных возможностей следует выделить размещение данных в памяти звуковой платы, использование аппаратного микширования звука, возможность создавать объёмный звук, используя специальные алгоритмы (это нужно для 3D-игр) - всё это мультимедиа-средства Windows обеспечить не в состоянии
Виктор Кода