Программирование стратегических игр с DirectX 9.0
bda5893f

Настройка параметров отображения


Теперь объект интерфейса трехмерной графики готов к работе и пришла пора настроить параметры отображения. В нашем примере первый этап — это определение формата вторичного буфера для визуализации. Чтобы освежить знания об экранных буферах, взгляните на рис. 6.16.


Рис. 6.16. Двойная буферизация в действии

На рис. 6.16 изображены два буфера — первичный (FB) и вторичный (BB). Оба буфера содержат графические данные. В первичном буфере находится изображение, которое в данный момент отображается на экране пользователя, а вторичный буфер хранит изображение, которое будет показано следующим. Когда наступает время показа следующего изображения, вторичный бувер меняется местами с первичным, либо содержимое вторичного буфера копируется в первичный буфер. В результате на экране появляется новое изображение.

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

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

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

HRESULT GetAdapterDisplayMode( UINT Adapter, D3DDISPLAYMODE *pMode );


У функции есть два параметра, Adapter и pMode. Параметр Adapter должен содержать порядковый номер используемой видеокарты. Поскольку в компьютере могут быть установлены несколько видеокарт, важно указать правильное значение параметра. Проще всего ограничиться поддержкой одного монитора, задав значение параметра равным D3DADAPTER_DEFAULT. В этом случае система будет использовать первичный видеоадаптер, который в системах с одним монитором является единственным устройством отображения.

Второй параметр, pMode, вызывает больше вопросов, поскольку является указателем на структуру данных D3DDISPLAYMODE. После завершения работы функции эта структура данных будет содержать информацию о текущем видеорежиме. На повестку дня выностися вопрос: «Как выглядит структура данных D3DDISPLAYMODE?» А вот и ответ на него:

typedef struct _D3DDISPLAYMODE { UINT Width; UINT Height; UINT RefreshRate; D3DFORMAT Format; } D3DDISPLAYMODE;

Первый член структуры, Width, хранит ширину экрана в пикселях.

Второй член структуры, Height, хранит высоту экрана.

Третий член структуры, RefreshRate, содержит частоту кадров текущего видеорежима. Если его значение равно 0, значит установлено значение частоты по умолчанию.

Четвертое значение, Format, значительно сложнее, чем предыдущие. Эта переменная является перечислением типа D3DFORMAT и может содержать различные значения, описывающие формат поверхности для текущего видеорежима. Существует слишком много доступных значений, чтобы перечислять их здесь, так что за дополнительной информацией я рекомендую обращаться к документации DirectX SDK.

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

typedef struct _D3DPRESENT_PARAMETERS_ { UINT BackBufferWidth; UINT BackBufferHeight; D3DFORMAT BackBufferFormat; UINT BackBufferCount; D3DMULTISAMPLE_TYPE MultiSampleType; DWORD MultiSampleQuality; D3DSWAPEFFECT SwapEffect; HWND hDeviceWindow; BOOL Windowed; BOOL EnableAutoDepthStencil; D3DFORMAT AutoDepthStencilFormat; DWORD Flags; UINT FullScreen_RefreshRateInHz; UINT PresentationInterval; } D3DPRESENT_PARAMETERS;



Первые два элемента структуры, BackBufferWidth и BackBufferHeight, достаточно просты; они просто хранят размеры буфера.



Следующий член данных, BackBufferFormat, содержит используемый для вторичного буфера формат поверхности. Здесь мы воспользуемся тем самым форматом, который получили ранее при вызове функции GetAdapterDisplayMode().

Затем мы задаем тип множественной выборки, хранящийся в переменной MultiSampleType. Эта переменная имеет тип D3DMULTISAMPLE_TYPE. Ух ты — еще одно перечисление! Давайте обратимся к таблице 6.1, чтобы разобраться в элементах этого нового перечисления и их назначении.

Таблица 6.1. Типы множественной выборки

Значение Описание
D3DMULTISAMPLE_NONE Множественная выборка отсутствует.
D3DMULTISAMPLE_NONMASKABLE Разрешает использование значений уровня качества.
D3DMULTISAMPLE_2_SAMPLES Доступно две выборки.
D3DMULTISAMPLE_3_SAMPLES Доступно три выборки.
D3DMULTISAMPLE_4_SAMPLES Доступно четыре выборки.
D3DMULTISAMPLE_5_SAMPLES Доступно пять выборок.
D3DMULTISAMPLE_6_SAMPLES Доступно шесть выборок.
D3DMULTISAMPLE_7_SAMPLES Доступно семь выборок.
D3DMULTISAMPLE_8_SAMPLES Доступно восемь выборок.
D3DMULTISAMPLE_9_SAMPLES Доступно девять выборок.
D3DMULTISAMPLE_10_SAMPLES Доступно десять выборок.
D3DMULTISAMPLE_11_SAMPLES Доступно одиннадцать выборок.
D3DMULTISAMPLE_12_SAMPLES Доступно двенадцать выборок.
D3DMULTISAMPLE_13_SAMPLES Доступно тринадцать выборок.
D3DMULTISAMPLE_14_SAMPLES Доступно четырнадцать выборок.
D3DMULTISAMPLE_15_SAMPLES Доступно пятнадцать выборок.
D3DMULTISAMPLE_16_SAMPLES Доступно шестнадцать выборок.
D3DMULTISAMPLE_FORCE_DWORD Не используется.
Множественная выборка необходима для визуализации с включенным сглаживанием. Не знаете что такое сглаживание? Взгляните на рис. 6.17, чтобы увидеть его в действии.

Рис. 6.17. Сглаживание
На рис. 6.17 изображены две линии. Линия, изображенная слева, имеет ступенчатые края. У линии справа края сглажены. Обратите внимание, что линия справа выглядит более гладкой, а линия слева — более зазубренной. Это достигается благодаря использованию более светлых серых пикселей по краям линии. Если ваша видеокарта поддерживает сглаживание, вы можете включить его, чтобы графика в играх, поддерживающих эту технологию, выглядела более гладкой. Если видеокарта не поддерживает данную технологию, возможно пора подумать о ее замене.

ПРИМЕЧАНИЕ



Запомните, что множественная выборка корректно работает только в том случае, если значение параметра, определяющего режим работы цепочки переключения экранных буферов равно D3DSWAPEFFECT_DISCARD. Вернемся к представленным параметрам. Следующий параметр в списке называется MultiSampleQuality и имеет тип DWORD. Как вы, возможно, догадались, этот параметр устанавливает качество множественной выборки. Его значение может находиться в диапазоне от нуля до максимально возможного уровня, возвращаемого функцией IDirect3D9::CheckDeviceMultiSampleType(), минус один.

Далее расположен параметр SwapEffect. Он сообщает системе визуализации о том, каким образом во время визуализации будет выполняться переключение экранных буферов. Параметр может принимать одно из значений перечисления D3DSWAPEFFECT. Значения этого перечисления и их описание приведены в таблице 6.2.

Таблица 6.2. Режимы переключения экранных буферов

Значение Описание
D3DSWAPEFFECT_DISCARD Разрешает драйверу видеокарты самому выбрать наиболее эффективный метод переключения. Этот метод обычно быстрее, чем другие. Единственная проблема этого метода заключается в том, что он негарантирует сохранность вторичного буфера и его содержимого. Так что при использовании этого метода вы не можете полагаться на неизменность содержимого вторичного буфера. Вы должны использовать этот метод, если значение параметра, определяющего тип множественной выборки, отличается от D3DMULTISAMPLE_NONE.
D3DSWAPEFFECT_FLIP Использует циклическую схему экранных буферов. Буферы перемещаются по кругу в замкнутой кольцевой очереди. Метод позволяет добиться гладкой визуализации, если значение параметра, определяющего интервал переключения не равно D3DPRESENT_INTERVAL_IMMEDIATE.
D3DSWAPEFFECT_COPY Этот метод может использоваться только в том случае, если у вас есть один вторичный буфер. Кроме того, этот метод гарантирует неизменность изображения во вторичном буфере. Недостатком метода является то, что в оконном режиме он может вызвать нарущения целостности графики. Это вызвано тем, что изображение выводится во время обратного хода кадровой развертки монитора. Не используйте этот метод, если ваша программа работает в оконном режиме и вам необходима гладкая графика.
D3DSWAPEFFECT_FORCE_DWORD Не используется
<


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

Следующий член данных, Windowed, указывает будет ли использоваться оконный режим, или программа будет работать в полноэкранном режиме. Установите значение TRUE для оконного режима и FALSE — для полноэкранной визуализации.

Затем расположен флаг EnableAutoDepthStencil. Он сообщает системе визуализации будет ли она управлять буфером глубины или нет. Если вы присвоите данному параметру значение TRUE, Direct3D будет управлять буфером глубины за вашу программу.

Следующий член структуры, названный AutoDepthStencilFormat, устанавливает используемый формат буфера глубины. Он используется только в том случае, если значение параметра EnableAutoDepthStencil равно TRUE. Если вы используете автоматическую установку буфера глубины, убедитесь, что в этом параметре вы указали корректный формат.

Следующий член данных в списке носит неопределенное имя Flags. Вы не слишком любите такие прямолинейные имена как это? Значения для этого параметра перечислены в таблице 6.3.

Таблица 6.3. Флаги режима отображения

Значение Описание
D3DPRESENTFLAG_LOCKABLE_BACKBUFFER Разрешает приложению блокировать вторичный буфер.
D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL Разрешает системе освобождать z-буфер после каждого отображения данных буфера. Это может увеличить быстродействие, если драйвер видеокарты поддерживает данную возможность.
D3DPRESENTFLAG_DEVICECLIP Область визуализации в оконном режиме будет обрезаться. Работает только в Windows 2000 и Windows XP.
D3DPRESENTFLAG_FORCEGDIBLT Для копирования изображений будет использоваться GDI. Работает только в Windows 2000 и Windows XP.
D3DPRESENTFLAG_VIDEO Сообщает драйверу видеокарты, что вторичный буфер содержит видеоданные.
Следующий член данных называется FullScreen_RefreshRateInHz. Его назначение достаточно очевидно: он задает частоту с которой видеокарта будет обновлять изображение на экране монитора. Для визуализации в оконном режиме здесь следует указать значение D3DPRESENT_RATE_DEFAULT; в этом случае будет установлена частота кадров по умолчанию данной видеокарты.



Ах, вот и последний элемент параметров отображения! Он называется PresentationInterval. Эта переменная устанавливает максимальную частоту, с которой будет отображаться вторичный буфер. Оконные приложения требуют, чтобы значение этого параметра было D3DPRESENT_INTERVAL_IMMEDIATE. Для полноэкранной визуализации можно использовать значение D3DPRESENT_INTERVAL_DEFAULT или одно из значений, перечисленных в таблице 6.4.

Таблица 6.4. Интервалы отображения

Значение Описание
D3DPRESENT_INTERVAL_DEFAULT Система сама выбирает частоту смены кадров. В оконном режиме используется частота по умолчанию.
D3DPRESENT_INTERVAL_ONE Перед отображением графики система ждет один период кадровой развертки.
D3DPRESENT_INTERVAL_TWO Перед отображением графики система ждет два периода кадровой развертки.
D3DPRESENT_INTERVAL_THREE Перед отображением графики система ждет три периода кадровой развертки.
D3DPRESENT_INTERVAL_FOUR Перед отображением графики система ждет четыре периода кадровой развертки.
D3DPRESENT_INTERVAL_IMMEDIATE Система не ожидает завершения кадровой развертки перед выводом изображения. Этот метод может вызвать несогласованность графики.

Содержание раздела