Przezroczystość i mgła

W czwartej części kursu OpenGL dla programistów C++Buildera i Delphi skoncentrujemy się na dwóch ważnych i efektownych procesach modyfikacji kolorów.

W czwartej części kursu OpenGL dla programistów C++Buildera i Delphi skoncentrujemy się na dwóch ważnych i efektownych procesach modyfikacji kolorów.

Co to znaczy, że obiekt jest przezroczysty? To znaczy, że w kolorze jego pikseli jest uwzględniony kolor tych, które znajdują się na dalszym planie. Gdyby nie przezroczystość, dalekie piksele byłyby po prostu niewidoczne. Dzięki przezroczystości widzimy światło dalekiego planu, odpowiednio przyciemnione, przebarwione, przefiltrowane. Przezroczystość jest specjalnym mechanizmem modyfikowania koloru dalekiego planu.

Co to znaczy, że obiekt jest zamglony? Oznacza to, że im dalej się znajduje, tym większy udział ma barwa ogólnego tła w jego kolorze. Dalekie obiekty wtapiają się w tło.

Przezroczystość

Rysunek 1. Efekt przezroczystości polega na odpowiednim składaniu kolorów pikseli przedniego i dalekiego planu.

Rysunek 1. Efekt przezroczystości polega na odpowiednim składaniu kolorów pikseli przedniego i dalekiego planu.

Umieśćmy na scenie jakikolwiek obiekt. Może to być kostka z poprzednich przykładów lub piramida z rysunku 1. Przed piramidą postawimy prostokątną płytkę - filtr o jakiejś określonej barwie. Oto szkic funkcji rysuj_scene(), która realizuje to zamierzenie. Pełny kod znajduje się na płycie dołączonej do wydania PCWK.

void TForm1::rysuj_scene(void)

{

...

glBegin(GL_TRIANGLES); //ścianki piramidy

glVertex3f(0, 1, 0);

...

glEnd();

...

glEnable(GL_BLEND); //włączenie przezroczystości

glBegin(GL_QUADS); //prostokąt - szyba

glColor4f(1.0, 0.5, 1, 0.5); //4. parametr -

// gęstość koloru

glVertex3f(-0.5, 0.5, 0);

...

glEnd();

glDisable(GL_BLEND); //wyłączenie przezroczystości

...

}

Funkcja ma dwie sekcje - rysowanie piramidy, zbudowanej z czterech trójkątów (kwadratową podstawę pominiemy, bo nigdy nie zaglądamy pod nią) oraz filtru. Niepokazane tutaj funkcje glTranslatef() ustawiają te obiekty na scenie w taki sposób, że między piramidą a obserwatorem znajdzie się prostokąt filtru. Standardowe podejście do tego problemu prowadzi do tego, że daleka piramida jest schowana za bliską płytą filtru.

Zauważmy jednak, że gdy wykreślamy prostokąt filtru, włączamy przezroczystość, a jego kolor ma określony czwarty argument - tzw. gęstość optyczną. Nasz filtr jest różowy i ma połówkową gęstość.

Należy zwrócić uwagę na jeszcze jeden szczegół, zrealizowany w funkcji przygotowującej scenę do renderingu:

void TForm1::inicjuj_scene(void)

{

glClearColor(1, 1, 1, 0); //tło białe

//definicja przezroczystości

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

...

}

Funkcja glBlendFunc() definiuje sposób realizowania przezroczystości, czyli algorytm mieszania koloru filtru z kolorem obserwowanego obiektu:

glBlendFunc(udział koloru szyby, udział koloru obiektu);

Jeśli gęstość filtru wynosi 0 (czyli jest całkowicie przezroczysty), kolor obiektu nie zmienia się, jeśli 1 (czyli jest całkowicie nieprzezroczysty) - obiekt przybiera kolor szyby, czyli jest niewidoczny.

kolor_obiektu = kolor_szyby * gęstość + kolor_obiektu * (1 - gęstość)

Funkcja glBlendFunc() dzięki różnym argumentom sterującym może realizować także inne algorytmy składania kolorów.

Włączanie i wyłączanie przezroczystości

Rysunek 2. Sekwencja nałożonych na siebie filtrów, których przezroczystość może być dynamicznie włączana i wyłączana.

Rysunek 2. Sekwencja nałożonych na siebie filtrów, których przezroczystość może być dynamicznie włączana i wyłączana.

Przezroczystością możemy sterować "w locie". W kolejnym przykładzie (rys. 2) narysujemy trzy różnokolorowe płytki, przy czym kolor każdej z nich będzie miał określoną gęstość. Przy okazji będziemy mogli spojrzeć na wirtualny świat nie przez jeden filtr, a ich kombinację.

Funkcja rysuj_scene() składa się z algorytmu wykreślania trzech przesuniętych w osi Z czworokątów - filtrów i przyjmuje następującą postać:

void TForm1::rysuj_scene(void)

{

...

glBegin(GL_QUADS);

glColor4f(0, 0, 1, 0.3); //4. parametr -

// gęstość optyczna

glVertex3f(-1, -1, 0);

...

glColor4f(0, 1, 0, 0.3);

glVertex3f(-1, -1, 0.5);

...

glColor4f(1, 0, 0, 0.3);

glVertex3f(-1, -1, 1);

glEnd();

...

}

Odpowiednik tej funkcji, napisany w Delphi, znajduje się na płycie. Funkcja glColor4f() zastąpiła znaną z wcześniejszych przykładów trójargumentową funkcję glColor3f(). Trzy pierwsze argumenty określają barwę filtru, czwarty definiuje jego gęstość. Pierwsza wykreślona płyta jest niebieska, druga zielona, trzecia czerwona. Wszystkie mają niewielką gęstość optyczną, czyli są w dużym stopniu przezroczyste.

Aby włączyć efekt przezroczystości, w funkcji inicjuj_scene() definiujemy algorytm łączenia kolorów jako standardową przezroczystość i znów uaktywniamy tzw. blending:

procedure TForm1.inicjuj_scene;

begin

glClearColor(0.8, 0.8, 0.8, 0.0);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glEnable(GL_BLEND);

end;

W poprzednim przykładzie przezroczystość włączaliśmy w funkcji rysuj_scene(), tuż przed wykreśleniem szkła, ale tam scena była zabudowana przezroczystym filtrem i pełną piramidą. Tutaj wszystko jest ze szkła, dlatego przezroczystość zostaje włączona jednorazowo w funkcji inicjuj_scene().

Funkcja glEnable() w tym przypadku włącza analizę gęstości kolorów.

W dowolnej chwili możemy również wyłączyć przezroczystość, korzystając z glDisable(GL_BLEND).

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);

begin

case key of

'1': glEnable (GL_BLEND);

'2': glDisable(GL_BLEND);

end;

end;


Zobacz również