Программирование графических процессоров с использованием Direct3D и HLSL


Полупрозрачность


Рассмотрим далее реализацию такого эффекта как полупрозрачность (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=0t=1/8t=2/8t=3/8t=4/8t=5/8t=6/8t=7/8t=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} );
Pascaldevice.SetRenderState( D3DRS_ALPHABLENDENABLE, {1, 0} );
Установка коэффициентов смешивания (SourceBlendFactor и DestBlendFactor) осуществляется следующим образом:

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)
Прозрачность может "содержаться" и в вершинах примитивов. В дополнение к красной (red), зеленой (green) и синей (blue) цветовым составляющим, каждый пиксель может иметь "прозрачную" составляющую или так называемый альфа канал (alpha channel). Альфа канал имеет 256 уровней прозрачности, 0…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);
Последовательность вывода примитивов будет такой:

  1. Первым рисуется красный треугольник (полупрозрачность выключена);
  2. Включаем полупрозрачность: SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  3. Рисуем синий треугольник (в вершинах задана 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)
Значения полупрозрачности для каждой вершины примитива могут отличаться друг от друга. В этом случае значения полупрозрачности для внутренних точек треугольника будут линейно проинтерполированы. Такой случай представлен ниже.



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

Последовательность вывода примитивов должна быть следующей:

  1. Вначале выводится квадрат с текстурой, при этом полупрозрачность выключена;
  2. Включается режим полупрозрачности с нужными коэффициентами смешивания;
  3. Выводится цветной треугольник поверх квадрата.




Информация о полупрозрачности пикселей может содержаться и в самой текстуре. В этом случае для альфа составляющей отводится, как правило, такое же количество бит, что и под каждый из цветовых каналов. Наиболее распространенный формат представления изображения с альфа-каналом это 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 канал)Альфа каналРезультат
Полупрозрачность в текстурах позволяет реализовать идею вывода спрайтов – небольших изображений без фона. Для этого достаточно взять изображение спрайта и добавить в него альфа канал. Те пиксели, которые считаются фоном должны быть черными в альфа канале, а которые относятся к спрайту – белыми.

Ниже приведен пример вывода спрайтов с помощью текстур, содержащих альфа канал.



















Исходное изображениеАльфа каналВывод на текстуру
В некотором смысле, альфа канал здесь используется в качестве маски вывода, при помощи которой происходит "отбрасывание" ненужных (фоновых) пикселей.


Содержание раздела