Blending – trochę zaMieszania.
Hej!
Jak już wszyscy doskonale wiedzą, nie mam talentu do pisania wstępów. Więc oto, bez zbędnych udziwnien zaczynamy kolejną lekcję – tym razem powiemy sobie trochę o blendingu - mieszaniu. Nazwa jest dosyć dziwna, ale jednak trafna.
Wyobraźmy sobię sielankową scenę. Siedzimy w pokoju, jest zima, ogień wesoło trzaska na kominie, a my wyglądamy przez okno, patrzymy na spadające particles, oglądamy wolumetryczną mgłę i światła latarni w oddali. Ale wróćmy do okna i zauważmy pewną zasadniczą różnicę, między nim a, dajmy, ścianą: szkło jest przeźroczyste! Możemy widzieć co znajduje się za nim, oraz to, co jest na samym szkle. I tutaj dochodzimy do sedna blendingu.
Blending, czyli mieszanie, polega na prostej rzeczy. Bierzemy kolor dwóch pikseli (A i B), przeprowadzamy na nich zadane operacje, a następnie zwracamy wynik będący połączeniem (“pomieszaniem”) kolorów A i B. Ilustruje to poniższy obrazek.
Dobra, wszystko ładnie pięknie, tylko według jakiego wzoru, jakiej funkcji, kolory są mieszane? Sprzętowy blending nie jest jeszcze programowalny, więc funkcje te są ustalone z góry. Mamy jednak możliwość zmiany ustawień. Na razie zobaczmy jak nasza karta radzi sobie z blendingiem:
1: KolorWynikowy = KolorA * SrcBlend + KolorB * DestBlend;
KolorWynikowy nie wymaga tłumaczenia, KolorA i KolorB także, ale cóż to takiego te SrcBlend (SourceBlend) i DestBlend (DestinationBlend)? Jako, że blending nie jest programowalny, są to stałe pomagające nam kontrolować ten proces. Wyróżniamy ich kilka (każdą można przypisać zarówno do stanu SourceBlend jak i DestBlend), z czego najważniejsze to
- Zero – stała wynosi po prostu 0.
- One – trudne do wymyślenia – stała wynosi 1. :P
- SrcAlpha – stałą wynosi wartość alpha piksela.
- InvSrcAlpha – oraz jej odwrotność: 1 – alpha.
- (tutaj warto obejrzeć dokumentację, która dużo mówi o innych stanach, rzadziej używanych ale również ważnych)
Zaraz zaraz, jaka alpha?. Jeszcze nie zaczęliśmy jednego, a już mówimy coś o jakiś tajemniczych literach greckiego alfabetu? Ale przemyślmy sprawę – skoro nasze szyby mogą już być dowolnie przeźroczyste, jak tę przeźroczystość kontrolować? A co ważniejsze, jak mógłby być przeźroczysty nasz toolbar na Viście, bez wartości, która pozwala ustalić ile jednego piksela ma być w wynikowym kolorze? Taką wartością jest właśnie alpha. Jest ona zazwyczaj przechowywana razem z kolorem. Jak przekonamy się oglądając kod, ustawienie tego żeby chodziło jest dosyć proste. Jest tak proste, że nie musimy nawet zmieniać nic w aplikacji, a jedynie wyedytować shader!
float4 psmain(float2 texc : TEXCOORD0) : COLOR
{
float4 color = tex2D(sampler0, texc);
color.a = 0.5;
return color;
}
technique std
{
pass
{
AlphaBlendEnable = true;
SrcBlend = SrcAlpha;
DestBlend = One;
ZWriteEnable = false;
CullMode = NONE;
VertexShader = compile vs_2_0 vsmain();
PixelShader = compile ps_2_0 psmain();
}
}
Jak widać, nie zmieniło się znów tak dużo. Dodaliśmy ustawienie wartości alpha w Pixel Shaderze na 0.5f, oraz ustawiliśmy odpowiednie stałe z naszego równania – SrcBlend na źródłową alfę (a więc 0.5), a DestBlend na 1. Nasze równanie wygląda więc tak:
KolorWynikowy = KolorA * 0.5 + KolorB;
Do tego ustawiamy zapis do bufora Z na false – nie jest on potrzebny, skoro chcemy narysować to, co jest za danym pikselem. Również Culling się nie przyda.
Jest jeszcze jedna rzecz, o której muszę wspomnieć – czasami ważna jest kolejność rysowania obiektów przeźroczystych. Jeśli wzór na mieszanie nie redukuje się do postaci przemiennej, musimy zadbać o to, by odpowiedni piksel blendował się w odpowiedni sposób. W przykładzie nie używamy przemiennego wzoru, więc w normalnej sytuacji musielibyśmy zadbać o odpowiednią kolejność rysowania. Dla dociekliwych, do paczki z kodem z dzisiejszej lekcji dolączone jest pewne rozwiązanie tego problemu – jego samodzielna analiza będzie ciekawa i pomoże zrozumieć blending.
Kończąc tę dosyć krótką, ale ważną część kursu pragnę zachęcić was do poeksperymentowania z blendingiem, szczególnie ze stanami SrcAlpha, InvSrcAlpha, One i Zero. Zrozumienie mieszania jest zasadnicze dla nauki dalszego programowania grafiki. :)
Do lekcji dołączony jest oczywiście exe oraz kod źródłowy.

Super — mam pytanie prosze o email mr1@plusnet.pl
“do paczki z kodem z dzisiejszej lekcji dolączone jest pewne rozwiązanie tego problemu” – nie widze ;|