Альфа-канал
7.3.1. Альфа-канал
Вместо того, чтобы вычислять альфа-компоненту при затенении, можно получать ее значение из альфа-канала (alpha channel) текстуры. Альфа-каналом называется дополнительный набор битов, резервируемых для каждого текселя, в которых кранится альфа-компонент. Когда текстура накладывается на примитив также накладываются и альфа-компоненты из альфа-канала и они становятся значениями альфа-компоненты пикселей текстурированного примитива. На Рисунок 7.3 представлено изображение 8-разрядного альфа-канала.
Формулы смешиванияВзгляните на Рисунок 7.1, где красный чайник изображен поверх фоновой картинки с текстурой деревянного ящика. СмешиваниеВ этой главе мы изучим технику, называемую смешивание (blending), которая позволяет смешивать (комбинировать) цвет растеризуемого в данный момент пикселя с цветами ранее растеризованных в том же самом месте пикселей. Другими словами, мы смешиваем текущий примитив с ранее нарисованными примитивами. Эта техника позволяет реализовать ряд эффектов (в частности, прозрачность).
смешивание позволяет комбинировать пиксель растеризуемогоАльфа- смешивание позволяет комбинировать пиксель растеризуемого в данный момент примитива с пикселом уже находящимся в той же самой позиции вторичного буфера. Коэффициенты смешивания позволяют нам управлять тем, как будут объединяться пиксели источника и приемника. Значения альфа-компоненты могут браться из рассеиваемой компоненты установленного материала, либо из альфа-канала установленной текстуры. Изменение формата текстуры
В результате будет создано изображение с 32-разрядной глубиной цвета, где у каждого пикселя 8 бит отведено под альфа-канал, 8 бит для красного цвета, 8 бит для зеленого и 8 бит для синего. Следующая задача — загрузить данные в альфа-канал. Мы будем загружать в альфа-канал 8-разрядную карту оттенков серого, изображенную на Рисунок 7.3. Раскройте меню File и выберите пункт Open Onto Alpha Channel Of This Texture. На экран будет выведено диалоговое окно, предлагающее выбрать файл изображения, содержащий данные, которые вы хотите загрузить в альфа-канал. Выберите файл alphachannel.bmp расположенный в папке примера к этой главе texAlpha. На Рисунок 7.6 показано окно программы после загрузки данных альфа-канала. Коэффициеты смешиванияЗадавая различные комбинации коэффициентов смешивания источника и приемника вы можете реализовать десятки различных эффектов. Поэкспериментируйте с различными комбинациями, чтобы увидеть что они делают. Чтобы установить коэффициент смешивания источника и коэффициент смешивания приемника надо задать значения режимов визуализации D3DRS_SRCBLEND и D3DRS_DESTBLEND соответственно. Например, мы можем написать: Device->SetRenderState(D3DRS_SRCBLEND, Source); Device->SetRenderState(D3DRS_DESTBLEND, Destination); где Source и Destination могут принимать значения одного из следующих коэффициентов смешивания: D3DBLEND_ZERO — коэффициент смешивания = (0, 0, 0, 0) D3DBLEND_ONE — коэффициент смешивания = (1, 1, 1, 1) D3DBLEND_SRCCOLOR — коэффициент смешивания = (rs, gs, bs, as) D3DBLEND_INVSRCCOLOR — коэффициент смешивания = (1 – rs, 1 – gs, 1 – bs, 1 – as) D3DBLEND_SRCALPHA — коэффициент смешивания = (as, as, as, as) D3DBLEND_INVSRCALPHA — коэффициент смешивания = (1 – as, 1 – as, 1 – as, 1 – as) D3DBLEND_DESTALPHA — коэффициент смешивания = (ad, ad, ad, ad) D3DBLEND_INVDESTALPHA — коэффициент смешивания = (1 – ad, 1 – ad, 1 – ad, 1 – ad) D3DBLEND_DESTCOLOR — коэффициент смешивания = (rd, gd, bd, ad) D3DBLEND_INVDESTCOLOR — коэффициент смешивания = (1 – rd, 1 – gd, 1 – bd, 1 – ad) D3DBLEND_SRCALPHASAT — коэффициент смешивания = (f, f, f, 1), где f = min(as, 1 – ad) D3DBLEND_BOTHINVSRCALPHA — Этот режим смешивания устанавливает коэффициент смешивания источника равным (1 – as, 1 – as, 1 – as, 1 – as), а коэффициент смешивания приемника равным (as, as, as, as). Его можно указывать только для режима визуализации D3DRS_SRCBLEND. Значениями по умолчанию для коэффициента смешивания источника и коэффициента смешивания приемника являются D3DBLEND_SRCALPHA и D3DBLEND_INVSRCALPHA соответственно. Непрозрачный чайник
Предположим, мы хотим нарисовать чайник с заданным уровнем прозрачности, чтобы сквозь него была видна фоновая текстура с изображением ящика (Рисунок 7.2). Полученная текстура с альфа-каналом
Теперь можно сохранить текстуру в файле; мы выбрали для файла имя cratewalpha.dds. Пример приложения: прозрачный чайникПример приложения, который мы будем рассматривать, рисует прозрачный чайник поверх фоновой текстуры с изображением ящика, как показано на Рисунок 7.2. Данные альфа-компоненты в этом примере берутся из материала. Приложение позволяет увеличивать и уменьшать значение альфа-компоненты нажатием на клавиши A и S. Нажатие на клавишу A увеличивает значение альфа-компоненты; нажатие на клавишу S — уменьшает его. Чтобы использовать смешивание необходимо выполнить следующие действия: Установить коэффициенты смешивания D3DRS_SRCBLEND и D3DRS_DESTBLEND. Если используется альфа-компонента, указать ее источник (материал или альфа-канал текстуры). Установить режим визуализации с альфа-смешиванием. В примере мы объявляем несколько самодокументируемых глобальных переменных: ID3DXMesh* Teapot = 0; // чайник D3DMATERIAL9 TeapotMtrl; // материал чайника IDirect3DVertexBuffer9* BkGndQuad = 0; // квадрат фона IDirect3DTexture9* BkGndTex = 0; // текстура ящика D3DMATERIAL9 BkGndMtrl; // материал фона Метод Setup делает много вещей, но мы опустим большую часть кода, которая не относится к рассматриваемой в этой главе теме. Что касается смешивания, метод Setup задает источник из которого будут браться значения альфа-компонент. В рассматриваемом примере мы указываем, что значения альфа-компонент будут браться из соответствующей компоненты материала. Обратите внимание, что для материала чайника мы задаем значение альфа-компоненты равное 0.5, а это значит, что чайник будет визуализирован с 50% прозрачностью. Помимо вышеперечисленных действий мы также задаем коэффициенты смешивания. Обратите внимание, что в этом методе мы не разрешаем альфа-смешивание. Дело в том, что альфа-смешивание — это ресурсоемкая операция, которая должна включаться только при визуализации тех объектов, для которых она нужна. Например, в рассматриваемой программе визуализация с альфа-смешиванием нужна только для чайника и не требуется для квадрата с фоновой текстурой. Поэтому мы разрешаем альфа-смешивание в функции Display. bool Setup() { TeapotMtrl = d3d::RED_MTRL; TeapotMtrl.Diffuse.a = 0.5f; // 50% прозрачность BkGndMtrl = d3d::WHITE_MTRL; D3DXCreateTeapot(Device, &Teapot, 0); ...// Код создания квадрата фона опущен ...// Код установки освещения и текстур опущен // В качестве источника альфа-компоненты используем параметры материала Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); // Устанавливаем коэффициенты смешивания таким образом, // чтобы альфа-компонента определяла прозрачность Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); ...// установка матриц проекции/вида опущена return true; } В функции Display мы проверяем нажаты ли клавиши A или S и, если да, то соответственно увеличиваем или уменьшаем значение альфа-компоненты материала. Обратите внимание, что метод гарантирует, что значение альфа-компоненты не выйдет за пределы диапазона [0, 1]. Затем мы разрешаем альфа-смешивание, визуализируем чайник с включенным альфа-смешиванием, после чего выключаем альфа-смешивание. bool Display(float timeDelta) { if(Device) { // // Обновление // // Увеличение/уменьшение альфа-компоненты с помощью клавиатуры if(::GetAsyncKeyState('A') & 0x8000f ) TeapotMtrl.Diffuse.a += 0.01f; if( ::GetAsyncKeyState('S') & 0x8000f ) TeapotMtrl.Diffuse.a -= 0.01f; // Проверяем не вышло ли значение за интервал [0, 1] if(TeapotMtrl.Diffuse.a > 1.0f) TeapotMtrl.Diffuse.a = 1.0f; if(TeapotMtrl.Diffuse.a < 0.0f) TeapotMtrl.Diffuse.a = 0.0f; // // Визуализация // Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); Device->BeginScene(); // Рисуем фон D3DXMATRIX W; D3DXMatrixIdentity(&W); Device->SetTransform(D3DTS_WORLD, &W); Device->SetFVF(Vertex::FVF); Device->SetStreamSource(0, BkGndQuad, 0, sizeof(Vertex)); Device->SetMaterial(&BkGndMtrl); Device->SetTexture(0, BkGndTex); Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); // Рисуем чайник Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); D3DXMatrixScaling(&W, 1.5f, 1.5f, 1.5f); Device->SetTransform(D3DTS_WORLD, &W); Device->SetMaterial(&TeapotMtrl); Device->SetTexture(0, 0); Teapot->DrawSubset(0); Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); Device->EndScene(); Device->Present(0, 0, 0, 0); } return true; } ПРИМЕЧАНИЕ | На веб- сайте этой книги есть еще один пример к данной главе, texAlpha, который демонстрирует использование альфа-канала текстуры. Единственное отлтчие кода этого примера от рассмотренного выше заключается в том, что мы указываем в качестве источника альфа-компоненты не материал, а альфа-канал текстуры. // Использовать альфа-канал в качестве источника альфа-компонент Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); Приложение загружает файл DDS, содержащий альфа-канал, созданный с помощью утилиты DX Tex Tool, рассмотренной в разделе 7.4. |
ПРАВИЛО | Сперва рисуйте объекты, которые не используют смешивание. Затем отсортируйте объекты, которые используют смешивание, по расстоянию от камеры; наиболее эффективно эта операция выполняется, если объекты находятся в пространстве вида — в этом случае достаточно отсортировать их по значению координаты Z. После этого рисуйте использующие смешивание объекты начиная от самых дальних и заканчивая самыми близкими. | |||
При смешивании значений двух пикселей используется следующая формула:
ИтоговыйПиксель = ПиксельИсточника
КоэффициентСмешиванияИсточника + ПиксельПриемника КоэффициентСмешиванияПриемникаКаждая из переменных в этой формуле является четырехмерным цветовым вектором (r, g, b, a), а символ
означает операцию перемножения компонент.ИтоговыйПиксель — Пиксель, получаемый в результате смешивания.
ПиксельИсточника — Обрабатываемый в данный момент пиксель, который смешивается с пикселем из вторичного буфера.КоэффициентСмешиванияИсточника — Значение в диапазоне [0, 1], определяющее какой процент пикселя источника участвует в смешивании.
Пиксель приемника — Пиксель, находящийся во вторичном буфере.
КоэффициентСмешиванияПриемника — Значение в диапазоне [0, 1], определяющее какой процент пикселя приемника участвует в смешивании.
Благодаря коэффициентам смешивания источника и приемника можно различными способами модифицировать исходные пиксели источника и приемника, что позволяет реализовать различные эффекты. В разделе 7.2 описаны предопределенные значения, которые можно использовать.
По умолчанию смешивание запрещено; чтобы разрешить его, присвойте режиму визуализации D3DRS_ALPHABLENDENABLE значение true:
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
СОВЕТ
Разрядная карта оттенков серого, представляющая альфа-канал текстуры
Рисунок 7.3. 8-разрядная карта оттенков серого, представляющая альфа-канал текстуры
На Рисунок 7.4 показан результат визуализации текстурированного квадрата с альфа-каналом, определяющим какие части будут прозрачными.
Создание альфа-канала с помощью утилиты DirectX Texture Tool
Большинство распространенных форматов графических файлов не хранят информацию альфа-компонент. В этом разделе мы покажем вам как создать файл формата DDS с альфа-каналом используя утилиту DirectX Texture Tool. DDS— это формат графических файлов специально разработанный для приложений и текстур DirectX. Файлы DDS могут быть загружены в объект текстуры с помощью функции D3DXCreateTextureFromFile точно так же как файлы BMP и JPG. Утилита DirectX Texture Tool находится в папке \Bin\DXUtils корневого каталога DXSDK.
Запустите утилиту DirectX Texture Tool и откройте файл crate.jpg, находящийся на сопроводительном компакт-диске в папке с примерами программ к данной главе. Изображение ящика автоматически загружается как 24-разрядная RGB-текстура, в которой у каждого пикселя 8 бит отведено под красный цвет, 8 бит — под зеленый и 8 бит — под синий. Нам надо преобразовать эту текстуру в 32-разрядную ARGB-текстуру, зарезервировав дополнительные 8 бит для альфа-канала. Выберите в меню Format команду Change Surface Format. Будет выведено диалоговое окно, показанное на Рисунок 7.5. Выберите формат A8 R8 G8 B8 и щелкните по кнопке OK.
Текстурированный квадрат, у которого альфа-канал задает прозрачность отдельных частей
Рисунок 7.4. Текстурированный квадрат, у которого альфа-канал задает прозрачность отдельных частей
Указание источника альфа-компоненты
7.3.2. Указание источника альфа-компоненты
Если у используемой в данный момент текстуры есть альфа-канал, то по умолчанию значения альфа-компоненты пикселей берутся из него. Если альфа-канала нет, значения альфа-компонент отдельных пикселей вычисляются на основании значений альфа-компонент вершин. В то же время с помощью показанных ниже режимов визуализации вы сами можете указать, какой источник альфа компоненты использовать (цвета вершин или альфа-канал):
// Вычисляем альфа-компоненту при затенении на основании цветов вершин Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
// Берем значение альфа-компоненты из альфа-канала Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);