netlib.narod.ru< Назад | Оглавление | Далее >

1.3. Предварительная подготовка

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

1.3.1. Поверхности

Поверхность (surface) — это прямоугольный массив пикселей, используемый Direct3D в основном для хранения двухмерных изображений. Основные параметры поверхности представлены на рис. 1.2. Обратите внимание, что хотя мы представляем данные поверхности в виде матрицы, в действительности данные пикселей хранятся в линейном массиве.


Рис. 1.2. Поверхность

Рис. 1.2. Поверхность


Ширина и высота поверхности измеряются в пикселах. Шаг (pitch) поверхности измеряется в байтах. Более того, шаг поверхности может отличаться от ее ширины в зависимости от используемого оборудования. Вы не должны считать, что шаг = ширина * sizeof(пиксель).

В коде поверхность представляется интерфейсом IDirect3DSurface9. Он предоставляет методы для прямого чтения и записи данных поверхности, а также методы для получения информации о поверхности. Вот наиболее важные методы интерфейса IDirect3DSurface9:

Принимая во внимание наличие такого параметра, как шаг поверхности, блокировка поверхности и запись отдельных пикселей могут вызвать затруднения. Поэтому мы приводим фрагмент кода в котором поверхность блокируется и заполняется пикселями красного цвета:

// Предполагается, что _surface - указатель на интерфейс IDirect3DSurface9
// Предполагается, что у поверхности 32-разрядный формат пикселей

// Получаем описание поверхности
D3DSURFACE_DESC surfaceDesc;
_surface->GetDesc(&surfaceDesc);

// Получаем указатель на данные пикселей поверхности
D3DLOCKED_RECT lockedRect;
_surface->LockRect(
      &lockedRect,    // получаемый указатель на данные
      0,              // блокируем всю поверхность
      0);             // дополнительных параметров блокировки нет

// Перебираем все пиксели поверхности и делаем их красными
DWORD* imageData = (DWORD*)lockedRect.pBits;
for(int i = 0; i < surfaceDesc.Height; i++)
{
    for(int j = 0; j < surfaceDesc.Width; j++)
    {
        // индекс в текстуре, обратите внимание, что мы используем шаг и
        // делим его на 4, поскольку шаг задается в байтах,
        // а каждый пиксель занимает 4 байта.
        int index = i * lockedRect.Pitch / 4 + j;

        imageData[index] = 0xffff0000; // красный цвет
    }
}
_surface->UnlockRect();

Структура D3DLOCKED_RECT определена следующим образом:

typedef struct _D3DLOCKED_RECT {
    INT Pitch;   // шаг поверхности
    void *pBits; // указатель на начало памяти поверхности
} D3DLOCKED_RECT;

Приведем несколько комментариев к коду блокировки поверхности. Очень важно предположение о 32-разрядном формате пикселей, поскольку мы выполняем приведение к типу DWORD, который является 32-разрядным. Благодаря этому мы можем считать, что каждое значение DWORD представляет один пиксель. И не заморачивайтесь о том, как 0xffff0000 представляет красный цвет — мы поговорим об этом в главе 4.

1.3.2. Множественная выборка

Множественная выборка (multisampling) — это техника, использующаяся для сглаживания ступенчатых линий на изображении, представленном в виде матрицы пикселей. Наиболее частое применение множественной выборки — полноэкранное сглаживание (full-screen antialiasing) (рис. 1.3).


Рис. 1.3. Множественная выборка

Рис. 1.3. Слева изображена линия с зазубренным краем. Справа — та же линия, но с использованием множественной выборки, выглядящая более гладкой


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

От типа множественной выборки зависит уровень качества. Тип констант — DWORD.

В примерах из этой книги множественная выборка не используется, поскольку она сильно замедляет работу приложений. Если вы захотите добавить ее, не забудьте вызвать метод IDirect3D9::CheckDeviceMultiSampleType, чтобы проверить поддерживает ли используемое устройство множественную выборку и определить допустимые уровни качества.

1.3.3. Формат пикселей

При создании поверхностей или текстур нам часто надо будет определить формат пикселей ресурсов Direct3D. Формат определяется как член перечисления D3DFORMAT. Вот некоторые форматы:

Полный список поддерживаемых форматов пикселей приведен в описании перечисления D3DFORMAT в документации к SDK.

ПРИМЕЧАНИЕ
Первые три формата (D3DFMT_R8G8B8, D3DFMT_X8R8G8B8 и D3DFMT_A8R8G8B8) широко распространены и поддерживаются большинством современных видеокарт. Поддержка форматов с плавающей точкой и некоторых других форматов (упомянутых в документации SDK) встречается реже. При использовании малораспространенного формата не забудьте проверить перед его использованием, что установленная видеокарта поддерживает его.

1.3.4. Пул памяти

Поверхности и другие ресурсы Direct3D могут быть размещены в различных областях памяти. Используемая область памяти задается с помощью одной из констант перечисления D3DPOOL. Доступны следующие варианты:

1.3.5. Цепочка обмена и переключение страниц

Direct3D управляет набором поверхностей, обычно двумя или тремя, который называется цепочка обмена (swap chain) и представляется интерфейсом IDirect3DSwapChain9. Мы не будем подробно говорить об этом интерфейсе, поскольку всю работу берет на себя Direct3D и вмешиваться в его действия приходится очень редко. Вместо этого мы поговорим о его назначении и общих принципах работы.

Цепочка обмена и, говоря более точно, техника переключения страниц, используется для достижения плавности анимации. На рис. 1.4 показана цепочка обмена, состоящая из двух поверхностей.


Рис. 1.4. Цепочка обмена

Рис. 1.4. Цепочка обмена из двух поверхностей (первичного и вторичного буфера)


На рис. 1.4 в первичном буфере (front buffer) находится та поверхность, которая в данный момент отображается на экране монитора. Монитор не показывает изображение находящееся в первичном буфере мгновенно; например, при установленной для монитора частоте кадров 60 Гц, вывод изображения занимает одну шестидесятую секунды. Частота кадров в приложении часто отличается от частоты кадров монитора (например, приложение может визуализировать кадр быстрее, чем монитор отобразит его). Мы не хотим обновлять содержимое первичного буфера, занося в него следующий кадр, в то время, когда монитор еще не закончил отображать текущий, но мы также не хотим останавливать визуализацию кадров, чтобы подождать, пока монитор полностью выведет текущий кадр. Поэтому мы визуализируем кадр во внеэкранной поверхности (вторичном буфере, back buffer); затем, когда монитор закончит отображение поверхности из первичного буфера, мы перемещаем этот буфер в конец цепочки обмена, и передвигаем в цепочке вторичный буфер, чтобы он стал первичным.

Этот процесс называется показом (presenting). На рис. 1.5 показана цепочка обмена до и после показа.


Рис. 1.5. Показ

Рис. 1.5. Показ. Используя содержащую две поверхности цепочку обмена, мы видим, что основу показа составляет переключение поверхностей


Таким образом, структура кода визуализации будет следующей:

  1. Визуализировать вторичный буфер.

  2. Показать вторичный буфер.

  3. Перейти к пункту 1.

1.3.6. Буфер глубины

Буфер глубины (depth buffer) — это поверхность, которая содержит не изображение, а информацию о глубине отдельных пикселей. Каждому пикселю в окончательном изображении соответствует элемент буфера глубины. Так, если размер окончательного изображения 640 × 480 пикселей, в буфере глубины должно быть 640 × 480 элементов.

На рис. 1.6 показана простая сцена, где одни объекты частично скрывают другие, находящиеся позади них. Чтобы определить, пиксели какого объекта находятся поверх всех других, Direct3D использует технологию, называемую буфером глубины (depth buffer) или z-буферизацией (z-buffering).


Рис. 1.6. Группа объектов, частично закрывающих друг друга

Рис. 1.6. Группа объектов, частично закрывающих друг друга


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

Формат буфера глубины определяет точность сравнения глубины пикселей. То есть 24-разрядный буфер глубины обеспечвает более высокую точность, чем 16-разрядный. Большинство приложений замечательно работают с 24-разрядным буфером глубины, хотя Direct3D поддерживает и 32-разрядный буфер.

 

ПРИМЕЧАНИЕ
Буфер трафарета представляет собой более сложную тему, которая будет подробно разобрана в главе 8.

1.3.7. Обработка вершин

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

Аппаратная обработка вершин всегда предпочтительнее, поскольку выполняется гораздо быстрее, чем программная. Кроме того, аппаратная обработка вершин освобождает центральный процессор, который, благодаря этому, может выполнять другие задачи.

ПРИМЕЧАНИЕ
Иногда, вместо того, чтобы сказать, что видеокарта поддерживает аппаратную обработку вершин, говорят что видеокарта поддерживает аппаратную обработку преобразований и расчета освещения.

1.3.8. Возможности устройств

Каждой возможности, предлагаемой Direct3D соответствует член данных или бит в структуре D3DCAPS9. Идея состоит в том, чтобы инициализировать экземпляр структуры D3DCAPS9 на основании фактических возможностей конкретного устройства. Затем, в нашем приложении, мы можем проверить, поддерживает ли устройство требуемую возможность, проверив соответствующий член данных или бит в экземпляре D3DCAPS9.

Это иллюстрирует следующий пример. Предположим, мы хотим проверить способно ли устройство осуществлять аппаратную обработку вершин (или, другими словами, поддерживает ли устройство аппаратную обработку преобразований и расчета освещения). Посмотрев описание структуры D3DCAPS9 в документации SDK, мы обнаружим, что бит D3DDEVCAPS_HWTRANSFORMANDLIGHT в члене данных D3DCAPS9::DevCaps указывает, поддерживает ли устройство аппаратную обработку преобразований и расчета освещенности. Следовательно наша проверка, подразумевая, что caps — это экземпляр структуры D3DCAPS9, будет выглядеть следующим образом:

bool supportsHardwareVertexProcessing;

// Если бит установлен, значит данная возможность
// поддерживается устройством
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
    // Бит установлен - возможность поддерживается
    supportsHardwareVertexProcessing = true;
}
else
{
    // Бит сброшен - возможность не поддерживается
    hardwareSupportsVertexProcessing = false;
}

 

ПРИМЕЧАНИЕ
DevCaps означает «возможности устройства» (device capabilities).

 

ПРИМЕЧАНИЕ
Как инициализировать экземпляр структуры D3DCAPS9 на основании возможностей конкретного устройства мы покажем в следующем разделе.

 

ПРИМЕЧАНИЕ
Мы рекомендуем вам посмотреть описание структуры D3DCAPS9 в документации к SDK и изучить полный список возможностей устройств, поддерживаемых в Direct3D.

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz