netlib.narod.ru | < Назад | Оглавление | Далее > |
Мультитекстурирование, возможно, является самой простой из техник, которые можно реализовать с помощью пиксельного шейдера. Более того, поскольку пиксельные шейдеры заменяют стадию мультитекстурирования фиксированного конвейера, нам необходимо иметь хотя бы базовое представление о том, что происходит на этапе мультитекстурирования. Данный раздел представляет собой краткий обзор мультитекстурирования.
Когда ранее, в главе 6, мы обсуждали наложение текстур, обсуждение мультитекстурирования в фиксированном конвейере функций было пропущено по двум причинам. Во-первых, мультитекстурирование это часть более сложного процесса и мы посчитали, что в тот момент эта тема была бы слишком сложна для восприятия. Во-вторых, фиксированные функции этапа мультитекстурирования заменяются новыми и более мощными пиксельными шейдерами; следовательно имеет смысл не тратить время на устаревшие фиксированные функции этапа мультитекстурирования.
Идея, лежащая в основе мультитекстурирования отчасти связана со смешиванием. В главе 7 мы узнали о смешивании растеризуемых пикселей с пикселями ранее записанными во вторичный буфер для реализации некоторых эффектов. Теперь мы расширим эту идею для нескольких текстур. Итак, мы разрешаем одновременное использование нескольких текстур и затем определяем, как эти текстуры должны быть смешаны одна с другой для получения требуемого эффекта. Наиболее часто мультитекстурирование используется для освещения. Вместо того, чтобы воспользоваться моделью освещения Direct3D на этапе обработки вершин, мы применяем специальные карты текстур, называемые картами освещения (light map), которые сообщают о том, как освещена поверхность. Представим, например, что нам надо осветить прожектором большой ящик. Мы можем описать прожектор в виде структуры D3DLIGHT9, или можно смешать вместе карту текстур, представляющую ящик и карту освещения, представляющую прожектор, как показано на рис 18.1.
Рис. 18.1. Визуализация освещенного прожектором ящика с использованием мультитекстурирования. Здесь мы комбинируем две текстуры, перемножая их соответствующие тексели |
Смешивание текстур (в данном примере двух) для освещения ящика имеет два преимущества по сравнению с использованием модели освещения Direct3D:
Освещение заранее вычисляется в карте освещения прожектора. Следовательно, во время выполнения освещение рассчитывать не нужно, что экономит время процессора. Конечно же, заранее можно вычислить освещение только для статических объектов и статических источников света.
Поскольку карты освещения вычисляются заранее, мы можем использовать более точные и сложные модели освещения, чем модель Direct3D. (Чем лучше результат освещения, тем реалистичнее выглядит сцена.)
Вспомните, что текстуры устанавливаются с помощью метода IDirect3DDevice9::SetTexture, а режимы выборки (sampler state) устанавливаются с помощью метода IDirect3DDevice9::SetSamplerState, чьи прототипы выглядят так:
HRESULT IDirect3DDevice9::SetTexture( DWORD Stage, // индекс этапа текстурирования IDirect3DBaseTexture9 *pTexture ); HRESULT IDirect3DDevice9::SetSamplerState( DWORD Sampler, // индекс этапа выборки D3DSAMPLERSTATETYPE Type, DWORD Value );
Индекс этапа текстурирования/выборки идентифицирует этап текстурирования/выборки для которого мы устанавливаем текстуру или режим выборки. Следовательно, мы можем разрешить использование нескольких текстур и установить для каждой из них требуемые режимы выборки, указывая различные индексы этапов. Ранее в этой книге мы всегда указывали индекс 0, задавая первый этап, поскольку использовали только одну текстуру одновременно. Если, например, нам надо разрешить использование трех текстур, мы используем этапы 0, 1 и 2, как показано ниже:
// Устанавливаем первую текстуру и режимы выборки для нее Device->SetTexture( 0, Tex1); Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); // Устанавливаем вторую текстуру и режимы выборки для нее Device->SetTexture( 1, Tex2); Device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); // Устанавливаем третью текстуру и режимы выборки для нее Device->SetTexture( 2, Tex3); Device->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
Данный код разрешает использование трех текстур, Tex1, Tex2 и Tex3, и устанавливает режимы фильтрации для каждой текстуры.
Вспомните, в главе 6 говорилось, что для каждого трехмерного треугольника мы определяем соответствующий треугольный фрагмент текстуры, который накладывается на трехмерный треугольник. Мы делаем это путем добавления к данным каждой вершины координат текстуры. Таким образом, три вершины определяющие треугольник, определяют и соответствующий треугольный фрагмент текстуры.
Поскольку теперь мы используем несколько текстур, для каждой из трех определяющих треугольник вершин нам требуется определение соответствующего треугольного фрагмента каждой из используемых текстур. Мы делаем это добавляя наборы координат текстуры в данные каждой вершины — по одному набору координат для каждой используемой текстуры. Например, если мы хотим смешивать вместе три текстуры, то у каждой вершины должны быть три набора координат текстуры, индексирующих три используемые текстуры. Таким образом, структура данных вершины для мультитекстурирования с использованием трех текстур может выглядеть так:
struct MultiTexVertex { MultiTexVertex(float x, float y, float z, float u0, float v0, float u1, float v1, float u2, float v2) { _x = x; _y = y; _z = z; _u0 = u0; _v0 = v0; _u1 = u1; _v1 = v1; _u2 = u2; _v2 = v2; } float _x, _y, _z; float _u0, _v0; // Координаты текстуры накладываемой на этапе 0. float _u1, _v1; // Координаты текстуры накладываемой на этапе 1. float _u2, _v2; // Координаты текстуры накладываемой на этапе 2. static const DWORD FVF; }; const DWORD MultiTexVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX3;
Обратите внимание на использованный в настраиваемом формате вершин флаг D3DFVF_TEX3, который указывает, что структура вершины содержит три набора координат текстур. Фиксированный конвейер поддерживает до восьми наборов координат текстур. Если этого вам мало, придется использовать объявление вершин и программируемый конвейер.
netlib.narod.ru | < Назад | Оглавление | Далее > |