Урок 7. Текстуры в Direct3D11

22.09.2012

В этом уроке вы узнаете: какие бывают типы текстур в Direct3D; каким образом осуществляется загрузка текстур в Direct3D; каким образом устанавливаются текстуры для использования их в шейдере.

Типы данных текстур Direct3D

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

Типы текстур, используемы в Direct3D11:

  • Обычная 2D текстура формата R8G8B8
  • Текстура 2D с картой прозрачности R8G8B8A8
  • Кубическая 2D текстура, которая может использоваться для поверхности неба типа скайбокс, состоящая из 6 фрагментов 2D текстуры формата R8G8B8
  • Трехмерная 3D текстура формата R8G8B8
  • Пустая текстура, используемая в качестве рендер-таргета
  • Пустая текстура, используемая для программной генерации рисунка текстуры

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

Загрузка текстур в Direct3D

Итак, вы подготовили вершинный и индексный буфер, загрузив меш из файла или заполнив процедурно-сгенерированными данными. Для того, чтобы одновременно загрузить текстуру, создав при этом объект для хранения этой текстуры типа ID3D11ShaderResourceView необходимо воспользоваться следующим кодом загрузки текстуры:

// Загрузка текстуры
hr = D3DX11CreateShaderResourceViewFromFile( g_pd3dDevice, L"seafloor.dds", NULL, NULL, &g_pTextureRV, NULL );

Обратите внимание, что в данном примере используется формат текстур типа .dds.Direct3D поддерживает большое разнообразие форматов, включая bmp, jpg иpng. Для текстур, использующих альфа канал подойдет формат png.

Создание объекта состояний семплера

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

// Создание объекта состояний семплера
D3D11_SAMPLER_DESC sampDesc;
ZeroMemory( &sampDesc, sizeof(sampDesc) );
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );

Теперь инициализация завершена. Все последующие действия с текстурами будут производится в функции Render.

Установка текстуры в качестве константы шейдера

Вы помните, как устанавливались матрицы в качестве констант шейдера. Также обстоит дело и с текстурами. Мы можем указать константу шейдера, и затем назначать ей новые значения (различные текстуры). В программе текстуры хранятся в виде экземпляров объекта типа ID3D11ShaderResourceView. Непосредственно в функции Render мы можем назначить этой константе шейдера новые значения точно также, как мы устанавливали константы шейдера для матриц:

g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV );

Обратите внимание, что у нас может быть несколько переменных g_pTextureRV, например, массив из загруженных текстур вида g_pTextureRV[]. Таким образом, мы можем выбирать текстуру, которую устанавливаем из нескольких загруженных текстур:

g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV[index] );

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

g_pImmediateContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );

Все готово. Теперь установка текстур в функции Render успешно завершена.

Использование текстуры в шейдере

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

Texture2DtxDiffuse : register( t0 );
SamplerState samLinear : register( s0 );

Входящие данные пиксельногошейдера должны включать такую переменную Tex храняющую информацию о координатах текстуры.

structVS_OUTPUT
{
float4 Pos: SV_POSITION;
float4 Color: COLOR0;
float2 Tex : TEXCOORD0;
}

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

VS_OUTPUT VS(float4 Pos:POSITION,float4 color: COLOR, float2 Tex: TEXCOORD)
{
    ...
    output.Tex=Tex;
}

Таким образом, пиксельный шейдер во входящей структуре PS_INPUT будет иметь переменную input.Tex типа float2.

float4 PS( PS_INPUT input) : SV_Target
{
    return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;
}

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

txDiffuse.Sample( samLinear, input.Tex )

Входящими данными является указание объекта из которого выполняется выборка txDiffuse, тип семплераsamLinear а также координаты текстуры input.Tex. Метод txDiffuse.Sample возращает значение типа float4, то есть цвет в формате R8G8B8A8.

Установка формата вершинного буфера, подходящего для использвания текстур

Для того, чтобы текстура могла использоваться в шейдере, каждая из вершин вершинного буфера должна содержать координаты текстуры. Обычно координаты текстуры обозначаются символами u и v, обозначающими координаты текстуры. Значения этих чисел лежат в диапазоне от 0 до 1. Таки образом, координаты текстуры образуют двухкомпонентный вектор.

Вы знаете, что трехмерные вектора в DirectX обозначаются как XMFLOAT3. Соответственно для двухмерных мы должны указать XMFLOAT2. Соответственно, если в нашем вершинном буфере содержатся только координаты о положении вершины, то мы должны добавить также и текстурные координаты.

structSimpleVertex
{
    XMFLOAT3 Pos; // Координата
    XMFLOAT2 Tex; // Координата текстуры
};

Также мы должны дополнить формат входящих данных вершинного буфера описанием типа вершинного буфера с учетом координат.

// Определение формата вершинного буфера
D3D11_INPUT_ELEMENT_DESC layout[] =
{
    { L"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
        D3D11_INPUT_PER_VERTEX_DATA, 0 },  
    { L"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, 
        D3D11_INPUT_PER_VERTEX_DATA, 0 }, 
};

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

Обзор приложения

Теперь посмотрим, какой результат мы достигли при загрузке текстуры.

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

Заключение

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

Заполнен: DirectX11
Присвоен тэг:

avatar

Об Авторе ()

Планета назначения, JO - 8703 - IV, обозначается светлой точкой на объемном экране корабля. К тому времени, как Робоид нанялся на юпитерианский круговой рейс, ему следовало бы стать главным инженером, но после Суховодного пионерского его вышибли, внеся в черный список, и высадили в Луна-Сити за то, что вместо слежения за приборами он провел время, программируя синтезатор пищи корабля строжайше запрещенной корабельными инструкциями последовательностью синтеза пива.

Комментирование закрыто.

Наверх