Настройка параметров отображения
Теперь объект интерфейса трехмерной графики готов к работе и пришла пора настроить параметры отображения. В нашем примере первый этап — это определение формата вторичного буфера для визуализации. Чтобы освежить знания об экранных буферах, взгляните на рис. 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. Сглаживание |
ПРИМЕЧАНИЕ
Далее расположен параметр 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 | Сообщает драйверу видеокарты, что вторичный буфер содержит видеоданные. |
Ах, вот и последний элемент параметров отображения! Он называется 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 | Система не ожидает завершения кадровой развертки перед выводом изображения. Этот метод может вызвать несогласованность графики. |