Полупрозрачность
Рассмотрим далее реализацию такого эффекта как полупрозрачность (alpha blending). Этот механизм позволяет задавать для выводимых примитивов прозрачные и полупрозрачные пиксели. Т.е. существует возможность указать, какие пиксели не будут выводиться в силу своей полной прозрачности, а какие будут выводиться частично прозрачными. Полупрозрачность основывается на принципе смешивания цветов. Математически это можно выразить так: ColorResult = Color1*(1-t) + Color2*t, 0<=t<=1. Эта векторная запись должна интерпретироваться для каждого отдельного цветового канала. Пусть ColorResult = (r, g, b), Color1 = (r1, g1, b1), Color2 = (r2, g2, b2), тогда
r = r1*(1-t) + r2*t g = g1*(1-t) + g2*t b = b1*(1-t) + b2*t, 0<=t<=1.
Ниже приведен пример смешивания двух цветов (красного и зеленого) для различных значений параметра t (Color1 = красный = (255,0,0) Color2 = зеленый = (0,255,0)).
t=0 | t=1/8 | t=2/8 | t=3/8 | t=4/8 | t=5/8 | t=6/8 | t=7/8 | t=1 |
При работе с полупрозрачностью, как правило, имеют дело (оперируют) с двумя цветами: цвет источника (source color) – это пиксель, который вы собираетесь отобразить (записать в буфер кадра) и цвет приемника (destination color) – это пиксель, который уже существует и записан в буфере кадра. Другими словами можно сказать, что цвет источника (source color) – "пиксель который рисуем", а цвет приемника (destination color) – "пиксель на котором рисуем". Механизм полупрозрачности использует следующую формулу для управления степенью полупрозрачности:
Финальный цвет = Цвет пикселя источника * Коэффициент прозрачности источника + Цвет пикселя приемника * Коэффициент прозрачности приемника.
Программист может управлять коэффициентами прозрачности с помощью флагов:
коэффициент прозрачности источника - D3DRS_SRCBLEND,
коэффициент прозрачности приемника - D3DRS_DESTBLEND и используя формулу FinalPixel = SourcePixelColor*SourceBlendFactor + DestPixelColor*DestBlendFactor.
Механизм полупрозрачности по умолчанию выключен как опция.
Активировать/деактивировать полупрозрачность можно следующим образом:
C++ | device->SetRenderState( D3DRS_ALPHABLENDENABLE, {TRUE, FALSE} ); |
Pascal | device.SetRenderState( D3DRS_ALPHABLENDENABLE, {1, 0} ); |
SetRenderState( D3DRS_SRCBLEND, SourceBlendFactor ), SetRenderState( D3DRS_DESTBLEND, DestBlendFactor ),
где в качестве SourceBlendFactor и DestBlendFactor могут выступать предопределенные константы:
D3DBLEND_ZERO—blendFactor=(0,0,0,0) D3DBLEND_ONE—blendFactor=(1,1,1,1) D3DBLEND_SRCCOLOR—blendFactor=(Rs, Gs, Bs, As) D3DBLEND_INVSRCCOLOR—blendFactor=(1–Rs, 1–Gs, 1–Bs, 1–As) D3DBLEND_SRCALPHA—blendFactor=(As, As, As, As) D3DBLEND_INVSRCALPHA—blendFactor=(1–As, 1–As, 1–As, 1–As) D3DBLEND_DESTALPHA—blendFactor=(Ad, Ad, Ad, Ad) D3DBLEND_INVDESTALPHA—blendFactor=(1–Ad, 1–Ad, 1–Ad, 1–Ad) D3DBLEND_DESTCOLOR—blendFactor=(Rd, Gd, Bd, Ad) D3DBLEND_INVDESTCOLOR—blendFactor=(1–Rd, 1–Gd, 1–Bd, 1–Ad) D3DBLEND_SRCALPHASAT—blendFactor=(f,f,f,1), где f=min(As, 1–Ad). По умолчанию SourceBlendFactor = D3DBLEND_SRCALPHA DestBlendFactor = D3DBLEND_INVSRCALPHA.
Рассмотрим несколько примеров использования механизма полупрозрачности.
Пример 1.
Если мы не хотим ничего "смешивать", тогда можно воспользоваться такой формулой:
FinalPixel = SourcePixelColor*1 + DestPixelColor*0.
Этого можно достичь, выставив следующие значения коэффициентов смешивания:
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); SetRenderState( D3DRS_DESTBLEND,D3DBLEND_ZERO );
Пример 2.
Чтобы происходило "сложение" цветов, можно использовать такую формулу:
FinalPixel = SourcePixelColor*1 + DestPixelColor*1.
Для этого, оба коэффициента смешивания выставим в единицу:
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
Ниже приведен визуальный пример такого "сложения" цветов.
Следует отметить, что примитивы при полупрозрачности могут быть не только однотонными.
Ниже показаны примеры "умножения" цветов для примитивов, с плавными переходами цветов.
Пример 3.
Эффект "перемножения" цветов примитивов можно получить с помощью формулы
FinalPixel = SourcePixelColor*0 + DestPixelColor*SourcePixelColor.
Значения коэффициентов смешивания выставим следующим образом:
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO ); SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );
Ниже показаны примеры подобного "умножения" цветов при различном фоне.
цвет фона D3DCOLOR_XRGB(0,0,0) | цвет фона D3DCOLOR_XRGB(255,255,255) |
0 – пиксель полностью прозрачен
255 – пиксель полностью непрозрачен
128 – пиксель прозрачен наполовину.
До сих пор цвет мы определяли с помощью тройки чисел RGB, используя макрос-функцию D3DCOLOR_XRGB(). Для задания значения альфа составляющей вершины можно воспользоваться функцией D3DCOLOR_ARGB(a, r, g, b), где первый параметр определяет значение полупрозрачности. Следует заметить, что значение альфа канала (как и всех цветовых составляющих) приводится к диапазону значений [0…1]. Ниже приводится пример заполнения вершин примитивов данными о цвете со значением полупрозрачности 50 процентов.
C++ | points[0].color = D3DCOLOR_ARGB( 128, 255, 0, 0 ); … |
Pascal | points[0].color := D3DCOLOR_ARGB( 128, 255, 0, 0 ); … |
FinalPixel = SourcePixelColor*SourceBlendFactor + DestPixelColor*DestBlendFactor,
при этом задействовав константы смешивания с суффиксом ALPHA. Так, например, следующие установки коэффициентов смешивания
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
преобразуют формулу к виду
FinalPixel = SourcePixelColor*(Alpha) + DestPixelColor*(1- Alpha),
где Alpha – значение альфа составляющей пикселя-источника.
В качестве примера разберем вывод одного полупрозрачного примитива на непрозрачном. Пусть имеется два треугольника, красный и синий, показанные ниже, причем первый из них не содержит значений полупрозрачности, а у второго все вершины имеют полупрозрачность – 50 процентов.
D3DCOLOR_XRGB(255,0,0); | D3DCOLOR_ARGB(128,0,0,255); |
- Первым рисуется красный треугольник (полупрозрачность выключена);
- Включаем полупрозрачность: SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
- Рисуем синий треугольник (в вершинах задана 50 % полупрозрачность);
В результате формула смешивания примет вид: FinalPixel = Синий*0.5 + Красный*(1-0.5).
Ниже приведены примеры вывода примитивов с различной степенью полупрозрачности.
ARGB = (32,0,0,255) | ARGB = (64,0,0,255) | ARGB = (128,0,0,255) |
ARGB = (160,0,0,255) | ARGB = (192,0,0,255) | ARGB(255,0,0,255) |
Полупрозрачность можно использовать не только на цветных примитивах. Ниже показан пример полупрозрачного треугольника на фоне квадрата, покрытого текстурой.
Последовательность вывода примитивов должна быть следующей:
- Вначале выводится квадрат с текстурой, при этом полупрозрачность выключена;
- Включается режим полупрозрачности с нужными коэффициентами смешивания;
- Выводится цветной треугольник поверх квадрата.
Информация о полупрозрачности пикселей может содержаться и в самой текстуре. В этом случае для альфа составляющей отводится, как правило, такое же количество бит, что и под каждый из цветовых каналов. Наиболее распространенный формат представления изображения с альфа-каналом это 32 битные изображения, где на каждый канал отводится по 8 бит.
Для создания полупрозрачной текстуры можно воспользоваться утилитой DirectX Texture Tool, которая поставляется совместно с DirectX SDK. Сам альфа-канал можно создать в виде изображения в оттенках серого цвета, в котором абсолютно черные пиксели будут соответствовать полной прозрачности, а белые пиксели – полной непрозрачности.
По умолчанию если текстура содержит альфа канал, то значение альфа составляющей берется из текстуры. Если же альфа канал не присутствует в текстуре, то значение альфа составляющей будет получено из вершины примитива. Тем не менее, можно явно указать "источник" альфа канала:
// вычисление альфа значения из текстуры device->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
// вычисление альфа значения из вершины примитива device->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
Ниже приведен пример вывода полупрозрачной текстуры.
Текстура (RGB канал) | Альфа канал | Результат |
Ниже приведен пример вывода спрайтов с помощью текстур, содержащих альфа канал.
Исходное изображение | Альфа канал | Вывод на текстуру |