На Рисунок 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, чтобы увидеть его в действии.