Цепочка текстур с понижаемой детализацией;
Рисунок 6.4. Цепочка текстур с понижаемой детализацией; обратите внимание, что каждое последующее изображение в цепочке в два раза меньше предыдущего
Детализируемые текстуры
Как говорилось в разделе6.3, треугольник на экране зачастую не совпадает по размерам с треугольным фрагментом текстуры. Чтобы уменьшить различие размеров, можно создать цепочку текстур с постепенно понижаемой детализацией (mipmap). Идея состоит в том, чтобы взять текстуру и на ее основе создать ряд изображений меньшего размера и с меньшим разрешением и для каждого из этих уровней индивидуально настроить фильтрацию, чтобы на изображении сохранялись важные для нас детали (Рисунок 6.4).
Фильтр детализации текстур
6.4.1. Фильтр детализации текстур
Фильтр детализации текстур используется для того чтобы управлять тем, как Direct3D использует детализируемые текстуры. Чтобы установить этот фильтр можно написать:
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, Filter);
где Filter может принимать одно из следующих значений:
D3DTEXF_NONE— Детализация выключена.
D3DTEXF_POINT — При использовании этого фильтра Direct3D выбирает тот уровень детализации, который наиболее точно соответсвует размеру треугольника на экране. После выбора наиболее подходящей текстуры, Direct3D применяет к ней установленные фильтры для увеличения или уменьшения.
D3DTEXF_LINEAR — При использовании этого фильтра Direct3D выбирает два уровня детализации, которые наиболее точно соответсвуют размеру треугольника на экране, применяет к ним установленные фильтры для увеличения или уменьшения и выполняет линейную интерполяцию двух уровней для получения итогового значения цвета.
Фильтры
Как упоминалось ранее, текстуры накладываются на треугольники в пространстве экрана. Обычно размер треугольного фрагмента текстуры отличается от размера треугольной грани на экране. Когда фрагмент текстуры меньше, чем изображение грани на экране, выполняется увеличение фрагмента текстуры до размеров грани. Когда текстура больше, чем грань на экране, она сжимается. И в том и в другом случае возникают искажения. Фильтрацией (filtering) называется используемая в Direct3D техника уменьшения этих искажений.
Direct3D предоставляет три различных метода фильтрации, от выбора которых зависит качество итогового изображения. Чем выше качество, тем меньше скорость визуализации, так что вам придется выбирать между качеством и скоростью. Устанавливаются фильтры текстур с помощью метода IDirect3DDevice9::SetSamplerState.
Выборка ближайшей точки (nearest point sampling) — Это используемый по умолчанию метод фильтрации, обеспечивающий грубое приближение, но требующий минимум вычислительных ресурсов. Чтобы использовать данный фильтр для увеличения и уменьшения текстур, добавьте в приложение следующий код:
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
Линейная фильтрация (linear filtering) — Этот тип фильтра обеспечивает хорошее качество изображения и на современном оборудовании выполняется достаточно быстро. Рекомендуется использовать в качестве минимального варианта именно этот метод. Чтобы использовать для увеличения и уменьшения текстур линейную фильтрацию, добавьте в приложение следующий код:
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Анизотропная фильтрация (anisotropic filtering) — Этот тип фильтра обеспечивает наилучшее качество изображения, но при этом требует значительного объема вычислений. Чтобы использовать для увеличения и уменьшения текстур анизотропную фильтрацию, добавьте в приложение следующий код:
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
Если вы используете анизотропную фильтрацию, необходимо также задать уровень фильтрации D3DSAMP_MAXANISOTROPY, определяющий качество фильтрации. Чем больше значение этого параметра, тем лучше результат. Чтобы узнать диапазон значений, поддерживаемый установленным оборудованием, необходимо проверить структуру D3DCAPS9. Приведенный ниже фрагмент кода устанавливает значение уровня фильтрации равным 4:
Device->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);
Текстурирование
Наложение текстур (texture mapping)— это техника, позволяющая наложить изображение на треугольную грань; ее применение во много раз увеличивает детализованность и реализм сцены. Например, мы можем создать куб и превратить его в деревянный ящик, наложив на каждую грань текстуру с изображением стенки ящика (Рисунок 6.1).
Использование детализируемых текстур в Direct
6.4.2. Использование детализируемых текстур в Direct3D
Использовать детализируемые текстуры в Direct3D очень просто. Если видеокарта поддерживает детализацию текстур, то функция D3DXCreateTextureFromFile сгенерирует цепочку текстур с понижаемой детализацией за вас. Кроме того, Direct3D автоматически выбирает то изображение из цепочки, которое наилучшим образом соответствует треугольнику на экране. Поэтому детализация текстур используется почти всегда и устанавливается автоматически.
Координаты текстуры используются для задания
Координаты текстуры используются для задания треугольного фрагмента текстуры, который будет наложен на треугольную грань трехмерного объекта.
Мы можем создавать текстуры из хранящихся на диске файлов изображений с помощью метода D3DXCreateTextureFromFile.
Фильтрация текстур выполняется путем задания фильтров для увеличения, уменьшения и детализации текстуры.
Режим адресации определяет поведение Direct3D в тех случаях, когда координаты текстуры выходят за диапазон [0, 1]. Текстура может копироваться, отражаться, обрезаться и т.д.
Координаты текстур
Direct3D использует для текстур систему координат, образованную горизонтальной осьюU и вертикальной осью V. Пара координат (u, v) идентифицирует элемент текстуры, называемый текселем (texel). Обратите внимание, что ось V направлена вниз (Рисунок 6.2).
Куб с текстурой деревянного ящика
В Direct3D текстура представляется с помощью интерфейса IDirect3DTexture9. Текстура, подобно поверхности, является двухмерной матрицей пикселей и может быть наложена на треугольную грань.
Окно с изображением текстурированого квадрата, полученное в приложении TexQuad
ПРИМЕЧАНИЕ | В сопроводительных файлах есть еще два примера приложений для данной главы. Один пример отображает куб с наложенной текстурой деревянного ящика (Рисунок 6.1). Другой пример демонстрирует различные режимы адресации. |
На этих рисунках координаты текстур для четырех вершин квадрата определены следующим образом: (0, 0), (0, 3), (3, 0) и (3, 3). Поскольку по осям U и V размер равен трем единицам, квадрат делится на матрицу 3 × 3. Если, к примеру, вы хотите, чтобы текстура накладывалась в виде матрицы размером 5 × 5, включите режим обертывания и задайте координаты текстур (0, 0), (0, 5), (5, 0) и (5, 5).
Приведенный ниже фрагмент кода взят из программы AddressModes и показывает, как устанавливаются четыре режима адресации:
// Установка режима обертывания if (::GetAsyncKeyState('W') & 0x8000f) { Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); }
// Установка режима цвета рамки if (::GetAsyncKeyState('B') & 0x8000f) { Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff); }
// Установка режима отсечения if (::GetAsyncKeyState('C') & 0x8000f) { Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); }
// Установка режима отражения if (::GetAsyncKeyState('M') & 0x8000f) { Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); }
Режимы адресации
Раньше мы утверждали, что координаты текстур должны находиться в диапазоне [0,1]. С технической точки зрения это неверно, и координаты могут выходить за указанный диапазон. Поведение Direct3D в том случае, если координаты выходят за диапазон [0, 1] определяется установленным режимом адресации. Поддерживаются четыре режима адресаци: обертывание (wrap), цвет рамки (border color), одиночное наложение (clamp) и отражение (mirror), которые показаны на Рисунок 6.5, 6.6, 6.7 и 6.8 соответственно.
Система координат текстуры иногда называемая пространством текстуры
|
Кроме того, обратите внимание, на нормализованные координаты в диапазоне [0, 1], которые обеспечивают для Direct3D работу со значениями из фиксированного диапазона, не зависящего от размеров конкретной текстуры.
Для каждой треугольной грани в трехмерном пространстве мы должны определить соответствующий треугольный фрагмент текстуры, который будет наложен на эту грань (Рисунок 6.3).
Слева изображена треугольная грань
Рисунок 6.3. Слева изображена треугольная грань в трехмерном пространстве, а справа — двухмерный треугольный фрагмент текстуры, который должен быть наложен на данную грань
Для этого мы еще раз модифицируем нашу структуру данных вершины и добавим в нее пару координат текстуры, которые будут определять соответствие между вершиной и точкой текстуры.
struct Vertex { float _x, _y, _z; float _nx, _ny, _nz; float _u, _v; // координаты текстуры
static const DWORD FVF; }; const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
Обратите внимание, что к описанию формата вершины мы добавили константу D3DFVF_TEX1, которая говорит о том, что наша структура данных вершины содержит пару координат текстуры.
Теперь для каждого треугольника, образованного тремя объектами Vertex также указывается соответствующий треугольный фрагмент текстуры, заданный с помощью координат текстуры.
ПРИМЕЧАНИЕ
Создание текстур и разрешение текстурирования
Данные текстур обычно считываются из хранящихся на диске файлов изображений и загружаются в объект IDirect3DTexture9. Для этого используется следующая функция библиотеки D3DX:
HRESULT D3DXCreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, // устройство для создания текстуры LPCSTR pSrcFile, // имя файла с загружаемым изображением LPDIRECT3DTEXTURE9* ppTexture // указатель для возврата созданной текстуры );
Данная функция позволяет загружать изображения в форматах BMP, DDS, DIB, JPG, PNG и TGA.
Например, чтобы создать текстуру из изображения, хранящегося в файле с именем stonewall.bmp, следует использовать такой код:
IDirect3Dtexture9* _stonewall; D3DXCreateTextureFromFile(_device, "stonewall.bmp", &_stonewall);
Для установки текущей текстуры используется следующий метод:
HRESULT IDirect3DDevice9::SetTexture( DWORD Stage, // Значение в диапазоне 0-7, идентифицирующее // этап текстурирования (см. примечание ниже) IDirect3DBaseTexture9* pTexture // Указатель на устанавливаемую текстуру );
Вот пример использования данного метода:
Device->SetTexture(0, _stonewall);
ПРИМЕЧАНИЕ
Чтобы запретить наложение текстуры на конкретном этапе текстурирования следует установить значение pTexture для соответствующего этапа равным 0.
Например, если мы не хотим использовать при отображении объекта текстуры, следует написать:
Device->SetTexture(0, 0); renderObjectWithoutTexture();
Если в нашей сцене присутствуют треугольники, для которых используются различные текстуры, код должен выглядеть похожим на приведенный ниже фрагмент:
Device->SetTexture(0, _tex0); drawTrisUsingTex0();
Device->SetTexture(0, _tex1); drawTrisUsingTex1();