You are on page 1of 150

4. Obiekty podstawowe .................................................................

3
kozdz|o 5. Ko|or, moIer|oy | ow|eI|en|e. FodsIowy..............................
Punkt 3
kozdz|o 5. Ko|or, moIer|oy | ow|eI|en|e. FodsIowy.............................. 221
................. 222 Czym jest kolor?...............................................................................................................
wiato jest fal ........................................................................................................................... 222
wiato jako czsteczka............................................................................................................... 222
Nasz osobisty wykrywacz fotonw............................................................................................. 224
Komputer generatorem fotonw.................................................................................................. 224
Sprzt komputerw PC...................................................................................................................... 225
Tryby graficzne komputerw PC....................................................................................................... 227
Rozdzielczo ekranu.................................................................................................................. 227
Gbia kolorw............................................................................................................................ 227
Uywanie kolorw w OpenGL.......................................................................................................... 229
Szecian kolorw......................................................................................................................... 229
Ustalanie koloru rysowania ......................................................................................................... 230
Cieniowanie................................................................................................................................. 231
Ustalanie modelu cieniowania..................................................................................................... 233
Kolory w wiecie rzeczywistym........................................................................................................ 234
wiato otaczajce ....................................................................................................................... 235
wiato rozproszone .................................................................................................................... 235
wiato odbite.............................................................................................................................. 235
A teraz wszystko razem............................................................................................................... 236
Materiay w wiecie rzeczywistym.................................................................................................... 237
Waciwoci materiaw.............................................................................................................. 237
Dodawanie wiata do materiaw............................................................................................... 237
Wyliczanie efektw owietlenia otoczenia.................................................................................. 238
Efekty wiata rozproszenia i odbitego........................................................................................ 238
Dodawanie wiate do sceny.............................................................................................................. 239
Wczenie owietlenia................................................................................................................. 239
Konfigurowanie modelu owietlenia........................................................................................... 239
Ustalanie waciwoci materiaw............................................................................................... 240
Uywanie rde wiata.................................................................................................................... 243
Gdzie jest gra?........................................................................................................................... 244
Normalne powierzchni ................................................................................................................ 244
Definiowanie normalnej .............................................................................................................. 245
Normalne jednostkowe................................................................................................................ 247
Znajdowanie normalnej ............................................................................................................... 248
Konfigurowanie rda................................................................................................................ 249
Ustalanie waciwoci materiaw............................................................................................... 250
Definiowanie wieloktw............................................................................................................ 251
Efekty wietlne .................................................................................................................................. 252
Odbyski ...................................................................................................................................... 253
wiato odbite.............................................................................................................................. 253
Wspczynnik odbicia ................................................................................................................. 254
Wykadnik odbysku ................................................................................................................... 255
Urednianie normalnych.............................................................................................................. 256
A teraz wszystko razem..................................................................................................................... 258
Tworzenie reflektora ................................................................................................................... 259
Rysowanie reflektorw................................................................................................................ 261
Spis treci
Cienie ................................................................................................................................................ 265
Czym jest cie? ........................................................................................................................... 266
Kod prasujcy.............................................................................................................................. 267
Przykad z cieniem...................................................................................................................... 268
Ponowna wizyta w wiecie kul.................................................................................................... 271
Podsumowanie................................................................................................................................... 271
Opisy funkcji ..................................................................................................................................... 272
Spis treci
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania ................. 241
GLSL 101 ..................................................................................................................................... 242
Zmienne i typy danych ...................................................................................................... 243
Kwalifikatory zmiennych .................................................................................................. 246
Prawdziwy shader ............................................................................................................... 248
Kompilowanie, wizanie i konsolidowanie .................................................................... 252
Praktyczne wykorzystanie shadera .................................................................................. 258
Wierzchoek prowokujcy ................................................................................................ 259
Dane uniform shadera .............................................................................................................. 259
Znajdowanie danych uniform .......................................................................................... 260
Zmienne uniform skalarne i wektorowe ......................................................................... 260
Tablice uniform .................................................................................................................. 261
Macierze uniform ............................................................................................................... 262
Paski shader ........................................................................................................................ 262
Funkcje standardowe ................................................................................................................ 265
Funkcje trygonometryczne ............................................................................................... 265
Funkcje wykadnicze .......................................................................................................... 266
Funkcje geometryczne ....................................................................................................... 267
Funkcje macierzowe ........................................................................................................... 267
Funkcje porwnywania wektorw ................................................................................... 267
Inne czsto uywane funkcje ............................................................................................ 267
Symulowanie wiata ................................................................................................................. 272
wiato rozproszone ........................................................................................................... 272
Shader wiata rozproszonego .......................................................................................... 274
Model owietlenia ADS ..................................................................................................... 278
Cieniowanie Phonga .......................................................................................................... 281
Korzystanie z tekstur ................................................................................................................. 285
Nic, tylko teksele ................................................................................................................. 285
Owietlanie tekseli .............................................................................................................. 287
Anulowanie przetwarzania fragmentw ......................................................................... 289
Teksturowanie w stylu kreskwkowym teksele w roli wiata ................................ 292
Podsumowanie ........................................................................................................................... 294
Rozdzia 9. Zaawansowane odwzorowania tekstur.................................................. 237
Tekstury wielokrotne................................................................................................... 237
Sprawdzanie dostpnoci tekstur wielokrotnych ....................................................... 238
Dostp do funkcji rozszerze.................................................................................. 239
Tworzenie jednostek tekstury................................................................................. 240
Okrelanie wsprzdnych tekstury ......................................................................... 241
Przykad zastosowania tekstur wielokrotnych........................................................... 242
Odwzorowanie otoczenia ............................................................................................. 250
Torus na niebie...................................................................................................... 250
Macierze tekstur.......................................................................................................... 253
Mapy owietlenia ........................................................................................................ 255
Stosowanie map owietlenia................................................................................... 255
Wieloprzebiegowe tekstury wielokrotne........................................................................ 261
Podsumowanie............................................................................................................ 265
74
Rozdzia 4. Obiekty podstawowe
Punkt
Punkt stanowi najwaniejszy element kadej rysowanej sceny.
Wszystkie obiekty rysowane za pomoc procedur OpenGL s
zbudowane z punktw. Punkty te mog wyznacza wierzchoki
obiektw (linia, trjkt) lub stanowi wypenienie tych obiektw.
Za pomoc punktw mona rwnie rysowa wykresy funkcji
matematycznych czy te dowolne figury uoone z kolejnych
punktw. Aby wyznaczy pooenie punktu i jego wielko,
wykorzystuje si specjalne procedury OpenGL. Bardzo wanym
zagadnieniem jest wzajemna zaleno pomidzy punktem ry-
sowanym w OpenGL a pikselem. Piksel jest najmniejszym ob-
szarem ekranu, jaki moe przy rozdzielczoci okrelonej para-
metrami danej karty graficznej w danej chwili by zapalony
(zgaszony). Na rozmiar piksela programista nie ma adnego
wpywu (poza zmian rozdzielczoci ekranu). Punkt natomiast
posiada rozmiar okrelony wielkoci paszczyzny rzutowania
i zadeklarowan wielkoci. Domyln wielkoci punktu jest 1
(jeden), co nie oznacza wcale, e na ekranie bdzie on odpo-
wiada jednemu pikselowi. W przypadku zmiany rozmiaru
paszczyzny rzutowania zmieni si rwnie rozmiar wywie-
tlanego punktu o wielkoci jednostkowej (moe wynosi kilka
lub kilkanacie pikseli). Zagadnienie to jest szczeglnie istotne
przy imporcie obrazkw, jak rwnie podczas wykorzystywa-
nia bitmap, ktrych wymiary s okrelane w pikselach. Rezultat
nieskorelowania wymiarw okna grafiki i paszczyzny rzuto-
wania przedstawia rysunek 4.1.
Rozdzia 4. Obiekty podstawowe | 75
Rysunek 4.1. Zaleno wymiarw wywietlania obiektu, ktrego
wymiary okrelane s w pikselach i w punktach
Obrazek z lewej strony zosta wykonany z wykorzystaniem
procedury glDrawPixels(), tzn. narysowano go pikselami, na-
tomiast ten z prawej strony jest tekstur naoon na kwadrat
o takich samych wymiarach, ale okrelonych w punktach. Wy-
miary obrazka wynosz 128 na 128 pikseli, wymiary kwadratu
128 na 128 punktw. Okno grafiki okrelone procedur
glViewPort() ma wymiary 600 na 600 pikseli, a wymiary pasz-
czyzny rzutowania zdefiniowane procedur glOrtho() wyno-
sz 400 na 400 punktw. Jak wynika z przedstawionego rysunku,
proporcje pomidzy rzeczywistymi rozmiarami rysunku a obiek-
tem o tych samych wymiarach, ale wyraonych w innych jed-
nostkach, s oczywiste. Z powyszego wywodu wynika wic
jasno, e piksel to nie to samo co punkt.
glPointSize()
Deklaracja: procedure glPointSize(Grubo : GLFloat);
Dziaanie: ustala now wielko rysowanych punktw.
76 | OpenGL. Leksykon kieszonkowy
Uwaga
Nowa wielko rysowanych punktw bdzie taka sama
dla wszystkich punktw rysowanych po jej ustaleniu. Aby
przywrci domyln wielko punktu 1 (jeden), naley po-
nownie wywoa procedur glPointSize(), z parametrem
Grubo rwnym 1 (jeden).
glPointSize(5); // Punkt o wielkoci 5 jednostek
glPointSize(1); // Powrt do wielkoci domylnej
glVertex*()
Deklaracja: procedure glVertex2*(x, y, z, w : GL**[PGL**]);
lub procedure glVertex3*(x, y, z, w : GL**[PGL**]);
lub procedure glVertex4*(x, y, z, w : GL**[PGL**]);
Uwaga
Znak * (gwiazdka) to jedno z: d, f, i, s, dv, fv, iv lub sv.
Dwuznak ** (dwie gwiazdki) to odpowiednio: Double, Float,
Int lub Short.
Dziaanie: rysuje wierzchoek (punkt) na paszczynie rzutowania,
w miejscu okrelonym parametrami wywoania. Tworzenie takich
obiektw jak linie, wielokty itp. odbywa si za pomoc okre-
lenia pooenia ich wierzchokw w przestrzeni. Cyfra przy-
rostka okrela liczb wymiarw w przestrzeni, w ktrej bdzie
umieszczony wierzchoek. Litera v oznacza, e parametry do
procedury bd przekazane w postaci tablicy (wektora). Najcz-
ciej procedura ta jest wywoywana w postaci: glVertex3f().
Naley w tym miejscu wspomnie, e liczby typu Double
(GLDouble) i Single (GLFloat) s bez konwersji akceptowane
przez koprocesor matematyczny (CPU) i z tego te wzgldu
naley z nich korzysta, oczywicie jeeli inne wzgldy nie
Rozdzia 4. Obiekty podstawowe | 77
wymuszaj stosowania innego typu liczb. W powyszym przy-
kadzie uwzgldniono procedur glPointSize(), ktra okrela
wielko rysowanych punktw na ekranie. Jeeli nie wywoamy
tej procedury, to wszystkie punkty bd miay domyln wiel-
ko rwn 1 (jeden). Dla punktw, podobnie jak dla innych
obiektw, mona wykorzysta narzdzie do wygadzania kra-
wdzi, czyli tzw. antialiasing. W razie zwikszenia rozmiarw
punktu okae si, e ma on ksztat kwadratu, co nie zawsze jest
podane. Aby tego unikn, wystarczy wywoa procedur
glEnable() z parametrem GL_POINT_SMOOTH, co spowoduje, e
naroniki zostan zaokrglone. Naley pamita o wywoaniu
procedury glDisable(GL_POINT_SMOOTH), jeeli kolejne punkty
maj by rysowane bez wygadzania. Wczanie wygadzania
dla punktw o domylnej wielkoci 1.0 jest bezcelowe i nie na-
ley go stosowa. Poniej przedstawiono fragment kodu, ktrego
wykonanie powoduje narysowanie punktu bez wygadzania
i z wygadzaniem:
// Punkt
glColor3f(0.0, 0.0, 1.0); // Kolor niebieski
// Punkt bez wygadzania
glPointSize(95); // Wielko punktu(95 pikseli);
glBegin(GL_POINTS); // Rysowanie punktw
glVertex3f(0, 0, 0); // Pooenie punktu(rodek okna
grafiki OpenGL)
glEnd; // Koniec rysowania
// Punkt wygadzony
glEnable(GL_POINT_SMOOTH); // Wczenie wygadzania
(antialiasing) punktu
glPointSize(95);
glTranslatef(100, 0, 0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
glEnd;
glDisable(GL_POINT_SMOOTH); // Wyczenie wygadzania
punktu
Rezultat dziaania powyszego fragmentu kodu ilustruje ry-
sunek 4.2.
78 | OpenGL. Leksykon kieszonkowy
Rysunek 4.2. Punkt o wielkoci 95 jednostek bez wygadzania i po wczeniu
wygadzania
Uwaga
Domylnie wygadzanie jest wyczone, a to ze wzgldu na
bardzo znaczce spowolnienie pracy programu. Przed w-
czeniem wygadzania naley przeanalizowa konieczno jego
uycia i wyczy, jeeli przestaje by faktycznie niezbdne.
4Q\F\KC
-QNQTOCVGTKC[KQYKGVNGPKG
2QFUVCY[
#WVQT4KEJCTF59TKIJV,T
%\GIQPCWE\[O[UKYV[OTQ\F\KCNG!
Jok Funkcje, z ktrych bqdz|emy korzystoc
Ustala kolor na podstawie skadowych RGB _!Co!or
Ustala model cieniowania _!ShaceMoce!
Ustala model owietlenia _!|:_h!Moce!
Ustala parametry owietlenia _!|:_h!
Skonfigurowa odblaskowe waciwoci materiaw _!Co!orMa!er:a!/_!Ma!er:a!
Stosowa normalne powierzchni _!Norma!
W niniejszym rozdziale grafika trjwymiarowa w kocu zacznie wyglda interesujco
(chyba e kto bardzo lubi modele szkieletowe), a w kadym nastpnym bdzie coraz lepiej.
Do tej pory uczylimy si biblioteki OpenGL od jej podstaw jak mona budowa
programy, jak w przestrzeni trjwymiarowej skada obiekty z obiektw podstawo-
wych, jak manipulowa tymi obiektami w trzech wymiarach. Cay czas kadlimy tylko
fundamenty, ale nadal nie wiemy, jak bdzie wyglda cay budynek! Parafrazujc fraz:
Gdzie jest arcie?.
Krtko mwic arcie zaczyna si tutaj. W wikszoci pozostaej czci tej ksiki
nauka zostanie odsunita na plan dalszy, a wadz przejmie magia. Zgodnie ze sowami
Arthura C. Clarkea kada wystarczajco rozwinita technologia jest nie do odrnienia
od magii. Oczywicie w kolorach i owietleniu nie ma adnej magii, cho czasami mona
odnie inne wraenie. Jeeli ktokolwiek jest zainteresowany t wystarczajco rozwinit
technologi, czyli matematyk, to odsyamy do dodatku A.
Alternatywn nazw tego rozdziau mogoby by Dodawane do sceny realizmu. W wie-
cie rzeczywistym na kolor obiektu wpywa duo wicej czynnikw ni proste naoenie
koloru znane z biblioteki OpenGL. Obiekty, poza tym, e maj jaki kolor, mog by ma-
towe lub byszczce, a nawet wieci wasnym wiatem. Widziany kolor obiektu moe
224 Cz I Klasyka OpenGL
by inny w jasnym owietleniu ni w wietle przytumionym. Znaczenie ma te kolor
padajcego na obiekt wiata. Owietlony obiekt moe mie te cieniowane powierzchnie,
jeeli owietlany bdzie pod odpowiednim ktem.
%\[OLGUVMQNQT!
Pomwmy przez chwil o samych kolorach. W jaki sposb widzimy kolory? Jak s one
tworzone w naturze? Teoria kolorw i metody odbierania kolorw przez ludzkie oko
bardzo uatwi nam zrozumienie programowych metod tworzenia barw. Jeeli kto ju
doskonale zna tajniki teorii kolorw, spokojnie moe pomin ten podrozdzia.
YKCVQLGUVHCN
Kolor jest po prostu fal wietln o pewnej dugoci, widoczn dla ludzkiego oka. Kady,
kto w szkole uwaa na lekcjach fizyki, zapewne pamita, e wiato jest jednoczenie
zarwno fal, jak i czsteczk. wiato modelowane jest jako fala przemieszczajca si
przez przestrze, jak fale na wodzie, ale take jako czsteczki, padajce na ziemie jak
krople deszczu. Jeeli komu ta koncepcja wydaje si pogmatwana, to chyba ju rozumie,
dlaczego tak niewiele osb studiuje fizyk kwantow.
wiato, jakie widzimy, tak naprawd jest mieszank wielu rnych rodzajw wiata.
Kady rodzaj wiata identyfikowany jest dugoci fali. Dugo fali wiata mierzona
jest odlegoci pomidzy dwiema kolejnymi wartociami szczytowymi, tak jak pokazano
to na rysunku 5.1.
kysunek 5.1.
Pomiar dugoci
fali wietlnej
wiato widzialne mieci si w zakresie dugoci fal od 390 nanometrw (miliardowych
czci metra) dla wiata fioletowego, do 720 nanometrw dla wiata czerwonego. Ten
zakres nazywany jest czsto spektrum wiata widzialnego. Z ca pewnoci kady sysza
ju okrelenia ultrafiolet i podczerwie opisuj one wiato niewidzialne dla ludzkiego
oka, lece tu poza podanym powyej spektrum. Cae spektrum widzialne zawiera w sobie
wszystkie kolory tczy (tak jak na rysunku 5.2).
YKCVQLCMQE\UVGE\MC
Mona sobie pomyle: Dobra, panie mdrala, jeeli kolor jest tylko dugoci fali wiata,
a wszystkie moliwe kolory widoczne s w tczy, to gdzie w takim razie podzia si
brz z czekolady, czer mojej porannej kawy albo biel kartki papieru? Odpowied na te
pytania zaczniemy od stwierdzenia, e czer nie jest kolorem, podobnie jak i biel. Tak
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 225
kysunek 5.2. Spektrum wiat widzialnego
naprawd czer jest barkiem jakiegokolwiek koloru, a biel to rwnomierna kombinacja
wszystkich kolorw. Oznacza to, e biay obiekt odbija wszystkie kolory w jednakowy spo-
sb, natomiast obiekt czarny tak samo rwno pochania wszystkie dugoci fali wietlnej.
Jeeli chodzi o brz czekolady, jak rwnie inne kolory, z jakimi spotykamy si w yciu,
to rzeczywicie jest on kolorem. Kolory rzeczywiste skadaj si one z rnych mieszanek
czystych kolorw widzialnego spektrum, w zwizku z czym pod wzgldem fizycznym s
one kolorami zoonymi. eby zrozumie, jak dziaa takie mieszanie kolorw, trzeba myle
o wietle jako o czsteczkach. Kady owietlony obiekt bombardowany jest miliardami, mi-
liardami (tutaj musz przeprosi Carla Sagana) fotonw, czyli malekich czsteczek wiata.
Przypomnijmy sobie ten fizyczny hokus-pokus, o ktrym mwilimy wczeniej kady
foton jest rwnie fal posiadajc pewn dugo, czyli konkretny kolor ze spektrum.
Kady obiekt fizyczny skada si z atomw. Sposb odbicia fotonw od obiektu uzaleniony
jest od rodzaju atomw, z jakich si on skada, liczby kadego rodzaju atomw, a take
ich uoenia (razem z elektronami) wewntrz obiektu. Cz fotonw jest odbijana, a cz
pochaniana (pochaniane fotony s zamieniane w ciepo). Kady materia lub mieszanka
materiaw lepiej odbija pewne dugoci fal ni inne. Zasada ta zostaa przedstawiona
na rysunku 5.3.
kysunek 5.3.
Kady obiekt odbija
cz fotonw, a cz
z nich pochania
226 Cz I Klasyka OpenGL
0CU\QUQDKUV[Y[MT[YCE\HQVQPY
wiato odbite od naszej tabliczki czekolady wpada do naszego oka, gdzie jest interpreto-
wane jako kolor. Miliardy fotonw wpadajcych do naszego oka skupiane s w jego czarnej
czci, gdzie siatkwka dziaa na zasadzie podobnej do kliszy fotograficznej. Miliony
komrek siatkwki pobudzanych jest przez uderzajce w nie fotony, co powoduje, e do
mzgu zaczynaj wdrowa sygnay nerwowe, ktre s nastpnie interpretowane jako wia-
to i kolor. Im wicej fotonw uderza w siatkwk, tym bardziej pobudzone s jej komrki.
Poziom pobudzenia interpretowany jest w mzgu jako jasno wiata. Wynika to z prostej
zalenoci im janiejsze jest wiato, tym wicej fotonw wpada do naszego oka.
W naszym oku znajduj si trzy rodzaje komrek. Wszystkie reaguj na uderzenia foto-
nw, ale kady rodzaj najmocniej reaguje na fale o okrelonej dugoci. Jedne komrki
pobudzane s wiatem czerwonym, drugie wiatem zielonym, a trzecie wiatem nie-
bieskim. Tak wic wiato skadajce si gwnie z czerwonych dugoci fal najbardziej
pobudza w siatkwce komrki reagujce na wiato czerwone, a mniej pozostae. Nasz
mzg przetwarza takie sygnay, stwierdzajc, e widziane wiato jest przede wszystkim
czerwone. A teraz prosta matematyka czenie rnych dugoci fal wietlnych o od-
miennych intensywnociach da nam w wyniku rne mieszanki kolorw. Jeeli wszyst-
kie fale bd miay identyczn intensywno, to takie wiato bdziemy odbiera jako
biae. Jeeli natomiast nie zobaczymy adnych fal wietlnych, to zinterpretujemy ten
stan jako czer.
Jak wida, kady odbierany przez nasze oczy kolor jest w rzeczywistoci mieszanin
wiata z caego widzialnego spektrum. Sprztowe elementy naszego oka wykrywaj
obrazy na podstawie wzgldnego skupienia i natenia wiata czerwonego, zielonego
i niebieskiego. Na rysunku 5.4 przedstawiono sposb, w jaki nasze oko odbiera kolor
brzowy, czyli mieszank 60% fotonw czerwonych, 40% fotonw zielonych i 10%
niebieskich.
kysunek 5.4.
Jak nasze oko widzi
kolor brzowy
-QORWVGTIGPGTCVQTGOHQVQPY
Skoro wiemy ju, jak ludzkie oko rozpoznaje kolory, cakiem rozsdnym wydaje si
pomys komputerowego generowania kolorw poprzez definiowanie oddzielnych inten-
sywnoci skadowych czerwonej, zielonej i niebieskiej. Tak si akurat skada, e moni-
tory komputerw zaprojektowane s w sposb pozwalajcy im emitowa trzy rodzaje
wiata (zgadnijcie jakie), z ktrych kady moe mie inn intensywno. W tylnej czci
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 227
monitora znajduje si dziao elektronowe wyrzucajce elektrony na tyln cz ekranu
monitora. Na powierzchni tego ekranu znajduj si materiay fosforyzujce, ktre w czasie
bombardowania strumieniem elektronw zaczynaj emitowa wiato czerwone, zielone
lub niebieskie. (No dobra, ale jak w takim razie dziaaj wywietlacze LCD? Znalezienie
odpowiedzi na to pytanie pozostawimy Czytelnikowi jako prac domow). Te trzy fos-
foryzujce materiay uoone s bardzo blisko siebie, tak e razem tworz jedn barwn
plamk na ekranie (rysunek 5.5).
kysunek 5.5.
Jak monitor
komputerowy generuje
kolory
Prosz sobie przypomnie, jak w rozdziale 2., Uywanie OpenGL, opisywalimy po-
lecenie Cccr pozwalajce na definiowanie kolorw poprzez podanie intensywnoci
skadowych czerwonej, zielonej i niebieskiej.
5RT\VMQORWVGTY2%
By taki czas, kiedy najnowoczeniejsz kart graficzn dla komputerw PC bya karta
Hercules. Karta pozwalaa na tworzenie bitmapowych obrazw o rozdzielczoci 720348
punktw. Jej wad byo to, e kady z punktw mg mie tylko dwa stany: zapalony
lub zgaszony. W tym czasie tworzenie bitmapowej grafiki na komputerach PC nie byo
zadaniem atwym, cho tworzone byy wspaniae monochromatyczne obrazy nawet
trjwymiarowe!
Jeszcze przed powstaniem kart Hercules dostpne byy karty CGA (ang. Color Graphics
Adapter). Karta powstaa razem z pierwszymi komputerami IBM PC moga obsugiwa
rozdzielczo 320200 pikseli i wywietla na ekranie 4 lub 16 kolorw naraz. Dostpna
bya te wysza rozdzielczo (640200) z dwoma kolorami, ale nie bya ona tak efek-
towna, jak w znacznie taszej karcie Hercules (monitory kolorowe oznaczay znacznie
wysze koszty). Jak na dzisiejsze standardy karta CGA wyglda mizernie. Jej graficzne
moliwoci prezentoway si nie najlepiej nawet w porwnaniu z moliwociami tanich
komputerw Commodore 64 i Atari. Ze wzgldu na brak wystarczajcych rozdzielczoci
228 Cz I Klasyka OpenGL
obrazu karta nie nadawaa si do tworzenia grafiki biznesowej ani nawet modelowania.
Najczciej znajdowaa zastosowanie w prostych grach i aplikacjach biznesowych, ktre
mogy najwicej skorzysta na moliwoci wywietlania kolorowego tekstu. Mwic ogl-
nie, trudno byo znale dobry powd, eby kupi t nietani wtedy kart.
Nastpna rewolucja w grafice komputerw PC nastpia, gdy firma IBM zaprezentowaa
kart EGA (ang. Enhanced Graphic Adapter). Udostpniaa ona dodatkowe tryby tekstowe,
w ktrych moliwe byo wywietlanie wikszej liczby ni 25 linii kolorowego tekstu,
a w trybie graficznym mona byo uzyska rozdzielczo 640350 pikseli w 16 kolorach!
Inne poprawki techniczne wyeliminoway problemy z migotaniem obrazu w karcie CGA
i umoliwiy tworzenie lepszej i pynniejszej animacji. Od tego momentu gry platformowe,
graficzne aplikacje biznesowe, a nawet proste grafiki trjwymiarowe stay si czym
normalnym w wiecie komputerw PC. By to ogromny krok w stosunku do kart CGA, ale
grafika w komputerach PC nadal pozostawaa w powijakach.
Ostatnim wanym standardem, jaki wrd komputerw PC wyznaczya firma IBM bya
karta VGA (skrt ten oznacza Vector Graphics Array, a nie, jak si powszechnie uwaa,
Video Graphics Adapter). Karta bya o wiele szybsza ni EGA, pozwalaa stosowa 16
kolorw w wysokich rozdzielczociach (640480), a w mniejszych (320200) nawet
265 kolorw, ktre byy wybierane z palety obejmujcej ponad 16 milionw kolorw.
W ten sposb otwarty zosta worek z graficznymi aplikacjami dla komputerw PC nagle
moliwe stao si tworzenie niemal fotorealistycznych obrazw, a na rynku pojawiy si
programy do ledzenia promieni (ray trace), gry trjwymiarowe, oprogramowanie do
obrbki zdj i inne.
Firma IBM posiadaa jeszcze inn, znacznie bardziej zaawansowan kart graficzn dla
swoich stacji roboczych 8514. Moga ona wywietla obraz o rozdzielczoci 1024768
w 256 kolorach. Wedug firmy IBM ta karta miaa by uywana wycznie w aplikacjach
CAD i naukowych, jednak klienci zawsze bd chcieli czego wicej. Bya to krtko-
wzroczno, ktra firm IBM kosztowaa pozycj ustanawiajcego standardy rynku graficz-
nego komputerw PC. Inni dostawcy zaczli tworzy karty Super-VGA, ktre mogy
wywietla obraz w rozdzielczoci 1024768 i wikszej w coraz szerszej palecie kolorw.
Na pocztku byo to 800600, pniej 1024768 i wicej, pocztkowo w 256, a pniej
w 32 000 i 65 000 kolorw. Dzisiejsze karty graficzne wywietlaj obrazy o rozdziel-
czoci 1024768 i wikszej, stosujc 24-bitow palet kolorw. Takie karty graficzne
dostpne s ju nawet w najprostszych konfiguracjach komputerw.
To wszystko daje nam naprawd ogromne moliwoci na przykad tworzenie fotoreali-
stycznej grafiki trjwymiarowej, eby wymieni tylko jedno zastosowanie. Gdy Microsoft
przenis bibliotek OpenGL na system Windows, umoliwi w ten sposb tworzenie
wysokiej jakoci aplikacji graficznych dla komputerw PC. Jeeli poczymy wydajno
dzisiejszych procesorw z moliwociami kart graficznych wyposaonych w akceleratory
grafiki trjwymiarowej, to uzyskamy moliwoci, jakie jeszcze kilka lat temu dostpne
byy wycznie na stacjach roboczych wartych setki tysicy dolarw. A to wszystko za
promocyjn cen komputera w supermarkecie. Dzisiejsze domowe komputery mog
tworzy zaawansowane symulacje naukowe, gry i duo, duo wicej. Ju dzisiaj termin
rzeczywisto wirtualna wydaje si przestarzay jak rakieta Bucka Rogersa, a grafika
trjwymiarowa wydaje si nam czym absolutnie oczywistym.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 229
6T[D[ITCHKE\PGMQORWVGTY2%
Systemy operacyjne Microsoft Windows i Apple Macintosh pod dwoma wzgldami zre-
wolucjonizoway wiat grafiki komputerw PC. Po pierwsze, utworzyy najwaniejsze
graficzne rodowiska systemw operacyjnych wykorzystywanych w biznesie, a wkrtce
potem rwnie na rynku konsumenckim. Po drugie, znaczco uatwiy prac programistw
grafiki. Sprzt graficzny poddany zosta wirtualizacji na poziomie sterownikw. Pro-
gramici nie musz ju wysya polece rysujcych bezporednio do kart graficznych.
Korzystaj ze specjalnych interfejsw programistycznych (takich jak OpenGL), a sprawami
komunikacji ze sprztem zajmuje si ju system operacyjny.
4Q\F\KGNE\QGMTCPW
W dzisiejszych komputerach stosowane s rozdzielczoci ekranw od 640480 do
16001200, a nawet wicej. Najnisze rozdzielczoci, takie jak 640480 uznawane s
za odpowiednie dla pewnych zada graficznych, a osoby z problemami ze wzrokiem sto-
suj te rozdzielczoci (czsto w poczeniu z duymi monitorami), co uatwia im prac
z komputerem. Zawsze trzeba mie na uwadze wielko okna i ustawienia widoku (roz-
dzia 2.), w ktrym wywietlana bdzie przestrze ograniczajca. Zrwnujc wielko
rysunku z wielkoci okna, bardzo atwo mona dostosowywa si do rnych kombinacji
wielkoci okna i rozdzielczoci ekranu. Dobrze napisane aplikacje wywietlaj mniej
wicej taki sam obraz niezalenie od rozdzielczoci ekranu. Oczywicie im wiksza bdzie
rozdzielczo, tym dokadniejszy obraz powinien zobaczy uytkownik.
)DKCMQNQTY
Jeeli powikszenie rozdzielczoci ekranu, czyli liczby dostpnych do rysowania pikseli
wpywa na popraw dokadnoci i ostroci obrazu, to w podobny sposb zwikszenie
liczby dostpnych kolorw powinno poprawia przejrzysto generowanego obrazu. Obraz
wywietlany przez komputer, ktry moe posugiwa si milionami kolorw, powinien
wyglda o wiele lepiej ni ten sam obraz wywietlany za pomoc zaledwie 16 kolorw.
Pod wzgldem programowym zajmowa bdziemy si zaledwie trzema gbiami kolorw:
4-bitow, 8-bitow i 24-bitow.
Iryb ko|oru 4-b|towego
W najgorszym przypadku nasz program bdzie musia dziaa w zaledwie 16 kolorach
ten tryb nazywany jest 4-bitowym, poniewa kolor kadego piksela reprezentowany jest
za pomoc czterech bitw. Mona w nich zapisa wartoci od 0 do 15, ktre bd in-
deksem w 16-elementowym zbiorze predefiniowanych kolorw (taki ograniczony zbir
kolorw, do ktrych mona odwoywa si za pomoc indeksw, nazywany jest palet
kolorw). Posiadajc zaledwie 16 kolorw, nie mamy zbyt wielkich moliwoci two-
rzenia dokadnego i ostrego obrazu. Najczciej zupenie bezpiecznie mona cakowicie
zignorowa tryb 4-bitowy w naszych programach, tym bardziej, e wikszo najnowszych
kart graficznych nie obsuguje ju adnego trybu 4-bitowego koloru.
230 Cz I Klasyka OpenGL
Iryb ko|oru 8-b|towego
Tryb koloru 8-bitowego pozwala wywietla na ekranie 256 kolorw. Nadal jest to do
powane ograniczenie, cho poprawa w stosunku do trybu 4-bitowego jest znaczca.
Wikszo akceleratorw graficznych wsppracujcych z bibliotek OpenGL nie przy-
spiesza dziaa na 8-bitowych kolorach, ale stosujc rendering programowy mona w pew-
nych warunkach uzyska satysfakcjonujce wyniki. Najwikszym problemem jest tutaj
zbudowanie prawidowej palety kolorw. Ten temat bdziemy krtko omawia w rozdziale
13., Wiggle. OpenGL w systemie Windows.
Iryb ko|oru 24-b|towego
Dzisiaj moliwie najlepszy obraz uzyskiwany jest w trybie koloru 24-bitowego. W tym try-
bie kolor kadego piksela definiowany jest za pomoc penych 24 bitw, w ktrych kade
8 bitw opisuje intensywno skadowej czerwonej, zielonej i niebieskiej (8+8+8 = 24).
Na ekranie moemy umieci piksel w dowolnym z ponad 16 milionw kolorw. Do
oczywist wad tego trybu jest ilo pamici, jaka jest potrzebna do zapisania wygldu
ekranw o wikszych rozdzielczociach (dla rozdzielczoci 1024768 bdzie to nieco
ponad 2 MB). Poza tym przenoszenie duych wycinkw pamici rwnie jest woln ope-
racj, szczeglnie jeeli pracujemy nad szybk animacj. Na cae szczcie dzisiejsze
akceleratory graficzne optymalizowane s do dziaania w tych wanie trybach kolorw
i dostarczane s z wystarczajc iloci wbudowanej pamici, eby sprosta rosncemu
zapotrzebowaniu na pami.
Iryby ko|oru 1- | 32-b|towego
Ze wzgldu na oszczdno pamici i popraw wydajnoci w wielu kartach graficznych
stosowane s rwnie rne inne tryby kolorw. W celu poprawy wydajnoci czsto uy-
wany jest tryb 32-bitowy, ktry czasami nazywany jest trybem true color (prawdziwy
kolor). Tak naprawd w tym trybie nie jest wywietlanych wicej kolorw ni w trybie
24-bitowym, a poprawa wydajnoci uzyskiwana jest poprzez ustawianie danych kadego
piksela do granicy adresw 32-bitowych. Niestety, w zwizku z tym marnowanych jest
osiem bitw (jeden bajt) dla kadego piksela. W dzisiejszych 32-bitowych komputerach PC
budowanych z wykorzystaniem procesorw firmy Intel stosowanie adresw pamici po-
dzielnych przez 32 pozwala na uzyskanie znacznie lepszych wynikw dostpu do pamici.
Nowoczesne akceleratory graficzne rwnie stosuj tryb 32-bitowy, w ktrym pierwsze
24 bity wykorzystane s na zapisanie kolorw RGB, a kocowe 8 bitw stosowane jest
do przechowywania wartoci kanau alfa. Na temat kanau alfa bdziemy mwi wicej
w nastpnym rozdziale.
Innym popularnym trybem jest tryb 16-bitowy, ktry czasami obsugiwany jest w celu
poprawienia efektywnoci wykorzystania pamici. Pozwala on nada kademu pikselowi
jeden z 65 536 kolorw. Ten tryb jest niemal tak samo skuteczny jeeli chodzi o odwzo-
rowywanie obrazw fotograficznych jak tryb 24-bitowy. Praktycznie trudno odrni od
siebie obraz wywietlany w obu tych trybach. To wanie poprawa wykorzystania pamici
i wzrost prdkoci wywietlania obrazw spowodoway, e tryb ten by bardzo popularny
w pierwszych akceleratorach grafiki trjwymiarowej przeznaczonych do gier. Jednak do-
datkowe kolory w trybie 24-bitowym bardzo podnosz jako obrazu, jeeli do jego gene-
rowania wykorzystywane s operacje cieniowania i mieszania kolorw.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 231
7[YCPKGMQNQTYY1RGP).
Wiemy ju, e biblioteka OpenGL definiuje kolory, okrelajc intensywnoci skadowych:
czerwonej, zielonej i niebieskiej. Wiemy te, e nowoczesny sprzt jest w stanie wywie-
tli niemal wszystkie moliwe kombinacje tych skadowych albo zaledwie kilka. Jak
w takim razie moemy okreli potrzebny nam kolor, podajc wspomniane trzy skadowe?
5\GEKCPMQNQTY
Kady kolor moemy zdefiniowa trzema dodatnimi wartociami, dlatego wszystkie
dostpne kolory mona przedstawi jako pewn przestrze nazywan przestrzeni kolorw
RGB. Na rysunku 5.6 przedstawiono, jak wyglda taka przestrze kolorw w pocztku
ukadu wsprzdnych z osiami kolorw czerwonego, zielonego i niebieskiego. Wsp-
rzdne poszczeglnych kolorw okrelane s na tej samej zasadzie jak wsprzdne x, y
i z. W pocztku ukadu wsprzdnych intensywno kadej skadowej jest rwna zero,
co oznacza kolor czarny. W komputerach PC wszystkie informacje o kolorze musza zmie-
ci si w 24 bitach, co daje 8 bitw na kad skadow. Mona wic powiedzie, e w ka-
dej skadowej warto 255 oznacza pene nasycenie tej skadowej koloru. Oznacza to, e
nasz szecian bdzie mia boki o dugoci 255 jednostek. Dokadnie na przeciwko rogu,
w ktrym panuje czer (0,0,0), znajduje si rg biay o wsprzdnych (255, 255, 255).
Wzdu kadej z osi, przy wartoci 255 znajduj si pene nasycenia kadego koloru
skadowego: czerwonego, zielonego i niebieskiego.
kysunek 5..
Pocztek ukadu
wsprzdnych
koloru RGB
Przedstawiony na rysunku 5.7 szecian kolorw, na swojej powierzchni jak i w swoim
wntrzu zawiera wszystkie moliwe kolory. Na przykad wszystkie moliwe odcienie
szaroci le wewntrz szecianu, na linii ukonej czcej punkty (0, 0, 0) i (255, 255, 255).
Rysunek 5.8 przedstawia gadko cieniowany szecian kolorw rysowany w przykadowym
programie CCUBE. Na powierzchni szecianu zobaczy mona przejcia kolorw od
czerni w jednym rogu, do bieli w przeciwlegym. W trzech rogach, odlegych od czarnego
o 255 jednostek, mona zobaczy kolory czerwony, zielony i niebieski w ich penych
intensywnociach. Dodatkowo w trzech rogach zobaczy mona kolory ty, zielono-nie-
bieski (cyan) i fuksyna (magenta), bdce kombinacjami kolorw podstawowych. Szecian
kolorw mona obraca, aby zobaczy wszystkie jego strony.
232 Cz I Klasyka OpenGL
kysunek 5.7.
Przestrze
kolorw RGB
kysunek 5.8.
Wynik dziaania
programu CCUBE
7UVCNCPKGMQNQTWT[UQYCPKC
Przyjrzyjmy si krtko funkcji Cccr. Jest ona prototypowana nastpujco:
XQKF _!Co!orx!rec _reen o!ue a!pha|,
W nazwie funkcji znak x oznacza liczb parametrw. Mog to by trzy parametry ozna-
czajce skadowe czerwon, zielon i niebiesk lub cztery parametry, w ktrych czwarty
oznacza skadow alfa koloru. Skadowa alfa okrelajca przezroczysto koloru opisana
jest dokadniej w dalszej czci rozdziau. Na razie bdziemy uywali trjparametrowej
wersji tej funkcji.
Symbol ' w nazwie funkcji okrela typ parametrw przyjmowanych przez funkcj.
Mog to by okrelenia | (|,'e), c (ccu|e), ' ('c.'), (n'), s (s|cr'), u| (unsnec
|,'e), u (unsnec n') lub us (unsnec s|cr'). Kolejna wersja funkcji ma na kocu
liter v. Oznacza ona, e ta wersja funkcji pobiera tablic zawierajc wszystkie para-
metry (litera v oznacza vector, czyli wektor). W podrozdziale Opisy funkcji znajduje si
duo dokadniejszy opis funkcji Cccr.
Wikszo programw, z jakimi przyjdzie nam si spotyka, wykorzystuje funkcj Cc
cro', w ktrej intensywno kadej skadowej okrelana jest liczb z zakresu od 00 do
`0. Jednak dla osb z dowiadczeniem w programowaniu w systemie Windows znacznie
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 233
atwiejsze moe by uycie funkcji Cccrou|. Ta wersja pobiera trzy bajty bez znaku,
czyli wartoci od 0 do bb. Stosowanie tej funkcji jest bardzo podobne do stosowania
makra systemu Windows:
_!Co!or:uo0 55 18| RB0 55 18|
Rzeczywicie, ta metoda moe uatwi dopasowanie kolorw w bibliotece OpenGL do kolo-
rw wykorzystywanych w programie w czasie rysowania niezwizanego z OpenGL. Mimo
to trzeba zaznaczy, e wewntrznie biblioteka OpenGL przechowuje dane kolorw jako
wartoci zmiennoprzecinkowe, wic stosowanie wartoci innego typu moe spowodowa
spadek wydajnoci z powodu koniecznych przeksztace wykonywanych w czasie dziaa-
nia programu. Poza tym w przyszoci moe si okaza, e powstan znacznie pojem-
niejsze bufory kolorw (tak naprawd to ju zaczynaj si pojawia bufory zapamitujce
wartoci zmiennoprzecinkowe), w ktrych przechowywane wartoci zmiennoprzecinkowe
najdokadniej odwzoruj stosowane kolory.
%KGPKQYCPKG
Poprzednio podawana definicja funkcji Cccr mwia, e ustala ona aktywny kolor
rysujcy, ktrym pokrywane s wszystkie obiekty rysowane po wywoaniu tej funkcji.
Po omwieniu w poprzednim rozdziale wszystkich obiektw podstawowych biblioteki
OpenGL moemy teraz nieco uszczegowi t definicj funkcja Cccr ustala ak-
tualny kolor rysujcy dla wszystkich wierzchokw definiowanych po wywoaniu tej
funkcji. W dotychczasowych przykadach rysowalimy obiekty tylko w postaci szkieletw,
a w ewentualnie wypenionych obiektach kada powierzchnia miaa inny kolor. Jeeli
jednak dla kadego wierzchoka obiektu podstawowego (punktu, linii lub wielokta) zdefi-
niujemy inny kolor, to jakiego koloru bdzie jego wntrze?
Odpowied na to pytanie zaczniemy od punktw. Kady punkt definiowany jest tylko
jednym wierzchokiem, dlatego jakikolwiek kolor zostanie przydzielony wierzchokowi,
bdzie to aktywny kolor punktu. Proste.
Ju jednak linia definiowana jest dwoma wierzchokami, z ktrych kady moe mie inny
kolor. Kolor samej linii tworzony jest przez model cieniowania. Cieniowanie definio-
wane jest po prostu jako pynne przejcie od jednego koloru do drugiego. W przestrzeni
kolorw RGB (musimy wrci do rysunku 5.7) dowolne dwa punkty mog by poczone
lini prost.
Pynne cieniowanie sprawia, e wzdu linii kolory zmieniaj si w taki sam sposb jak
kolory linii czcej dwa punkty wewntrz szecianu kolorw. Na rysunku 5.9 przed-
stawiony zosta szecian kolorw z zaznaczonymi punktami kolorw biaego i czarnego.
Poniej znajduje si linia definiowana dwoma wierzchokami jednym biaym, a drugim
czarnym. Kolory wybierane w czasie rysowania tej linii pokrywaj si dokadnie z kolo-
rami lecymi na prostej czcej w szecianie kolorw punkty biay i czarny. W ten
sposb powstaje linia, ktra na pocztku jest czarna, a w dalszej czci jej kolor zmienia si
w coraz janiejszy szary, a na kocu osiga biel.
234 Cz I Klasyka OpenGL
kysunek 5..
Rysowanie linii
z kolorami
zmieniajcymi si
od czerni do bieli
Moemy sami wykona cieniowanie linii, znajdujc matematyczne rwnanie linii czcej
dwa punkty wewntrz trjwymiarowej przestrzeni kolorw RGB. Pniej wystarczy
przej w ptli od jednego koca linii do drugiego, sprawdzajc po drodze odpowiednie
wsprzdne w przestrzeni kolorw wyznaczajce kolor kadego piksela linii. W wielu
dobrych ksikach opisujcych grafik komputerow podawane jest wyjanienie algo-
rytmu pozwalajcego na uzyskanie doskonaych efektw cieniowania, przeniesienia
kolorw linii z szecianu kolorw na ekran komputera i tym podobne. Na szczcie ca
t prac wykona za nas biblioteka OpenGL.
W przypadku wieloktw zadanie cieniowania staje si znacznie trudniejsze. Na przy-
kad trjkt moe by rwnie przedstawiony jako paszczyzna wewntrz szecianu
kolorw. Na rysunku 5.10 przedstawiono trjkt, ktrego wierzchokom nadano kolory
o penym nasyceniu skadowych czerwonej, zielonej i niebieskiej. Kod wywietlajcy
taki trjkt podany zosta na listingu 5.1. Pochodzi on z programu TRIANGLE znajdujcego
si na pycie CD doczonej do tej ksiki.
I|st|ng 5.1. Rysowanie trjkta cieniowanego kolorami czerwonym, zielonym i niebieskim
// Wczenie gadkiego cieniowania
_!ShaceMoce!|SMJJT'|,
// Rysowanie trjkta
_!Be_:n|TRT/N|FS|,
// Wierzchoek czerwony
_!Co!or:uo|uo,!e|55|uo,!e|0|uo,!e|0|,
_!Ver!ex:f00f000f00f|,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 235
kysunek 5.10.
Trjkt w przestrzeni
kolorw RGB
// Wierzchoek zielony - na dole po prawej stronie
_!Co!or:uo|uo,!e|0|uo,!e|55|uo,!e|0|,
_!Ver!ex:f000f-700f00f|,
// Wierzchoek niebieski - na dole po lewej stronie
_!Co!or:uo|uo,!e|0|uo,!e|0|uo,!e|55|,
_!Ver!ex:f-000f -700f 00f|,
_!Fnc|,
7UVCNCPKGOQFGNWEKGPKQYCPKC
W pierwszej linii listingu 5.1 ustalamy, e modelem cieniowania stosowanym przez biblio-
tek OpenGL bdzie cieniowanie gadkie, czyli model omawiany wczeniej. Co prawda
jest to ustawienie domylne, ale i tak lepiej wywoywa t funkcj upewniamy si w ten
sposb, e wszystko bdzie dziaao zgodnie z zaoeniami.
Drugim modelem cieniowania, jaki mona wczy funkcj S|.ceMcce, jest O|_||AT,
czyli cieniowanie paskie. Cieniowanie paskie oznacza, e wewntrz obiektw podstawo-
wych nie s wykonywane adne obliczenia zwizane z cieniowaniem. Mwic oglnie,
przy wczonym cieniowaniu paskim kolor caego obiektu podstawowego definiowany jest
kolorem ostatniego wierzchoka definiujcego ten obiekt. Jedynym wyjtkiem s obiekty
podstawowe O|_PO|YOON. Tutaj kolor obiektu definiuje kolor pierwszego wierzchoka.
Nastpnie, kod z listingu 5.1 nadaje grnemu wierzchokowi kolor czerwony, dolnemu
prawemu wierzchokowi kolor zielony, a dolnemu lewemu kolor niebieski. Wczone
jest cieniowanie gadkie, dlatego wntrze trjkta wypenione jest pynnym przejciem
pomidzy kolorami wierzchokw.
Wynik dziaania programu TRIANGLE pokazany zosta na rysunku 5.11. Wida na nim
paszczyzn przedstawion graficznie na rysunku 5.10.
Wielokty znacznie bardziej zoone od trjktw rwnie mog mie definiowane rne
kolory w poszczeglnych wierzchokach. Jednak w ich przypadku logika cieniowania
moe by ju bardzo skomplikowana. Na cae szczcie dziki bibliotece OpenGL nigdy
nie bdziemy musieli si o to martwi. Niezalenie od tego, jak zoony wielokt zdefiniu-
jemy, OpenGL doskonale wycieniuje jego wntrze, stosujc kolory nadane wierzchokom.
236 Cz I Klasyka OpenGL
kysunek 5.11.
Wynik dziaania
programu TRIANGLE
-QNQT[YYKGEKGT\GE\[YKUV[O
W rzeczywistoci kolory obiektw nie s niezmienne, nie s te cieniowaniem pomidzy
kilkoma wartociami RGB. Rysunek 5.12 przedstawia wynik dziaania programu JET znaj-
dujcego si na pycie CD. Jest to prosty samolot odrzutowy, poskadany rcznie z trjktw
za pomoc tych metod, ktre opisywalimy do tej pory. Tak jak i w innych programach
z tego rozdziau, moliwe jest obracanie samolotu poprzez naciskanie klawiszy strzaek.
kysunek 5.12.
Prosty samolot
odrzutowy, zbudowany
z rnokolorowych
trjktw
Kolory samolotu zostay tak dobrane, eby podkrela jego trjwymiarow struktur.
Nawet pomijajc dziwaczn struktur trjktw tworzcych samolot, mona zauway,
e nie wyglda on tak jak obiekty rzeczywiste. Zamy, e zbudowalimy model tego
samolotu i kad z powierzchni pomalowalimy odpowiednim kolorem. W zalenoci od
uytej farby model sprawiaby wraenie byszczcego lub matowego, a kolor kadej pa-
skiej powierzchni zmieniaby si wraz ze zmianami kta patrzenia i padania wiata.
Biblioteka OpenGL cakiem dobrze radzi sobie z jak najlepszym odwzorowywaniem rze-
czywistego wygldu obiektw pod wzgldem warunkw owietlenia. Kady obiekt, o ile nie
generuje wasnego wiata, owietlany jest trzema rodzajami wiata: otaczajcym (ambient),
rozproszonym (diffuse) i odbitym (specular).
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 237
YKCVQQVCE\CLEG
wiato otaczajce nie pochodzi z adnego konkretnego kierunku. Posiada ono co prawda
rdo, ale promienie wiata odbijay si ju po caej scenie tyle razy, e wiato to ca-
kowicie stracio jakikolwiek kierunek. Wszystkie powierzchnie obiektw znajdujcych si
w wietle otaczajcym s owietlone rwnomiernie, niezalenie od kierunku. We wszyst-
kich poprzednich przykadach mona zauway, e prezentowane obiekty owietlone s
wanie takim wiatem s pokryte jednakowym kolorem niezalenie od ich pooenia
i naszego kta patrzenia. Rysunek 5.13 przedstawia obiekt owietlony wiatem otaczajcym.
kysunek 5.13.
Obiekt owietlony
wycznie wiatem
otaczajcym
YKCVQTQ\RTQU\QPG
wiato rozproszone pada na obiekt z okrelonego kierunku, ale jest na nim rozpraszane
we wszystkich kierunkach. Mimo to powierzchnie obiektu owietlone bezporednio bd
janiejsze od powierzchni ustawionych w stosunku do kierunku padania wiata pod pew-
nym ktem. Dobrym przykadem takiego wiata bdzie wiato jarzeniowe albo wiato
soneczne wpadajce w poudnie przez okna. Obiekt pokazany na rysunku 5.14 owietlany
jest wiatem rozproszonym.
kysunek 5.14.
Obiekt owietlony
wycznie wiatem
rozproszonym
YKCVQQFDKVG
Jeeli wiato pada na obiekt z pewnego kierunku (podobnie jak wiato rozproszone), ale
odbijane jest w jednym konkretnym kierunku, to mamy do czynienia ze wiatem odbitym.
Mocno odbite wiato najczciej powoduje wystpienie na powierzchni owietlanej jasnej
plamy nazywanej odbyskiem (ang. specular highlight). Przykadami wiata odbitego
mog by latarka lub soce. Na rysunku 5.15 mona zobaczy obiekt owietlony wycz-
nie wiatem odbitym.
238 Cz I Klasyka OpenGL
kysunek 5.15.
Obiekt owietlony
wiatem odbitym
#VGTC\YU\[UVMQTC\GO
Nie istnieje rdo wiata, ktre skadaoby si wycznie z jednego z opisanych wyej
rodzajw wiata. Niemal kade wiato skada si natomiast z rnych kombinacji tych
rodzajw. Na przykad promie czerwonego lasera laboratoryjnego skada si niemal
w caoci z czerwonego wiata odbitego. Jednak czsteczki kurzu lub dymu mog rozpra-
sza ten promie tak, e bdzie on widoczny na caej swojej dugoci. W ten sposb
uwidacznia si skadowa wiata rozproszenia. Dodatkowo, jeeli promie bdzie jasny,
a w pokoju nie bd dziaay adne inne rda wiata, to na wszystkich obiektach bdzie
mona zobaczy delikatn czerwon powiat. Jest ona spowodowana bardzo ma ska-
dow wiata otaczajcego obecn w promieniu lasera.
Jak wida, kade rdo wiata obecne na scenie musi skada si z trzech skadowych
owietlenia: otaczajcego, rozproszenia i odbitego. Podobnie jak zwyke kolory kada ska-
dowa owietlenia rwnie definiowana jest skadowymi RGBA opisujcymi wzgldne
intensywnoci wiata czerwonego, zielonego i niebieskiego w kadym rodzaju wiata
(w opisie koloru wiata skadowa alfa jest ignorowana). Na przykad, wiato wspo-
mnianego czerwonego lasera moe by opisywane wartociami skadowych podanymi
w tabeli 5.1.
Iobe|o 5.1. Rozkad skadowych wiata w promieniu czerwonego lasera
Czerwony I|e|ony N|eb|esk| A|fo
Odbite 099 00 00 10
Rozproszone 010 00 00 10
Otoczenia 005 00 00 10
Prosz zauway, e promie czerwonego lasera nie posiada skadowej wiata zielonego
ani niebieskiego. Wane jest rwnie to, e kada skadowa wiata (odbitego, rozpro-
szonego i otoczenia) moe przyjmowa wartoci od 00 do `0. Mona to interpretowa
w ten sposb, e wiato lasera czerwonego bdzie miao w pewnych scenach bardzo wy-
sok warto skadowej wiata odbitego, niewielk warto skadowej wiata rozproszo-
nego i bardzo ma warto skadowej wiata otoczenia. Tam, gdzie bdzie pada pro-
mie lasera, z pewnoci zobaczymy czerwon plamk. Poza tym w wyniku panujcych
w pokoju warunkw (dym, kurz itp.), skadowa rozproszenia z pewnoci pozwoli nam
dojrze w powietrzu promie lasera. W kocu skadowa owietlenia otoczenia (rwnie
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 239
z powodu wystpujcych w powietrzu czsteczek dymu lub kurzu) niewielk cz wiata
skieruje na elementy wyposaenia pokoju. Bardzo czsto czy si skadowe owietlenia
rozproszonego i otoczenia ze wzgldu na ich podobn natur.
/CVGTKC[YYKGEKGT\GE\[YKUV[O
wiato jest tylko jedn czci rwnania. W wiecie rzeczywistym obiekty maj swoje
wasne kolory. Wczeniej opisywalimy kolor obiektu jako kolor odbitego przez niego
wiata. Niebieska pika odbija wikszo niebieskich fotonw, a pochania wikszo
pozostaych. Zakadalimy wtedy, e wiato padajce na pik zawiera w sobie niebieskie
fotony, ktre mogyby by odbite i odebrane przez obserwatora. Najczciej, sceny owie-
tlane s wiatem biaym, ktre jest rwnomiern mieszank wszystkich kolorw. Dla-
tego w wietle biaym obiekty ujawniaj swoje naturalne kolory. Niestety, nie zawsze
mamy tak doskonae warunki. Jeeli nasza niebiesk pik umiecimy w ciemnym po-
koju i owietlimy j wiatem tym, to dla obserwatora pika bdzie czarna, poniewa
cae te wiato zostanie pochonite przez pik, a z braku niebieskich fotonw nic
nie bdzie si od niej odbijao.
9CEKYQEKOCVGTKCY
Korzystajc z owietlenia, nie definiujemy wieloktw, nadajc im jaki kolor, ale raczej
przypisujc im materia posiadajcy pewne waciwoci odblaskowe. Nie mwimy, e
wielokt jest czerwony, ale e jest zbudowany z materiau odbijajcego gwnie czerwone
wiato. Nadal moemy powiedzie, e obiekt ma czerwon powierzchni, ale teraz mu-
simy okreli jego waciwoci odblaskowe dla wiata otoczenia, rozproszenia i odbi-
tego. Materia moe by byszczcy i doskonale odbija wiato odbite, ale jednoczenie
pochania wiksz cz wiata rozproszenia lub otoczenia. Z drugiej strony materiay
matowe mog pochania wszelkie wiato odbite i w adnych okolicznociach nie mie
byszczcego wygldu. Inn waciwoci, jak musimy okreli, jest informacja o waci-
wociach emisji obiektw generujcych wasne wiato, takich jak tylne wiata samo-
chodw albo zegarki wiecce w ciemnociach.
&QFCYCPKGYKCVCFQOCVGTKCY
Takie ustawienie parametrw owietlenia i materiau, eby uzyska podane efekty,
wymaga pewnej praktyki. Nie ma adnych doskonaych porad, ani oglnych zasad, do
jakich naleaoby si stosowa. W tym miejscu analiza musi ustpi miejsca sztuce,
a nauka magii. Biblioteka OpenGL w czasie rysowania kadego obiektu decyduje
o kolorze, w jakim bdzie rysowany kady piksel tego obiektu. Sam obiekt ma kolor
odblasku, a i rdo wiata dysponuje wasnymi kolorami. W jaki sposb biblioteka okre-
la kolor nadawany pikselom? Stosowane tu zasady nie s trudne, cho wymaga to uycia
choby najprostszego mnoenia (a nauczyciele mwili, e kiedy si przyda!).
240 Cz I Klasyka OpenGL
Kademu wierzchokowi obiektu podstawowego przepisywana jest warto koloru RGB
wynikajca z iloczynu poczonych efektw owietlenia obiektu wiatem otoczenia,
rozproszenia i odbitym przez waciwoci odblaskowe materiau dla wiata otoczenia,
rozproszenia i odbitego. Efekt penego owietlenia obiektu uzyskiwany jest pniej po-
przez zastosowanie pynnego cieniowania wntrza wieloktw.
9[NKE\CPKGGHGMVYQYKGVNGPKCQVQE\GPKC
Wyliczajc efekty owietlenia otoczenia, musimy odoy na bok pojcie koloru i zacz
myle wycznie o intensywnociach skadowych czerwonej, zielonej i niebieskiej. Dla
rda wiata otoczenia o poowicznej intensywnoci wszystkich skadowych koloru
wartoci RGB tego rda wynosz (0.5, 0.5, 0.5). Jeeli to rdo owietla obiekt, ktrego
waciwoci odblaskowe dla wiata otoczenia wynosz (0.5, 1.0, 0.5), to wynikowy
kolor skadowych tego wiata wynosi:
05 ' 05 05 ' 10 05 ' 05| 05 05 05|
Jest to wynik mnoenia kadej skadowej rda wiata otoczenia przez odpowiadajce
im waciwoci odblaskowe materiau (rysunek 5.16).
kysunek 5.1.
Wyliczanie koloru
owietlenia otoczenia
dla obiektu
Wynika z tego, e skadowe koloru okrelaj tylko procent iloci wiata, jakie bdzie
odbijane od obiektu. W naszym przykadzie skadowa czerwona wiata miaa warto 0b,
a waciwoci materiau obiektu powodoway, e bya ona odbijana tylko w poowie
swojej poowicznej intensywnoci. Prosta matematyka mwi nam, e p razy p to
wier, czyli 0b.
'HGMV[YKCVCTQ\RTQU\GPKCKQFDKVGIQ
Wyliczenia dla wiata otoczenia s jednak wyjtkowo proste. wiato rozproszone rwnie
opisywane jest wartociami intensywnoci RGB, ktre w taki sam sposb cz si z wa-
ciwociami materiau obiektu. Jednak w tym przypadku wiato ma pewien kierunek,
dlatego jego intensywno na powierzchni obiektu bdzie rna w zalenoci od kta
padania wiata, odlegoci obiektu od rda, dowolnego czynnika tumicego (na przy-
kad mgy znajdujcej si midzy obiektem a rdem wiata) itp. Dokadnie te same
zalenoci dotycz rwnie rde i intensywnoci wiata odbitego. Efekt netto wartoci
RGB wyliczany jest w ten sam sposb co dla wiata otoczenia, czyli intensywno rda
wiata (zmodyfikowana przez kt padania) mnoona jest przez wspczynnik odblasku
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 241
materiau. Na kocu wszystkie trzy skadowe koloru czone s ze sob, tworzc kocowy
kolor obiektu. Jeeli ktrakolwiek ze skadowych bdzie miaa w wyniku tych wylicze
warto wiksz od `0, to zostanie ograniczona do tej wartoci. Nie mona przecie
mie intensywnoci wikszej od maksymalnej.
Oglnie, skadowe wiata otoczenia i rozproszonego maj prawie takie samo dziaanie
w rdach wiata i materiaach, dlatego najbardziej wpywaj na efektywny kolor obiek-
tw. wiato odbite i odpowiadajce mu waciwoci materiau najczciej s koloru
szarego lub biaego. Skadowa wiata odbitego najbardziej zaley od kta padania, wic
miejsca padania wiata odbitego najczciej s biae.
&QFCYCPKGYKCVGFQUEGP[
Moe si wydawa, e powysze wywody s ogromn iloci nagle podanej teorii. Zwol-
nimy wic i spokojnie przeanalizujemy przykady kodu koniecznego, jeeli chcemy stoso-
wa owietlenie sceny. W ten sposb utrwalimy sobie wszystkie podane wyej informacje,
a na dodatek zademonstrujemy kilka nowych funkcji i wymaga mechanizmu wiate
w bibliotece OpenGL. Nastpnych kilka przykadw opiera si bdzie na programie JET.
Pierwotna wersja nie stosuje adnych mechanizmw zwizanych z owietleniem i rysuje
po prostu trjkty z wczonym mechanizmem usuwania niewidocznych powierzchni
(testowanie gbi). Gdy zakoczymy wprowadza do niego poprawki i zaczniemy obraca
samolot, metaliczne powierzchnie naszego odrzutowca bd wspaniale lni w socu.
9E\GPKGQYKGVNGPKC
Aby nakaza bibliotece OpenGL przeprowadzanie oblicze zwizanych z owietleniem,
wystarczy wywoa funkcj ln.|e z parametrem O|_|1OHT1NO:
_!Fnao!e||T'TTN|,
Ju to proste wywoanie spowoduje, e biblioteka OpenGL w czasie okrelania kolorw
wszystkich wierzchokw sceny bdzie stosowaa waciwoci materiaw i parametry
owietlenia. Niestety, bez sprecyzowania tych waciwoci i parametrw nasz obiekt pozo-
staby ciemny i nieowietlony tak jak nasz przykadowy samolot z rysunku 5.17. Jeeli spoj-
rzymy na kod dowolnego z przykadowych programw wywodzcych si z programu JET,
to zobaczymy, e funkcj Se'u,RC wywoujemy zaraz po utworzeniu kontekstu renderowa-
nia. W tym wanie miejscu wykonywane s wszystkie inicjalizacje parametrw owietlenia.
-QPHKIWTQYCPKGOQFGNWQYKGVNGPKC
Pierwsz rzecz, jak musimy wykona zaraz po wczeniu obliczania owietlenia, to skon-
figurowanie modelu owietlenia. Trzy parametry wpywajce na model owietlenia usta-
wiane s za pomoc funkcji ||'Mcce.
242 Cz I Klasyka OpenGL
kysunek 5.17.
Nieowietlony samolot
nie odbija adnego
wiata
Pierwszym parametrem owietlenia uywanym w naszym nastpnym przykadzie (pro-
gram AMBIENT) jest O|_|1OHT_MODl|_AMB1lNT. Pozwala on okreli globalne wiato
otoczenia owietlajce wszystkie obiekty w ten sam sposb ze wszystkich stron. Podany
poniej kod definiuje jasne, biae wiato:
// Jasne biae wiato - pena intensywno wszystkich wartoci RGB
|f!oa! amo:en!|:_h! 10f 10f 10f 10f ,
// Wczenie owietlenia
_!Fnao!e||T'TTN|,
// Konfigurujemy model owietlenia tak, eby stosowa
// wiato otoczenia zdefiniowane tablic ambientLight[]
_!|:_h!Moce!fv||T'TMJOF|/MBTFNTamo:en!|:_h!|,
Podana tutaj wersja funkcji ||'Mcce ||'Mcce'v w pierwszym parametrze
pobiera informacj o typie owietlenia, jakie poddajemy modyfikacjom, a w drugim para-
metrze pobiera tablic wartoci RGBA opisujc wiato. Domylne wartoci RGBA dla
globalnego wiata otoczenia wynosz 0, 0, 0, `0), co oznacza bardzo przy-
ciemnione wiato. Pozostae parametry modelu owietlenia pozawalaj okreli, czy
owietlane maj by przednie, tylnie czy moe obie strony wieloktw oraz metody obli-
czania owietlenia wiatem odbitym. Wicej informacji o tych parametrach znajduje si
w podrozdziale Opisy funkcji.
7UVCNCPKGYCEKYQEKOCVGTKCY
Mamy ju rdo wiata otoczenia. Musimy teraz ustali waciwoci materiaw, tak eby
nasze wielokty mogy odbija to wiato, a my zobaczy samolot. Istniej dwie metody
ustalania waciwoci materiaw. Pierwsza z nich polega na uyciu funkcji M.'er.
przed zdefiniowaniem kadego wielokta lub zbioru wieloktw. Przyjrzymy si poni-
szemu fragmentowi kodu:
|f!oa! _ra, 075f 075f 075f 10f,

_!Ma!er:a!fv|FRJNT |/MBTFNT/NOOTFFUSF _ra,|,


_!Be_:n|TRT/N|FS|,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 243
_!Ver!ex:f-150f 00f :00f|,
_!Ver!ex:f00f 150f :00f|,
_!Ver!ex:f00f 00f -5b0f|,
_!Fnc|,
Pierwszy parametr funkcji M.'er.'v okrela, czy definiowane bd waciwoci mate-
riau przedniej, tylnej czy moe obu stron wieloktw (O|_|RONT, O|_BAC|, O|_|RONT_AND_BAC|).
W drugim parametrze podawana jest waciwo, ktra bdzie zmieniana; w tym przy-
padku waciwoci odblaskowe dla wiata otoczenia i rozproszenia bd takie same.
Ostatnim parametrem jest tablica zawierajc wartoci RGBA opisujce odblaskowe wa-
ciwoci materiau. Wszystkie obiekty podstawowe rysowane po wywoaniu tej funkcji
bd miay ustalone przez ni waciwoci odblaskowe a do momentu ponownego
wywoania funkcji M.'er..
W wikszoci przypadkw skadowe wiata otoczenia i rozproszenia s takie same, a jeeli
nie chcemy stosowa specjalnych efektw owietlenia (iskrzenia, rozbyskw), nie mu-
simy definiowa adnych waciwoci dla wiata odbitego. Mimo to przygotowywanie
tablicy kolorw i wywoywanie funkcji M.'er. przed rysowaniem kadego wielo-
kta lub grupy wieloktw moe by zajciem bardzo nucym.
Jestemy wiec gotowi na zastosowanie drugiej, lepszej metody ustalania waciwoci
materiaw nazywanej ledzeniem kolorw (ang. color tracking). Dziki tej metodzie
moemy ustali waciwoci materiau ju w momencie wywoania funkcji Cccr.
Aby wczy ten mechanizm, trzeba najpierw wywoa funkcj ln.|e z parametrem
O|_CO|OR_MATlR1A|:
_!Fnao!e|CJ|JRM/TFRT/||,
Nastpnie funkcj CccrM.'er. okrelamy parametry podawane zaraz za wartociami
funkcji Cccr. Na przykad, aby ustawi waciwoci materiau dla wiata otoczenia
i rozproszenia dla przednich stron wieloktw tak, aby ledziy one kolory ustawiane
funkcj Cccr, naley wywoa:
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
Teraz podany wyej fragment kodu ustawiajcy waciwoci materiaw moglibymy
zmodyfikowa nastpujco. Moe to wyglda na tworzenie wikszej iloci kodu, ale tak
naprawd oszczdza si w ten sposb wiele linii kodu, co przekada si na szybsze ryso-
wanie wielu rnokolorowych wieloktw:
// Wczenie ledzenia kolorw
_!Fnao!e|CJ|JRM/TFRT/||,
// Kolory waciwoci materiaw dla wiata otoczenia i rozproszenia
// bd ledziy wartoci podawane w funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,

_!Co!or:f075f 075f 075f|,


_!Be_:n|TRT/N|FS|,
_!Ver!ex:f-150f 00f :00f|,
_!Ver!ex:f00f 150f :00f|,
_!Ver!ex:f00f 00f -5b0f|,
_!Fnc|,
244 Cz I Klasyka OpenGL
Na listingu 5.2 podajemy kod, jaki dodany zosta do funkcji Se'u,RC z przykadowego
programu JET, w ktrym ustalamy jasne rdo wiata otoczenia, a take waciwoci
materiaw pozwalajce obiektom odbija wiato i w efekcie pojawi si na ekranie. Po-
zmienialimy te kolory samolotu. Teraz rne kolory nadalimy poszczeglnym sekcjom
samolotu, a nie tworzcym go wieloktom. Kocowy wynik (pokazany na rysunku 5.18)
nie rni si jednak znaczco od tego, co uzyskalimy jeszcze przed wczeniem owie-
tlenia. Jeeli jednak zredukujemy wiato otoczenia o poow, to uzyskamy obraz przed-
stawiony na rysunku 5.19. Aby o poow obniy intensywno owietlenia, wartoci
RGBA dla wiata otoczenia ustalamy nastpujco:
|f!oa! amo:en!|:_h! 05f 05f 05f 10f ,
I|st|ng 5.2. Konfiguracja warunkw owietlenia otoczenia
// Ta funkcja wykonuje wszystkie konieczne inicjalizacje kontekstu renderowania
// Tutaj ustala i inicjalizuje owietlenie sceny
XQKF Se!upRC|

// Wartoci wiata
// Jasne biae wiato
|f!oa! amo:en!|:_h! 10f 10f 10f 10f ,
_!Fnao!e|OFPT'TFST|, // Usuwanie powierzchni ukrytych
_!Fnao!e|CU||F/CF|, // Nie bdziemy prowadzi oblicze wntrza samolotu
_!Fron!Face|CC.|, // Wielokty z nawiniciem przeciwnym do ruchu wskazwek
zegara
// Owietlenie
_!Fnao!e||T'TTN|, // Wczenie owietlenia
// Ustalamy, e model owietlenia bdzie stosowa wiato otoczenia
// zdefiniowane w tablicy ambientLight []
_!|:_h!Moce!fv||T'TMJOF|/MBTFNTamo:en!|:_h!|,
_!Fnao!e|CJ|JRM/TFRT/||, // Wczenie ledzenia kolorw materiaw
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT|/MBTFNT/NOOTFFUSF|,
// liczny jasny bkit
_!C!earCo!or00f 00f 05f10f|,

Teraz wiemy ju, jak mona obniy jasno owietlenia otoczenia tak, aby uzyska ciem-
niejszy obraz. Ta waciwo bardzo przydaje si w symulacjach, w ktrych zmierzch za-
pada stopniowo albo w momentach, gdy zablokowane zostaje gwne rdo wiata dla
sceny, czyli gdy jeden obiekt znajduje si w cieniu drugiego.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 245
kysunek 5.18.
Wynik dziaania
przykadowego
programu AMBIENT
kysunek 5.1.
Wynik dziaania
przykadowego
programu AMBIENT
po przyciemnieniu
owietlenia
7[YCPKGTFGYKCVC
Manipulacje wiatem otoczenia z pewnoci s uyteczne, ale w wikszoci aplikacji sta-
wiajcych sobie za zadanie modelowanie wiata rzeczywistego konieczne jest zdefiniowanie
wicej ni tylko jednego rda wiata. Takie rda wiata, poza rnymi intensyw-
nociami i kolorami, maj rwnie swoje pozycje i kierunki w przestrzeni. Rozmiesz-
czenie takich wiate moe mie znaczcy wpyw na wygld naszej sceny.
Biblioteka OpenGL pozwala na obsug przynajmniej omiu niezalenych rde wiata
umieszczonych w dowolnych punktach na scenie albo poza przestrzeni widoczn. Mo-
emy umieci rdo wiata w nieskoczonej odlegoci od sceny, tak eby jego pro-
mienie padajce na scen byy zawsze rwnolege albo umieci je bardzo blisko, tak eby
promieniowao we wszystkich kierunkach. Moliwe jest te zdefiniowanie wiata punk-
towego o dowolnych charakterystykach, ktre wiecio by wewntrz zadanego stoka.
246 Cz I Klasyka OpenGL
)F\KGLGUVITC!
Definiujc rdo wiata, musimy poinformowa bibliotek OpenGL gdzie si ono znaj-
duje i w ktrym kierunku wieci. Bardzo czsto rda wiata wiec we wszystkich
kierunkach, ale moliwe jest te tworzenie wiate kierunkowych. W kadym przypadku
na powierzchni rysowanego obiektu promienie wiata (pochodzce z dowolnego rda
innego ni czyste wiato otoczenia) padaj pod bardzo rnymi ktami. Oczywicie
w przypadku wiate kierunkowych nie musz by owietlane wszystkie wielokty, z jakich
skada si obiekt. Aby okreli stopie zacienienia poszczeglnych powierzchni obiektu,
biblioteka OpenGL musi by w stanie wyliczy kt padania promieni wiata.
Na rysunku 5.20 wielokt (kwadrat) owietlany jest promieniami wiata generowanego
przez pewne rdo. Promienie te tworz z powierzchni pewien kt (A), a nastpnie
odbijane s pod ktem (B) w kierunku widza (inaczej bymy go nie zobaczyli). Do wyli-
czania wynikowego koloru kadego elementu stosowane s odpowiednie kty padania
promieni wiata w poczeniu z parametrami owietlenia i omawianymi wczeniej waci-
wociami materiaw. Tak si akurat skada, e konstrukcja biblioteki OpenGL wylicza
te wartoci dla kadego wierzchoka opisujcego wielokt. Dziki temu, a take dziki
tworzeniu pynnych przej pomidzy kolorami poszczeglnych wierzchokw, tworzona
jest doskonaa iluzja owietlenia. Czary!
kysunek 5.20.
wiato odbija si
od powierzchni pod
rnymi ktami
Z punktu widzenia programisty z takimi wyliczeniami owietlenia wi si pewne pro-
blemy. Kady wielokt tworzony jest jako zbir wierzchokw bdcych zaledwie punk-
tami. Na kady z tych wierzchokw pod pewnym ktem pada promie wiata. Ale jak
mona wyznaczy kt pomidzy punktem a lini (promieniem wiata)? Oczywicie
z geometrycznego punktu widzenia nie mona wyznaczy kta pomidzy punktem a lini
umieszczon w trzech wymiarach, poniewa w takich warunkach istnieje nieskoczona
liczba moliwoci. Z tego powodu konieczne jest zwizanie z kadym wierzchokiem
dodatkowej informacji wskazujcej kierunek w gr wierzchoka, czyli powierzchni
wielokta.
0QTOCNPGRQYKGT\EJPK
Linia prowadzona od wierzchoka w kierunku grnym, pod ktem prostym w stosunku do
pewnej wyimaginowanej powierzchni (lub naszego wielokta) nazywana jest wektorem
normalnym. Termin wektor normalny moe kojarzy si z rozmowami, jakie prowadz
midzy sob bohaterowie serialu StarTrek, ale oznacza on po prostu lini prostopad
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 247
do rzeczywistej lub wyimaginowanej powierzchni. Wektor jest lini wskazujc w pew-
nym kierunku, a sowo normalny, to inne okrelenie na prostopady, czyli ustawiony
pod ktem 90. Bardzo lubi stosowa je jajogowi jakby prostopady nie byo do
paskudnym sowem! Podsumowujc wektor normalny to linia wskazujca kierunek
ustawiony pod ktem 90 w stosunku do powierzchni wielokta. Na rysunku 5.21 przed-
stawiono przykady wektorw normalnych w dwch i trzech wymiarach.
kysunek 5.21.
Wektor normalny
w dwch i trzech
wymiarach
Powstaje tutaj pytanie, dlaczego musimy definiowa wektor normalny dla kadego wierz-
choka w wielokcie. Dlaczego nie moemy zdefiniowa pojedynczego wektora dla wielo-
kta i stosowa go we wszystkich jego wierzchokach? Oczywicie, e moemy i w kilku
pierwszych przykadach bdziemy tak robi. Czasami jednak nie bdziemy chcieli, eby
wektory normalne byy dokadnie prostopade do powierzchni wielokta. Z pewnoci
kady zauway, e nie wszystkie powierzchnie s paskie! Mona tworzy przyblienia
takich powierzchni, stosujc paskie wielokty, ale powstaj w ten sposb kanciaste
powierzchnie o wielu fasetach. Pniej omawia bdziemy techniki pozwalajce na
tworzenie iluzji agodnych krzywizn za pomoc wykrconych wektorw normalnych
(kolejne czary!). Ale zacznijmy od pocztku
&GHKPKQYCPKGPQTOCNPGL
Aby zobaczy, jak definiuje si normaln dla wierzchoka, spjrzmy na rysunek 5.22, na
ktrym znajduje si paszczyzna umieszczona w przestrzeni trjwymiarowej ponad
paszczyzn xz. Staralimy si jak najbardziej uproci ten rysunek, aby zademonstrowa
pojcie normalnej. Prosz zauway lini biegnc przez wierzchoek `, `, 0) pro-
stopadle do paszczyzny. Jeeli wybierzemy na tej linii dowolny inny punkt, na przy-
kad `, `0, 0), to linia od pierwszego punktu do drugiego bdzie naszym wektorem
normalnym. Drugi z podanych punktw okrela, e kierunek normalnej wskazuje w gr
osi y. W ten sposb okrelana jest te przednia i tylna strona wielokta, poniewa wektor
normalny wskazuje te przedni stron powierzchni.
Jak wida, drugi punkt podawany jest jako liczba jednostek w osi x, y i z, opisujcych
pewien punkt na wektorze normalnym wychodzcym z wierzchoka. Zamiast podawa
dwa punkty dla kadego wektora normalnego, moemy odj wsprzdne wierzchoka
od wsprzdnych tego drugiego punktu, a otrzymamy trzy wartoci wsprzdnych
okrelajcych odlego drugiego punktu od wierzchoka w osi x, y i z. W naszym przy-
kadzie byoby to:
1 10 0| - 1 1 0| 1 - 1 10 - 1 0| 0 9 0|
248 Cz I Klasyka OpenGL
kysunek 5.22.
Wektor normalny
oddalajcy si
prostopadle
od paszczyzny
Na powyszy przykad mona spojrze jeszcze inaczej. Jeeli wierzchoek zostanie przesu-
nity do pocztku ukadu wsprzdnych, to punkt wyznaczony przez powysze odejmo-
wanie nadal bdzie okrela kierunek wektora normalnego w stosunku do powierzchni.
Na rysunku 5.23 przedstawiony zosta wektor przesunity w ten wanie sposb.
kysunek 5.23.
Przesunity wektor
normalny
Wektor jest wielkoci kierunkow informujc bibliotek OpenGL o kierunku, w jakim
ustawione s wierzchoki (lub wielokty). Poniszy fragment kodu pochodzi z naszego
przykadowego programu JET i przedstawia okrelanie wektora normalnego dla jednego
z trjktw.
_!Be_:n|TRT/N|FS|,
_!Norma!:f00f -10f 00f|,
_!Ver!ex:f00f 00f b00f|,
_!Ver!ex:f-150f 00f :00f|,
_!Ver!ex:f150f 00f :00f|,
_!Fnc|,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 249
Nawinicie wieloktw
Prosz przyjrze si kolejnoci definiowania wierzchokw trjkta pochodzcego z samolotu.
Jeeli bdziemy si mu przyglda od strony wskazywanej przez wektor normalny, to wierzchoki
bd ukada si w kierunku przeciwnym do ruchu wskazwek zegara. Nazywane jest to nawi-
niciem wielokta. Domylnie przodem wielokta okrela si t stron, po ktrej wierzchoki
ukadaj si wanie w kierunku przeciwnym do ruchu wskazwek zegara.
Funkcja Ncr.o' pobiera w parametrach trzy wsprzdne okrelajce wektor nor-
malny wskazujcy kierunek prostopady do powierzchni trjkta. W tym przykadzie
normalne wszystkich trzech wierzchokw maj dokadnie taki sam kierunek wskazujcy
w d ujemnych wartoci osi y. Jest to bardzo prosty przykad, poniewa cay trjkt ley
w paszczynie xz; jest on po prostu wycinkiem brzucha samolotu. Jak bdzie mona
zobaczy pniej, czsto bdziemy musieli okrela inne wektory normalne dla kadego
wierzchoka wielokta.
Perspektywa definiowania wektora normalnego dla kadego wierzchoka wielokta moe
by nieco przeraajca, szczeglnie e wiele powierzchni nie ley dokadnie na jednej
z gwnych paszczyzn. Bez obaw! Szybko podamy przydatn funkcj, z ktrej moemy
korzysta cay czas do wyliczania wektorw normalnych.
0QTOCNPGLGFPQUVMQYG
W czasie gdy biblioteka OpenGL bdzie odprawia swoje czary, wszystkie wektory nor-
malne musz zosta zamienione w normalne jednostkowe. Normalna jednostkowa jest
zwykym wektorem normalnym o dugoci `. Normalna przedstawiona na rysunku 5.23 ma
dugo 9 jednostek. Dugo kadej normalnej mona uzyska, podnoszc do kwadratu
warto kadej wsprzdnej, sumujc wyniki, a nastpnie wycigajc z tej sumy pierwia-
stek kwadratowy. Jeeli teraz podzielimy kad skadow wektora normalnego przez t
dugo, to otrzymamy identycznie skierowany wektor, ale o dugoci rwnej `. W tym
przypadku nasz nowy wektor normalny bdzie okrelany wsprzdnymi 0, `, 0). Proces
ten nazywany jest normalizacj. Tak wic dla potrzeb oblicze owietlenia, wszystkie
wektory normalne musza zosta znormalizowane. wietny argon!
Moemy nakaza bibliotece OpenGL wykonywanie normalizacji wszystkich wektorw
normalnych. Trzeba tylko wywoa funkcj ln.|e z parametrem O|_NORMA|1/l:
_!Fnao!e|NJRM/|TZF|,
Z t metod wi si jednak pewne spadki wydajnoci. Znacznie lepszym wyjciem
jest od razu wyliczy znormalizowany wektor normalny, ni zleca bibliotece OpenGL
wykonywanie tego zadania.
Trzeba zaznaczy, e wywoanie funkcji Sc.e rwnie bdzie wpywa na dugo
naszego wektora normalnego. Jeeli bdziemy jednoczenie stosowa funkcj Sc.e i me-
chanizmy owietlenia, to moemy uzyska rne niepodane efekty. Po zdefiniowaniu dla
jakiego obiektu wszystkich normalnych jednostkowych i w uyciu funkcji skalujcej ze
staym wspczynnikiem skalowania (skalowanie jest takie samo we wszystkich kierunkach),
to moemy zamiast parametru O|_NORMA|1/l zastosowa nowy (wprowadzony w wersji 1.2
biblioteki) parametr O|_RlSCA|l_NORMA|S. Parametr ten wczany jest prostym wywoaniem:
250 Cz I Klasyka OpenGL
_!Fnao!e|RFSC/|FNJRM/|S|,
W ten sposb informujemy bibliotek OpenGL, e nasze normalne nie maj jednostkowej
dugoci, ale mona je przeskalowa o dokadnie tak sam warto, eby osigny du-
go jednostkow. Biblioteka OpenGL sprawdza to, kontrolujc macierz model-widok.
W efekcie musimy wykona mniej operacji matematycznych ni w innych przypadkach.
Ze wzgldu na to, e najlepszym rozwizaniem jest podanie bibliotece OpenGL ju znor-
malizowanych wektorw, w bibliotece glTools dostpna jest funkcja pobierajca dowolny
wektor i poddajca go normalizacji:
XQKF _!!Norma!:zeVec!or|TVec!or vNorma!|,
<PCLFQYCPKGPQTOCNPGL
Na rysunku 5.24 przedstawiony zosta kolejny wielokt, ktry nie ley w caoci na adnej
z paszczyzn osiowych. Teraz znalezienie wektora normalnego do powierzchni wielokta
nie jest ju tak oczywiste, potrzebujemy wic prostego sposobu na wyliczenie wektora
normalnego dla dowolnego wielokta w przestrzeni trjwymiarowej.
kysunek 5.24.
Nietrywialny problem
szukania wektora
normalnego
Biorc trzy punkty lece na paszczynie dowolnego wielokta, mona w prosty sposb
wyliczy normaln do tej paszczyzny. Rysunek 5.25 przedstawia trzy punkty P1, P2
i P3 ktrych mona uy do zdefiniowania dwch wektorw: wektora V1 od punktu P1
do punktu P2 i wektora V2 od punktu P1 do punktu P3. Dwa wektory w przestrzeni defi-
niuj paszczyzn (a na paszczynie definiowanej przez te dwa wektory ley nasz wielo-
kt). Jeeli teraz wykonamy iloczyn wektorowy tych dwch wektorw (w matematyce
zapisuje si to jako V` V), to wynikowy wektor bdzie prostopady do naszej pasz-
czyzny. Rysunek 5.26 przedstawia wektor V3 bdcy wynikiem iloczynu wektorowego
wektorw V1 i V2.
I znowu biblioteka glTools zawiera w sobie funkcj wyliczajc wektor normalny na pod-
stawie trzech punktw wielokta:
XQKF _!!e!Norma!Vec!or|TVec!or X2 |TVec!or X2 |TVec!or X2
|TVec!or X0QTOCN|,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 251
kysunek 5.25.
Dwa wektory definiowane
przez trzy punkty
lece na paszczynie
kysunek 5.2.
Wektor normalny bdcy
iloczynem wektorowym
dwch wektorw
Aby skorzysta z tej funkcji, trzeba przekaza jej trzy wektory (kady bdcy tablic trzech
wartoci typu HNQCV) opisujce punkty naszego trjkta (musz by podawane z nawi-
niciem przeciwnym do ruchu wskazwek zegara) oraz tablic dodatkowego wektora,
do ktrej zostan wpisane wartoci wektora normalnego.
-QPHKIWTQYCPKGTFC
Znamy ju teraz zasady, jakich trzeba przestrzega w czasie tworzenia wieloktw, tak aby
mogy na nie oddziaywa rda wiata. Nadszed czas wczenia wiate! Na listingu 5.3
mona zobaczy kod funkcji Se'u,RC pochodzcej z przykadowego programu LITJET.
W czasie konfigurowania sceny tworzone jest w nim rdo wiata i umieszczane po
lewej grnej stronie, nieco za obserwatorem. Skadowym wiata otoczenia i rozproszo-
nego w rdle O|_|1OHT0 nadawane s intensywnoci zdefiniowane w tablicach .|en'
||' i c''use||'. W efekcie powstaje rdo delikatnego wiata biaego:
|f!oa! amo:en!|:_h! 0:f 0:f 0:f 10f ,
|f!oa! c:ffuse|:_h! 07f 07f 07f 10f ,

// Konfiguracja i wczenie wiata numer 0


_!|:_h!fv||T'T0|/MBTFNTamo:en!|:_h!|,
_!|:_h!fv||T'T0|OTFFUSFc:ffuse|:_h!|,
I|st|ng 5.3. Konfiguracja owietlenia i kontekstu renderowania w programie LITJET
// Ta funkcja wykonuje wszystkie konieczne inicjalizacje kontekstu renderowania,
// a take konfiguruje i inicjalizuje owietlenie sceny
XQKF Se!upRC|

// Wsprzdne i wartoci owietlenia
|f!oa! amo:en!|:_h! 0:f 0:f 0:f 10f ,
|f!oa! c:ffuse|:_h! 07f 07f 07f 10f ,
252 Cz I Klasyka OpenGL
_!Fnao!e|OFPT'TFST|, // Usuwanie ukrytych powierzchni
_!Fron!Face|CC.|, // Wielokty z nawiniciem przeciwnym do ruchu
wskazwek zegara
_!Fnao!e|CU||F/CF|, // Nie bdziemy prowadzi oblicze wntrza samolotu
// Wczenie owietlenia
_!Fnao!e||T'TTN|,
// Konfiguracja i wczenie wiata numer 0
_!|:_h!fv||T'T0|/MBTFNTamo:en!|:_h!|,
_!|:_h!fv||T'T0|OTFFUSFc:ffuse|:_h!|,
_!Fnao!e||T'T0|,
// Wczenie ledzenia kolorw
_!Fnao!e|CJ|JRM/TFRT/||,
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
// Jasnoniebieskie to
_!C!earCo!or00f 00f 10f 10f |,

Na koniec wiato O|_|1OHT0 zostaje wczone:
_!Fnao!e||T'T0|,
Pozycja wiata ustalana jest wewntrz kodu funkcji C|.neS.e:
|f!oa! !:_h!Pos -50f 500f 1000f 10f ,

_!|:_h!fv||T'T0|PJSTTTJN!:_h!Pos|,
W powyszych wierszach w tablicy |'Pcs zapisywana jest pozycja rda wiata.
Ostatnia warto w tej tablicy to `0, co oznacza, e rdo wiata zlokalizowane jest
w podanych wsprzdnych. Gdybymy podali tam warto 00, oznaczaoby to, e rdo
wiata znajduje si w nieskoczonej odlegoci od sceny, a w tablicy podany jest wektor
kierunku, z ktrego bd paday promienie. Pniej powiemy nieco wicej na ten temat.
wiata s podobne do obiektw geometrycznych pod tym wzgldem, e moemy je prze-
mieszcza za pomoc macierzy model-widok. Umiejscawiajc wiato w momencie wyko-
nywania przeksztacenia punktu widzenia, zyskujemy pewno, e bdzie ono ustawione
prawidowo, niezalenie od pniejszych przeksztace geometrii.
7UVCNCPKGYCEKYQEKOCVGTKCY
Prosz zauway, e na listingu 5.3 wczany jest mechanizm ledzenia kolorw. Jest on
te konfigurowany tak, e ledzeniu podlegaj waciwoci odblasku wiata otoczenia
i rozproszenia dla przednich powierzchni wieloktw. Dokadnie tak samo postpowalimy
w przykadowym programie AMBIENT:
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 253
// Wczenie ledzenia kolorw
_!Fnao!e|CJ|JRM/TFRT/||,
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
&GHKPKQYCPKGYKGNQMVY
W zwizku z obsug nowego modelu owietlenia kod renderujcy znany z dwch pierw-
szych przykadowych programw JET musia zosta znaczco przebudowany. Na listingu
5.4 przedstawiono wycinek kodu pochodzcy z funkcji RencerScene z programu LITJET.
I|st|ng 5.4. Przykadowy kod ustalajcy kolor oraz wyliczajcy wektory normalne wieloktw
|TVec!or vNorma!, // Przechowuje wyliczone wektory normalne

// Ustalenie koloru materiau


_!Co!or:uo18 18 18|,
_!Be_:n|TRT/N|FS|,
_!Norma!:f00f -10f 00f|,
_!Norma!:f00f -10f 00f|,
_!Ver!ex:f00f 00f b00f|,
_!Ver!ex:f-150f 00f :00f|,
_!Ver!ex:f150f00f:00f|,
// Wierzchoki tego panelu

|TVec!or vPo:n!s: 150f 00f :00f
00f 150f :00f
00f 00f b00f,
// Wyliczenie wektora normalnego dla tego wielokta
_!!e!Norma!Vec!orvPo:n!s0 vPo:n!s1 vPo:n!s vNorma!|,
_!Norma!:fvvNorma!|,
_!Ver!ex:fvvPo:n!s0|,
_!Ver!ex:fvvPo:n!s1|,
_!Ver!ex:fvvPo:n!s|,


|TVec!or vPo:n!s: 00f 00f b00f
00f 150f :00f
-150f 00f :00f ,
_!!e!Norma!Vec!orvPo:n!s0 vPo:n!s1 vPo:n!s vNorma!|,
_!Norma!:fvvNorma!|,
_!Ver!ex:fvvPo:n!s0|,
_!Ver!ex:fvvPo:n!s1|,
_!Ver!ex:fvvPo:n!s|,

254 Cz I Klasyka OpenGL
Warto wektora normalnego wyliczamy za pomoc funkcji 'Oe'Ncr.Vec'cr po-
chodzcej z biblioteki glTools. Poza tym waciwoci materiaw bd ustalane zgodnie
z kolorami podawanymi funkcji Cccr. Mona te zauway, e trjki wierzchokw
definiujcych trjkty nie s zamykane midzy funkcjami Ben i lnc. Wystarczyo
raz okreli, e bdziemy definiowa trjkty, a do momentu wywoania funkcji lnc
kada kolejna trjka wierzchokw bdzie wykorzystywana jako definicja nowego trj-
kta. Jeeli bdziemy definiowa due iloci wieloktw, to ta technika moe bardzo
podnie wydajno naszego programu poprzez wyeliminowanie niepotrzebnych wywo-
a funkcji i konfigurowania kolejnych wieloktw.
Na rysunku 5.27 przedstawiono wynik dziaania programu LITJET. Samolot nie jest ju
rnokolorowy, ale pokryty jest jednolit, jasnoszar barw. Kolor zosta zmieniony w ten
sposb, aby uwidoczni wpyw owietlenia na powierzchnie samolotu. Mimo e wszystkie
powierzchnie samolotu maj ten sam kolor, to jednak moemy wyrni wszystkie
jego elementy. Obracajc samolot klawiszami strzaek, moemy zobaczy zmiany odcieni
poszczeglnych powierzchni i sprawdzi wpyw, jaki owietlenie ma na nie pod rny-
mi ktami.
kysunek 5.27.
Wynik dziaania
programu LITJET
Najbardziej oczywist metod poprawienia wydajnoci tego kodu jest wczeniejsze
wyliczenie wszystkich wektorw normalnych i pniejsze wykorzystanie ich w funkcji
RencerScene. Zanim ktokolwiek zacznie dry ten temat, powinien najpierw przeczyta
w rozdziale 11., Wszystko o potokach szybkie przekazywanie geometrii informacje
o listach wywietlania i tablicach wierzchokw. Umoliwiaj one zapisywanie wyliczonych
wartoci nie tylko wektorw normalnych, ale rwnie danych wieloktw. Prosz pamita,
e te przykady byy wycznie demonstracj poj i z pewnoci nie stanowi
najefektywniejszego rozwizania.
'HGMV[YKGVNPG
wiato otoczenia i rozproszone stosowane w programie LITJET s cakowicie wystar-
czajce, aby uzyska efekt owietlenia. W zalenoci od kta padania promieni wiata
poszczeglne powierzchnie samolotu cieniowane s w rny sposb. W czasie gdy samolot
si obraca, kty te ulegaj cigym zmianom, a my moemy obserwowa zmiany owie-
tlenia i na tej podstawie okreli pooenie rda wiata.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 255
Do tej pory ignorowalimy jednak skadow wiata skupienia w rdach wiata, jak
rwnie odpowiadajc jej skadow waciwoci materiau. Co prawda efekty owie-
tlenia s wyliczane, ale kolory powierzchni samolotu s raczej matowe. wiato otoczenia
i rozproszone i odpowiadajce im waciwoci materiaw s wystarczajce w czasie
modelowania obiektw z gliny, drewna, tektury, tkaniny i innych matowych materiaw.
Jednak samolot skada si gwnie z powierzchni metalizowanych, ktrym przydaoby
si nieco poysku.
1FD[UMK
Waciwoci materiau i wiata odbitego nadaj naszym materiaom wymaganego po-
ysku. Ma on wybielajcy wpyw na kolory obiektu, co moe doprowadzi do powstania
odbyskw, jeeli kt padania wiata na powierzchni bdzie odpowiedni w stosunku
do pozycji obserwatora. Odbysk powstaje wtedy, kiedy niemal cae wiato padajce na
powierzchni odbijane jest w stron obserwatora. Dobrym przykadem takiego odbysku
jest jasna plama na powierzchni, lecej w socu, czerwonej piki.
YKCVQQFDKVG
Do rda wiata mona bardzo atwo doda skadow wiata odbitego. Poniej przed-
stawiono kod konfigurujcy owietlenie pochodzcy z programu LITJET, w ktrym dodano
instrukcje konfigurujce skadow wiata odbitego:
// Wsprzdne i wartoci owietlenia
|f!oa! amo:en!|:_h! 0:f 0:f 0:f 10f ,
|f!oa! c:ffuse|:_h! 07f 07f 07f 10f ,
|f!oa! specu!ar 10f 10f 10f 10f ,

// Wczenie owietlenia
_!Fnao!e||T'TTN|,
// Konfiguracja i wczenie wiata numer 0
_!|:_h!fv||T'T0|/MBTFNTamo:en!|:_h!|,
_!|:_h!fv||T'T0|OTFFUSFc:ffuse|:_h!|,
_!|:_h!fv||T'T0|SPFCU|/Rspecu!ar|,
_!Fnao!e||T'T0|,
W tablicy s,ecu.r zdefiniowana zostaa bardzo jasna skadowa biaego wiata odbitego.
Chcemy w ten sposb zasymulowa jasne wiato soneczne. Ponisz lini dodajemy
do rda wiata O|_|1OHT0 przygotowan wczeniej skadow wiata odbitego:
_!|:_h!fv||T'T0|SPFCU|/Rspecu!ar|,
Jeeli byaby to jedyna zmiana, jak wprowadzilibymy do programu LITJET, to wygld
wywietlanego samolotu nie zmieniby si ani troch. Po prostu nie zdefiniowalimy
jeszcze adnych waciwoci odblaskowych materiau samolotu.
256 Cz I Klasyka OpenGL
9URE\[PPKMQFDKEKC
Uzupenienie waciwoci materiau o wspczynnik odbicia jest niemal tak proste jak
uzupenienie rda wiata o skadow wiata odbitego. Poniszy fragment kodu pochodzi
z programu LITJET i ponownie zosta zmodyfikowany tak, aby doda do waciwoci
materiau informacj o wspczynniku odbicia wiata odbitego:
// Wsprzdne i wartoci owietlenia
|f!oa! specref 10f 10f 10f 10f ,

// Wczenie ledzenia kolorw


_!Fnao!e|CJ|JRM/TFRT/||,
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
// Od tego momentu wszystkie materiay uzyskaj poysk
// i bd doskonale odbijay wiato odbite
_!Ma!er:a!fv|FRJNT |SPFCU|/R specref|,
_!Ma!er:a!:|FRJNT |S'TNTNFSS 18|,
Tak jak poprzednio wczamy mechanizm ledzenia kolorw, aby waciwoci odbijania
wiata otoczenia i rozproszonego byy zgodne z aktualnym kolorem definiowanym funk-
cj Cccr. Oczywicie nie chcemy, eby funkcja Cccr definiowaa rwnie wa-
ciwoci odbijania wiata odbitego. T waciwo zdefiniujemy sami i nie bdzie ona
podlegaa adnym zmianom.
Dodalimy teraz tablic s,ecre' zawierajc wartoci RGBA opisujce wspczynnik
odbicia dla materiau. Zapisujemy w niej same jedynki, dziki czemu tworzymy powierzch-
nie odbijajce praktycznie kade wiato odbite. Ponisza linia ustala waciwoci mate-
riau dla wszystkich definiowanych po niej wieloktw tak, aby zawieray w sobie dane
wspczynnika odbicia:
_!Ma!er:a!fv|FRJNT |SPFCU|/R specref|,
Pniej ju nie wywoujemy funkcji M.'er. z parametrem O|_SPlCU|AR, dlatego
wszystkie materiay bd miay takie same waciwoci dla wiata odbitego. Celowo
tworzymy ten przykad w taki sposb, poniewa chcemy, aby cay samolot sprawia wra-
enie, e zbudowany jest z bardzo byszczcych materiaw.
To, co zrobilimy w naszej funkcji konfigurujcej, jest niezwykle istotne. Spowodowa-
limy, e waciwoci odblaskowe materiaw dla wiata otoczenia i rozproszonego dla
wszystkich tworzonych w przyszoci wieloktw (do czasu a zmienimy to wywoaniem
funkcji M.'er. lub CccrM.'er.), bd zmieniay si razem ze zmianami kolo-
rw tych wieloktw, a jednoczenie waciwoci tych samych materiaw dla wiata
odbitego bd niezmienne.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 257
9[MCFPKMQFD[UMW
Jak mwilimy ju wczeniej, wysoka warto jasnoci wiata odbitego i odpowiednich
waciwoci odblaskowych bd rozjaniay kolory obiektu. W naszym przykadzie za-
stosowalimy wyjtkowo wysok warto jasnoci wiata (pena intensywno) oraz
wspczynnika odbicia (najlepsze odbicia). W efekcie samolot byby niemal wycznie
biay lub szary, za wyjtkiem powierzchni odwrconych od rda wiata (te byyby
cakowicie czarne i nieowietlone). Moemy zagodzi ten efekt za pomoc poniszej
linii kodu umieszczonej zaraz za definicj waciwoci odblaskowych materiaw:
_!Ma!er:a!:|FRJNT |S'TNTNFSS 18|,
Waciwo O|_SH1N1NlSS ustala wykadnik odbysku (ang. specular exponent) mate-
riau okrelajcy, jak may i skupiony na by rozmiar odbysku. Warto 0 oznacza, e
odbysk w ogle nie bdzie skupiony, co w efekcie prowadzi do rwnomiernego rozja-
niania kolorw na powierzchni caych wieloktw. Zmieniajc t warto, zwikszamy
skupienie rozbysku, co powoduje, e na obiekcie pojawia si coraz mniejsza, jasna plama.
Im wysza warto, tym bardziej byszczca bdzie powierzchnia obiektu. We wszystkich
implementacjach biblioteki OpenGL warto tego parametru mona ustala w zakresie
od 0 do `8.
Listing 5.5 przedstawia kod funkcji Se'u,RC pochodzcy z przykadowego programu
SHINYJET. Jest to jedyny kod, jaki zosta zmieniony w stosunku do programu LITJET
(no, moe poza nazw okna), a na ekranie pojawia si piknie byszczcy samolot. Na
rysunku 5.28 przedstawiony zosta efekt dziaania programu, jednak wszystkie efekty
mona w peni doceni, dopiero wczajc sam program i klawiszem strzaki obracajc sa-
molot w wietle sonecznym.
I|st|ng 5.5. Kod konfigurujcy tworzcy w programie SHINYJET efekty odbyskw wietlnych
// Ta funkcja wykonuje wszystkie konieczne inicjalizacje kontekstu renderowania,
// a take konfiguruje i inicjalizuje owietlenie sceny
XQKF Se!upRC|

// Wsprzdne i wartoci owietlenia
|f!oa! amo:en!|:_h! 0:f 0:f 0:f 10f ,
|f!oa! c:ffuse|:_h! 07f 07f 07f 10f ,
|f!oa! specu!ar 10f 10f 10f 10f ,
|f!oa! specref 10f 10f 10f 10f ,
_!Fnao!e|OFPT'TFST|, // Usuwanie ukrytych powierzchni
_!Fron!Face|CC.|, // Wielokty z nawiniciem przeciwnym do ruchu
wskazwek zegara
_!Fnao!e|CU||F/CF|, // Nie bdziemy prowadzi oblicze wntrza samolotu
// Wczenie owietlenia
_!Fnao!e||T'TTN|,
// Konfiguracja i wczenie wiata numer 0
_!|:_h!fv||T'T0|/MBTFNTamo:en!|:_h!|,
_!|:_h!fv||T'T0|OTFFUSFc:ffuse|:_h!|,
_!|:_h!fv||T'T0|SPFCU|/R specu!ar|,
_!Fnao!e||T'T0|,
258 Cz I Klasyka OpenGL
kysunek 5.28.
Wynik dziaania
programu SHINYJET
// Wczenie ledzenia kolorw
_!Fnao!e|CJ|JRM/TFRT/||,
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
// Od tego momentu wszystkie materiay uzyskaj poysk
// i bd doskonale odbijay wiato odbite
_!Ma!er:a!fv|FRJNT |SPFCU|/R specref|,
_!Ma!er:a!:|FRJNT |S'TNTNFSS 18|,
// Jasnoniebieskie to
_!C!earCo!or00f 00f 10f 10f |,

7TGFPKCPKGPQTOCNP[EJ
Wczeniej wspominalimy, e wykrzywiajc wektory normalne moemy wytworzy
gadk powierzchni za pomoc paskich wieloktw. Za pomoc tej techniki, znanej jako
urednianie normalnych (normal averaging), mona uzyska wiele interesujcych iluzji
optycznych. Zamy, e posiadamy kul zoon z czworoktw i trjktw podobn do
przedstawionej na rysunku 5.29.
Jeeli kadej fasecie tej kuli przypisano by tylko jeden wektor normalny, to wygldaaby
ona jak wielki diament o bardzo wielu fasetach. Jeeli jednak kademu wierzchokowi
przypiszemy jego prawdziwy wektor normalny, to obliczenia owietlenia wygeneruj
wartoci kolorw, ktre zostan przez bibliotek OpenGL pynnie interpolowane wewntrz
wieloktw. W ten sposb paskie wielokty zostan wycieniowane tak, jakby byy gadk
powierzchni kuli.
Czym jednak jest prawdziwy wektor normalny? Aproksymacja wieloktami jest tylko
przyblieniem rzeczywistej powierzchni. Teoretycznie, jeeli zastosowalibymy wystar-
czajc liczb wieloktw, to powierzchnia zaczaby wyglda na gadk. Z podobnego
pomysu skorzystalimy w rozdziale 3., Rysowanie w przestrzeni. Geometryczne obiekty
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 259
kysunek 5.2.
Typowa kula zbudowana
z czworoktw
i trjktw
podstawowe i bufory, do rysowania gadkich linii krzywych za pomoc wielu krtkich
linii prostych. Jeeli uznamy, e kady wierzchoek jest punktem na rzeczywistej po-
wierzchni obiektu, to jego prawdziwym wektorem normalnym bdzie wektor normalny
powierzchni w tym punkcie.
W przypadku naszej kuli wektor normalny mgby by poprowadzony od rodka kuli na
zewntrz poprzez nasz punkt na powierzchni. Na rysunkach 5.30 i 5.31 przedstawimy t
ide dla prostych dwch wymiarw. Na rysunku 5.30 kada paska powierzchnia posiada
wasny, prostopady do niej, wektor normalny. T metod wykorzystalimy w podanym
wczeniej przykadzie programu LITJET, jednak ju na rysunku 5.31 mona zobaczy,
e kady wektor normalny nie jest prostopady do jakiejkolwiek linii przybliajcej wy-
gld kuli, ale do rzeczywistej powierzchni kuli albo linii stycznej (ang. tangent line) do
tej powierzchni.
kysunek 5.30.
Aproksymowanie
za pomoc normalnych
prostopadych
do kadej fasety
Linia styczna dotyka krzywej w jednym punkcie, ale jej nie przecina. W trzech wymiarach
podobnie zachowuje si paszczyzna styczna. Na rysunku 5.31 mona zobaczy kontur
rzeczywistej powierzchni, jak rwnie to, e normalna jest zawsze prostopada do linii
stycznej do powierzchni.
260 Cz I Klasyka OpenGL
kysunek 5.31.
Kada normalna
jest prostopada
do rzeczywistej
powierzchni kuli
Jeeli chodzi o kul, to wyliczenie normalnych do jej powierzchni nie jest bardzo trudne
(normalne maj dokadnie te same wartoci co wektory wyprowadzone ze rodka kuli).
Niestety, dla innych, nietrywialnych powierzchni takie obliczenia z pewnoci nie bd
proste. W takich przypadkach wylicza si normalne dla wszystkich wieloktw wsp-
dzielcych jeden wierzchoek, a nastpnie do wierzchoka przypisuje si wektor nor-
malny bdcy redni wszystkich wektorw normalnych wieloktw. W wyniku takiego
dziaania otrzymamy adn, gadk powierzchni, mimo e skada si ona z pewnej liczby
niewielkich paskich segmentw.
#VGTC\YU\[UVMQTC\GO
Nadszed czas na napisanie nieco bardziej rozbudowanego programu. Zademonstrujemy
w nim, jak uywa normalnych do uzyskania wygldu gadkich powierzchni, jak przesu-
wa rdo wiata na scenie, tworzy reflektor kierunkowy. Na koniec wskaemy wad
stosowanego przez bibliotek OpenGL modelu owietlenia.
Wszystkie te zadania wykonywa bdzie nasz nastpny program przykadowy SPOT. Na
rodku naszej przestrzeni widocznej tworzymy kul za pomoc funkcji u'SccS,|ere.
Kul owietlimy za pomoc reflektora, ktry bdzie mona przesuwa po scenie. Bdziemy
te zmienia gadko powierzchni kuli, a take wskazywa pewne ograniczenia modelu
owietlenia stosowanego w bibliotece OpenGL.
Jak dotd pozycj rda wiata okrelalimy za pomoc funkcji ||':
// Tablica okrelajca pozycj rda wiata
|f!oa! !:_h!Pos 00f 1500f 1500f 10f ,

// Ustalenie pozycji rda wiata


_!|:_h!fv||T'T0|PJSTTTJN!:_h!Pos|,
W tablicy |'Pcs przechowywane s wartoci wsprzdnych x, y i z okrelajcych
aktualn pozycj rda wiata na scenie albo kierunek, z ktrego wiato pada na scen.
Ostatnia warto w tablicy, w tym przypadku `0, oznacza, e rdo wiata rzeczywicie
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 261
znajduje si na podanej pozycji. Domylnie, rda wiata wiec we wszystkich kierun-
kach jednakowo, jednak mona zmieni to ustawienie i utworzy reflektor kierunkowy.
Umieszczajc warto 00 na ostatniej pozycji tablicy |'Pcs, powodujemy, e rdo
wiata znajduje si w nieskoczonej odlegoci od sceny, a wszystkie promienie jego
wiata docieraj do sceny z zadanego kierunku. Kade rdo wiata kierunkowego
(tak nazywaj si te rda) jednakowo owietla wszystkie obiekty na scenie. Oznacza
to, e promienie tego wiata s do siebie rwnolege. Z drugiej strony promienie wiata
pozycjonowanego rozchodz si od rda we wszystkich kierunkach.
6YQT\GPKGTGHNGMVQTC
rda wiata typu reflektorw tworzy si dokadnie tak samo jak inne pozycjonowane
rda wiata. Kod z listingu 5.6 przedstawia funkcj Se'u,RC pochodzc z programu
SPOT. Program ten umieszcza porodku okna niebiesk kul. Poza tym tworzy te reflek-
tor, ktry moemy przesuwa nad kul w pionie (klawisze ze strzakami w gr i w d)
oraz w poziomie (klawisze ze strzakami w lewo i w prawo). Poruszanie reflektora wok
kuli powoduje, e efekty odblaskowe zmieniaj si, dostosowujc si do nowej pozycji
reflektora.
I|st|ng 5.. Konfiguracja owietlenia w programie przykadowym SPOT
// Wartoci i wsprzdne owietlenia
|f!oa! !:_h!Pos 00f 00f 750f 10f ,
|f!oa! specu!ar 10f 10f 10f 10f,
|f!oa! specref 10f 10f 10f 10f ,
|f!oa! amo:en!|:_h! 05f 05f 05f 10f,
|f!oa! spo!O:r 00f 00f -10f ,
// Ta funkcja wykonuje wszystkie konieczne inicjalizacje kontekstu renderowania,
// a take konfiguruje i inicjalizuje owietlenie sceny
XQKF Se!upRC|

_!Fnao!e|OFPT'TFST|, // Usuwanie powierzchni ukrytych
_!Fron!Face|CC.|, // Wielokty z nawiniciem przeciwnym do ruchu
wskazwek zegara
_!Fnao!e|CU||F/CF|, // Nie bdziemy prowadzi oblicze wntrza samolotu
// Wczenie owietlenia
_!Fnao!e||T'TTN|,
// Konfiguracja i wczenie wiata numer 0
// Musimy dostarczy nieco wiata otoczenia, eby w ogle
// zobaczy jakiekolwiek obiekty
_!|:_h!Moce!fv||T'TMJOF|/MBTFNT amo:en!|:_h!|,
// rdo wiata bdzie emitowa wycznie wiato rozproszone i odbite
_!|:_h!fv||T'T0|OTFFUSFamo:en!|:_h!|,
_!|:_h!fv||T'T0|SPFCU|/Rspecu!ar|,
_!|:_h!fv||T'T0|PJSTTTJN!:_h!Pos|,
262 Cz I Klasyka OpenGL
// Ze rda wiata tworzymy reflektor
// Kt odcicia ma 60 stopni
_!|:_h!f||T'T0|SPJTCUTJFFb00f|,
// Nie moemy zapomnie o wczeniu tego wiata
_!Fnao!e||T'T0|,
// Wczenie ledzenia kolorw
_!Fnao!e|CJ|JRM/TFRT/||,
// Waciwoci owietlenia otoczenia i rozproszenia
// bd ledzi wartoci podawane funkcji glColor
_!Co!orMa!er:a!|FRJNT |/MBTFNT/NOOTFFUSF|,
// Od tego momentu wszystkie materiay uzyskaj poysk
// i bd doskonale odbijay wiato odbite
_!Ma!er:a!fv|FRJNT |SPFCU|/Rspecref|,
_!Ma!er:a!:|FRJNT |S'TNTNFSS18|,
// Czarne to
_!C!earCo!or00f 00f 00f 10f |,

Ponisze linie kodu sprawiaj, e pozycjonowane rdo wiata zmienia si w reflektor:
// Ze rda wiata tworzymy reflektor
// Kt odcicia ma 60 stopni
_!|:_h!f||T'T0|SPJTCUTJFFb00f|,
Warto parametru O|_SPOT_CUTO|| okrela kt mierzony od linii rodkowej stoka wiata,
do brzegu tego stoka. Dla normalnego wiata pozycjonowanego warto tego kta wy-
nosi `80`, co oznacza, e nie jest ono ograniczane jakimkolwiek stokiem. Jednak ju dla
reflektorw warto ta wynosi od 0` do 90`. Reflektory generuj wiato wycznie we-
wntrz zadanego stoka. Wszystko, co znajduje si poza nim, nie jest owietlane. Na ry-
sunku 5.32 mona zobaczy, w jaki sposb podawany tu kt zamieniany jest na szeroko
stoka wiata.
kysunek 5.32.
Kty w stoku wiata
z refletora
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 263
4[UQYCPKGTGHNGMVQTY
Umieszczajc na scenie reflektor, musimy zaznaczy, skd pochodzi rzucane przez niego
wiato. To, e w jakim miejscu bdzie znajdowa si rdo wiata, nie oznacza od razu,
e zobaczymy tam jasn plam. W przykadowym programie SPOT w miejscu reflektora
umiecimy te czerwony stoek, a w jego podstawie t kul symbolizujc arwk.
W programie przygotowalimy menu kontekstowe, z pomoc ktrego bdziemy demon-
strowa kilka rzeczy. Mona w nim przecza si midzy cieniowaniem paskim i gadkim,
a take wybiera modele kuli o rnych stopniach mozaikowoci. Mozaikowo (ang.
tessellation) oznacza zamian siatki obiektu w siatk o wikszej dokadnoci (skadajcej
si z wikszej liczby wierzchokw). Na rysunku 5.33 mona zobaczy siatkow reprezen-
tacj kuli o wysokiej mozaikowoci. Obok niej wida siatk kuli skadajc si z mniejszej
liczby wierzchokw.
kysunek 5.33.
Po lewej stronie
znajduje si kula
o wysokiej
mozaikowoci,
natomiast po prawej
kula skadajca si
z niewielkiej liczby
wierzchokw
Rysunek 5.34 przedstawia nasz przykadowy program w swojej konfiguracji pocztkowej,
przy czym reflektor owietlajcy kul zosta przesunity nieco w prawo (reflektor prze-
suwany jest klawiszami strzaek). Kula zbudowana jest z niewielkiej liczby pasko cie-
niowanych wieloktw. W systemie Windows prawym klawiszem myszy wywoujemy
menu kontekstowe (w komputerach Mac ten sam efekt uzyskujemy, przytrzymujc klawisz
Ctrl i klikajc mysz), z ktrego moemy wybra paski lub gadki model cieniowania,
a take trzy rne poziomy mozaikowoci modelu kuli. Listing 5.7 przedstawia peny
kod renderujcy scen w tym programie.
kysunek 5.34.
Przykadowy program
SPOT niska
mozaikowo,
paskie cieniowanie
264 Cz I Klasyka OpenGL
I|st|ng 5.7. Funkcja renderujca programu SPOT. Mona tu zobaczy, jak przesuwany jest
na scenie reflektor
// Wywoywana w celu przerysowania sceny
XQKF RencerSceneXQKF|

KH:Shace MJOFF|/T|
_!ShaceMoce!|F|/T|,
GNUG // iShade = MODE_SMOOTH;
_!ShaceMoce!|SMJJT'|,
// Czyszczenie okna aktualnym kolorem czyszczcym
_!C!ear|CJ|JRBUFFFRBTT | |OFPT'BUFFFRBTT|,
// Najpierw trzeba umieci na scenie rdo wiata
// Zapisa przeksztacenie wsprzdnych
_!PushMa!r:x|,
// Obrt ukadu wsprzdnych
_!Ro!a!ef,Ro! 00f 10f 00f|,
_!Ro!a!efxRo! 10f 00f 00f|,
// Zdefiniowanie nowej pozycji i kierunku w obrconym ukadzie wsprzdnych
_!|:_h!fv||T'T0|PJSTTTJN!:_h!Pos|,
_!|:_h!fv||T'T0|SPJTOTRFCTTJNspo!O:r|,
// Rysowanie czerwonego stoka obejmujcego rdo wiata
_!Co!or:uo5500|,
// Przesuwamy pocztek ukadu wsprzdnych, umieszczajc stoek w miejscu,
// w ktrym znajduje si rdo wiata
_!Trans!a!ef!:_h!Pos0!:_h!Pos1!:_h!Pos|,
_!u!So!:cCone40fb0f1515|,
// Rysujemy niewielk t kul wygldajc jak arwka
// Zapisanie zmiennych stanu owietlenia
_!Push/!!r:o||T'TTNBTT|,
// Wyczenie owietlenia i rysowanie jasnej tej kuli
_!O:sao!e||T'TTN|,
_!Co!or:uo55550|,
_!u!So!:cSphere:0f 15 15|,
// Odtworzenie zmiennych stanu owietlenia
_!Pop/!!r:o|,
// Odtworzenie przeksztacenia wsprzdnych
_!PopMa!r:x|,
// Ustawienie koloru materiau i narysowanie kuli na rodku ekranu
_!Co!or:uo0 0 55|,
KH:Tess MJOFVFRY|J.|
_!u!So!:cSphere:00f 7 7|,
GNUG
KH:Tess MJOFMFOTUM|
_!u!So!:cSphere:00f 15 15|,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 265
GNUG // iTess = MODE_MEDIUM;
_!u!So!:cSphere:00f 50 50|,
// Wywietlenie obrazu
_!u!S.apBuffers|,

Wartoci zmiennych Tess i Mcce ustawiane s w funkcji obsugujcej menu. Zmienne te
kontroluj liczb wieloktw, z jakich skada si kula, a take stosowany model cienio-
wania. Prosz zauway, e rdo wiata umieszczane jest na scenie jeszcze przed
wykonaniem jakiejkolwiek operacji renderowania. Jak wspominalimy w rozdziale 2.,
biblioteka OpenGL jest interfejsem trybu natychmiastowego, dlatego, jeeli chcemy
owietli jakie obiekty na scenie, to rda wiata musimy umieci na niej jeszcze przed
narysowaniem owietlanych obiektw.
Na rysunku 5.34 widzielimy, e kula jest owietlona w niewyszukany sposb, a po-
wierzchnie wszystkich wieloktw s wyranie widoczne. Wczenie trybu gadkiego
cieniowania nieco poprawia sytuacj, co wida na rysunku 5.35.
kysunek 5.35. Kula z gadkim cieniowaniem, ale niewystarczajc mozaikowoci
Jak pokazano na rysunku 5.36, podniesienie stopnia mozaikowoci pozwala na znacznie
lepsze odwzorowanie artefaktw w czasie przesuwania reflektora wok kuli. To wanie
te artefakty s jedn z wad modelu owietlenia stosowanego przez bibliotek OpenGL.
Tak naprawd, naleaoby powiedzie, e jest to wada modelu owietlenia opartego na
266 Cz I Klasyka OpenGL
kysunek 5.3. Wybranie dokadniejszej siatki wieloktw oznacza lepsze efekty owietlenia
wierzchokw
wierzchokach (czyli niekoniecznie samej biblioteki OpenGL!). Wyliczajc wartoci jedynie
w wierzchokach, a pniej tworzc interpolacje pomidzy nimi na powierzchni wielo-
ktw, otrzymujemy tylko zgrubne przyblienie rzeczywistego owietlenia. W wielu przy-
padkach takie rozwizanie jest wystarczajce, ale jak moglimy si przekona w programie
SPOT nie we wszystkich. Jeeli jednak zastosujemy model kuli o bardzo wysokiej
mozaikowoci i zaczniemy porusza wok niej reflektorem, to zauwaymy, e wada
tego modelu owietlenia zacznie znika.
Od czasu, gdy akceleratory grafiki wsppracujce z bibliotek OpenGL zaczy rwnie
przyspiesza dziaania przeksztace geometrycznych i efektw owietlenia, a procesory
bardzo zyskay na mocy obliczeniowej, moemy stosowa w naszych scenach obiekty
o znacznie wikszej mozaikowoci i uzyskiwa znacznie lepsze efekty wietlne.
Ostatni rzecz, o jakiej musimy wspomnie przy omawianiu programu SPOT, bdzie
mona zaobserwowa po wczeniu redniego stopnia mozaikowoci i paskiego cienio-
wania. Jak pokazano na rysunku 5.37, kada faseta kuli jest jednolicie owietlona. Kady
z wierzchokw ma ten sam kolor modulowany jedynie przez waciwoci owietlenia
i wektor normalny wielokta. W cieniowaniu paskim kady wielokt otrzymuje kolor
pobrany z ostatniego wierzchoka definiujcego ten wielokt. Nie nastpuje tu pynna
interpolacja pomidzy poszczeglnymi wierzchokami.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 267
kysunek 5.37. Kula zoona z wielu wieloktw
%KGPKG
W rozdziale dotyczcym kolorw i owietlenia nie moe zabrakn dyskusji o cieniach.
Uzupenienie sceny o cienie obiektw moe bardzo podnie jej realizm. Na rysunkach
5.38 i 5.39 mona zobaczy dwa obrazy kolorowego szecianu. Mimo e w obu zastoso-
wano owietlenie, to jednak ten z cieniem jest znacznie bardziej przekonujcy.
kysunek 5.38.
Owietlony szecian
bez cieni
268 Cz I Klasyka OpenGL
kysunek 5.3.
Owietlony szecian
z cieniem
%\[OLGUVEKG!
Pod wzgldem pojciowym rysowanie cieni powinno by prost operacj. Cie tworzony
jest wtedy, gdy jaki obiekt zatrzymuje wiato padajce z pewnego rda wiata i nie
pozwala mu pa na powierzchnie znajdujce si za tym obiektem. Obszar na zacienionej
powierzchni jest bardzo ciemny i ma ksztat obiektu rzucajcego cie. Moemy wic pro-
gramowo wygenerowa cie, wykonujc spaszczajcy rzut obiektu rzucajcego cie na
zacienion powierzchni. W takim rzucie obiekt rysowany jest kolorem czarnym lub innym
ciemnym, z zachowaniem pewnego stopnia przezroczystoci. Istnieje wiele metod i algo-
rytmw generowania cieni, z ktrych cz naley do bardzo zoonych. W tej ksice
skupia bdziemy si przede wszystkim na interfejsie programistycznym OpenGL.
Mamy nadziej, e po opanowaniu tego narzdzia kolejne pozycje sugerowane w do-
datku A udostpni kademu ogromne moliwoci jego wykorzystania w wielu rnych
nowych aplikacjach. W rozdziale 18., Tekstury gbi oraz cienie, opisujemy jedn z no-
wych bezporednich metod generowania cieni oferowan przez bibliotek OpenGL.
Jednak w tym rozdziale skupimy si na zaprezentowaniu jednej z prostszych metod, dosko-
nale si sprawdzajcych, jeeli cie rzucany jest na paskie powierzchnie (na przykad na
ziemi). Spaszczenie, o ktrym mwilimy wczeniej, zilustrowane zostao na rysunku 5.40.
kysunek 5.40.
Spaszczenie obiektu
tworzce jego cie
Przy wykorzystaniu zaawansowanych manipulacji macierzowych, o ktrych mwilimy
ju wczeniej, obiekt rzucajcy cie sprasowywany jest na powierzchni na ktr ten cie
rzuca. Poniej postaramy si jak najbardziej uproci ten proces.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 269
-QFRTCUWLE[
Musimy spaszczy macierz rzutowania widoku modelu w taki sposb, eby wszystkie
rysowane w niej obiekty byy spaszczone do wiata dwuwymiarowego. Niezalenie od
uoenia obiektu w przestrzeni zostanie on sprasowany na powierzchni, na ktrej poo-
ony bdzie jego cie. Trzeba przy tym wzi pod uwag kierunek i odlego rda
wiata. Kierunek rda wiata bdzie wpywa na ksztat i rozmiar cienia obiektu.
Kady, kto przyglda si swojemu cieniowi wczesnym rankiem lub pnym wieczorem,
wie dokadnie, jak dugi i powykrzywiany moe si on wydawa.
Pochodzca z biblioteki glTools funkcja 'M.eS|.cc.M.'rx przedstawiona zostaa na
listingu 5.8. Pobiera ona trzy punkty lece na paszczynie, na ktrej ma si pojawi
cie (nie mog by uoone na jednej linii!), pozycj rda wiata oraz wskanik na
macierz przeksztacenia wyliczonego przez t funkcj. Nie bdziemy za bardzo wgbia
si w algebr liniow, ale musimy powiedzie, e ta funkcja wyznacza wspczynniki
rwnania paszczyzny, na ktr pada bdzie cie i wykorzystuje je w poczeniu z infor-
macj o pozycji rda wiata do zbudowania macierzy przeksztacenia. Jeeli t macierz
pomnoymy przez aktualn macierz model-widok, to wszystkie kolejne operacje rysowania
bd odbyway si na podanej do funkcji paszczynie.
I|st|ng 5.8. Funkcja tworzca macierz przeksztacenia generujcego cienie
// Tworzy macierz rzutowania cienia na podstawie wspczynnikw
// rwnania paszczyzny i pozycji rda wiata
// Warto zwracana zapisywana jest pod wskanikiem destMat
XQKF _!!Ma|eShaco.Ma!r:x|TVec!or: vPo:n!s: |TVec!or4 v|:_h!Pos
|TMa!r:x ces!Ma!|

|TVec!or4 vP!aneFqua!:on,
|f!oa! co!,
_!!e!P!aneFqua!:onvPo:n!s0 vPo:n!s1 vPo:n!s vP!aneFqua!:on|,
// Iloczyn skalarny paszczyzny i pozycji rda wiata
co! vP!aneFqua!:on0'v|:_h!Pos0
vP!aneFqua!:on1'v|:_h!Pos1
vP!aneFqua!:on'v|:_h!Pos
vP!aneFqua!:on:'v|:_h!Pos:,
// Teraz wykonujemy rzutowanie
// Pierwsza kolumna
ces!Ma!0 co! - v|:_h!Pos0 ' vP!aneFqua!:on0,
ces!Ma!4 00f - v|:_h!Pos0 ' vP!aneFqua!:on1,
ces!Ma!8 00f - v|:_h!Pos0 ' vP!aneFqua!:on,
ces!Ma!1 00f - v|:_h!Pos0 ' vP!aneFqua!:on:,
// Druga kolumna
ces!Ma!1 00f - v|:_h!Pos1 ' vP!aneFqua!:on0,
ces!Ma!5 co! - v|:_h!Pos1 ' vP!aneFqua!:on1,
ces!Ma!9 00f - v|:_h!Pos1 ' vP!aneFqua!:on,
ces!Ma!1: 00f - v|:_h!Pos1 ' vP!aneFqua!:on:,
270 Cz I Klasyka OpenGL
// Trzecia kolumna
ces!Ma! 00f - v|:_h!Pos ' vP!aneFqua!:on0,
ces!Ma!b 00f - v|:_h!Pos ' vP!aneFqua!:on1,
ces!Ma!10 co! - v|:_h!Pos ' vP!aneFqua!:on,
ces!Ma!14 00f - v|:_h!Pos ' vP!aneFqua!:on:,
// Czwarta kolumna
ces!Ma!: 00f - v|:_h!Pos: ' vP!aneFqua!:on0,
ces!Ma!7 00f - v|:_h!Pos: ' vP!aneFqua!:on1,
ces!Ma!11 00f - v|:_h!Pos: ' vP!aneFqua!:on,
ces!Ma!15 co! - v|:_h!Pos: ' vP!aneFqua!:on:,

2T\[MCF\EKGPKGO
Aby zademonstrowa zastosowanie funkcji z listingu 5.8, zawiesimy nasz samolot wysoko
nad ziemi, a rdo wiata nad samolotem, lekko przesunite w lew stron. Klawi-
szami strzaek mona obraca samolot w rnych kierunkach, a wtedy cie rzucany przez
samolot na ziemi bdzie si dostosowywa do nowej pozycji samolotu. Na rysunku 5.41
przedstawiono wynik dziaania programu SHADOW.
kysunek 5.41.
Wynik dziaania
programu SHADOW
Listing 5.9 przedstawia metod tworzenia macierzy rzutowania wykorzystan w tym
przykadzie. Prosz zwrci uwag, e macierz tworzona jest jeden raz w funkcji Se'u,RC
i zapisywana w zmiennej globalnej.
I|st|ng 5.. Tworzenie macierzy rzutowania cienia
|f!oa! !:_h!Pos -750f 1500f -500f 00f ,

// Macierz przeksztacenia rzucanych cieni


|TMa!r:x shaco.Ma!,

// Ta funkcja wykonuje wszystkie konieczne inicjalizacje kontekstu renderowania,


// a take konfiguruje i inicjalizuje owietlenie sceny
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 271
XQKF Se!upRC|

// Trzy dowolne punkty lece na podou
// (podane z nawiniciem przeciwnym do ruchu wskazwek zegara)
|TVec!or: po:n!s: -:00f -1490f -00f
-:00f -1490f 00f
400f -1490f 00f ,
_!Fnao!e|OFPT'TFST|, // Usuwanie ukrytych powierzchni
_!Fron!Face|CC.|, // Wielokty z nawiniciem przeciwnym do ruchu
wskazwek zegara
_!Fnao!e|CU||F/CF|, // Nie bdziemy prowadzi oblicze wntrza samolotu
// Wczenie owietlenia
_!Fnao!e||T'TTN|,

// Kod konfigurujcy owietlenie itd.

// To jasnoniebieskie
_!C!earCo!or00f 00f 10f 10f |,
// Wyliczenie macierzy rzutowania stosowanej do generowania cieni
_!!Ma|eShaco.Ma!r:xpo:n!s !:_h!Pos shaco.Ma!|,

Na listingu 5.10 przedstawiono kod renderujcy stosowany w przykadowym programie
generowania cieni. Na pocztku rysowane jest podoe, a nastpnie normalnie rysujemy
samolot, tak jak we wszystkich pozostaych przykadach. Na koniec odtwarzamy macierz
model-widok, mnoymy j przez macierz cieni i tworzymy w ten sposb nasz macierz
prasujc. Teraz trzeba jeszcze raz narysowa samolot (kod zosta zmodyfikowany tak,
eby funkcja Dr..Je' raz rysowaa w normalnych kolorach, a raz tylko w czerni). Po
ponownym odtworzeniu macierzy model-widok rysujemy niewielk t kul ustawion
mniej wicej w miejscu rda wiata. Prosz zauway, e przed rysowaniem cienia
samolotu wyczylimy mechanizm testowania gbi.
I|st|ng 5.10. Renderowanie samolotu i jego cienia
// Wywoywana w celu przerysowania sceny
XQKF RencerSceneXQKF|

// Czyszczenie okna aktualnym kolorem czyszczcym
_!C!ear|CJ|JRBUFFFRBTT | |OFPT'BUFFFRBTT|,
// Rysowanie podoa. Rcznie wykonujemy cieniowanie podoa,
// stosujc coraz ciemniejsze odcienie zielonego,
// otrzymujc w ten sposb iluzj gbi
_!Be_:n|JU/OS|,
_!Co!or:uo0:0|,
_!Ver!ex:f4000f -1500f -000f|,
_!Ver!ex:f-4000f -1500f -000f|,
_!Co!or:uo0550|,
_!Ver!ex:f-4000f -1500f 000f|,
_!Ver!ex:f4000f -1500f 000f|,
_!Fnc|,
272 Cz I Klasyka OpenGL
// Przed wykonaniem obrotw zapisanie macierzy stanu
_!PushMa!r:x|,
// Rysowanie samolotu w nowej pozycji i umieszczenie rda wiata
// jeszcze przed jego obrceniem.
_!Fnao!e||T'TTN|,
_!|:_h!fv||T'T0|PJSTTTJN!:_h!Pos|,
_!Ro!a!efxRo! 10f 00f 00f|,
_!Ro!a!ef,Ro! 00f 10f 00f|,
Ora.Je!F/|SF|,
// Odtworzenie oryginalnego stanu macierzy
_!PopMa!r:x|,
// Przygotowania do rysowania cienia i podoa
// Najpierw wyczamy owietlenie i zapisujemy stan rzutowania
_!O:sao!e|OFPT'TFST|,
_!O:sao!e||T'TTN|,
_!PushMa!r:x|,
// Mnoenie przez macierz rzutowania cienia
_!Mu!!Ma!r:xf|f!oa! '|shaco.Ma!|,
// Teraz obracamy samolot w nowej, spaszczonej przestrzeni
_!Ro!a!efxRo! 10f 00f 00f|,
_!Ro!a!ef,Ro! 00f 10f 00f|,
// Informujemy funkcj, e rysowany bdzie cie
Ora.Je!TRUF|,
// Odtworzenie normalnej wartoci macierzy rzutowania
_!PopMa!r:x|,
// Rysowanie rda wiata
_!PushMa!r:x|,
_!Trans!a!ef!:_h!Pos0!:_h!Pos1 !:_h!Pos|,
_!Co!or:uo55550|,
_!u!So!:cSphere50f1010|,
_!PopMa!r:x|,
// Odtworzenie zmiennych stanu owietlenia
_!Fnao!e|OFPT'TFST|,
// Wywietlenie wynikw
_!u!S.apBuffers|,

Prostokt ziemi ley na dokadnie tej samej paszczynie, na ktrej rysowane s cienie,
a chcemy by pewni, e cienie jednak zostan narysowane. Do tej pory nie zastanawiali-
my si, co si stanie, gdy na jednej paszczynie bdziemy rysowa dwa obiekty. Opisy-
walimy jednak mechanizm testowania gbi stosowany do sprawdzania, jakie elementy
maj by rysowane przed innymi. Jeeli dwa obiekty znajduj si w tej samej odlegoci
od obserwatora, to najczciej pojawia si ten, ktry by rysowany jako ostatni. Czasami
jednak, w wyniku efektu zwanego walk w buforze z (ang. z-fighting), na ekranie poja-
wiaj si pomieszane ze sob czci obu obiektw, co powoduje zamazanie obrazu!
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 273
2QPQYPCYK\[VCYYKGEKGMWN
Ostatni przykad tego rozdziau jest zbyt duy, eby w caoci podawa jego kod rdowy.
W poprzednim rozdziale, w programie SPHEREWORLD, tworzylimy cay trjwymia-
rowy wiat wraz z animacjami i ruchami kamery. W tym rozdziale ponownie odwie-
dzimy wiat kul i dodamy do niego owietlenie, a torusowi i wszystkim kulom nadamy
waciwoci ich materiaw. Zastosujemy te opisan przed chwil technik generowa-
nia cieni! Do tego przykadu bdziemy wraca od czasu do czasu, dodajc do niego coraz
wicej funkcji biblioteki OpenGL. Na rysunku 5.42 przedstawiony zosta wynik dziaa-
nia programu SPHEREWORLD uzupenionego o funkcje opisywane w tym rozdziale.
kysunek 5.42. W peni owietlony wiat kul rzucajcych cienie
2QFUWOQYCPKG
W niniejszym rozdziale wprowadzilimy kilka bardziej zaawansowanych moliwoci
biblioteki OpenGL. Rozpoczlimy od dodawania do sceny kolorw i zastosowania
gadkiego cieniowania. Nastpnie dowiedzielimy si, jak mona utworzy jedno lub
wicej rde wiata i zdefiniowa ich charakterystyki skadowych wiata otoczenia,
rozproszenia i odbicia. Wyjanilimy te, w jaki sposb poszczeglne waciwoci mate-
riaw wspdziaaj ze rdami wiata. Zademonstrowalimy kilka efektw specjalnych
takich jak generowanie rozbyskw wietlnych na powierzchni obiektw i agodzenie
ostrych krawdzi wystpujcych pomidzy ssiadujcymi trjktami.
274 Cz I Klasyka OpenGL
Omwilimy rwnie pozycjonowanie rde wiata, a take metody tworzenia i mani-
pulowania reflektorami. Opisana przez nas macierz wysokiego poziomu bardzo uatwia
generowanie cieni, jeeli s one rzucane na pask powierzchni.
1RKU[HWPMELK
g|Co|or
Zastosowanie: Ustala aktualny kolor w trybie RGBA.
Plik nagwkowy: |
Rodzaje:
XQKF Cccro|O||,'e TGF, O||,'e ITGGP, O||,'e DNWG)
XQKF CccrocO|ccu|e TGF, O|ccu|e ITGGP, O|ccu|e DNWG)
XQKF Cccro'O|'c.' TGF, O|'c.' ITGGP, O|'c.' DNWG)
XQKF CccroO|n' TGF, O|n' ITGGP, O|n' DNWG)
XQKF CccrosO|s|cr' TGF, O|s|cr' ITGGP, O|s|cr' DNWG)
XQKF Cccrou|O|u|,'e TGF, O|u|,'e ITGGP, O|u|,'e DNWG)
XQKF CccrouO|un' TGF, O|un' ITGGP, O|un' DNWG)
XQKF CccrousO|us|cr' TGF, O|us|cr' ITGGP, O|us|cr' DNWG)
XQKF Cccr4|O||,'e TGF, O||,'e ITGGP, O||,'e DNWG, O||,'e CNRJC)
XQKF Cccr4cO|ccu|e TGF, O|ccu|e ITGGP, O|ccu|e DNWG, O|ccu|e CNRJC)
XQKF Cccr4'O|'c.' TGF, O|'c.' ITGGP, O|'c.' DNWG, O|'c.' CNRJC)
XQKF Cccr4O|n' TGF, O|n' ITGGP, O|n' DNWG, O|n' CNRJC)
XQKF Cccr4sO|s|cr' TGF, O|s|cr' ITGGP, O|s|cr' DNWG, O|s|cr' CNRJC)
XQKF Cccr4u|O|u|,'e TGF, O|u|,'e ITGGP, O|u|,'e DNWG, O|u|,'e CNRJC)
XQKF Cccr4uO|un' TGF, O|un' ITGGP, O|un' DNWG, O|un' CNRJC)
XQKF Cccr4usO|us|cr' TGF, O|us|cr' ITGGP, O|us|cr' DNWG, O|us|cr' CNRJC)
XQKF Cccro|vEQPUV O||,'e *X)
XQKF CccrocvEQPUV O|ccu|e *X)
XQKF Cccro'vEQPUV O|'c.' *X)
XQKF CccrovEQPUV O|n' *X)
XQKF CccrosvEQPUV O|s|cr' *X)
XQKF Cccrou|vEQPUV O|u|,'e *X)
XQKF CccrouvEQPUV O|un' *X)
XQKF CccrousvEQPUV O|us|cr' *X)
XQKF Cccr4|vEQPUV O||,'e *X)
XQKF Cccr4cvEQPUV O|ccu|e *X)
XQKF Cccr4'vEQPUV O|'c.' *X)
XQKF Cccr4vEQPUV O|n' *X)
XQKF Cccr4svEQPUV O|s|cr' *X)
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 275
XQKF Cccr4u|vEQPUV O|u|,'e *X)
XQKF Cccr4uvEQPUV O|un' *X)
XQKF Cccr4usvEQPUV O|us|cr' *X)
Opis: Funkcja ustala aktualny kolor, pozwalajc poda osobno skadowe czerwon,
zielon i niebiesk. Funkcja umoliwia te podanie wartoci kanau alfa.
Kada skadowa reprezentowana jest liczb z zakresu od zera (00) do penej
intensywnoci koloru (`0). Funkcje posiadajce w nazwie przyrostek v
pobieraj wskanik na tablic przechowujc wszystkie skadowe koloru.
Wszystkie elementy takiej tablicy musz by tego samego typu. Jeeli
skadowa alfa nie zostanie sprecyzowana, to nadawana jest jej domylna
warto `0. W funkcjach przyjmujcych wartoci niezmiennoprzecinkowe,
wartoci z zakresu od zera do maksymalnej wartoci dopuszczalnej w danym
typie przeksztacane s w wartoci zmiennoprzecinkowe z zakresu od 00
do `0.
Parametry:
TGF Skadowa czerwona koloru.
ITGGP Skadowa zielona koloru.
DNWG Skadowa niebieska koloru.
CNRJC Skadowa kanau alfa koloru. Parametr ten stosowany jest wycznie
w wersjach funkcji pobierajcych cztery parametry.
*X Wskanik na tablic przechowujc wartoci skadowych czerwonej,
zielonej, niebieskiej i alfa.
Warto zwracana: Brak
Zobacz te: CccrM.'er., M.'er.
g|Co|orMosk
Zastosowanie: Wcza i wycza moliwo modyfikowania skadowych koloru znajdujcych
si w buforze koloru.
Plik nagwkowy: |
Skadnia:
XQKF CccrM.sO||cce.n D4GF, O||cce.n D)TGGP, O||cce.n D$NWG, O||cce.n D#NRJC)
Opis: Funkcja umoliwia wczanie i wyczanie pozwolenia na modyfikowanie
poszczeglnych skadowych koloru znajdujcego si w buforze koloru
(domylnie mona modyfikowa wszystkie skadowe). Na przykad nadanie
parametrowi D#NRJC wartoci O|_|A|Sl spowoduje, e w buforze koloru
nie bdzie moliwe modyfikowanie kanau alfa.
Parametry:
D4GF O||cce.n okrela, czy moliwe bd modyfikacje skadowej czerwonej
koloru.
D)TGGP O||cce.n okrela, czy moliwe bd modyfikacje skadowej zielonej
koloru.
276 Cz I Klasyka OpenGL
D$NWG O||cce.n okrela, czy moliwe bd modyfikacje skadowej niebieskiej
koloru.
D#NRJC O||cce.n okrela, czy moliwe bd modyfikacje skadowej kanau alfa.
Warto zwracana: Brak
Zobacz te: Cccr
g|Co|orMoter|o|
Zastosowanie: Pozwala na ustalanie waciwoci materiaw wieloktw zgodnie z kolorami
nadanymi mu funkcj Cccr.
Plik nagwkowy: |
Skadnia:
XQKF CccrM.'er.O|enu HCEG, O|enu OQFG)
Opis: Funkcja pozwala na ustalenie waciwoci materiaw bez koniecznoci
wywoywania funkcji M.'er.. Za pomoc tej funkcji moemy sprawi,
e waciwoci materiaw bd dostosowyway si do kolorw definiowanych
funkcj Cccr. Domylnie mechanizm ledzenia kolorw jest wyczony.
Mona go wczy, wywoujc funkcj ln.|eO|_CO|OR_MATlR1A|),
a nastpnie ponownie wyczy funkcj Ds.|eO|_CO|OR_MATlR1A|).
Parametry:
HCEG O|enu okrela, czy mechanizm ledzenia kolorw bdzie dotyczy
przednich (O|_|RONT), tylnych (O|_BAC|) lub obu (O|_|RONT_AND_BAC|)
stron wieloktw.
OQFG O|enu definiuje, ktra z waciwoci materiau ma by modyfikowana
zgodnie z aktualnym kolorem. Mona tu poda wartoci O|_lM1SS1ON,
O|_AMB1lNT, O|_D1||USl, O|_SPlCU|AR albo O|_AMB1lNT_AND_D1||USl.
Warto zwracana: Brak
Zobacz te: Cccr, M.'er., ||', ||'Mcce
g|GetL|ght
Zastosowanie: Zwraca informacje o aktualnych parametrach rda wiata.
Plik nagwkowy: |
Rodzaje:
XQKF Oe'||''vO|enu NKIJV, O|enu RPCOG, O|'c.' *RCTCOU)
XQKF Oe'||'vO|enu NKIJV, O|enu RPCOG, O|n' *RCTCOU)
Opis: Tej funkcji mona uywa do sprawdzania aktualnych wartoci ustawie
jednego z omiu obsugiwanych przez bibliotek rde wiata. Wartoci
zwracane s pod adresem wskazywanym przez parametr RCTCOU. W wikszoci
przypadkw zwracana jest tablica czterech wartoci opisujcych skadowe
RGBA danego parametru.
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 277
Parametry:
NKIJV O|enu okrela rdo wiata, ktrego dotycz dane informacje. Mog
to by wartoci z zakresu od 0 do O|_MAX_|1OHTS (specyfikacja biblioteki
wymaga obsugiwania minimum omiu wiate). Wartoci stae wyliczane
s od O|_|1OHT0 do O|_|1OHT/.
RPCOG O|enu okrela odpytywan waciwo rda wiata. Moliwe jest
podanie jednej z poniszych wartoci: O|_AMB1lNT, O|_D1||USl, O|_SPlCU|AR,
O|_POS1T1ON, O|_SPOT_D1RlCT1ON, O|_SPOT_lXPONlNT, O|_SPOT_CUTO||,
O|_CONSTANT_ATTlNUAT1ON, O|_|1NlAR_ATTlNUAT1ON lub
O|_OUADRAT1C_ATTlNUAT1ON.
RCTCOU O|'c.'* lub O|n'* krela tablic wartoci cakowitych lub
zmiennoprzecinkowych, do ktrej zapisane bd wartoci zwracane.
Do tablicy zapisywane mog by dane w postaci tablicy trj- lub
czteroelementowej, a take w postaci pojedynczej wartoci. W tabeli 5.2
podano rodzaje wartoci zwracanych dla kadej waciwoci.
Iobe|o 5.2. Prawidowe wartoci parametrw owietlenia dla funkcji glGetLight
Woc|woc Inoczen|e wortoc| zwroconej
|/MBTFNT Cztery skadowe RGBA
|OTFFUSF Cztery skadowe RGBA
|SPFCU|/R Cztery skadowe RGBA
|PJSTTTJN Cztery elementy okrelajce pozycj rda wiata. Pierwsze trzy wartoci
definiuj pozycj rda wiata. Jeeli czwartemu elementowi nadana zostanie
warto 10, oznacza to, e wiato rzeczywicie znajduje si na podanej
pozycji. Jeeli jednak czwartemu elementowi nadana zostanie warto 00,
to rdo wiata jest rdem kierunkowym, a wszystkie jego promienie
padaj rwnolegle z kierunku zdefiniowanego przez pierwsze trzy wartoci
|SPJTOTRFCTTJN Trzy elementy okrelajce kierunek reflektora. Wektor musi by
znormalizowany i definiowany we wsprzdnych oka
|SPJTFXPJNFNT Pojedyncza warto reprezentujca wykadnik reflektora
|SPJTCUTJFF Pojedyncza warto reprezentujca kt odcicia reflektora
|CJNST/NT/TTFNU/TTJN Pojedyncza warto reprezentujca sta tumienia wiata
||TNF/R/TTFNU/TTJN Pojedyncza warto reprezentujca liniowe tumienie wiata
|JU/OR/TTC/TTFNU/TTJN Pojedyncza warto reprezentujca kwadratowe tumienie wiata
Warto zwracana: Brak
Zobacz te: ||'
g|GetMoter|o|
Zastosowanie: Zwraca aktualne ustawienia waciwoci materiau.
Plik nagwkowy: |
278 Cz I Klasyka OpenGL
Rodzaje:
XQKF Oe'M.'er.'vO|enu HCEG, O|enu RPCOG, O|'c.' *RCTCOU)
XQKF Oe'M.'er.vO|enu HCEG, O|enu RPCOG, O|n' *RCTCOU)
Opis: Funkcja pozwala na sprawdzenie waciwoci materiau przedniej lub tylnej
strony wielokta. Wartoci zwracane zapisywane s pod adresem pamici
wskazywanym przez parametr RCTCOU. W wikszoci przypadkw zwracana
jest tablica czterech wartoci RGBA opisujcych dan waciwo.
Parametry:
HCEG O|enu okrela, czy sprawdzane s wartoci waciwoci przednich
(O|_|RONT) lub tylnych (O|_BAC|) stron wieloktw.
RPCOG O|enu definiuje, ktra z waciwoci materiau jest sprawdzana. Mona
tu poda wartoci O|_AMB1lNT, O|_D1||USl, O|_SPlCU|AR, O|_lM1SS1ON,
O|_SH1N1NlSS albo O|_CO|OR_1NDlXlS.
RCTCOU O|n'* lub O|'c.'* skazuje na tablic wartoci cakowitych lub
zmiennoprzecinkowych, do ktrej bd zapisywane wartoci zwracane.
W przypadku zapytania o waciwoci O|_AMB1lNT, O|_D1||USl, O|_SPlCU|AR
i O|_lM1SS1ON zwracana jest czteroelementowa tablica zawierajca wartoci
RGBA opisujce waciwo. Dla zapytania o waciwo O|_SH1N1NlSS
zwracana jest pojedyncza warto opisujca wykadnik odblasku materiau.
Przy zapytaniu o waciwo O|_CO|OR_1NDlXlS zwracana jest tablica
trjelementowa opisujca skadowe wiata otoczenia, rozproszonego i obitego,
zapisane w postaci indeksw kolorw. Parametr O|_CO|OR_1NDlXlS stosowany
jest wycznie wtedy, gdy stosowane jest owietlenie kolorami indeksowanymi.
Warto zwracana: Brak
Zobacz te: M.'er.
g|L|ght
Zastosowanie: Ustala parametry jednego z dostpnych rde wiata.
Plik nagwkowy: |
Rodzaje:
XQKF ||''O|enu NKIJV, O|enu RPCOG, O|'c.' RCTCO)
XQKF ||'O|enu NKIJV, O|enu RPCOG, O|n' RCTCO)
XQKF ||''vO|enu NKIJV, O|enu RPCOG, EQPUV O|'c.' *RCTCOU)
XQKF ||'vO|enu NKIJV, O|enu RPCOG, EQPUV O|n' *RCTCOU)
Opis: Funkcja uywana jest do ustalania parametrw jednego z omiu obsugiwanych
rde wiata. Dwie pierwsze wersje funkcji pobieraj tylko jeden parametr
i pozwalaj na ustawienie wartoci nastpujcych waciwoci:
O|_SPOT_lXPONlNT, O|_SPOT_CUTO||, O|_CONSTANT_ATTlNUAT1ON,
O|_|1NlAR_ATTlNUAT1ON i O|_OUADRAT1C_ATTlNUAT1ON. Dwie pozostae wersje
funkcji stosowane s do ustalania waciwoci opisywanych tablic kilku
wartoci. Takimi waciwociami s O|_AMB1lNT, O|_D1||USl, O|_SPlCU|AR,
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 279
O|_POS1T1ON i O|_SPOT_D1RlCT1ON. Tablicowych wersji funkcji ||' mona
uywa te do ustalania wartoci waciwoci opisywanych pojedyncz
wartoci; wystarczy w tablicy *RCTCOU umieci tylko jeden parametr.
Parametry:
NKIJV O|enu: Okrela numer rda wiata poddawanego modyfikacjom. Mona
podawa tu wartoci od 0 do O|_MAX_|1OHTS (przynajmniej 8). Zdefiniowane
s stae wartoci wyliczeniowe od O|_|1OHT0 do O|_|1OHT/.
RPCOG O|enu okrela parametr owietlenia ustawiany w danym wywoaniu
funkcji. W tabeli 5.2 podana zostaa pena lista parametrw wraz z ich
znaczeniami.
RCTCO O|n' lub O|'c.' podaje warto dla parametru owietlenia definiowanego
pojedyncz wartoci. Takimi parametrami s O|_SPOT_lXPONlNT,
O|_SPOT_CUTO||, O|_CONSTANT_ATTlNUAT1ON, O|_|1NlAR_ATTlNUAT1ON
i O|_OUADRAT1C_ATTlNUAT1ON. Parametry te maj znaczenie tylko
przy definiowaniu reflektorw.
RCTCOU O|n'* lub O|'c.'* okrela tablic zawierajc wartoci cakowicie
opisujce ustawiany parametr. W tabeli 5.2 mona znale pen list
takich parametrw wraz z ich znaczeniami.
Warto zwracana: Brak
Zobacz te: Oe'||'
g|L|ghtMode|
Zastosowanie: Ustala parametry modelu owietlenia stosowanego przez bibliotek OpenGL.
Plik nagwkowy: |
Rodzaje:
XQKF ||'Mcce'O|enu RPCOG, O|'c.' RCTCO)
XQKF ||'McceO|enu RPCOG, O|n' RCTCO)
XQKF ||'Mcce'vO|enu RPCOG, EQPUV O|'c.' *RCTCOU)
XQKF ||'MccevO|enu RPCOG, EQPUV O|n' *RCTCOU)
Opis: T funkcj stosuje si do ustalania parametrw modelu owietlenia
stosowanego przez bibliotek OpenGL. Moliwe jest ustalenie wartoci
dowolnego z czterech parametrw modelu. Parametr O|_|1OHT_MODl|_AMB1lNT
stosowany jest do ustalania domylnego owietlenia otoczenia. Domylnie,
parametr ten ma przypisan warto RGBA 0, 0, 0, `0).
Do ustawiania tego parametru stosowane mog by tylko dwie ostatnie
wersje tej funkcji, poniewa pobieraj one wskanik na tablic opisujc
wszystkie wartoci RGBA.
Parametr O|_|1OHT_MODl|_TwO_S1Dl pozwala okreli, czy owietlane bd
obie strony wieloktw. Domylnie owietlane s wycznie przednie strony
wieloktw, przy czym w czasie wyliczania owietlenia stosowane s
waciwoci materiaw zdefiniowane funkcj M.'er.. Okrelenie
280 Cz I Klasyka OpenGL
parametru O|_|1OHT_MODl|_|OCA|_V1lwlR powoduje zmodyfikowanie oblicze
ktw odbicia wiata odbitego w zalenoci od tego, czy obserwator patrzy
w d wzdu ujemnych wartoci osi z czy te z pocztku ukadu wsprzdnych
oka. W kocu parametr O|_|1OHT_MODl|_CO|OR_CONTRO| moe by stosowany
do kontrolowania, czy owietlenie bdzie tworzyo dodatkowy kolor (tekstury
bd owietlane wiatem odbitym) czy te wszystkie trzy skadowe wiata
bd czone w parametrze O|_S1NO|l_CO|OR.
Parametry:
RPCOG O|enu okrela modyfikowany parametr owietlenia. Przyjmowane s
wartoci O|_|1OHT_MODl|_AMB1lNT, O|_|1OHT_MODl|_|OCA|_V1lwlR,
O|_|1OHT_MODl|_TwO_S1Dl, O|_|1OHT_MODl|_CO|OR_CONTRO|.
RCTCO O|n' lub O|'c.' dla parametru O|_|1OHT_MODl|_|OCA|_V1lwlR warto
00 oznacza, e kty padania wiata odbitego musz bra pod uwag kierunek
patrzenia obserwatora rwnolegy do ujemnych wartoci osi z. Kada inna
warto oznacza, e obserwator znajduje si w pocztku ukadu wsprzdnych
oka. Dla parametru O|_|1OHT_MODl|_TwO_S1Dl warto 00 oznacza,
e wyliczane bdzie owietlenie wycznie przednich stron wieloktw.
Kada inna warto oznacza, e obliczenia prowadzone bd dla przednich
i tylnych stron wieloktw. Parametr ten nie ma adnego wpywu na punkty,
linie i bitmapy. Dla parametru O|_|1OHT_MODl|_CO|OR_CONTRO| mona poda
wartoci O|_SlPARATl_SPlCU|AR_CO|OR lub O|_S1NO|l_CO|OR.
RCTCOU O|n'* lub O|'c.'* dla parametrw O|_|1OHT_MODl|_AMB1lNT lub
O|_|1OHT_MODl|_|OCA|_V1lwlR, poda naley wskanik na tablic wartoci
cakowitych lub zmiennoprzecinkowych. Z podanej tablicy wykorzystana
bdzie tylko pierwsza warto. W przypadku parametru O|_|1OHT_MODl|_AMB1lNT
z tablicy pobierane s cztery wartoci opisujce skadowe RGBA wiata
otoczenia.
Warto zwracana: Brak
Zobacz te: ||', M.'er.
g|Moter|o|
Zastosowanie: Ustala waciwoci materiau stosowane w modelu owietlenia.
Plik nagwkowy: |
Rodzaje:
XQKF M.'er.'O|enu HCEG, O|enu RPCOG, O|'c.' RCTCO)
XQKF M.'er.O|enu HCEG, O|enu RPCOG, O|n' RCTCO)
XQKF M.'er.'vO|enu HCEG, O|enu RPCOG, EQPUV O|'c.' *RCTCOU)
XQKF M.'er.vO|enu HCEG, O|enu RPCOG, EQPUV O|n' *RCTCOU)
Opis: Tej funkcji uywa si do ustalenia parametrw odblaskowych materiau
pokrywajcego wielokty. Waciwoci O|_AMB1lNT, O|_D1||USl i O|_SPlCU|AR
okrelaj sposb, w jaki materia odbija padajce na niego wiato. Waciwo
O|_lM1SS1ON stosowana jest dla materiaw sprawiajcych wraenie emitowania
wasnego wiata. Warto przypisywana waciwoci O|_SH1N1NlSS musi
Rozdzia 5. Kolor, materiay i owietlenie. Podstawy 281
znajdowa si w zakresie od 0 do `8, przy czym wysze wartoci tworz
wiksze efekty rozbyskw na powierzchni materiau. Waciwo
O|_CO|OR_1NDlXlS stosowana jest do ustalania waciwoci odblaskowych
materiaw w trybie kolorw indeksowanych.
Parametry:
HCEG O|enu okrela, czy waciwoci materiaw bd ustalane dla przednich
(O|_|RONT), tylnych (O|_BAC|) czy te obu (O|_|RONT_AND_BAC|) stron
wieloktw.
RPCOG O|enu w pierwszych dwch wersjach funkcji okrela poddawan
modyfikacjom waciwo przyjmujc pojedyncz warto. Aktualnie
jedyn tego rodzaju waciwoci jest O|_SH1N1NlSS. Pozostae dwie wersje
funkcji przyjmuj te tablice wartoci przypisywanych waciwociom.
Za ich pomoc mona modyfikowa waciwoci O|_AMB1lNT, O|_D1||USl,
O|_SPlCU|AR, O|_lM1SS1ON, O|_SH1N1NlSS, O|_AMB1lNT_AND_D1||USl
oraz O|_CO|OR_1NDlXlS.
RCTCO O|n' lub O|'c.' krela warto przypisywan do waciwoci zdefiniowanej
parametrem RPCOG (aktualnie tylko O|_SH1N1NlSS).
RCTCOU O|n'* lub O|'c.'* krela tablic wartoci cakowitych lub
zmiennoprzecinkowych zawierajc wartoci przypisywane ustawianej
waciwoci.
Warto zwracana: Brak
Zobacz te: Oe'M.'er., CccrM.'er., ||', ||'Mcce
g|Normo|
Zastosowanie: Definiuje normaln dla nastpnego definiowanego wierzchoka lub zbioru
wierzchokw.
Plik nagwkowy: |
Rodzaje:
XQKF Ncr.o|O||,'e PZ, O||,'e P[, O||,'e P\)
XQKF Ncr.ocO|ccu|e PZ, O|'cu|e P[, O|ccu|e P\)
XQKF Ncr.o'O|'c.' PZ, O|'c.' P[, O|'c.' P\)
XQKF Ncr.oO|n' PZ, O|n' P[, O|n' P\)
XQKF Ncr.osO|s|cr' PZ, O|s|cr' P[, O|s|cr' P\)
XQKF Ncr.o|vEQPUV O||,'e *X)
XQKF Ncr.ocvEQPUV O|ccu|e *X)
XQKF Ncr.o'vEQPUV O|'c.' *X)
XQKF Ncr.ovEQPUV O|n' *X)
XQKF Ncr.osvEQPUV O|s|cr' *X)
Opis: Wektor normalny okrela kierunek prostopady do grnej powierzchni
wielokta. Funkcja stosowana jest w obliczeniach zwizanych z owietleniem
i cieniowaniem. Podanie wektora jednostkowego (o dugoci 1) bardzo
282 Cz I Klasyka OpenGL
podnosi prdko renderowania. Biblioteka OpenGL automatycznie moe
zamienia wszystkie wektory normalne w wektory jednostkowe; wystarczy
wywoa funkcj ln.|eO|_NORMA|1/l).
Parametry:
PZ Okrela warto x w wektorze normalnym.
P[ Okrela warto y w wektorze normalnym.
P\ Okrela warto z w wektorze normalnym.
X Okrela tablic trjelementow zawierajc wartoci x, y i z wektora
normalnego.
Warto zwracana: Brak
Zobacz te: TexCccrc, Ver'ex
g|ShodeMode|
Zastosowanie: Ustala, czy stosowany bdzie model cieniowania paskiego czy te gadkiego.
Plik nagwkowy: |
Skadnia:
XQKF S|.ceMcceO|enu OQFG)
Opis: Obiekty podstawowe biblioteki OpenGL zawsze s cieniowane, jednak
model cieniowania moe by paski (O|_||AT) lub gadki (O|_SMOOTH).
W najprostszym scenariuszu przed narysowaniem wielokta jego kolor
musi zosta zdefiniowany wywoaniem funkcji Cccr. Taki obiekt
podstawowy zawsze wypeniany jest kolorem jednolitym, niezalenie od
modelu cieniowania. Jeeli dla kadego wierzchoka zdefiniowany zostanie
inny kolor, to rysunek takiego wielokta bdzie wyglda inaczej w kadym
modelu cieniowania. W cieniowaniu gadkim wntrze wielokta wypeniane
jest interpolacj kolorw wszystkich jego wierzchokw. Oznacza to,
e kolor powierzchni wielokta bdzie zmienia si na odcinku czcym
dwa wierzchoki. W czasie interpolowania, kolory pobierane bd
z szecianu kolorw z odcinka czcego punkty odpowiadajce kolorom
dwch wierzchokw. Jeeli wczone bdzie te owietlenie, biblioteka
OpenGL wykonywa bdzie dodatkowe obliczenia majce na celu ustalenie
waciwej wartoci koloru kadego wierzchoka. W cieniowaniu paskim
kolor nadany ostatniemu wierzchokowi stosowany jest do wypenienia
caego obiektu podstawowego. Jedynym wyjtkiem od tej zasady s obiekty
podstawowe O|_PO|YOON, ktre wypeniane s kolorem pierwszego wierzchoka.
Parametry:
OQFG O|enu okrela stosowany model cieniowania. Mona poda tu wartoci
O|_||AT (cieniowanie paskie) lub O|_SMOOTH (cieniowanie gadkie). Domylnie
stosowane jest cieniowanie gadkie.
Warto zwracana: Brak
Zobacz te: Cccr, ||', ||'Mcce
Rozdzia 6.
Mylenie niekonwencjonalne
programy do cieniowania
Autor: Richard S. Wright, Jr
242
Cz I Podstawy
Po raz pierwszy ze shaderami spotkalimy si w rozdziale 3., w ktrym opisane zostay podsta-
wowe techniki renderowania. Osoby, ktre ten rozdzia pominy, aby od razu przej do pisania
shaderw, powinny w razie potrzeby do niego wrci i dokadnie zapozna si z atrybutami
i danymi typu uniform oraz sposobami ich przekazywania do shadera z kodu klienckiego.
W tamtym rozdziale w krgu naszych zainteresowa bya wycznie strona kliencka. Uylimy te
niektrych standardowych shaderw oraz kilku typowych funkcji i procedur renderujcych. Na
pocztku tego rozdziau mona bdzie pogbi sw wiedz na temat pracy po stronie klienckiej,
a nastpnie pokaemy, jak pisa wasne shadery, czyli serwerow cz procesu renderowania.
W tym celu naley zapozna si z jzykiem do pisania programw do cieniowania, czyli shaderw.
GLSL 101
OpenGL Shading Language (GLSL) to wysokopoziomowy jzyk programowania podobny do
jzyka C. Napisane w nim programy podlegaj kompilacji i konsolidacji przez implementacj
OpenGL i najczciej w caoci dziaaj na sprzcie graficznym. Kod shaderw wyglda podob-
nie do programw w jzyku C. Ich wykonywanie zaczyna si od funkcji main oraz mona w nich
pisa funkcje pobierajce argumenty i zwracajce wartoci. Poniszy rysunek 6.1 to kopia
rysunku 3.1 z rozdziau 3., przedstawiajca podstawowe cechy architektury shadera.
Jak wynika z powyszego schematu, zawsze potrzebne bd nam przynajmniej dwa shadery
wierzchokw i fragmentw. Trzeci rodzaj shadera, ktry rwnie moe by potrzebny, to tzw.
shader geometrii, ale jego szczegowy opis odoymy do rozdziau 11. Programy cieniujce
techniki zaawansowane. Dane do shadera wierzchokw mona przesya na trzy sposoby
jako atrybuty, czyli elementy danych dotyczce poszczeglnych wierzchokw; dane rodzaju
uniform, ktre s takie same dla caej porcji danych wierzchokowych; oraz jako tekstury, o kt-
rych szerzej pisalimy w rozdziale 5. Dane uniform i teksturowe mona take przesya do sha-
dera fragmentw. Nie ma natomiast sensu wysya do tego shadera atrybutw wierzchokw,
poniewa suy on tylko do wypeniania fragmentw (pikseli) po rasteryzacji danego obiektu
podstawowego. Dane wierzchokowe mog natomiast by przesyane do shadera fragmentw
przez program wierzchokowy. Wwczas jednak dane takie mog by stae (kady fragment
dysponuje tak sam wartoci) lub wartoci mog by interpolowane na rne sposoby na
powierzchni obiektu.
Kod shaderw jest bardzo podobny do kodu programw w jzyku C. Wykonywanie zaczyna si
od funkcji main, obowizuj takie same konwencje stosowania komentarzy i taki sam zestaw
znakw oraz uywa si wielu takich samych dyrektyw preprocesora. Pen specyfikacj jzyka
mona znale w dokumencie OpenGL Shading Language Specification. Wskazwki, jak znale
t specyfikacj, zamieszczono w dodatku A. S tam wymienione przydatne adresy internetowe
oraz inne wartociowe rda i kursy uzupeniajce. Przyjmujemy zaoenie, e znasz ju jzyki
C i C++, i dlatego bdziemy opisywa jzyk GLSL z perspektywy programisty tych jzykw.
243
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Rysunek 6.1.
Schemat architektury
shadera
Zmienne i typy danych
Nauk jzyka GLSL dobrze jest rozpocz od zapoznania si z dostpnymi w nim typami
danych. S cztery typy: liczby cakowite (ze znakiem i bez znaku), liczby zmiennoprzecinkowe (od
OpenGL 3.3 tylko pojedynczej precyzji) oraz wartoci logiczne (bool). W GLSL nie ma wska-
nikw ani typw acuchowych i znakowych. Funkcje mog zwraca wartoci dowolnego
z dostpnych typw lub nie zwraca nic, jeli zostan zadeklarowane jako void, ale niedozwo-
lone jest stosowanie wskanikw void. Sposb uycia typw danych GLSL jest podobny do spo-
sobu ich uycia w jzykach C i C++.
bool bDone = false; // Warto logiczna: true lub false
int iValue = 42; // Liczba cakowita ze znakiem
uint uiValue = 3929u; // Liczba cakowita bez znaku
float fValue = 42.0f; // Warto zmiennoprzecinkowa
244
Cz I Podstawy
Typy wektorowe
Jedn z najbardziej interesujcych rzeczy dostpnych w GLSL, a ktrej nie ma w C i C++, s
wektorowe typy danych. Wartoci kadego z czterech podstawowych typw danych mona prze-
chowywa w dwu-, trzy- lub czterowymiarowych wektorach. Pen list wektorowych typw
danych przedstawia tabela 6.1.
Tabela 6.1. Wektorowe typy danych jzyka GLSL
Typ Opis
vec2, vec3, vec4 Dwu-, trzy- i czteroskadnikowy wektor wartoci zmiennoprzecinkowych
ivec2, ivec3, ivec4 Dwu-, trzy- i czteroskadnikowy wektor wartoci cakowitoliczbowych
uvec2, uvec3, uvec4 Dwu-, trzy- i czteroskadnikowy wektor wartoci cakowitoliczbowych bez znaku
bvec2, bvec3, bvec4 Dwu-, trzy- i czteroskadnikowy wektor wartoci logicznych
Zmienne typu wektorowego deklaruje si tak samo, jak wszystkie inne rodzaje zmiennych.
Ponisza instrukcja deklaruje pooenie wierzchoka w postaci czteroskadnikowego wektora war-
toci zmiennoprzecinkowych:
vec4 vVertexPos;
Wektor mona take zainicjalizowa przy uyciu konstruktora:
vec4 vVertexPos = vec4(39.0f, 10.0f, 0.0f, 1.0f);
Nie naley jednak tego sposobu inicjalizacji myli z konstruktorem klasy w jzyku C++. Wekto-
rowe typy danych w jzyku GLSL nie s klasami, lecz typami wbudowanymi. Wektory mona
przypisywa jeden do drugiego, dodawa, skalowa przez wartoci skalarne (nie wektorowe) itd.
vVertexPos = vOldPos + vOffset;
vVertexPos = vNewPos;
vVertexPos += vec4(1.0f, 1.0f, 0.0f, 0.0f);
vVertexPos *= 5.0f;
Kolejn niezwyk cech jzyka GLSL jest sposb odwoywania si do poszczeglnych elemen-
tw wektora. Jeli wiesz, co to takiego konstrukcja union w jzyku C++, wektory moesz sobie
wyobrazi jako unie na steroidach. W celu odwoania si do elementw wektora mona uy
kropki albo dowolnego z trzech zestaww identyfikatorw: xyzw, rgba oraz stpq. Podczas pracy
z typami wektorowymi najczciej uywamy identyfikatorw xyzw.
vVertexPos.x = 3.0f;
vVertexPos.xy = vec2(3.0f, 5.0f);
vVertexPos.xyz = vNewPos.xyz;
Podczas pracy z kolorami korzystamy z identyfikatorw rgba.
vOutputColor.r = 1.0f;
vOutputColor.rgba = vec4(1.0f, 1.0f, 0.5f, 1.0f);
245
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Identyfikatorw stpq uywany w pracy ze wsprzdnymi tekstur.
vTexCoord.st = vec2(1.0f, 0.0f);
Dla jzyka GLSL nie ma znaczenia, ktrego zestawu identyfikatorw uyjemy, tzn. nie ma ad-
nego bdu w poniszej instrukcji:
vTexCoord.st = vVertex.st;
Nie mona natomiast miesza rnych zestaww w jednej operacji dostpu do wektora:
vTexCoord.st = vVertex.xt; // Nie mona uy jednoczenie x i t!
Wektorowe typy danych obsuguj rwnie technik transformacji o nazwie swizzling. Polega
ona na zamianie miejscami dwch lub wikszej liczby elementw wektora. Moe si to np. przy-
da do zamiany danych kolorw w formacie RGB na BGR:
vNewColor.bgra = vOldColor.rgba;
Wektorowe typy danych s typami rodzimymi nie tylko jzyka GLSL, lecz rwnie sprztu. S
szybkie, a operacje wykonywane s na wszystkich czterech skadnikach naraz. Na przykad poni-
sza operacja:
vVertex.x = vOtherVertex.x + 5.0f;
vVertex.y = vOtherVertex.y + 4.0f;
vVertex.z = vOtherVertex.z + 1.0f;
zostaaby wykonana znacznie szybciej, gdyby uyto rodzimej notacji wektorowej:
vVertex.xyz = vOtherVertex.xyz + vec3(5.0f, 4.0f, 1.0f);
Typy macierzowe
Oprcz typw wektorowych, jzyk GLSL obsuguje kilka typw macierzowych. Jednak w przeci-
wiestwie do tych pierwszych, typy macierzowe obsuguj tylko wartoci zmiennoprzecinkowe. Nie
mona tworzy macierzy wartoci typu cakowitoliczbowego ani logicznych, poniewa nie maj
one praktycznego zastosowania. W tabeli 6.2 znajduje si lista dostpnych typw macierzowych.
Macierz w jzyku GLSL to w istocie tablica wektorw kolumnowych (moe warto sobie w tym
momencie powtrzy wiadomoci o porzdku kolumnowym macierzy z rozdziau 4. Podstawy
przeksztace geometrycznych. Najwaniejsze informacje o wektorach i macierzach). Aby na
przykad ustawi ostatni kolumn macierzy 44, mona zastosowa nastpujcy kod:
mModelView[3] = vec4(0.0f, 0.0f, 0.0f, 1.0f);
Aby pobra ostatni kolumn macierzy:
vec4 vTranslation = mModelView[3];
Jeszcze precyzyjniejsze zapytanie:
vec3 vTranslation = mModelView[3].xyz;
246
Cz I Podstawy
Tabela 6.2. Typy macierzowe jzyka GLSL
Typ Opis
mat2, mat2x2 Dwie kolumny i dwa wiersze
mat3, mat3x3 Trzy kolumny i trzy wiersze
mat4, mat4x4 Cztery kolumny i cztery wiersze
mat2x3 Dwie kolumny i trzy wiersze
mat2x4 Dwie kolumny i cztery wiersze
mat3x2 Trzy kolumny i dwa wiersze
mat3x4 Trzy kolumny i cztery wiersze
mat4x2 Cztery kolumny i dwa wiersze
mat4x3 Cztery kolumny i trzy wiersze
Macierze mona take mnoy przez wektory. Dziaanie takie czsto wykonuje si w celu prze-
ksztacenia wierzchoka przez macierz rzutowania model-widok:
vec4 vVertex;
mat4 mvpMatrix;

vOutPos = mvpMatrix * vVertex;


Typy macierzowe, podobnie jak wektory, maj rwnie swoje konstruktory. Aby na przykad
wpisa bezporednio do kodu macierz 44, mona napisa ponisz instrukcj:
mat4 vTransform = mat4(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
Jako macierz przeksztacenia zastosowalimy macierz jednostkow. Mona take uy szybszego
konstruktora macierzy wypeniajcego tylko przektn jedn wartoci.
mat4 vTransform = mat4(1.0f);
Kwalifikatory zmiennych
Deklaracje zmiennych shadera mona rozszerzy o pewne kwalifikatory suce do okrelania
ich jako zmiennych wejciowych (in i uniform), wyjciowych (out) lub staych (const). Zmienne
wejciowe odbieraj dane od klienta OpenGL (atrybuty przesyane poprzez C lub C++) lub
z poprzedniego etapu pracy shadera (np. zmienne przekazywane przez shadera wierzchokw
do shadera fragmentw). Zmienne wyjciowe su do zapisywania na dowolnym etapie pracy
247
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
wartoci, ktre chcemy udostpni w nastpnych etapach, np. w celu przekazania danych z sha-
dera wierzchokw do shadera fragmentw albo zapisania ostatecznej wartoci koloru przez shader
fragmentw. W tabeli 6.3 zostay zebrane gwne kwalifikatory zmiennych.
Tabela 6.3. Kwalifikatory zmiennych
Kwalifikator Opis
<brak> Zwyka zmienna lokalna niedostpna i niewidoczna na zewntrz
const Staa czasu kompilacji lub parametr tylko do odczytu funkcji
in Zmienna przekazana z poprzedniego etapu
in centroid Zmienna przekazana z poprzedniego stanu, stosuje interpolacj rodkow
out Zmienna przekazywana do nastpnego etapu przetwarzania lub przechowujca warto zwrotn funkcji
out centroid Zmienna przekazywana do nastpnego etapu przetwarzania, stosuje interpolacj rodkow
inout Zmienna do odczytu i zapisu. Dozwolona tylko jako parametr funkcji lokalnej
uniform Warto przekazywana od klienta, taka sama dla wszystkich wierzchokw
Kwalifikatora inout mona uywa tylko do deklarowania parametrw funkcji. Poniewa jzyk
GLSL nie obsuguje wskanikw (czyli referencji), kwalifikator ten stanowi jedyny sposb na
przekazanie wartoci do funkcji i umoliwienie jej zmodyfikowania i zwrcenia wartoci
zmiennej. Na przykad funkcja zadeklarowana poniej:
int CalculateSometing(float fTime, float fStepSize, inout float fVariance);
zwrciaby warto cakowitoliczbow (np. znacznik powodzenia lub niepowodzenia) i dodat-
kowo mogaby zmodyfikowa warto zmiennej fVariance, a kod wywoujcy mgby odczyta
rwnie t jej now warto. Aby umoliwi modyfikowanie parametru w jzykach C i C++,
mona by byo zadeklarowa t funkcj przy uyciu wskanika:
int CalculateSomething(float fTime, float fStepSize, float* fVariance);
Kwalifikator centroid dziaa wycznie w przypadku renderowania buforw wieloprbkowa-
nych. W buforze o pojedynczym prbkowaniu interpolacj wykonuje si zawsze od rodka pik-
sela. W przypadku wieloprbkowania, gdy zostanie uyty kwalifikator centroid, warto inter-
polowana wypada w obrbie zarwno obiektu podstawowego, jak i piksela. Wicej na temat
wieloprbkowania piszemy w rozdziale 9. Buforowanie techniki zaawansowane.
Domylnie parametry s interpolowane midzy etapami shaderw w sposb odpowiedni dla
perspektywy. Mona zastosowa interpolacj nieperspektywiczn za pomoc sowa kluczowego
noperspective, a nawet cakiem j wyczy za pomoc sowa flat. Mona take uy sowa
kluczowego smooth, aby bezporednio zaznaczy, e zmienna jest pynnie interpolowana
w sposb perspektywiczny, ale to jest i tak dziaanie domylne. Poniej znajduje si kilka przy-
kadowych deklaracji:
248
Cz I Podstawy
smooth out vec3 vSmoothValue;
flat out vec3 vFlatColor;
noperspective float vLinearlySmoothed;
Prawdziwy shader
Nadszed czas, aby w kocu przyjrze si prawdziwej parze shaderw, ktre robi co uytecz-
nego. W klasie GLShaderManager znajduje si standardowy shader nazywany shaderem jednost-
kowym. Nie stosuje on adnych przeksztace geometrii i rysuje obiekty podstawowe wype-
nione tylko jednym kolorem. To wydaje si nieco zbyt mao. Rozbudujemy go zatem troch, aby
zobaczy, jak si cieniuje obiekty podstawowe, takie jak np. trjkt, stosujc inn warto koloru
dla kadego wierzchoka. Na listingu 6.1 przedstawiony jest kod shadera wierzchokw, a na
listingu 6.2 shadera fragmentw.
Listing 6.1. Shader wierzchokw ShadedIdentity
// Shader ShadedIdentity
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
in vec4 vVertex; // Atrybut pooenia wierzchoka
in vec4 vColor; // Atrybut koloru wierzchoka
out vec4 vVaryingColor; // Warto koloru przekazywana do shadera fragmentw
void main(void)
{
vVaryingColor = vColor; // Kopiowanie wartoci koloru
gl_Position = vVertex; // Przekazanie dalej pooenia wierzchoka
}
Listing 6.2. Shader fragmentw ShadedIdentity
// Shader ShadedIdentity
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
out vec4 vFragColor; // Kolor fragmentu do rasteryzacji
in vec4 vVaryingColor; // Kolor przychodzcy od shadera wierzchokw
void main(void)
{
vFragColor = vVaryingColor; // Kolor interpolowany na fragment
}
249
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Wersje jzyka GLSL
Pierwszy wiersz niebdcy komentarzem w kadym shaderze to okrelenie wersji jzyka:
#version 330
To oznacza, e niniejszy shader wymaga przynajmniej wersji 3.3 jzyka GLSL. Jeli sterownik
OpenGL jej nie obsuguje, shadera nie uda si skompilowa. W OpenGL 3.2 wprowadzono jzyk
GLSL 1.5, w OpenGL 3.1 GLSL 1.4, a w OpenGL 3.0 GLSL 1.3. Trudno si poapa? Nie
tylko Tobie. Dlatego rada ARB zdecydowaa, e od OpenGL 3.3 numer wersji jzyka GLSL bdzie
odpowiada wersji biblioteki. Wersja 4.0 biblioteki OpenGL zostaa opublikowana w tym samym
czasie, co wersja 3.3, i odpowiadajcy jej jzyk GLSL ma rwnie numer 4.0. Konstrukcja wyma-
gajca wersji 4.0 GLSL wygldaaby nastpujco:
#version 400
Jeli zajrzysz do kodu shaderw standardowych w bibliotece GLTools, nie znajdziesz w nich
takiej informacji o wersji jzyka. Biblioteka ta jest przeznaczona do pracy z profilem zgodno-
ciowym i zastosowano w niej starsze konwencje z GLSL 1.1. W istocie biblioteka ta wsppracuje
ze sterownikami OpenGL nawet w wersji 2.1. Pamitajmy, e stanowi ona tylko pomoc w roz-
poczciu korzystania z biblioteki OpenGL.
Deklaracje atrybutw
Atrybuty s okrelane dla poszczeglnych wierzchokw przez kliencki kod C/C++. W naszym
shaderze wierzchokw zostay one zadeklarowane przy uyciu specyfikatora in.
in vec4 vVertex;
in vec4 vColor;
Dwie powysze instrukcje deklaruj dwa atrybuty wejciowe, czteroskadnikowe pooenie wierz-
choka oraz czteroskadnikow warto koloru wierzchoka. Shader ten jest wykorzystywany przez
program ShadedTriangle. Przy uyciu klasy GLBatch utworzylimy trzy pooenia wierzcho-
kw i trzy wartoci kolorw. Jak klasa GLBatch przekazuje te wartoci do shadera, dowiesz si
w podrozdziale Kompilowanie, wizanie i konsolidowanie. Przypomnijmy z rozdziau 3., e
w jzyku GLSL mona mie maksymalnie 16 atrybutw w programie wierzchokowym. Ponadto
kady atrybut jest zawsze czteroskadnikowym wektorem, nawet jeli nie wszystkich skadnikw
uywamy. Gdybymy na przykad wewntrznie wyznaczyli jako atrybut tylko jedn warto typu
float, i tak zajaby ona przestrze czterech wartoci zmiennoprzecinkowych.
Dodatkow rzecz do zapamitania jest fakt, e zmienne oznaczone jako in s przeznaczone
tylko do odczytu. Moe si wydawa sprytnym rozwizaniem ponowne uycie nazwy zmiennej
w jakich porednich obliczeniach w shaderze, ale kompilator GLSL w sterowniku zgosiby
w takiej sytuacji bd.
250
Cz I Podstawy
Deklarowanie danych wyjciowych
Dalej zadeklarowalimy jedn zmienn wyjciow, bdc rwnie czteroskadnikowym wek-
torem liczb zmiennoprzecinkowych.
out vec4 vVaryingColor;
Zmienna ta bdzie okrela warto koloru wierzchoka, ktry ma zosta przekazany do shadera
fragmentw. W shaderze fragmentw musi ona zosta zadeklarowana jako in, aby nie zosta
zwrcony bd konsolidatora podczas kompilacji i konsolidacji shaderw.
Gdy w shaderze wierzchokw zmienna zostanie zadeklarowana jako out, a w shaderze fragmen-
tw jako in, shader fragmentw odbierze j jako warto interpolowan. Domylnie interpolacja
ta jest wykonywana zgodnie z perspektyw. Aby mie pewno, e tak si stanie, mona przed
zmienn wstawi dodatkowy specyfikator smooth. Mona take zastosowa specyfikator flat,
aby wyczy interpolacj, lub noperspective, aby zastosowa prost interpolacj liniow
midzy wartociami. Podczas uywania sowa kluczowego flat trzeba wzi pod uwag pewne
dodatkowe fakty, o ktrych szerzej piszemy w podrozdziale Wierzchoek prowokujcy.
Przetwarzanie wierzchokw
Dochodzimy do gwnej czci naszego shadera wierzchokw, ktra jest wykonywana jeden raz
dla kadego wierzchoka w porcji danych.
void main(void)
{
vVaryingColor = vColor;
gl_Position = vVertex;
}
Ten kod jest bardzo prosty. Przypisalimy przychodzcy atrybut koloru do wychodzcej wartoci
interpolowanej i przypisalimy przychodzc warto wierzchoka bezporednio do zmiennej
gl_Position bez transformacji. Zmienna gl_Position to wbudowany czteroskadnikowy
wektor zawierajcy wymagany wynik shadera wierzchokw. Wartoci z tej zmiennej s wyko-
rzystywane na etapie skadania geometrii do tworzenia obiektu podstawowego. Pamitajmy, e
poniewa nie wykonujemy adnych dodatkowych przeksztace, nasz wierzchoek zostanie
odwzorowany na kartezjaski ukad wsprzdnych o zakresie wartoci od 1,0 do 1,0 na wszyst-
kich trzech osiach.
Przetwarzanie fragmentw
Teraz przechodzimy do shadera fragmentw. W przypadku renderowania obiektu podstawo-
wego, takiego jak trjkt, najpierw wierzchoki s przetwarzane przez shader wierzchokw, pniej
s one skadane w trjkt, a nastpnie rasteryzowane przez sprzt. Urzdzenie okrela pooenie
poszczeglnych fragmentw na ekranie (a mwic dokadniej w buforze kolorw), a nastpnie
dla kadego z nich (jeli nie jest stosowane wieloprbkowanie, fragment odpowiada pikselowi)
wywouje egzemplarz shadera fragmentw. Kolor zwracany przez naszego shadera fragmentw
to czteroskadnikowy wektor liczb zmiennoprzecinkowych, ktry deklarujemy nastpujco:
251
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
out vec4 vFragColor;
Jeli shader fragmentw zwraca tylko jedn warto, jest ona wewntrznie okrelana jako war-
to wyjciowa zero. Jest to pierwszy wynik shadera fragmentw, ktry nastpnie zostaje wysany
do bufora ustawionego przez funkcj glDrawBuffers. Domylnym buforem jest GL_BACK,
czyli tylny bufor koloru (oczywicie w kontekstach z podwjnym buforowaniem). Czsto zdarza
si tak, e bufor koloru nie zawiera czterech skadnikw zmiennoprzecinkowych i wwczas warto-
ci wyjciowe s rzutowane na zakres bufora docelowego. W wikszoci przypadkw mog to
by np. cztery bajty bez znaku (o wartociach od 0 do 255). Moglibymy take zwrci wartoci
cakowitoliczbowe przy uyciu typu wektorowego ivec4 i rwnie one zostayby odwzorowane
na zakres bufora kolorw. Moliwe jest take zwrcenie czego wicej ni tylko warto koloru,
jak rwnie zapisywanie danych w kilku buforach jednoczenie. Te techniki jednak wykraczaj
daleko poza zakres tego wstpnego rozdziau.
Do shadera fragmentw zostaje przesana pynnie interpolowana warto koloru pochodzca
z shadera wierzchokw. Deklaruje si j jako zmienn z kwalifikatorem in:
in vec4 vVaryingColor;
Gwna cz shadera fragmentw jest jeszcze prostsza ni shadera wierzchokw. Przypisujemy
w niej otrzyman warto koloru bezporednio do koloru fragmentu.
void main(void)
{
vFragColor = vVaryingColor;
}
Efekt dziaania tego shadera przedstawia rysunek 6.2.
Rysunek 6.2.
Wynik dziaania
programu
ShadedTriangle
252
Cz I Podstawy
Kompilowanie, wizanie i konsolidowanie
Opisalimy zasad dziaania prostego shadera, wic teraz powiniene dowiedzie si, jak jest on
kompilowany i konsolidowany w celu przygotowania do uytku w OpenGL. Kod rdowy sha-
dera jest przekazywany sterownikowi, kompilowany, a nastpnie konsolidowany, tak jak kady
typowy program w jzykach C i C++. Dodatkowo konieczne jest powizanie nazw atrybutw
z shadera z jednym z 16 gniazd atrybutw alokowanych i udostpnianych przez GLSL. Po drodze
sprawdzamy bdy i nawet otrzymujemy informacje diagnostyczne od sterownika, jeli prba
skompilowania projektu si nie powiedzie.
API OpenGL nie obsuguje adnych operacji wejcia i wyjcia na plikach. Programista musi sam
zdoby kod rdowy swoich shaderw w najbardziej odpowiadajcy mu sposb. Jedn z naj-
prostszych metod jest zapisanie tego kodu w plikach tekstowych ASCII. Wwczas kod rdowy
mona z takich plikw pobra za pomoc typowych funkcji systemu plikw. Podejcie to zasto-
sowalimy w naszym przykadzie. Zastosowalimy rwnie konwencj, wedug ktrej plikom
shaderw wierzchokw nadaje si rozszerzenie .vp, a plikom shaderw fragmentw .fp.
Innym rozwizaniem jest zapisanie tekstw w postaci tablic znakw wbudowanych w kod
C lub C++. Jednak tak zapisany kod trudno si modyfikuje i mimo i cay kod znajduje si
w jednym miejscu, zmienianie shaderw i eksperymentowanie z kodem rdowym jest utrud-
nione. Oczywicie kod shaderw mona take generowa za pomoc specjalnych algorytmw,
a nawet pobiera go z bazy danych albo pliku zaszyfrowanego. Te metody mog by bardzo
przydatne, gdy bdziemy chcieli przesya gdzie nasze aplikacje, ale w zastosowaniach eduka-
cyjnych nic nie przebije zwykych plikw tekstowych.
Funkcja gltLoadShaderPairWithAttributes to prawdziwy kombajn do wczytywania i ini-
cjalizowania shaderw. Jej kod przedstawia listing 6.3. Na podstawie jego analizy przestudiujemy
proces wczytywania shadera.
Listing 6.3. Funkcja gltLoadShaderPairWithAttributes
/////////////////////////////////////////////////////////////////
// Wczytuje par shaderw oraz je kompiluje i czy.
// Podaj kod rdowy kadego shadera. Nastpnie
// podaj nazwy tych shaderw, okrel liczb atrybutw
// oraz podaj indeks i nazw kadego atrybutu.
GLuint gltLoadShaderPairWithAttributes(const char *szVertexProg,
const char *szFragmentProg, ...)
{
// Tymczasowe obiekty shadera
GLuint hVertexShader;
GLuint hFragmentShader;
GLuint hReturn = 0;
GLint testVal;
// Tworzenie obiektw shadera
hVertexShader = glCreateShader(GL_VERTEX_SHADER);
hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
253
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
// adowanie obiektw. W razie niepowodzenia naley wszystko usun i zwrci warto NULL
// Shader wierzchokw
if(gltLoadShaderFile(szVertexProg, hVertexShader) == false)
{
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
cout << "Shader " << szVertexProg
<< " nie zosta znaleziony.\n";
return (GLuint)NULL;
}
// Shader fragmentw
if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false)
{
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
cout << "Shader " << szFragmentProg
<< " nie zosta znaleziony.\n";
return (GLuint)NULL;
}
// Kompilacja shaderw
glCompileShader(hVertexShader);
glCompileShader(hFragmentShader);
// Sprawdzanie bdw w shaderze wierzchokw
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetShaderInfoLog(hVertexShader, 1024, NULL, infoLog);
cout << "Kompilacja shadera " << szVertexProg
<< " nie powioda si. Bd:\n"
<< infoLog << "\n";
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
return (GLuint)NULL;
}
// Sprawdzanie bdw w shaderze fragmentw
glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetShaderInfoLog(hFragmentShader, 1024, NULL, infoLog);
cout << "Kompilacja shadera " << hFragmentShader
<< " nie powioda si. Bd:\n"
<< infoLog << "\n";
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
return (GLuint)NULL;
}
// Tworzenie finalnego obiektu programu i doczenie shaderw
hReturn = glCreateProgram();
254
Cz I Podstawy
glAttachShader(hReturn, hVertexShader);
glAttachShader(hReturn, hFragmentShader);
// Teraz musimy powiza nazwy atrybutw z odpowiadajcymi im lokalizacjami
// Lista atrybutw
va_list attributeList;
va_start(attributeList, szFragmentProg);
// Iteracja przez list argumentw
char *szNextArg;
int iArgCount = va_arg(attributeList, int); // Liczba atrybutw
for(int i = 0; i < iArgCount; i++)
{
int index = va_arg(attributeList, int);
szNextArg = va_arg(attributeList, char*);
glBindAttribLocation(hReturn, index, szNextArg);
}
va_end(attributeList);
// Prba konsolidacji
glLinkProgram(hReturn);
// Te ju nie s potrzebne
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
// Sprawdzenie, czy konsolidacja si udaa
glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetProgramInfoLog(hReturn, 1024, NULL, infoLog);
cout << "Konsolidacja programu " << hReturn
<< " nie powioda si. Bd:\n"
<< infoLog << "\n";
glDeleteProgram(hReturn);
return (GLuint)NULL;
}
// Wszystko zrobione. Zwrcenie shadera gotowego do uytku
return hReturn;
}
Okrelanie atrybutw
W prototypie funkcji wida, e pobiera ona nazw pliku shadera wierzchokw i shadera frag-
mentw oraz mogc si zmienia liczb parametrw okrelajcych atrybuty.
GLuint gltLoadShaderPairWithAttributes(const char *szVertexProg,
const char *szFragmentProg, ...);
Dla osb, ktre nigdy nie widziay deklaracji funkcji przyjmujcej zmienn liczb parametrw,
znajdujce si na kocu listy argumentw trzy kropki mog wyglda jak pomyka w druku.
255
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Inne funkcje jzyka C pobierajce zmienn liczb argumentw to np. printf i sprintf. W tej
funkcji pierwszy dodatkowy parametr okrela liczb atrybutw znajdujcych si w shaderze
wierzchokw. Po nim znajduje si warto indeksu (liczona od zera) pierwszego atrybutu,
a nastpnie nazwa atrybutu w postaci tablicy znakw. Numer gniazda atrybutu i nazwa atrybutu
s powtarzane tyle razy, ile potrzeba. Aby na przykad wczyta shader majcy atrybuty pooenia
wierzchoka i normalnej do powierzchni, wywoanie funkcji gltLoadShaderPairWithAttributes
mogoby wyglda nastpujco:
hShader = gltLoadShaderPairWithAttributes("vertexProg.vp",
"fragmentProg.fp", 2, 0, "vVertexPos", 1, "vNormal");
Wartoci 0 i 1 jako lokalizacje atrybutw zostay wybrane arbitralnie. Naley tylko pamita, aby
zawieray si one w przedziale od 0 do 15. Rwnie dobrze moglibymy uy wartoci 7 i 13.
Natomiast w klasach biblioteki GLTools GLBatch i GLTriangleBatch stosowany jest spjny
zestaw lokalizacji atrybutw okrelanych za pomoc nastpujcej instrukcji typedef:
typedef enum GLT_SHADER_ATTRIBUTE { GLT_ATTRIBUTE_VERTEX = 0,
GLT_ATTRIBUTE_COLOR, GLT_ATTRIBUTE_NORMAL,
GLT_ATTRIBUTE_TEXTURE0, GLT_ATTRIBUTE_TEXTURE1,
GLT_ATTRIBUTE_TEXTURE2, GLT_ATTRIBUTE_TEXTURE3,
GLT_ATTRIBUTE_LAST};
Uywajc tych identyfikatorw lokalizacji atrybutw, mona zacz uywa wasnych shaderw
obok shaderw standardowych dostarczanych w klasie GLShaderManager. To rwnie oznacza,
e nadal moemy przesya geometri przy uyciu klas GLBatch i GLTriangleBatch, a do roz-
dziau 12. Zarzdzanie geometri techniki zaawansowane, w ktrym bardziej szczegowo
zajmiemy si technikami przesyania atrybutw wierzchokw.
Pobieranie kodu rdowego
Najpierw trzeba utworzy dwa obiekty shaderw po jednym dla shadera wierzchokw i sha-
dera fragmentw.
hVertexShader = glCreateShader(GL_VERTEX_SHADER);
hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
Przy uyciu identyfikatorw shaderw moemy wczyta ich kod rdowy. Pominiemy szczegy
funkcji gltLoadShaderFile, poniewa jej gwnym zadaniem jest wczytanie tekstu shadera
z pliku tekstowego o podanej nazwie, zapisanego na dysku. Gdy ju to zostanie zrobione, poniszy
kod przesya kod rdowy shadera do obiektu shadera. Pamitaj, e musimy to zrobi dwa razy
raz dla shadera wierzchokw i raz dla shadera fragmentw.
GLchar *fsStringPtr[1];
fsStringPtr[0] = (GLchar *)szShaderSrc;
glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL);
Zmienna szShaderSrc to wskanik znakowy wskazujcy cay tekst shadera. Natomiast shader
to identyfikator obiektu shadera, ktry jest wczytywany.
256
Cz I Podstawy
Kompilowanie shaderw
Kompilacja shaderw to prosta operacja polegajca na wywoaniu jednej funkcji dla kadego z nich.
glCompileShader(hVertexShader);
glCompileShader(hFragmentShader);
W kadej implementacji OpenGL znajduje si wbudowany kompilator jzyka GLSL dostarczony
przez producenta sprztu. Uznano bowiem, e kady producent wie najlepiej, jak powinien dziaa
kompilator dla jego sprztu. Oczywicie, podobnie jak w przypadku kadego programu w jzy-
kach C i C++, kompilacj shadera GLSL moe uniemoliwi wiele czynnikw, takich jak bdy
skadni czy bdy implementacji itp. Do sprawdzania, czy operacja si powioda, suy funkcja
glGetShader z argumentem GL_COMPILE_STATUS.
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal);
Jeli po powrocie funkcji testVal ma warto GL_FALSE, oznacza to, e kompilacja si nie
powioda. Gdybymy jednak mieli moliwo tylko dowiedzenia si, czy kompilacja zostaa
zakoczona powodzeniem, czy nie, pisanie shaderw byoby bardzo trudne. Dlatego w przypadku
nieudanej operacji moemy sprawdzi w dzienniku shadera, co takiego si stao wystarczy
wywietli jego zawarto za pomoc funkcji glGetShaderInfoLog. W funkcji, ktr anali-
zujemy, komunikat o bdzie jest wywietlany w oknie konsoli, po czym nastpuje usunicie
obiektw shaderw i zwrcenie wartoci NULL.
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetShaderInfoLog(hVertexShader, 1024, NULL, infoLog);
cout << "Kompilacja shadera " << szVertexProg
<< " nie powioda si. Bd:\n"
<< infoLog << "\n";
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
return (GLuint)NULL;
}
Doczanie i wizanie
Skompilowanie kodu shaderw to dopiero poowa sukcesu. Zanim przejdziemy do ich konsoli-
dacji, zdobdziemy si na ma dygresj. Najpierw musimy utworzy finalny obiekt shadera i do-
czy do niego shadery wierzchokw i fragmentw.
hReturn = glCreateProgram();
glAttachShader(hReturn, hVertexShader);
glAttachShader(hReturn, hFragmentShader);
Teraz shader jest gotowy do konsolidacji. Zanim to jednak zrobimy, musimy zrobi jedn
wan rzecz zwiza nazwy zmiennych atrybutw z okrelonymi numerami ich lokalizacji. Do
tego suy funkcja glBindAttribLocation. Oto jej prototyp:
void glBindAttribLocation(GLuint shaderProg, GLuint attribLocation,
const GLchar *szAttributeName);
257
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Funkcja ta pobiera identyfikator interesujcego nas shadera, lokalizacj atrybutu, ktra ma
zosta uyta w wizaniu, oraz nazw zmiennej atrybutu. Na przykad w shaderach standardowych
biblioteki GLTools przyjlimy konwencj, e dla zmiennej atrybutu pooenia wierzchoka
zawsze stosujemy nazw vVertex, a dla lokalizacji atrybutu warto GLT_ATTRIBUTE_VERTEX
(warto 0). Rwnie moesz zastosowa tak konwencj.
glBindAttribLocation(hShader, GLT_ATTRIBUTE_VERTEX, "vVertex");
Wizanie lokalizacji atrybutw musi zosta wykonane przed konsolidacj. W poniszym kodzie
przechodzimy iteracyjnie przez list argumentw i wywoujemy funkcj dla kadego atrybutu,
ktry chcemy zwiza.
// Iteracja przez list argumentw
char *szNextArg;
int iArgCount = va_arg(attributeList, int); // Liczba atrybutw
for(int i = 0; i < iArgCount; i++)
{
int index = va_arg(attributeList, int);
szNextArg = va_arg(attributeList, char*);
glBindAttribLocation(hReturn, index, szNextArg);
}
va_end(attributeList);
Konsolidacja shaderw
Nadszed w kocu czas na skonsolidowanie naszych shaderw, po czym bdziemy mogli usun
reprezentujce je obiekty.
glLinkProgram(hReturn);
// Te ju nie s potrzebne
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
Podobnie jak w przypadku kompilacji, w pomylnym zakoczeniu konsolidacji moe prze-
szkodzi wiele czynnikw. Stanie si tak na przykad wwczas, gdy w shaderze wierzchokw
zadeklarujemy zmienn out, a nie zadeklarujemy jej odpowiednika w shaderze fragmentw.
Nawet jeli o tym nie zapomnimy, musimy jeszcze pamita, e zmienne te musz by tego samego
typu. Dlatego przed powrotem sprawdzamy bdy i w razie ich wystpienia wywietlamy stosowny
komunikat diagnostyczny, podobnie jak przy kompilacji.
Teraz nasz shader jest w peni gotowy do uycia. Powinnimy jeszcze zaznaczy, e jeli utwo-
rzymy program cieniujcy i zakoczymy jego uywanie (np. przy zamykaniu programu), powin-
nimy go usun za pomoc poniszej funkcji.
void glDeleteProgram(GLuint program);
258
Cz I Podstawy
Praktyczne wykorzystanie shadera
Aby uy naszego shadera GLSL, ch zrobienia tego musimy zakomunikowa za pomoc funk-
cji glUseProgram:
glUseProgram(myShaderProgram);
W ten sposb aktywowalimy naszego shadera, dziki czemu wszystkie nasze obiekty geome-
tryczne bd przetwarzane przez nasze shadery wierzchokw i fragmentw. Dane uniform
i teksturowe naley utworzy przed przesaniem atrybutw wierzchokw. Jak to zrobi, wyja-
nimy ju za chwil. Natomiast przesyanie atrybutw wierzchokw to bardzo obszerny temat,
ktry zasuguje na osobne omwienie w rozdziale 12. Na razie pozwolimy zarzdza nasz
geometri klasom GLBatch i GLTriangleBatch.
W pierwszym przykadowym programie, jaki przedstawilimy w tym rozdziale, ShadedTriangle,
wczytalimy trjkt do egzemplarza klasy GLBatch o nazwie triangleBatch przy uyciu naj-
prostszego (nazwalimy go ukadem jednostkowym) ukadu wsprzdnych:
// Wczytywanie trjkta
GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f };
GLfloat vColors [] = { 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f };
triangleBatch.Begin(GL_TRIANGLES, 3);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.CopyColorData4f(vColors);
triangleBatch.End();
myIdentityShader = gltLoadShaderPairWithAttributes("ShadedIdentity.vp",
"ShadedIdentity.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex",
GLT_ATTRIBUTE_COLOR, "vColor");
Kademu wierzchokowi ustawilimy inny kolor, odpowiednio czerwony, zielony i niebieski. Na
zakoczenie zaadowalimy nasz par shaderw przy uyciu funkcji gltLoadShaderPairWith
Attributes, z ktr ju moge si zapozna. Zauwamy, e mamy dwa zbiory atrybutw
wartoci wierzchokw i kolorw odpowiadajce zbiorom danych przesyanym do klasy GLBatch.
Teraz, aby przesa porcj danych, wystarczy wybra shader i pozwoli klasie GLBatch przekaza
nasze atrybuty wierzchokw:
glUseProgram(myIdentityShader);
triangleBatch.Draw();
Wynik tych wszystkich naszych dziaa przedstawia rysunek 6.2.
259
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Wierzchoek prowokujcy
Program ShadedTriangle stanowi znakomity przykad pynnej interpolacji wierzchokw. Dla
kadego wierzchoka zosta zdefiniowany inny kolor, w wyniku czego powsta trjkt (widoczny
na rysunku 6.2), na ktrym przejcia midzy kolorami s pynne. wietnie, prawda? Moemy rw-
nie przekazywa zmienne z jednego etapu shadera do drugiego jako typ flat. Jeli chcemy,
aby jaka warto pozostaa niezmienna dla caej porcji danych, najlepiej zastosowa typ uniform,
o czym bya mowa w rozdziale 3. Czasami jednak chcemy, aby jaka warto bya niezmienna na
caej powierzchni danego obiektu podstawowego, np. trjkta, ale moga si zmienia midzy
rnymi trjktami. Przesyanie duej liczby trjktw, np. po jednym trjkcie na porcj danych,
tak jak w przypadku uycia zmiennych uniform, byoby bardzo nieefektywnym rozwizaniem.
W takich przypadkach najlepiej uy kwalifikatora flat. W shaderze ShadedTraiangle.vp pyn-
nie cieniowana wychodzca warto koloru jest zadeklarowana nastpujco:
out vec4 vVaryingColor;
Gdybymy jednak do jej deklaracji dodali kwalifikator flat (i nie zapomnieli wprowadzi
odpowiedniej poprawki w shaderze fragmentw), trjkt miaby kolor niebieski.
flat out vec4 vFlatColor;
W przypadku, gdy dla kadego wierzchoka obiektu zdefiniowana jest inna warto zapisana
w pasko cieniowanej zmiennej, tylko jedna z nich moe zosta zastosowana. Standardowo
w takich przypadkach stosowana jest warto ostatniego z wierzchokw, a wic w tym przypadku
trjkt bdzie mia kolor niebieski. Konwencja ta nosi nazw wierzchoka prowokujcego (ang.
provoking vertex). Ponisza funkcja pozwala zmieni ten sposb dziaania z ostatniego wierzchoka
na pierwszy:
void glProvokingVertex(GLenum provokeMode);
Funkcja provokeMode przyjmuje wartoci GL_FIRST_VERTEX_CONVENTION i GL_LAST_VERTEX_
CONVENTIONS (domylna).
Jak to dziaa, mona zobaczy w programie ProvokingVertex, ktry stanowi nieznacznie
zmodyfikowan wersj programu ShadedTriangle. Naciniciem spacji mona zmieni kon-
wencj, co z kolei spowoduje zmian koloru trjkta.
Dane uniform shadera
Podczas gdy atrybuty su do okrelania pooenia wierzchokw, normalnych do powierzchni,
wsprzdnych teksturowych itp., zmienne uniform su do przekazywania do shadera infor-
macji, ktre powinny by stae w caej porcji danych obiektu. Najczciej spotykanym rodzajem
danych tego typu dla shadera wierzchokw jest macierz przeksztacenia. Wczeniej wszystko
robia za nas klasa GLShaderManager wykorzystujca wbudowane standardowe shadery i ich dane
260
Cz I Podstawy
uniform. Teraz jednak piszemy wasne shadery, a wic musimy nauczy si samodzielnie two-
rzy dane uniform i to nie tylko do przechowywania macierzy. Jako uniform mona zdefi-
niowa dowoln zmienn w dowolnym z trzech etapw cieniowania (przypomnijmy, e w tym
rozdziale zajmujemy si tylko shaderami wierzchokw i fragmentw). Aby to zrobi, wystarczy
przed wybran zmienn postawi sowo kluczowe uniform:
uniform float fTime;
uniform int iIndex;
uniform vec4 vColorValue;
uniform mat4 mvpMatrix;
Zmiennych uniform nie mona deklarowa jako in ani out, nie mona ich interpolowa
midzy etapami cieniowania (chocia mona je kopiowa do interpolowanych zmiennych) i nie
mona zmienia ich wartoci.
Znajdowanie danych uniform
Po skompilowaniu i skonsolidowaniu shadera musimy w nim znale lokalizacj naszej zmien-
nej uniform. Suy do tego funkcja glGetUniformLocation.
GLint glGetUniformLocation(GLuint shaderID, const GLchar* varName);
Funkcja ta zwraca liczb cakowit ze znakiem, reprezentujc lokalizacj zmiennej okrelonej
parametrem varName w shaderze okrelonym parametrem shaderID. Na przykad ponisze
wywoanie zwraca lokalizacj zmiennej uniform o nazwie vColorValue:
GLint iLocation = glGetUniformLocation(myShader, "vColorValue");
Jeli funkcja zwrci warto 1, oznacza to, e nie udao si zlokalizowa w shaderze zmiennej
o podanej nazwie. Naley take pamita, e w nazwach zmiennych w shaderach rozpoznawana
jest wielko liter. Miejmy wiadomo, e pomylne zakoczenie kompilacji shadera wcale nie
oznacza, e zmienna uniform moe nam znikn, jeli nie bdzie do niczego bezporednio
wykorzystana. Nie musimy si martwi, e zmienne uniform zostan usunite w procesie
optymalizacji kodu, ale jeli zadeklarujemy tak zmienn i nie bdziemy jej uywa, kompilator
j nam usunie.
Zmienne uniform skalarne i wektorowe
Do ustawienia wartoci pojedynczego skalarnego lub wektorowego typu danych mona uy
jednej z kilku wersji funkcji glUniform:
void glUniform1f(GLint location, GLfloat v0);
void glUniform2f(GLint location, Glfloat v0, GLfloat v1);
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
GLfloat v3);
void glUniform1i(GLint location, GLint v0);
void glUniform2i(GLint location, GLint v0, GLint v1);
261
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2);
void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
Wyobramy sobie na przykad, e mamy w shaderze ponisze cztery deklaracje zmiennych:
uniform float fTime;
uniform int iIndex;
uniform vec4 vColorValue;
uniform bool bSomeFlag;
Kod w jzyku C lub C++ znajdujcy je i ustawiajcy ich wartoci mgby wyglda nastpujco:
GLint locTime, locIndex, locColor, locFlag;
locTime = glGetUniformLocation(myShader, "fTime");
locIndex = glGetUniformLocation(myShader, "iIndex");
locColor = glGetUniformLocation(myShader, "vColorValue")
locFlag = glGetUniformLocation(myShader, "bSomeFlag");

glUseProgram(myShader);
glUniform1f(locTime, 45.2f);
glUniform1i(locIndex, 42);
glUniform4f(locColor, 1.0f, 0.0f, 0.0f, 1.0f);
glUniform1i(locFlag, GL_FALSE);
Zwrmy uwag, e do przekazania wartoci logicznej uylimy cakowitoliczbowej wersji
funkcji glUniform. Wartoci logiczne mona rwnie przekazywa jako wartoci zmiennoprze-
cinkowe, gdzie 0.0 oznacza fasz, a 1.0 prawd.
Tablice uniform
Istniej rwnie wersje funkcji glUniform pobierajce jako parametr wskanik, ktry moe wska-
zywa tablic wartoci.
void glUniform1fv(GLint location, GLuint count, GLfloat* v);
void glUniform2fv(GLint location, GLuint count, Glfloat* v);
void glUniform3fv(GLint location, GLuint count, GLfloat* v);
void glUniform4fv(GLint location, GLuint count, GLfloat* v);
void glUniform1iv(GLint location, GLuint count, GLint* v);
void glUniform2iv(GLint location, GLuint count, GLint* v);
void glUniform3iv(GLint location, GLuint count, GLint* v);
void glUniform4iv(GLint location, GLuint count, GLint* v);
Parametr count okrela liczb elementw w tablicy zawierajcej x skadnikw, gdzie x oznacza
liczb na kocu nazwy funkcji. Jeli np. mamy zmienn uniform zawierajc cztery skadniki:
uniform vec4 vColor;
W C i C++ moglibymy j zdefiniowa jako tablic liczb zmiennoprzecinkowych:
GLfloat vColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
262
Cz I Podstawy
Poniewa jest to pojedyncza tablica czterech wartoci, do przekazania jej do shadera wykorzy-
stalibymy nastpujc konstrukcj:
glUniform4fv(iColorLocation, 1, vColor);
Gdybymy jednak mieli w shaderze tak tablic wartoci kolorw:
uniform vec4 vColors[2];
Wwczas w C++ dane te moglibymy zdefiniowa i przekaza nastpujco:
GLfloat vColors[2][4] = {{ 1.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f }};
...
glUniform4fv(iColorLocation, 2, vColors);
Najprostsze ustawienie jednej zmiennoprzecinkowej wartoci uniform moe wyglda tak:
GLfloat fValue = 45.2f;
glUniform1fv(iLocation, 1, &fValue);
Macierze uniform
Na zakoczenie pokaemy, jak si ustawia macierz uniform. W shaderach typy macierzowe
przechowuj tylko wartoci zmiennoprzecinkowe, przez co mamy znacznie mniej rnych wer-
sji. Ponisze funkcje aduj odpowiednio macierze 22, 33 oraz 44.
glUniformMatrix2fv(GLint location, GLuint count, GLboolean transpose,
const GLfloat *m);
glUniformMatrix3fv(GLint location, GLuint count, GLboolean transpose,
const GLfloat *m);
glUniformMatrix4fv(GLint location, GLuint count, GLboolean transpose,
const GLfloat *m);
Zmienna count okrela liczb macierzy we wskaniku m (tak, mona tworzy tablice macierzy!).
Znacznik logiczny transpose zostaje ustawiony na warto true, jeli macierz jest ustawiona
w porzdku kolumnowym (ustawienie to jest preferowane w OpenGL). Ustawienie tej wartoci
na GL_FALSE powoduje transpozycj macierzy podczas jej kopiowania do shadera. Moe to by
przydatne, gdybymy korzystali z biblioteki macierzowej stosujcej porzdek wierszowy macierzy
(np. Direct3D).
Paski shader
Zobaczmy przykadowy shader wykorzystujcy zmienne uniform. W zestawie shaderw stan-
dardowych mamy paski shader, ktry tylko przeksztaca geometri i ustawia jej jaki pojedynczy
kolor. Uywane s w nim atrybuty pooenia wierzchokw i dwie zmienne uniform macierz
przeksztacenia i warto koloru.
263
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Program FlatShader rysuje obracajcy si torus i ustawia jego kolor na niebieski. Renderujemy
go w trybie szkieletowym za pomoc funkcji glPolygonMode, aby byo wyranie wida, e jest
trjwymiarowy. Wikszo zastosowanego kodu klienckiego OpenGL jest ju nam dobrze
znana, dlatego nie zamieszczamy tu penego kodu programu. Na listingach 6.4 i 6.5 przedstawiony
jest peny kod obu shaderw.
Listing 6.4. Shader wierzchokw FlatShader
// Shader paski
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
// Macierz przeksztacenia
uniform mat4 mvpMatrix;
// Dane wejciowe wierzchokw
in vec4 vVertex;
void main(void)
{
// To wszystko, przeksztacamy geometri
gl_Position = mvpMatrix * vVertex;
}
Listing 6.5. Shader fragmentw FlatShader
// Shader paski
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 130
// Tworzenie jednolitej geometrii
uniform vec4 vColorValue;
// Wyjcie koloru fragmentu
out vec4 vFragColor;
void main(void)
{
vFragColor = vColorValue;
}
W shaderze wierzchokw na listingu 6.4 znajduje si jedna zmienna uniform reprezentujca
konkatenowan macierz przeksztacenia:
uniform mat4 mvpMatrix;
264
Cz I Podstawy
Jedyn czynnoci wykonywan przez ten shader jest przeksztacenie wierzchoka przy uyciu
macierzy rzutowania model-widok. Jak wida, mnoenie macierzowego typu danych przez wekto-
rowy w jzyku GLSL jest czym naturalnym.
gl_Position = mvpMatrix * vVertex;
W shaderze fragmentw na listingu 6.5 rwnie znajduje si tylko jedna zmienna uniform
bdca czteroskadnikow wartoci koloru, ktry zostanie zastosowany na rasteryzowanych
fragmentach.
uniform vec4 vColorValue;
Po stronie klienckiej program wczytuje oba pliki shaderw i w funkcji SetupRC tworzy wskaniki
do obu zmiennych uniform.
GLuint flatShader;
GLint locMP;
GLint locColor;

flatShader = gltLoadShaderPairWithAttributes("FlatShader.vp", "FlatShader.fp",


1, GLT_ATTRIBUTE_VERTEX, "vVertex");
locMVP = glGetUniformLocation(flatShader, "mvpMatrix");
locColor = glGetUniformLocation(flatShader, "vColorValue");
Na listingu 6.6 zamieszczony zosta w caoci kod funkcji RenderScene, ktra renderuje obra-
cajcy si torus (przypomnijmy, e tryb wielokta ustawilimy na GL_LINE). Po wybraniu
paskiego shadera nastpuje ustawienie zmiennych uniform koloru i macierzy przeksztacenia,
a nastpnie jest wywoywana funkcja Draw na obiekcie torusa. Efekt tego wida na rysunku 6.3.
Listing 6.6. Praktyczne zastosowanie utworzonego paskiego shadera
// Rysowanie sceny
void RenderScene(void)
{
static CStopWatch rotTimer;
// Wyczyszczenie okna i bufora gbi
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix(viewFrame);
modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f,
1.0f, 0.0f);
GLfloat vColor[] = { 0.1f, 0.1f, 1.f, 1.0f };
glUseProgram(flatShader);
glUniform4fv(locColor, 1, vColor);
glUniformMatrix4fv(locMVP, 1, GL_FALSE,
transformPipeline.GetModelViewProjectionMatrix());
torusBatch.Draw();
265
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Rysunek 6.3.
Okno programu
FlatShader
modelViewMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
Funkcje standardowe
Prawie kady jzyk programowania wysokiego poziomu ma zestaw standardowych funkcji.
W jzykach C i C++ mamy do dyspozycji standardow bibliotek wykonawcz C, standardowe
funkcje wejcia i wyjcia itd. W GLSL rwnie dostpny jest zestaw standardowych funkcji.
Wikszo z nich suy do wykonywania dziaa matematycznych na wartociach skalarnych
i caych wektorach. Niektre z nich maj bardzo oglne zastosowanie, jednak cz z nich wyko-
rzystuje si w pewnych typowych algorytmach renderowania grafiki. Funkcje zebrane w poni-
szych tabelach zostay prawie bez zmian skopiowane ze specyfikacji jzyka GLSL.
Funkcje trygonometryczne
W tabeli 6.4 znajduje si lista funkcji trygonometrycznych udostpnianych przez jzyk GLSL.
Obsuguj one typy danych float, vec2, vec3 oraz vec4. Zapis anyFloat w tabeli oznacza, e
dana funkcja obsuguje kady z wymienionych typw.
266
Cz I Podstawy
Tabela 6.4. Funkcje trygonometryczne
Funkcja Opis
anyFloat radians(anyFloat degrees) Konwertuje stopnie na radiany
anyFloat degrees(anyFloat radians) Konwertuje radiany na stopnie
anyFloat sin(anyFloat angle) Sinus
anyFloat cos(anyFloat angle) Cosinus
anyFloat tan(anyFloat angle) Tangens
anyFloat asin(anyFloat x) Arcus sinus
anyFloat acos(anyFloat x) Arcus cosinus
anyFloat atan(anyFloat y, anyFloat x) Arcus tangens y/x
anyFloat atan(anyFloat y_over_x) Arcus tangens y_over_x
anyFloat sinh(anyFloat x) Sinus hiperboliczny
anyFloat cosh(anyFloat x) Cosinus hiperboliczny
anyFloat tanh(anyFloat x) Tangens hiperboliczny
anyFloat asinh(anyFloat x) Arcus sinus hiperboliczny
anyFloat acosh(anyFloat x) Arcus cosinus hiperboliczny
anyFloat atanh(anyFloat x) Arcus tangens hiperboliczny
Funkcje wykadnicze
Podobnie jak funkcje trygonometryczne, funkcje wykadnicze dziaaj na zmiennoprzecinkowych
typach danych (skalarnych i wektorach). Pena lista tych funkcji znajduje si w tabeli 6.5.
Tabela 6.5. Funkcje wykadnicze
Funkcja Opis
anyFloat pow(anyFloat x, anyFloat y) x podniesiony do potgi y
anyFloat exp(anyFloat x) Wykadnik naturalny x
anyFloat log(anyFloat x) Logarytm naturalny x
anyFloat exp2(anyFloat x) 2 do potgi x
anyFloat log2(anyFloat angle) Logarytm x o podstawie 2
anyFloat sqrt(anyFloat x) Pierwiastek kwadratowy z x
anyFloat inversesqrt(anyFloat x) Odwrotno pierwiastka kwadratowego z x
267
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Funkcje geometryczne
W jzyku GLSL dostpna jest te pewna liczba oglnych funkcji geometrycznych. Niektre z nich
przyjmuj tylko argumenty okrelonego typu (np. iloczyn wektorowy), a inne kady z wek-
torowych zmiennoprzecinkowych typw danych (vec2, vec3 i vec4), ktre w tabeli 6.6 ozna-
czamy zbiorczo jako vec.
Tabela 6.6. Funkcje geometryczne
Funkcja Tabela
float length(vec2/vec3/vec4 x) Zwraca dugo wektora x
float distance(vec p0, vec p1) Zwraca odlego midzy p0 i p1
float dot(vec x, vec y) Zwraca iloczyn skalarny x i y
vec3 cross(vec3 x, vec3 y) Zwraca iloczyn wektorowy x i y
vec normalize(vec x) Zwraca wektor o dugoci jeden skierowany w tym samym
kierunku, co x
vec faceforward(vec N, vec I, vec nRef) Jeli dot(Nref, I) < 0, zwraca N, w przeciwnym
przypadku zwraca N
vec reflect(vec I, vec N) Zwraca kierunek odbicia wektora padajcego I oraz orientacj
paszczyzny N
vec refract(vec I, vec N, float eta) Zwraca wektor zaamania wektora padajcego I, orientacj
paszczyzny N oraz wspczynnik wskanikw zaamania eta
Funkcje macierzowe
Wiele dziaa na macierzach wykonuje si przy uyciu zwykych operatorw matematycznych.
W tabeli 6.7 znajduje si wykaz kilku dodatkowych funkcji macierzowych, ktre mog by bar-
dzo przydatne. Kada z nich pobiera okrelony typ argumentw, ktre zostay wyszczeglnione.
Funkcje porwnywania wektorw
Wartoci skalarne mona porwnywa za pomoc standardowych operatorw porwnywania
(<, <=, >, >=, ++ oraz !=). Do porwnywania wektorw su funkcje zebrane w tabeli 6.8. Wszyst-
kie zwracaj wektory wartoci logicznych o takiej samej liczbie wymiarw, jak argumenty.
Inne czsto uywane funkcje
Na zakoczenie w tabeli 6.9 przedstawiamy zbir rnych funkcji oglnego przeznaczenia.
Wszystkie dziaaj zarwno na skalarnych, jak i wektorowych typach danych oraz mog takie typy
zwraca.
268
Cz I Podstawy
Tabela 6.7. Funkcje macierzowe
Funkcja Opis
mat matrixCompMult(mat x, mat y) Mnoy dwie macierze skadnik po skadniku. To nie jest to samo,
co mnoenie macierzy w algebrze liniowej.
mat2 outerProduct(vec2 c, vec2 r)
mat3 outerProduct(vec3 c, vec3 r)
mat4 outerProduct(vec4 c, vec4 r)
mat2x3 outerProduct(vec3 c, vec2 r)
mat3x2 outerProduct(vec2 c, vec3 r)
mat2x4 outerProduct(vec4 c, vec2 r)
mat4x2 outerProduct(vec2 c, vec4 r)
mat3x4 outerProduct(vec4 c, vec3 r)
mat4x3 outerProduct(vec3 c, vec4 r)
Zwraca macierz bdc iloczynem zewntrznym dwch
podanych wektorw.
mat2 transpose(mat2 m)
mat3 transpose(mat3 m)
mat4 transpose(mat4 m)
mat2x3 transpose(mat3x2 m)
mat3x2 transpose(mat2x3 m)
mat2x4 transpose(mat4x2 m)
mat4x2 transpose(mat2x4 m)
mat3x4 transpose(mat4x3 m)
mat4x3 transpose(mat3x4 m)
Transponuje podan macierz
float determinant(mat2 m)
float determinant(mat3 m)
float determinant(mat4 m)
Zwraca wyznacznik podanej macierzy
mat2 inverse(mat2 m)
mat3 inverse(mat3 m)
mat4 inverse(mat4 m)
Zwraca odwrcon wersj podanej macierzy
Tabela 6.8. Funkcje porwnywania wektorw
Funkcja Opis
bvec lessThan(vec x, vec y)
bvec lessThan(ivec x, ivec y)
bvec lessThan(uvec x, uvec y)
Zwraca wynik porwnywania x < y kadej pary skadnikw
269
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Tabela 6.8. Funkcje porwnywania wektorw cig dalszy
Funkcja Opis
bvec lessThanEqual(vec x, vec y)
bvec lessThanEqual(ivec x, ivec y)
bvec lessThanEqual(uvec x, uvec y)
Zwraca wynik porwnywania x <= y kadej pary skadnikw
bvec greaterThan(vec x, vec y)
bvec greaterThan(ivec x, ivec y)
bvec greaterThan(uvec x, uvec y)
Zwraca wynik porwnywania x > y kadej pary skadnikw
bvec greaterThanEqual(vec x, vec y)
bvec greaterThanEqual(ivec x, ivec y)
bvec greaterThanEqual(uvec x, uvec y)
Zwraca wynik porwnywania x >= y kadej pary skadnikw
bvec equal(vec x, vec y)
bvec equal(ivec x, ivec y)
bvec equal(uvec x, uvec y)
bvec equal(bvec x, bvec y)
Zwraca wynik porwnywania x == y kadej pary skadnikw
bvec notEqual(vec x, vec y)
bvec notEqual(ivec x, ivec y)
bvec notEqual(uvec x, uvec y)
bvec notEqual(bvec x, bvec y)
Zwraca wynik porwnywania x != y kadej pary skadnikw
bool any(bvec x) Zwraca warto true, jeli ktrykolwiek skadnik x ma warto
true
bool all(bvec x) Zwraca warto true, jeli wszystkie skadniki x maj warto
true
bvec not(bvec x) Zwraca dopenienie x dla kadego komponentu
Tabela 6.9. Inne czsto uywane funkcje
Funkcja Opis
anyFloat abs(anyFloat x)
anyInt abs(anyInt x)
Zwraca warto bezwzgldn x
anyFloat sign(anyFloat x)
anyInt sign(anyInt x)
Zwraca warto 1.0 lub 1.0 w zalenoci od znaku x
anyFloat floor(anyFloat x) Zwraca najmniejsz liczb cakowit nie wiksz od x
anyFloat trunc(anyFloat x) Zwraca liczb cakowit najblisz, ale nie wiksz ni warto
bezwzgldna x
270
Cz I Podstawy
Tabela 6.9. Inne czsto uywane funkcje cig dalszy
Funkcja Opis
anyFloat round(anyFloat x) Zwraca warto cakowit najblisz wartoci x. Uamek 0,5
moe zosta zaokrglony w obie strony, w zalenoci
od implementacji
anyFloat roundEven(anyFloat x) Zwraca warto cakowit najblisz wartoci x. Uamek 0,5
jest zaokrglany do najbliszej parzystej liczby cakowitej
anyFloat ceil(anyFloat x) Zwraca warto najbliszej liczby cakowitej wikszej od x
anyFloat fract(anyFloat x) Zwraca cz uamkow wartoci x
anyFloat mod(anyFloat x, float y)
anyFloat mod(anyFloat x, anyFloat y)
Zwraca warto bezwzgldn wyniku dziaania x mod y
anyFloat modf(anyFloat x, out anyFloat i Zwraca cz uamkow wartoci x zapisan w i
anyFloat min(anyFloat x, anyFloat y)
anyFloat min(anyFloat x, float y)
anyInt min(anyInt x, anyInt y)
anyInt min(anyInt x, int y)
anyUInt min(anyUInt x, anyUInt y)
anyUint min(anyUInt x, uint y)
Zwraca mniejsz spord wartoci x i y
anyFloat max(anyFloat x, anyFloat y)
anyFloat max(anyFloat x, float y)
anyInt max(anyInt x, anyInt y)
anyInt max(anyInt x, int y)
anyUInt max(anyUInt x, anyUInt y)
anyUint max(anyUInt x, uint y)
Zwraca wiksz spord wartoci x i y
anyFloat clamp(anyFloat x,
anyFloat minVal,
anyFloat maxVal)
anyFloat clamp(anyFloat x,
float minVal,
float maxVal);
anyInt clamp(anyInt x,
anyInt minVal,
anyInt maxVal)
anyInt clamp(anyInt x,
int minVal,
int maxVal)
Zwraca warto x przycit do przedziau minVal-maxVal
271
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Tabela 6.9. Inne czsto uywane funkcje cig dalszy
Funkcja Opis
anyUint clamp(anyUint x,
anyUint minVal,
anyUint maxVal);
anyUint clamp(anyUint x,
uint minVal,
uint maxVal)
anyFloat mix(anyFloat x,
anyFloat y,
anyFloat a)
anyFloat mix(anyFloat x,
anyFloat y,
float a)
Zwraca przejcie liniowe midzy x i y. Warto a moe si
zawiera w przedziale od 0 do 1
anyFloat mix(anyFloat x,
anyFloat y,
anyBool a)
Zwraca skadniki x, gdy a ma warto false, lub skadniki y,
gdy a ma warto true
anyFloat step(anyFloat edge, anyFloat x)
anyFloat step(float edge, anyFloat x)
Zwraca warto 0.0, jeli warto x jest mniejsza od edge
lub 1.0 w przeciwnym przypadku
anyFloat smoothstep(anyFloat edge0,
anyFloat edge1,
anyFloat x)
anyFloat smoothStep(float edge0,
float edge1,
anyFloat x)
Zwraca warto 0.0, jeli x <= edge0, lub 1.0, jeli x
>= edge1, oraz pynn interpolacj Hermitea dla
argumentw midzy 0.0 i 1.0
anyBool isnan(anyFloat x) Zwraca true, jeli x jest Nan
anyBool isinf(anyFloat x) Zwraca true, jeli x jest dodatni lub ujemn
nieskoczonoci
anyInt floatBitsToInt(anyFloat x)
anyUint floatBitsToUint(anyFloat x)
Konwertuje wartoci zmiennoprzecinkowe na cakowite
anyFloat intBitsToFloat(anyInt x)
anyFloat uintBitsToFloat(anyUint x)
Konwertuje wartoci cakowite na zmiennoprzecinkowe
272
Cz I Podstawy
Symulowanie wiata
Znamy ju solidne podstawy jzyka GLSL, a wic czas na rozpoczcie pisania bardziej rozbudo-
wanych shaderw. Jedn z fundamentalnych technik grafiki komputerowej jest symulowanie
wiata. Poniewa techniki te nie s bardzo skomplikowane, doskonale nadaj si do przedsta-
wienia metod programowania shaderw. Symulowanie wiata, owietlenia i waciwoci materia-
w to tak obszerne tematy, e mona by im byo powici ca osobn ksik. I rzeczywicie
takie ksiki istniej! W tym rozdziale omwimy tylko podstawowe techniki zwizane z symu-
lowaniem wiata w komputerze oraz pokaemy, jak je implementowa w jzyku GLSL. Techniki
te stanowi baz, na ktrej opieraj si techniki bardziej zaawansowane.
wiato rozproszone
Rodzajem wiata najczciej stosowanym do owietlania powierzchni w grafice trjwymiarowej
jest tzw. wiato rozproszone (ang. diffuse light). Jest to wiato skierowane odbijajce si od
powierzchni z nateniem proporcjonalnym do kta, pod jakim si od niej odbija. Dziki temu
powierzchnia obiektu jest janiejsza, gdy wiato pada na ni pod ktem prostym, ni wwczas,
gdyby padao na ni pod jakim wikszym ktem. W wielu modelach wiata skadowa wiata
rozproszonego jest uywana do tworzenia cieni (lub zmian kolorw) na powierzchni owietlonych
obiektw.
Do okrelenia natenia wiata w danym wierzchoku potrzebne s dwa wektory. Jeden z nich
okrela kierunek w stron rda wiata. W niektrych technikach owietleniowych dostarczany
jest tylko wektor skierowany w stron rda wiata. Takie wiato nazywamy kierunkowym
(ang. directional), poniewa wszystkie wierzchoki dysponuj tym samym wektorem w stron r-
da wiata. Wszystko jest dobrze, jeli rdo wiata znajduje si bardzo (lub nieskoczenie)
daleko od owietlanych obiektw. Wyobramy sobie boisko pikarskie, na ktrym jest rozgry-
wany mecz. Kt padania promieni sonecznych na jednym kocu boiska niewiele rni si od kta
padania na jego drugim kocu. Gdyby jednak mecz by rozgrywany w nocy, efekt istnienia
pojedynczego grnego rda wiata byby dobrze widoczny podczas przemieszczania si
zawodnikw po boisku. Gdybymy do kodu symulujcego wiato przekazali pooenie rda
wiata, to aby okreli wektor w stron rda wiata, musielibymy w naszym shaderze odj
przeksztacone (wsprzdne oka) pooenie wierzchoka od pooenia rda wiata.
Normalne do powierzchni
Drugi wektor potrzebny do uzyskania wiata rozproszonego (i nie tylko, o czym si niedugo
przekonasz) to normalna do powierzchni. Normalna do powierzchni (wektor normalny) to linia
majca swj pocztek na paszczynie, do ktrej jest prostopada. Nazwa ta moe wydawa si
273
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
niezwyka, jakby poyczona z jakiego filmu fantastycznego, ale tak naprawd sowo normalny
oznacza tu po prostu prostopady do jakiej realnej lub wyobraonej paszczyzny. Wektor to
linia skierowana w okrelonym kierunku, a wektor normalny to linia prostopada do paszczyzny.
Podsumowujc, wektor normalny to linia ustawiona pod ktem 90 stopni do przedniej pasz-
czyzny naszej figury geometrycznej. Na rysunku 6.4 pokazano przykadowe wektory normalne
w dwch i trzech wymiarach.
Rysunek 6.4.
Dwu- i trjwymiarowy
wektor normalny
Pewnie si dziwisz, czemu musimy okreli wektor normalny dla kadego wierzchoka. Dlaczego
nie moemy zdefiniowa jednej normalnej dla caego wielokta i zastosowa jej do wszystkich
wierzchokw? Moemy, ale nie zawsze chcemy, aby normalna bya prostopada do powierzchni
figury. Jak zapewne zauwaye, nie wszystkie powierzchnie s paskie. Mona prbowa jak
najwierniej je odtworzy za pomoc paskich wieloktw, ale efekt zawsze bdzie niejednorodny
lub poszarpany. Aby utworzy powierzchni wygldajc na gadk, mona uy paskich
wieloktw i tak dostosowa normalne do powierzchni, aby j optycznie wygadziy. Na przy-
kad w przypadku kuli normalna do powierzchni kadego wierzchoka jest prostopada do
powierzchni samej bryy, a nie do poszczeglnych trjktw, z ktrych ta brya zostaa zoona.
Owietlanie wierzchokw
Na rysunku 6.5 przedstawiono oba wektory, ktrymi si zajmujemy. Natenie wiata w ka-
dym wierzchoku okrela si poprzez obliczenie iloczynu skalarnego wektora do rda wiata
i wektora normalnego. Wektory te musz mie dugo o wartoci jeden, poniewa wynikiem
oblicze moe by warto z przedziau od 1.0 do 1.0. Warto 1.0 otrzymujemy, gdy oba
wektory s skierowane w tym samym kierunku, natomiast 1.0 oznacza, e wektory wskazuj
przeciwne kierunki. Gdy otrzymamy warto 0.0, wiemy, e wektory s ustawione wzgldem
siebie pod ktem 90 stopni. W istocie otrzymana warto to cosinus kta midzy wektorami.
Jak mona si domyli, dodatnie wartoci oznaczaj, e wiato pada na wierzchoek. Im wiksza
warto (czyli im blisza wartoci 1.0), tym wiksze natenie wiata; i odwrotnie, im mniejsza
warto (nawet poniej zera), tym natenie wiata mniejsze.
274
Cz I Podstawy
Rysunek 6.5.
Podstawowe wektory
wiata rozproszonego
Jeli pomnoymy obliczony iloczyn skalarny przez warto koloru wierzchoka, otrzymamy war-
to koloru ze wiatem o odpowiednim nateniu. Takie pynne cieniowanie wartoci kolorw
midzy wierzchokami czasami nazywane jest owietlaniem wierzchokw (ang. vertex lighting)
lub cieniowaniem Gourauda (ang. Gouraud shading). Obliczenie iloczynu skalarnego w jzyku
GLSL jest atwe. Najczciej wykorzystuje si co w rodzaju poniszego wywoania:
float intensity = dot(vSurfaceNormal, vLightDirection);
Shader wiata rozproszonego
Przeanalizujemy kolejny przykadowy program, o nazwie DiffuseLight. Posuy nam on do
zademonstrowania dziaania prostego shadera wiata rozproszonego na niebieskiej kuli. Wy-
korzystalimy w nim take punktowe rdo wiata, a wic zobaczymy rwnie, jak uzyskuje
si ten rodzaj owietlenia w shaderze. Oczywicie uycie kierunkowego rda wiata byoby
prostsze, poniewa ju mamy ten wektor, ale to pozostawiamy jako wiczenie do samodzielne-
go wykonania. Na listingu 6.7 znajduje si kod shadera wierzchokw DiffuseLight.vp.
Listing 6.7. Shader wierzchokw wiata rozproszonego
// Prosty shader wiata rozproszonego
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
// Zmienne wejciowe danych wierzchokw... pooenie i normalna
in vec4 vVertex;
in vec3 vNormal;
// Ustawienia dla kadej porcji danych
uniform vec4 diffuseColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
// Kolor
smooth out vec4 vVaryingColor;
275
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
void main(void)
{
// Obliczanie normalnej do powierzchni we wsprzdnych oka
vec3 vEyeNormal = normalMatrix * vNormal;
// Obliczenie pooenia wierzchoka we wsprzdnych oka
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Obliczenie wektora do rda wiata
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// Obliczenie intensywnoci wiata przy uyciu iloczynu skalarnego
float diff = max(0.0, dot(vEyeNormal, vLightDir));
// Mnoenie intensywnoci przez kolor rozproszenia
vVaryingColor.rgb = diff * diffuseColor.rgb;
vVaryingColor.a = diffuseColor.a;
// Przeksztacenie geometrii
gl_Position = mvpMatrix * vVertex;
}
W shaderze zostay zdefiniowane tylko dwa atrybuty pooenie wierzchoka (vVertex) i nor-
malna do powierzchni (vNormal). Natomiast zmiennych uniform potrzebowalimy a piciu:
uniform vec4 diffuseColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
Zmienna diffuseColor przechowuje kolor kuli, vLightPosition okrela pooenie wiata we
wsprzdnych oka, mpvMatrix zawiera macierz rzutowania model-widok, mvMatrix natomiast
reprezentuje macierz model-widok. Wszystko to znamy z korzystania z shaderw standardowych
(tyle e od strony klienta). Nowoci jest natomiast macierz 33 o nazwie normalMatrix.
Normaln do powierzchni najczciej przesya si jako jeden z atrybutw wierzchoka. Trzeba j
tylko obrci, aby jej kierunek znalaz si w przestrzeni oka. Nie mona jednak w tym celu
pomnoy jej przez macierz model-widok, poniewa zawiera ona dodatkowo przesunicie, ktre
przesunoby nasz wektor. Problem ten rozwizujemy poprzez przekazanie zmiennej uniform
reprezentujcej macierz normaln (ang. normaln matrix) zawierajc tylko skadnik obrotowy
macierzy model-widok. Na szczcie w klasie GLTransformationPipeline dostpna jest funk-
cja GetNormalMatrix, ktra zwraca t potrzebn nam macierz. Dziki temu uzyskanie kierunku
normalnej we wsprzdnych oka to kwestia pomnoenia dwch macierzy:
vec3 vEyeNormal = normalMatrix * vNormal;
Poza funkcj gwn zadeklarowalimy pynnie cieniowan warto koloru o nazwie
vVaryingColor.
276
Cz I Podstawy
smooth out vec4 vVaryingColor;
To jest jedyna poza przeksztacon geometri informacja wyjciowa shadera wierzchokw.
Shader fragmentw jest banalnie prosty. Przypisujemy w nim przychodzc warto do wyjcio-
wego koloru fragmentu.
vFragColor = vVaryingColor;
Ze wzgldu na fakt, e przesyamy pooenie wiata, a nie wektor w stron rda wiata,
pooenie wierzchoka musimy przekonwertowa na wsprzdne oka i odj t warto od
pooenia wiata.
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Obliczenie wektora w stron rda wiata
vec3 vLightDir = normalize(vLightPosition - vPosition3);
Osobna macierz model-widok jest nam w tym shaderze potrzebna dlatego, e wsprzdnych
oka wierzchoka nie mona pomnoy przez macierz zawierajc rzutowanie. W tym miejscu do
gry wkracza wsprzdna w. Wykonanie tego dzielenia jest wane na wypadek, gdyby macierz
przeksztacenia zawieraa jakie informacje skalowania (aby dowiedzie si, dlaczego jest to lub
nie jest wane dla Ciebie, wr do rozdziau 4.).
Wektory s po prostu pikne, prawda? Aby otrzyma wektor w stron wiata, odejmujemy od
siebie te dwa wektory i normalizujemy wynik. Teraz moemy wykorzysta iloczyn skalarny do
obliczenia intensywnoci wiata na wierzchoku. Przy uyciu funkcji max jzyka GLSL ograni-
czylimy zakres natenia do wartoci z przedziau od zera do jeden.
float diff = max(0.0, dot(vEyeNormal, vLightDir));
Na zakoczenie oblicze wiata mnoymy kolor powierzchni przez natenie wiata. W tym
przypadku uywamy tylko kanaw RGB, a kana alfa zostawiamy bez zmian.
vVaryingColor.rgb = diff * diffuseColor.rgb;
vVaryingColor.a = diffuseColor.a;
Listing 6.8 przedstawia funkcje SetupRC i RenderScene z programu DiffuseLight.
Listing 6.8. Kod funkcji SetupRC i RenderScene z programu DiffuseLight
// Ta funkcja wykonuje wszystkie dziaania zwizane z inicjalizowaniem w kontekcie renderowania.
void SetupRC(void)
{
// To
glClearColor(0.3f, 0.3f, 0.3f, 1.0f );
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
shaderManager.InitializeStockShaders();
viewFrame.MoveForward(4.0f);
277
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
// Tworzenie kuli
gltMakeSphere(sphereBatch, 1.0f, 26, 13);
diffuseLightShader =
shaderManager.LoadShaderPairWithAttributes("DiffuseLight.vp",
"DiffuseLight.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex",
GLT_ATTRIBUTE_NORMAL, "vNormal");
locColor = glGetUniformLocation(diffuseLightShader, "diffuseColor");
locLight = glGetUniformLocation(diffuseLightShader, "vLightPosition");
locMVP = glGetUniformLocation(diffuseLightShader, "mvpMatrix");
locMV = glGetUniformLocation(diffuseLightShader, "mvMatrix");
locNM = glGetUniformLocation(diffuseLightShader, "normalMatrix");
}
// Rysowanie sceny
void RenderScene(void)
{
static CStopWatch rotTimer;
// Wyczyszczenie okna i bufora gbi
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix(viewFrame);
modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f,
1.0f, 0.0f);
GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };
GLfloat vDiffuseColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
glUseProgram(diffuseLightShader);
glUniform4fv(locColor, 1, vDiffuseColor);
glUniform3fv(locLight, 1, vEyeLight);
glUniformMatrix4fv(locMVP, 1, GL_FALSE,
transformPipeline.GetModelViewProjectionMatrix());
glUniformMatrix4fv(locMV, 1, GL_FALSE,
transformPipeline.GetModelViewMatrix());
glUniformMatrix3fv(locNM, 1, GL_FALSE,
transformPipeline.GetNormalMatrix());
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
Jest to nasze pierwsze powaniejsze spotkanie z niestandardowym shaderem. Jak wida, aby go
skonfigurowa, w funkcji renderujcej potrzebnych byo a pi wywoa funkcji glUniform.
Czsto spotykanym bdem, zwaszcza popenianym przez programistw przyzwyczajonych do
starego stylu pracy, jest dalsze modyfikowanie jednego ze stosw macierzy po ustawieniu danych
278
Cz I Podstawy
uniform shadera, ale przed wyrenderowaniem geometrii. Pamitajmy, e funkcje glUniform nie
kopiuj do shaderw referencji do danych, lecz same dane. Stanowi to okazj do pozbycia si kilku
wywoa funkcji dla wartoci uniform, ktre nie zmieniaj si czsto. Rysunek 6.6 przedstawia
wynik dziaania naszego programu.
Rysunek 6.6.
Program DiffuseLight
Model owietlenia ADS
Jednym z najczciej wykorzystywanych modeli owietlenia, w szczeglnoci przez osoby zazna-
jomione z aktualnie wycofywanym staym potokiem funkcji, jest tzw. model owietlenia ADS.
Akronim ten tworz pierwsze litery angielskich wyrazw ambient, diffuse oraz specular, ozna-
czajcych trzy waciwoci odblaskowe materiau pokrywajcego obiekty dla wiata otacza-
jcego (ang. ambient), rozproszonego (ang. diffuse) oraz odbitego zwierciadlanie (ang. specular).
Tym waciwociom materiau przypisuje si wartoci kolorw, przy czym wysza warto ozna-
cza wyszy wspczynnik odblasku. rda wiata rwnie maj te waciwoci i im rwnie
przypisuje si wartoci koloru reprezentujce jasno wiata. Zatem o ostatecznym kolorze
wierzchoka decyduje wypadkowa tych trzech waciwoci materiau i rda wiata.
wiato otaczajce
wiato otaczajce (ang. ambient light) nie pochodzi z adnego konkretnego kierunku. Ma ono
rdo, ale promienie wiata odbijay si ju po caej scenie tyle razy, e wiato to cakowicie
stracio jakikolwiek kierunek. Wszystkie powierzchnie obiektw znajdujcych si w wietle
otaczajcym s owietlone rwnomiernie, niezalenie od kierunku. wiato otaczajce mona
traktowa jako globalny wspczynnik rozjaniajcy stosowany dla kadego rda wiata.
279
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Aby obliczy udzia rda wiata otaczajcego w ostatecznym kolorze wierzchoka, naley prze-
skalowa warto waciwoci odblaskowej wiata otaczajcego materiau przez warto wiata
otaczajcego (naley pomnoy te dwa wektory przez siebie). W jzyku GLSL zapisalibymy to
nastpujco:
uniform vec3 vAmbientMaterial;
uniform vec3 vAmbientLight;
vec3 vAmbientColor = vAmbientMaterial * vAmbientLight;
wiato rozproszone
wiato rozproszone to kierunkowa skadowa rda wiata. Byo ono w naszym centrum
zainteresowania w poprzednim shaderze owietlenia. Warto materiau rozpraszajcego naley
pomnoy przez warto wiata rozproszonego, tak jak si to robi w przypadku skadowych
wiata otaczajcego. Warto ta jest nastpnie skalowana przez iloczyn skalarny normalnej do
powierzchni i wektora wiata (czyli natenie wiata rozproszonego). W jzyku shaderw
mona to wyrazi w nastpujcy sposb:
uniform vec3 vDiffuseMaterial;
uniform vec3 vDiffuseLight;
float fDotProduct = max(0.0, dot(vNormal, vLightDir));
vec3 vDiffuseColor = vDiffuseMaterial * vDiffuseLight * fDotProduct;
Zauwamy, e obliczanie iloczynu skalarnego wektorw umiecilimy w funkcji GLSL o nazwie
max. Zrobilimy to dlatego, e iloczyn skalarny moe mie warto ujemn, a przecie nie moemy
zastosowa ujemnego owietlenia czy koloru. Dlatego wszystkie wartoci poniej zera zamieniamy
na zero.
wiato odbicia zwierciadlanego
Podobnie jak wiato rozproszone, wiato odbicia zwierciadlanego to waciwo kierunkowa,
ale w odrnieniu od niego silniej oddziauje z powierzchni materiau i oddziaywanie to ma cile
okrelony kierunek. Mocno odbite wiato najczciej powoduje wystpienie na powierzchni
owietlanej jasnej plamy nazywanej odbyskiem (ang. specular highlight). Ze wzgldu na do
precyzyjne ukierunkowanie odbysk moe by niewidoczny dla osoby patrzcej pod okrelonym
ktem. Przykadami rde wiata tworzcych mocne odbyski s reflektor i soce, ale oczywicie
warunkiem powstania tych odbyskw jest padanie promieni wiata na byszczcy przedmiot.
Udzia koloru w materiale poyskujcym i kolorach owietlenia skalowany jest przez pewn
warto, ktrej otrzymanie wymaga nieco wikszej iloci oblicze ni wykonywane do tej pory.
Najpierw musimy znale wektor odbicia wiata i odwrcony wektor wiata. Nastpnie oblicza
si iloczyn skalarny tych dwch wektorw i podnosi si go do potgi wartoci poyskliwoci.
Im wiksza warto poyskliwoci, tym mniejszy odbysk. Poniej znajduje si fragment kodu
shadera wykonujcy te obliczenia:
uniform vec3 vSpecularMaterial;
uniform vec3 vSpecularLight;
float shininess = 128.0;
vec3 vReflection = reflect(-vLightDir, vEyeNormal);
280
Cz I Podstawy
float EyeReflectionAngle = max(0.0, dot(vEyeNormal, vReflection);
fSpec = pow(EyeReflectionAngle, shininess);
vec3 vSpecularColor = vSpecularLight * vSpecularMaterial * fSpec;
Parametr poyskliwoci mona okreli jako dan typu uniform. Tradycyjnie przypisuje si mu
maksymaln warto 128 (tradycja ta siga jeszcze czasw staego potoku). Zastosowanie wik-
szych wartoci zwykle powoduje powstanie bardzo maych odbyskw.
Shader ADS
Ostateczny kolor wierzchoka mona zatem, biorc pod uwag trzy ostatnie przykady, obliczy
nastpujco:
vVertexColor = vAmbientColor + vDiffuseColor + vSpecularColor;
Implementacj opisywanego rodzaju shadera zawiera program ADSGouraud. Zastosowalimy
w nim jednak pewne uproszczenie. Zamiast przekazywa osobno informacje na temat kolorw
i natenia waciwoci materiau i wiata, przekazalimy po jednej wartoci koloru dla mate-
riaw wiata otaczajcego, rozproszonego i odbijanego w sposb zwierciadlany. To tak, jak-
bymy wczeniej pomnoyli waciwo materiau przez kolory wiata. Jeli nie planujesz
zmienia waciwoci materiau w kadym wierzchoku, jest to atwy sposb na optymalizacj.
W nazwie programu znalazo si sowo Gouraud, poniewa wartoci wiata obliczamy dla
kadego wierzchoka, a nastpnie stosujemy cieniowanie z interpolacj przestrzeni kolorw
midzy wierzchokami. Peny kod shadera wierzchokw znajduje si na listingu 6.9.
Listing 6.9. Shader wierzchokw programu ADSGouraud
// Shader owietlenia punktowego ADS
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 130
// Dane wejciowe wierzchokw... pooenie i normalna
in vec4 vVertex;
in vec3 vNormal;
// Ustawienia dla porcji danych
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
// Kolor do shadera fragmentw
smooth out vec4 vVaryingColor;
void main(void)
{
281
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
// Obliczanie normalnej do powierzchni we wsprzdnych oka
vec3 vEyeNormal = normalMatrix * vNormal;
// Obliczenie pooenia wierzchoka we wsprzdnych oka
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Obliczenie wektora w stron rda wiata
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// Obliczenie natenia wiata rozproszonego przy uyciu iloczynu skalarnego
float diff = max(0.0, dot(vEyeNormal, vLightDir));
// Pomnoenie natenia przez kolor rozproszenia, warto alfa wynosi 1.0
vVaryingColor = diff * diffuseColor;
// Dodanie wiata otoczenia
vVaryingColor += ambientColor;
// wiata odbicia zwierciadlanego
vec3 vReflection = normalize(reflect(-vLightDir, vEyeNormal));
float spec = max(0.0, dot(vEyeNormal, vReflection));
if(diff != 0) {
float fSpec = pow(spec, 128.0);
vVaryingColor.rgb += vec3(fSpec, fSpec, fSpec);
}
// Przeksztacenie geometrii!
gl_Position = mvpMatrix * vVertex;
}
Nie pokazujemy caego kodu shadera, poniewa przypisuje on tylko przychodzc warto zmien-
nej vVaryingColor do koloru fragmentw:
vFragColor = vVaryingColor;
Kady trjkt skada si z trzech wierzchokw i wikszej liczby wypeniajcych go fragmentw.
Dziki temu owietlanie wierzchokw i technika cieniowania Gourauda s bardzo wydajne,
poniewa wszystkie obliczenia dla kadego wierzchoka s wykonywane tylko raz. Rysunek 6.7
przedstawia wynik dziaania programu ADSGouraud.
Cieniowanie Phonga
Na rysunku 6.7 wida jedn z najwikszych wad cieniowania Gourauda odbysk ukada si
w ksztat gwiazdy. W niektrych przypadkach mona by byo powiedzie, e to zamierzony
efekt artystyczny. Ale kula widoczna na rysunku w programie si obraca, przez co wida cha-
rakterystyczne pasma, ktre nie wygldaj adnie i s nieestetyczne. Powodem tych niedosko-
naoci jest brak cigoci midzy trjktami wynikajcy z zastosowania liniowej interpolacji
282
Cz I Podstawy
Rysunek 6.7.
Owietlanie
wierzchokowe metod
cieniowania Gourauda
w przestrzeni kolorw. Te jasne linie to granice midzy poszczeglnymi trjktami. Problem ten
mona prbowa wyeliminowa poprzez zwikszenie liczby wierzchokw. Jednak lepszym i bar-
dziej efektywnym sposobem jest zastosowanie techniki o nazwie cieniowanie Phonga (ang. Phong
shading). Zamiast wartoci kolorw bdziemy interpolowa normalne do powierzchni midzy
wierzchokami. Efekt zastosowania cieniowania Phonga przedstawia rysunek 6.8, na ktrym
wida okno programu ADSPhong (rysunki 6.7 i 6.8 znajduj si rwnie na tablicy 5 w koloro-
wej wkadce).
Rysunek 6.8.
Owietlenie pikselowe
(cieniowanie Phonga)
283
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Oczywicie nie ma nic za darmo. W tej technice musimy wicej popracowa w shaderze frag-
mentw, ktry bdzie wywoywany o wiele czciej ni shader wierzchokw. Podstawowy kod
niczym nie rni si od kodu programu ADSGouraud. Natomiast due rnice s w kodzie
shaderw. Na listingu 6.10 znajduje si kod nowego shadera wierzchokw.
Listing 6.10. Shader wierzchokw ADSPhong
// Shader owietlenia punktowego ADS
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
// Dane wejciowe wierzchokw... pooenie i normalna
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
// Kolor do shadera fragmentw
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
void main(void)
{
// Obliczanie normalnej do powierzchni we wsprzdnych oka
vVaryingNormal = normalMatrix * vNormal;
// Obliczenie pooenia wierzchoka we wsprzdnych oka
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Obliczenie wektora wskazujcego kierunek w stron rda wiata
vVaryingLightDir = normalize(vLightPosition - vPosition3);
// Przeksztacenie geometrii!
gl_Position = mvpMatrix * vVertex;
}
We wszystkich obliczeniach owietlenia wykorzystywana jest normalna do powierzchni i wektor
kierunku wiata. Wektory te przekazujemy zamiast obliczonych wartoci kolorw wierzchokw
(po jednej dla kadego):
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
Teraz shader fragmentw ma znacznie wicej pracy, co wida na listingu 6.11.
284
Cz I Podstawy
Listing 6.11. Shader fragmentw programu ADSPhong
// Shader owietlenia punktowego ADS
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
void main(void)
{
// Obliczenie natenia skadowej wiata rozproszonego poprzez obliczenie iloczynu skalarnego wektorw
float diff = max(0.0, dot(normalize(vVaryingNormal),
normalize(vVaryingLightDir)));
// Mnoenie natenia przez kolor rozproszony, alfa ma warto 1.0
vFragColor = diff * diffuseColor;
// Dodanie skadowej wiata otaczajcego
vFragColor += ambientColor;
// wiato odbite zwierciadlanie
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),
normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if(diff != 0) {
float fSpec = pow(spec, 128.0);
vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
}
}
Przy obecnym rozwoju techniki wybr takich zaawansowanych metod wysokiej jakoci rende-
rowania jest czsto uzasadniony. Poprawa jakoci obrazu jest znaczna, a utrata wydajnoci
czsto zaniedbywana. Jednak w niektrych sytuacjach, np. przy programowaniu mao wydajnego
sprztu (takiego jak ukad wbudowany) lub duym obcieniu sceny innymi wysokiej jakoci
algorytmami, najlepszym wyborem moe by cieniowanie Gourauda. Oglna zasada optymali-
zacji dziaania shaderw gosi, aby jak najwicej zada wykonywa w shaderze wierzchokw,
a jak najmniej w shaderze fragmentw. Chyba ju wiadomo dlaczego.
285
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Korzystanie z tekstur
Pobranie tekstury do shadera jest bardzo atwe. Najpierw do shadera wierzchokw przekazy-
wane s wsprzdne tekstury jako atrybuty. Nastpnie w shaderze fragmentw interpoluje si
je pynnie midzy wierzchokami. Pniej shader ten wykorzystuje interpolowane wsprzdne
do prbkowania (ang. sample) tekstury. Obiekt tekstury zwizany z shaderem jest ju przy-
gotowany do ewentualnego mipmapowania, ma ustawione tryby filtrowania i zawijania itd.
Poddany prbkowaniu i filtrowaniu kolor tekstury wraca w postaci wartoci koloru RGBA, ktr
mona zapisa bezporednio we fragmencie lub poczy z innymi obliczeniami kolorw.
Pobieraniem i zwracaniem tekstur przy uyciu jzyka GLSL zajmiemy si bardziej szczegowo
w nastpnym rozdziale. Tutaj pokaemy tylko podstawowe techniki, abymy mogli kontynuowa
prac.
Nic, tylko teksele
Dziaanie najprostszego moliwego shadera wykorzystujcego tekstur przedstawimy na przy-
kadzie programu TexturedTriangle. Jego zadanie polega tylko na narysowaniu trjkta i pokry-
ciu go tekstur, tak jak wida na rysunku 6.9.
Rysunek 6.9.
Program rysujcy
trjkt z naoon
tekstur
Kod kliencki w C/C++ renderujcy trjkt jest bardzo prosty. Take samo naoenie tekstury na
trjkt nie jest dla nas niczym nowym, poniewa robilimy to ju przy uyciu shaderw stan-
dardowych. Na listingu 6.12 przedstawiamy kod shadera wierzchokw odbierajcego atrybuty
wierzchokw.
286
Cz I Podstawy
Listing 6.12. Shader wierzchokw programu TexturedTriangle
// Shader TexturedIdentity
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL SuperBible
#version 330
in vec4 vVertex;
in vec2 vTexCoords;
smooth out vec2 vVaryingTexCoords;
void main(void)
{
vVaryingTexCoords = vTexCoords;
gl_Position = vVertex;
}
Najwaniejszymi elementami tego shadera s wejciowy atrybut wierzchoka o nazwie
vTexCoords zawierajcy wsprzdne tekstury s i t dla wierzchoka oraz zmienna wyjciowa
vVaryingTexCoords. To wszystko, czego potrzeba do interpolowania wsprzdnych tekstury
na powierzchni naszego trjkta.
Kod shadera fragmentw, przedstawiony na listingu 6.13, rwnie jest krtki i zawiera co nowego.
Listing 6.13. Shader fragmentw programu TexturedTriangle
// Shader TexturedIdentity
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
uniform sampler2D colorMap;
out vec4 vFragColor;
smooth in vec2 vVaryingTexCoords;
void main(void)
{
vFragColor = texture(colorMap, vVaryingTexCoords.st);
}
Na pocztku programu zosta uyty nowy typ zmiennej o nazwie sampler2D:
uniform sampler2D colorMap;
Typ sampler to liczba cakowita (jej warto ustawia si za pomoc funkcji glUniform1i) repre-
zentujca jednostk tekstury, z ktr zwizana jest tekstura majca zosta poddana prbkowa-
287
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
niu. Przyrostek 2D oznacza, e uywana jest tekstura dwuwymiarowa. Mona rwnie korzysta
z wersji 1D, 3D i innych, ktrych szczegowy opis znajduje si w nastpnym rozdziale. W roz-
dziale 5. opisalimy obiekty tekstur pozwalajce zarzdza dowoln liczb stanw tekstur, a do
wybierania tych obiektw suya nam funkcja glBindTexture. We wszystkich tych przypad-
kach wykonywalimy wizanie z domyln jednostk tekstury o numerze 0. Jednostek takich
jest jednak wicej i z kad z nich mona zwiza inny obiekt tekstury. Moliwo korzystania
z wielu tekstur jednoczenie pozwala uzyska mnstwo ciekawych efektw, ale wicej informacji
na ten temat znajduje si w nastpnym rozdziale.
Ustawienie zmiennej sampler, ktra jest typu uniform, i wyrenderowanie trjkta w kodzie
klienckim jest bardzo proste.
glUseProgram(myTexturedIdentityShader);
glBindTexture(GL_TEXTURE_2D, textureID);
GLint iTextureUniform = glGetUniformLocation(myTexturedIdentityShader,
"colorMap");
glUniform1i(iTextureUniform, 0);
triangleBatch.Draw();
W shaderze wywoujemy wbudowan funkcj mapowania tekstur o nazwie texture. Robimy to
w celu wykonania prbkowania naszej tekstury przy uyciu interpolowanych wsprzdnych
tekstury i przypisania wartoci koloru bezporednio do koloru fragmentw.
vFragColor = texture(colorMap, vVaryingTexCoords.st);
Owietlanie tekseli
Wiemy ju, jak prbkowa tekstury, a wic moemy sprbowa zrobi co ciekawszego, np.
doda tekstur do shadera ADSPhong. We wszystkich shaderach owietlenia postpowalimy
wedug jednego schematu mnoylimy podstawowe wartoci kolorw przez natenie wia-
ta dla kadego wierzchoka lub kadego piksela. Zmodyfikowany shader ADSPhong, ktry
nazwiemy ADSTexture, prbkuje tekstur, a nastpnie mnoy jej wartoci kolorw przez nat-
enie wiata. Wynik tego dziaania przedstawia rysunek 6.10, na ktrym wida okno programu
LitTexture. Zwr szczegln uwag na jasny biay odblask po lewej stronie grnej czci kuli.
Ten biay rozbysk przypomina nam o jednej wanej rzeczy, ktr musimy bra pod uwag
przy owietlaniu teksturowanych powierzchni. Suma wiate otaczajcego i rozproszonego moe
da wiato biae, ktre w przestrzeni kolorw reprezentuj same jedynki. Wynikiem pomnoenia
koloru tekstury przez kolor biay s oryginalne, w aden sposb niezmienione wartoci kolorw
tekseli. Oznacza to, e nie da si pomnoy koloru tekstury przez prawidow warto wiata,
aby uzyska biay rozbysk. Przynajmniej z zaoenia tak powinno by.
W rzeczywistoci wyniki oblicze wiata, take rozbysku, wykraczaj nieco ponad 1.0 dla ka-
dego kanau koloru. Oznacza to, e istnieje moliwo przesycenia kolorw i uzyskania biaego
288
Cz I Podstawy
Rysunek 6.10.
Poczenie wiata
z tekstur w programie
LitTexture
rozbysku. Prawidowo jednak powinno si pomnoy sum nate wiata otaczajcego i roz-
proszonego przez kolor tekstury, a nastpnie doda skadow wiata odbitego zwierciadlanie.
Na listingu 6.14 znajduje si odpowiednio zmodyfikowana wersja shadera ADSPhong.
Listing 6.14. Shader fragmentw programu ADSTexture
// Shader owietlenia punktowego ADS
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform sampler2D colorMap;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vTexCoords;
void main(void)
{
// Obliczenie natenia skadowej wiata rozproszonego poprzez obliczenie iloczynu skalarnego wektorw
float diff = max(0.0, dot(normalize(vVaryingNormal),
normalize(vVaryingLightDir)));
// Mnoenie natenia przez kolor rozproszony, alfa ma warto 1.0
vFragColor = diff * diffuseColor;
289
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
// Dodanie skadowej wiata otaczajcego
vFragColor += ambientColor;
// Dodanie tekstury
vFragColor *= texture(colorMap, vTexCoords);
// wiato odbite zwierciadlanie
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),
normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if(diff != 0) {
float fSpec = pow(spec, 128.0);
vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
}
}
Anulowanie przetwarzania fragmentw
Shadery fragmentw umoliwiaj anulowanie przetwarzania i w konsekwencji zapisywania
wartoci kolorw fragmentw (a take wartoci gbi i szablonw). Do zatrzymania dziaania
shadera fragmentw suy instrukcja discard. Czsto uywa si jej do wykonywania testw
alfa. Typowa operacja mieszania skada si z odczytywania danych z bufora kolorw, wykonania
przynajmniej dwch dziaa mnoenia, zsumowania kolorw oraz zapisania wartoci z powro-
tem w buforze kolorw. Jeli kana alfa ma warto zero lub bardzo blisk zeru, fragmentw
praktycznie nie wida. Co gorsza, fragmenty te tworz w buforze gbi niewidoczny wzr, ktry
moe zakci wynik testowania gbi. Testowanie alfa ma na celu znalezienie wszystkich warto-
ci poniej jakiego okrelonego progu i anulowanie rysowania wszystkich fragmentw, dla
ktrych kana alfa ma tak wanie warto. Poniej znajduje si przykadowy kod wyszukujcy
wartoci alfa mniejsze od 0.1:
if(vColorValue.a < 0.1f)
discard;
Moliwo t mona wykorzysta do uzyskania ciekawego efektu, jakim jest shader erozyjny.
Shader erozyjny daje zudzenie, e obiekty geometryczne w miar upywu czasu ulegaj erozji.
Dziki instrukcji discard mona sterowa wywietlaniem fragmentw z pikselow precyzj.
Przykad opisywanego efektu przedstawia program Dissolve. Najpierw zdobylimy tekstur
o odpowiednim wzorze przypominajcym chmury. Tekstur tak mona atwo wykona przy
uyciu wikszoci programw do obrbki grafiki. Tekstura, z ktrej my skorzystalimy, jest
widoczna na rysunku 6.11.
W kodzie klienckim utworzylimy czasow zmienn uniform zmieniajc wartoci w zakresie
od 1.0 do 0.0 w czasie 10 sekund. Naszym celem jest to, aby nasz zielony torus w cigu tych
10 sekund uleg cakowitemu rozkadowi. W tym celu prbkujemy tekstur chmury i porw-
nujemy jeden ze skadnikw koloru z nasz zmienn odliczania, anulujc rysowanie wszystkich
fragmentw, dla ktrych warto koloru jest mniejsza od ustalonej minimalnej wartoci. Kod
rdowy tego shadera fragmentw przedstawia listing 6.15.
290
Cz I Podstawy
Rysunek 6.11.
Tekstura z chmur uyta
do zademonstrowania
efektu erozji
Listing 6.15. Shader fragmentw programu Dissolve
// Shader owietlenia punktowego ADS
// Shader fragmentw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform sampler2D cloudTexture;
uniform float dissolveFactor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vVaryingTexCoord;
void main(void)
{
vec4 vCloudSample = texture(cloudTexture, vVaryingTexCoord);
if(vCloudSample.r < dissolveFactor)
discard;
// Obliczenie natenia skadowej wiata rozproszonego poprzez obliczenie iloczynu skalarnego wektorw
float diff = max(0.0, dot(normalize(vVaryingNormal),
normalize(vVaryingLightDir)));
// Mnoenie natenia przez kolor rozproszony, alfa ma warto 1.0
vFragColor = diff * diffuseColor;
// Dodanie skadowej wiata otaczajcego
vFragColor += ambientColor;
291
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
// wiato odbite zwierciadlanie
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),
normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if(diff != 0) {
float fSpec = pow(spec, 128.0);
vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
}
}
Jest to kolejna modyfikacja shadera fragmentw programu ADSPhong, do ktrego dodalimy
efekt rozkadania si obiektu. Najpierw utworzylimy zmienne uniform do przechowywania
samplera tekstury i zegara.
uniform sampler2D cloudTexture;
uniform float dissolveFactor;
Nastpnie prbkujemy nasz tekstur i sprawdzamy, czy warto koloru czerwonego (biorc
pod uwag, e obraz jest w skali szaroci, wybr skadowej koloru nie ma wikszego znaczenia) jest
mniejsza od ustalonej wartoci. Jeli tak, nie rysujemy takiego fragmentu.
vec4 vCloudSample = texture(cloudTexture, vVaryingTexCoord);
if(vCloudSample.r < dissolveFactor)
discard;
Naley rwnie zauway, e dziaania te wykonujemy we wczesnej fazie dziaania shadera. Nie
ma przecie sensu wykonywa czasochonnych oblicze pikselowych, jeli fragment i tak nie
zostanie narysowany. Rysunek 6.12 przedstawia jedn klatk z naszej animacji.
Rysunek 6.12.
Okno programu
Dissolve
292
Cz I Podstawy
Teksturowanie w stylu kreskwkowym
teksele w roli wiata
We wszystkich przykadach mapowania tekstur w tym i poprzednim rozdziale uywalimy tek-
stur dwuwymiarowych. S one najprostsze i najatwiej zrozumie sposb ich uywania. Wik-
szo osb intuicyjnie rozumie proces nakadania dwuwymiarowego obrazu na paszczyzn dwu-
lub trjwymiarowego obiektu. Teraz jednak przedstawimy przykad odwzorowywania tekstury
jednowymiarowej. Technika ta czsto wykorzystywana jest w grach komputerowych do two-
rzenia obrazw cieniowanych w sposb podobny do stosowanego w kreskwkach. Taki rodzaj
cieniowania czsto nazywany jest cieniowaniem kreskwkowym (ang. toon shading albo cel
shading). Sposb ten polega na wykorzystaniu jednowymiarowych tekstur jako tabeli wyszuki-
wania kolorw do wypenienia obiektw jednolitym kolorem (w trybie GL_NEAREST).
Podstaw tej metody jest wykorzystanie natenia wiata rozproszonego (iloczyn skalarny
normalnej do powierzchni przestrzeni oka i wektora wiata padajcego) jako wsprzdnej
okrelajcej lokalizacj koloru w jednowymiarowej teksturze stanowicej tabel kolorw o r-
nym poziomie jasnoci (ustawionych od najciemniejszego do najjaniejszego). Na rysunku 6.13
przedstawiona jest tekstura jednowymiarowa skadajca si z czterech czerwonych tekseli (zde-
finiowanych jako skadowe koloru RGB typu unsigned byte).
Rysunek 6.13.
Jednowymiarowa
tabela wyszukiwania
kolorw
Przypomnijmy, e warto iloczynu skalarnego wiata rozproszonego mieci si w granicach od
0.0, co oznacza brak natenia, do 1.0, co oznacza maksymalne natenie. Ten zakres dobrze
pasuje do zakresu wsprzdnych jednowymiarowej tekstury. Zaadowanie takiej tekstury jest
bardzo atwe, co wida poniej:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_1D, texture);
GLubyte textureData[4][3] = { 32, 0, 0,
64, 0, 0,
128, 0, 0,
255, 0, 0};
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 4, 0, GL_RGB,
GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
293
Rozdzia 6. Mylenie niekonwencjonalne programy do cieniowania
Kod ten pochodzi z programu ToonShader wywietlajcego obracajcy si torus renderowany
technik cieniowania kreskwkowego. Mimo i klasa GLTriangleBatch uyta do utworzenia
torusa dostarcza zestaw dwuwymiarowych wsprzdnych teksturowych, my je w naszym sha-
derze wierzchokw ignorujemy, co wida na listingu 6.16.
Listing 6.16. Shader wierzchokw programu ToonShader
// Shader cieniowania kreskwkowego
// Shader wierzchokw
// Richard S. Wright Jr
// OpenGL. Ksiga eksperta
#version 330
// Dane wejciowe wierzchokw... pooenie i normalna
in vec4 vVertex;
in vec3 vNormal;
smooth out float textureCoordinate;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
void main(void)
{
// Obliczanie normalnej do powierzchni we wsprzdnych oka
vec3 vEyeNormal = normalMatrix * vNormal;
// Obliczenie pooenia wierzchoka we wsprzdnych oka
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Obliczenie wektora wskazujcego kierunek w stron rda wiata
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// Obliczenie natenia wiata rozproszonego przy uyciu iloczynu skalarnego
textureCoordinate = max(0.0, dot(vEyeNormal, vLightDir));
// Przeksztacenie geometrii!
gl_Position = mvpMatrix * vVertex;
}
Oprcz pooenia obiektw po przeksztaceniu shader ten zwraca jeszcze tylko interpolowan
wsprzdn teksturow textureCoordinate zadeklarowan jako typu float. Obliczenia ska-
dowej wiata rozproszonego s wykonywane w sposb identyczny, jak w programie DiffuseLight.
Shader fragmentw prbkuje nasz jednowymiarow tekstur i zapisuje warto we fragmencie
w buforze obrazu.
vFragColor = texture(colorTable, textureCoordinate);
294
Cz I Podstawy
Wynik dziaania tego programu przedstawia rysunek 6.14. Kolorowy obraz tekstury jednowy-
miarowej i poniszy rysunek mona znale take w kolorowej wkadce na tablicy 6.
Rysunek 6.14.
Torus cieniowany
technik cieniowania
kreskwkowego
Podsumowanie
W tym rozdziale wydostalimy si z ogranicze standardowych shaderw, ktrych uywalimy
w piciu pocztkowych rozdziaach. Klasy typu GLBatch z biblioteki GLTools uatwiaj prze-
syanie najbardziej typowych atrybutw. Teraz wiemy, jak podczepi do tych klas wasne atry-
buty shaderw. Czytelnicy zobaczyli, jakie s podobiestwa midzy jzykami C/C++ i GLSL,
poznali funkcje standardowe GLSL oraz nauczyli si pisa w nim wasne funkcje. Poznali te
dwa modele owietlenia i nauczyli si je implementowa we wasnych shaderach, poznali wady
i zalety wykonywania skomplikowanych oblicze w shaderze fragmentw i wierzchokw.
Poruszony te zosta temat pozyskiwania danych teksturowych w shaderach.
Czytelnicy dowiedzieli si, jak odwzorowuje si tekstury dwuwymiarowe na powierzchni obiektw,
oraz nauczyli si, jak mona wykorzystywa tekstury jako dane, traktujc je jako tabele wyszuki-
wania wykorzystywane do eliminowania elementw geometrii za pomoc instrukcji discard oraz
jako jednowymiarowe tabele kolorw do implementowania cieniowania kreskwkowego.
W tym rozdziale przedstawiono tylko niewielk cz moliwoci oferowanych przez jzyk GLSL.
W dalszych rozdziaach mona bdzie pozna go znacznie dokadniej i nauczy si stosowa
wiele innych ciekawych efektw graficznych, rozszerzajc przy tym swoj wiedz na temat API
OpenGL. Po co wic zwleka? Masz ju wystarczajc wiedz, aby zacz eksperymentowa na
wasn rk. Moesz zacz od modyfikowania przykadowych programw albo wymyli wasne!
Rozdzia 9.
Zaawansowane
odwzorowania tekstur
W rodziale tym przedstawione zostan zaawansowane techniki tworzenia tekstur, ktre
pozwol kolejny raz na zwikszenie realizmu tworzonej grafiki. Omwione zostan na-
stpujce zagadnienia:
tekstury wielokrotne;
mapy otoczenia;
macierz tekstur;
mapy owietlenia;
wieloprzebiegowe tworzenie tekstur wielokrotnych.
Zastosowanie kadego z wymienionych efektw powoduje, e grafika trjwymiarowa
nabiera jeszcze doskonalszego wygldu.
Tekstury wielokrotne
Dotychczas wykorzystywana bya pojedyncza tekstura dla kadego wielokta. OpenGL
umoliwia jednak pokrycie wielokta sekwencj tekstur, czyli tworzenie tekstur wielo-
krotnych. Moliwo ta stanowi obecnie jedynie rozszerzenie specyfikacji OpenGL. Roz-
szerzenia interfejsu programowego OpenGL zatwierdzane s przez rad ARB (Archi-
tectural Review Board) nadzorujc rozwj specyfikacji OpenGL. Tekstury wielokrotne
stanowi opcjonalne rozszerzenie OpenGL i nie s dostpne w kadej implementacji.
Tekstury wielokrotne tworzone s za pomoc sekwencji jednostek tekstury. Jednostki
tekstury omwione zostan szczegowo w dalszej czci rozdziau. Obecnie wystarczy
jedynie informacja dotyczca tego, e kada jednostka tekstury reprezentuje pojedyncz
tekstur, a take to, e podczas tworzenia tekstury wielokrotnej kada jednostka tekstury
przekazuje wynik jej zastosowania kolejnej jednostce tekstury a do utworzenia kocowej
tekstury wielokrotnej. Rysunek 9.1 ilustruje proces tworzenia tekstur wielokrotnych.
238 Cz II Korzystanie z OpenGL
Rysunek 9.1.
Tekstura wielokrotna
powstaje na skutek
naoenia na wielokt
wicej ni jednej
tekstury za pomoc
jednostek tekstur
W procesie tworzenia tekstury wielokrotnej mona wyrni cztery gwne etapy.
1. Sprawdzenie, czy implementacja OpenGL udostpnia moliwo tworzenia
tekstur wielokrotnych.
2. Uzyskanie wskanika funkcji rozszerzenia.
3. Tworzenie jednostki tekstury.
4. Okrelenie wsprzdnych tekstury.
Teraz naley przyjrze si bliej kademu z wymienionych etapw.
Sprawdzanie dostpnoci tekstur wielokrotnych
Przed rozpoczciem stosowania tekstur wielokrotnych trzeba najpierw sprawdzi, czy
udostpnia je uywana implementacja OpenGL. Tekstury wielokrotne s rozszerzeniem
specyfikacji OpenGL zaaprobowanym przez rad ARB. List takich rozszerze udo-
stpnianych przez konkretn implementacj mona uzyska wywoujc funkcj glCet
Strrg` z parametrem C|_LXTL|SI0|S. Lista ta posiada posta acucha znakw, w kt-
rym nazwy kolejnych rozszerze rozdzielone s znakami spacji. Jeli w acuchu tym
znaleziona zostanie nazwa C|_A|O_ulttexture, to oznacza to dostpno tekstur wie-
lokrotnych.
W celu sprawdzenia dostpnoci konkretnego rozszerzenia OpenGL mona skorzysta
z dostpnej w bibliotece GLU funkcji gluC|ec|Lxteror` o nastpujcym prototypie:
|buuean uChec|Exlensunchar *GZV0COG, cunsl |ubyle *GZV5VTKPI),
Funkcja ta zwraca warto true, jeli nazwa rozszerzenia GZV0COG znajduje si w acuchu
GZV5VTKPI lub warto ele w przeciwnym razie.
acuch zwrcony przez funkcj glCetStrrg` mona take przeszuka indywidualnie.
Oto przykad implementacji odpowiedniej funkcji:
Rozdzia 9. Zaawansowane odwzorowania tekstur 239
buu nSlrchar *searchSlr, char *slr)
{
char *endfSlr, ws|an| uslalneu zna|u acucha
nl dx - D,
endfSlr - slr + slrenslr), uslaln zna| acucha
pela wy|unywana a du usaneca |uca acucha
whe slr < endfSlr)
{
udnadue puuene |ueneu zna|u spac
dx - slrcspnslr, ' '),
sprawdza slr ws|azue puszu|wana nazwe
f slrensearchSlr) -- dx) && slrncnpsearchSlr, slr, dx) -- D))
{
relurn lrue,
}
ne esl lu puszu|wana nazwa, przesuwany ws|an| du |uene nazwy
slr +- dx + 1),
}
relurn fase,
}
Funkcja ta zwraca warto true, jeli acuch tr zawiera acuch eerc|Str przy zao-
eniu, e tr skada si z podacuchw oddzielonych znakami spacji. Aby sprawdzi,
czy dana implementacja umoliwia stosowanie tekstur wielokrotnych, mona skorzysta
ostatecznie z poniszego fragmentu kodu:
char *exlensunSlr, sla duslepnych ruzszerze
pubera sle duslepnych ruzszerze
exlensunSlr - char*)elSlrn|_EX1ENSNS),
f nSlr'|_ARB_nullexlure', exlensunSlr))
{
le|slury weu|rulne sa duslepne
}
Po sprawdzeniu dostpnoci tekstur wielokrotnych kolejnym krokiem bdzie uzyskanie
wskanikw funkcji rozszerze.
Dostp do funkcji rozszerze
Aby korzysta z rozszerze OpenGL na platformie Microsoft Windows musimy uzy-
ska dostp do funkcji rozszerze. Funkcja wglCetProcAddre` zwraca wskanik danej
funkcji rozszerzenia. Dla tekstur wielokrotnych dostpnych jest sze funkcji rozszerze:
IN/WNVK6GZ%QQTFKH#4$ (gdzie K =1..4) funkcje te okrelaj wsprzdne
tekstur wielokrotnych;
IN#EVKXG6GZVWTG#4$ wybiera biec jednostk tekstury;
IN%NKGPV#EVKXG6GZVWTG#4$ wybiera jednostk tekstury, na ktrej
wykonywane bd operacje.
240 Cz II Korzystanie z OpenGL
Poniszy fragment kodu suy do uzyskania dostpu do wymienionych funkcji rozszerze:
P|N||U|11EXCRD?|ARBPRC |ul1exCuurd?fARB - NU||,
P|N|AC1VE1EX1UREARBPRC Aclve1exlureARB - NU||,
P|N|C|EN1AC1VE1EX1UREARBPRC CenlAclve1exlureARB - NU||,
|ul1exCuurd?fARB - P|N||U|11EXCRD?|ARBPRC)
welPrucAddress'|ul1exCuurd?fARB'),
Aclve1exlureARB - P|N|AC1VE1EX1UREARBPRC)
welPrucAddress'Aclve1exlureARB'),
CenlAclve1exlureARB - P|N|C|EN1AC1VE1EX1UREARBPRC)
welPrucAddress'CenlAclve1exlureARB'),
Po wykonaniu tego kodu mona tworzy tekstury wielokrotne za pomoc funkcji glMul
tTexCoord2A|O` i glActveTextureA|O`.
Tworzenie jednostek tekstury
Tworzenie tekstur wielokrotnych odbywa si poprzez nakadanie wielu jednostek tek-
stury. Jednostka tekstury skada si z obrazu tekstury, parametrw filtrowania, stosu
macierzy tekstury, a ponadto posiada zdolno automatycznego tworzenia wsprzd-
nych tekstury.
Aby skonfigurowa parametry jednostki tekstury, trzeba najpierw wybra biec jed-
nostk tekstury za pomoc funkcji glActveTextureA|O` zdefiniowanej w nastpujcy
sposb:
vud Aclve1exlureARB|enun VGZ7PKV),
Po wykonaniu tej funkcji wszystkie wywoania funkcji glTexIege`, glTexPereeter`,
glTexLrv`, glTexCer` i glOrdTexture` dotyczy bd jednostki tekstury okrelo-
nej przez parametr VGZ7PKV. Parametr VGZ7PKV moe posiada warto C|_TLXTU|LK_A|O,
gdzie K jest liczb cakowit z przedziau od 0 do wartoci o jeden mniejszej od dopusz-
czalnej liczby jednostek tekstur. Na przykad C|_TLXTU|LC_A|O oznacza pierwsz z do-
stpnych jednostek tekstur. Liczb jednostek tekstur dopuszczaln dla danej implemen-
tacji OpenGL uzyska mona wykonujc poniszy fragment kodu:
nl nax1exlUnls, na|synana czba ednusle| le|slur
elnleerv|_|AX_1EX1URE_UN1S_ARB, &nax1exlUnls),
Jeli w wyniku wywoania funkcji glCetIrtegerv` uzyskana zostanie warto 1, ozna-
cza to bdzie, e dana implementacja nie umoliwia tworzenia tekstur wielokrotnych.
Jednostki tekstur mona konfigurowa za porednictwem obiektw tekstur. Informacja,
ktr zawiera obiekt tekstury, jest automatycznie przechowywana z jednostk tekstury.
Aby korzysta z jednostek tekstur, wystarczy wic podobnie jak w przypadku zwy-
kych tekstur utworzy obiekt tekstury, a nastpnie aktywowa jednostk tekstury za
pomoc funkcji glActveTextureA|O`. Nastpnie naley zwiza obiekty tekstur z od-
powiadajcymi im jednostkami tekstur. Ilustruje to nastpujcy fragment kodu:
ube|ly le|slur
nl lexbecls[?],

en1exlures?, lexbecls), lwurzy dwa ube|ly le|slur


Rozdzia 9. Zaawansowane odwzorowania tekstur 241
lwurzy perwsza le|slure
Bnd1exlure|_1EX1URE_?D, lexbecls[D]),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
uBud?D|pnaps|_1EX1URE_?D, |_RB, G4, G4, |_RB, |_UNSNED_B\1E, lexne),

lwurzy drua le|slure


Bnd1exlure|_1EX1URE_?D, lexbecls[1]),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
uBud?D|pnaps|_1EX1URE_?D, |_RB, G4, G4, |_RB, |_UNSNED_B\1E, lex1wu),

lwurzy ednusl| le|slur za punuca ube|luw le|slur


Aclve1exlureARB|_1EX1URED_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, sne1ex->lexD),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
Aclve1exlureARB|_1EX1URE1_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_|DU|A1E),

Powyszy fragment kodu tworzy najpierw dwa obiekty tekstur, a nastpnie kreuje za ich
pomoc dwie jednostki tekstur uywane do tworzenia tekstur wielokrotnych.
Okrelanie wsprzdnych tekstury
Teraz, gdy wiadomo ju, w jaki sposb tworzy jednostki tekstur, naley zapozna si ze
sposobem ich uycia. Jako e pojedynczy wielokt bdzie wicej ni jedn tekstur,
trzeba zdefiniowa dla niego take wicej ni jeden zestaw wsprzdnych tekstury. Dla
kadej jednostki tekstury naley wic dysponowa osobnym zbiorem wsprzdnych
tekstury i zastosowa je dla kadego wierzchoka z osobna. Aby okreli wsprzdne
tekstury dwuwymiarowej mona zastosowa funkcj glMultTexCoord2A|O` zdefinio-
wan w nastpujcy sposb:
vud |ul1exCuurd?fARB|enun VGZ7PKV, fual EQQTFU),
Inne wersje tej funkcji umoliwiaj okrelenie wsprzdnych tekstu jedno-, trj- oraz
czterowymiarowych take za pomoc wartoci innych typw ni loet. Na przykad
funkcja glMultTexCoord8dA|O` pozwala okreli wsprzdne tekstury trjwymiaro-
wej za pomoc wartoci typu double. Korzystajc z tych funkcji naley poda najpierw
jednostk tekstury, a nastpnie jej wsprzdne. Oto przykad:
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
Powysze wywoanie funkcji nadaje biecemu wierzchokowi wsprzdne (C.C, C.C)
pierwszej jednostki tekstur. Podobnie jak w przypadku funkcji glTexCoord2` trzeba
242 Cz II Korzystanie z OpenGL
okreli najpierw wsprzdne wszystkich uywanych jednostek tekstur, a dopiero po-
tem zdefiniowa wierzchoek. Ilustruje to poniszy fragment kodu:
Ben|_UADS),
ewy, duny werzchue|
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8f-5Df, -5Df, -5Df),
prawy, duny werzchue|
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8f5Df, -5Df, -5Df),
prawy, urny werzchue|
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8f5Df, 5Df, -5Df),
ewy, urny werzchue|
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8f-5Df, 5Df, -5Df),
End),
Fragment ten rysuje kwadrat pokryty dwiema teksturami. Dla kadego wierzchoka de-
finiuje wsprzdne obu tekstur.
Naley pamita, e przy stosowaniu tekstur wielokrotnych funkcja glTexCoord2` po-
zwala na zdefiniowanie wsprzdnych tekstury tylko dla pierwszej jednostki tekstury.
W takim przypadku wywoanie funkcji glTexCoord2` jest wic rwnowane wywoa-
niu glMultTexCoord2C|_TLXTU|LC_A|O, ...`.
Przykad zastosowania tekstur wielokrotnych
Teraz analizie zostanie poddany kompletny przykad programu, ktry pokrywa szecian
dwiema teksturami pokazanymi na rysunku 9.2.
Rysunek 9.2.
Dwie tekstury,
ktrymi pokryty
zostanie szecian
A oto pierwszy fragment kodu programu:
Defnce
#defne B1|AP_D Dx4D4? denlyf|alur furnalu B|P
#defne P 814195
ncudes
#ncude <wnduwsh> slandarduwy p| nauw|uwy unduws
#ncude <slduh>
#ncude <sldbh>
#ncude <nalhh>
Rozdzia 9. Zaawansowane odwzorowania tekstur 243
#ncude <h> slandarduwy p| nauw|uwy pen|
#ncude <uh> p| nauw|uwy bbule| |U
#ncude 'exlh' p| nauw|uwy ruzszerze pen|
1ypy
lypedef slrucl
{
nl wdlh, szeru|uc le|slury
nl hehl, wysu|uc le|slury
unsned nl lexD, ube|l le|slury
unsned char *dala, dane le|slury
} lexlure_l,
Znenne ubane
HDC _HDC, ubany |unle|sl urzadzena
buu fuScreen - fase, lrue - lryb penue|ranuwy
fase - lryb u|en|uwy
buu |eyPressed[?5G], labca przycnec |awszy
fual ane - DDf, |al ubrulu
fual radans - DDf, |al ubrulu |anery w radanach
Znenne nyszy |anery
nl nuuseX, nuuse\, wspurzedne nyszy
fual caneraX, canera\, caneraZ, wspurzedne |anery
fual uu|X, uu|\, uu|Z, pun|l wyceuwana |anery
Znenne le|slur
lexlure_l *sne1ex,
lexlure_l *chec|er1ex,
Znenne zwazane z le|sluran weu|rulnyn
P|N||U|11EXCRD?|ARBPRC |ul1exCuurd?fARB - NU||,
P|N|AC1VE1EX1UREARBPRC Aclve1exlureARB - NU||,
P|N|C|EN1AC1VE1EX1UREARBPRC CenlAclve1exlureARB - NU||,
nl nax1exlureUnls - D, dupuszczana czba ednusle| le|slur
Plik nagwkowy glext.h naley docza wtedy, gdy korzysta si z jakichkolwiek roz-
szerze OpenGL zatwierdzonych przez ARB. Plik ten zawiera definicje wszystkich roz-
szerze. Jego kopia umieszczona zostaa take na dysku CD.
Powyszy fragment kodu prezentuje take sposb wykorzystania struktur do przecho-
wywania informacji o teksturze i jej danych. Typ texture_t umoliwia zapamitanie
obiektu tekstury, jej szerokoci i wysokoci oraz danych. Upraszcza to proces adowania
i stosowania tekstur w OpenGL.
Omawiany program bdzie umoliwia sterowanie kamer OpenGL w podobny sposb
do programu prezentujcego rzeb terenu, ktry przedstawiony zosta w rozdziale 8.
Gdy mysz bdzie porusza si poziomo, szecian bdzie obracany wok osi y. Nato-
miast przy wykonywaniu pionowych ruchw mysz, mona spowodowa oddalanie si
bd przyblianie kamery do szecianu.
Pierwsz z funkcji, ktr definiuje program, jest omwiona ju wczeniej funkcja IrStr`.
Zwraca ona warto true, jeli acuch eerc|Str zostanie odnaleziony wewntrz a-
cucha tr, ktry zawiera wiele nazw oddzielonych znakami spacji.
244 Cz II Korzystanie z OpenGL
buu nSlrchar *searchSlr, char *slr)
{
char *endfSlr, ws|an| uslalneu zna|u acucha
nl dx - D,
endfSlr - slr + slrenslr), uslaln zna| acucha
pela wy|unywana a du usaneca |uca acucha
whe slr < endfSlr)
{
udnadue puuene |ueneu zna|u spac
dx - slrcspnslr, ' '),
sprawdza, czy slr ws|azue puszu|wana nazwe
f slrensearchSlr) -- dx) && slrncnpsearchSlr, slr, dx) -- D))
{
relurn lrue,
}
ne esl lu puszu|wana nazwa, przesuwany ws|an| du |uene nazwy
slr +- dx + 1),
}
relurn fase,
}
W celu umoliwienia korzystania z tekstur wielokrotnych program definiuje funkcj Irt
MultTex`, ktra sprawdza, czy dostpne jest rozszerzenie o nazwie C|_A|O_ulttexture,
a ponadto pozyskuje wskaniki funkcji rozszerze. Funkcja IrtMultTex` zwraca war-
to ele, jeli tworzenie tekstur wielokrotnych nie jest dostpne.
buu nl|ul1ex)
{
char *exlensunSlr, sla duslepnych ruzszerze
exlensunSlr - char*)elSlrn|_EX1ENSNS),
f exlensunSlr -- NU||)
relurn fase,
f nSlr'|_ARB_nullexlure', exlensunSlr))
{
zwraca dupuszczana czbe ednusle| le|slur
elnleerv|_|AX_1EX1URE_UN1S_ARB, &nax1exlureUnls),
pubera adresy fun|c ruzszerze
|ul1exCuurd?fARB - P|N||U|11EXCRD?|ARBPRC)
welPrucAddress'|ul1exCuurd?fARB'),
Aclve1exlureARB - P|N|AC1VE1EX1UREARBPRC)
welPrucAddress'Aclve1exlureARB'),
CenlAclve1exlureARB - P|N|C|EN1AC1VE1EX1UREARBPRC)
welPrucAddress'CenlAclve1exlureARB'),
relurn lrue,
}
ese
relurn fase,
}
Rozdzia 9. Zaawansowane odwzorowania tekstur 245
Kolejna funkcja, |oedTextureFle`, aduje pojedyncz tekstur i umieszcza jej opis
w strukturze typu texture_t i zwraca wskanik tej struktury. Parametrem funkcji |oed
TextureFle` jest nazwa pliku. W celu zaadowania jego zawartoci wywouje ona
funkcj |oedOtepFle` i umieszcza informacje o zaadowanym obrazie w strukturze
typu texture_t. Funkcja |oedTextureFle` tworzy take obiekt tekstury.
lexlure_l *|uad1exlure|echar *fenane)
{
B1|APN|HEADER lexnfu,
lexlure_l *lhs1exlure,
przydzea panec slru|lurze lypu lexlure_l
lhs1exlure - lexlure_l*)naucszeuflexlure_l)),
f lhs1exlure -- NU||)
relurn NU||,
adue ubraz le|slury sprawdza puprawne wy|unane le uperac
lhs1exlure->dala - |uadBlnap|efenane, &lexnfu),
f lhs1exlure->dala -- NU||)
{
freelhs1exlure),
relurn NU||,
}
uneszcza nfurnace u szeru|uc wysu|uc le|slury
lhs1exlure->wdlh - lexnfubudlh,
lhs1exlure->hehl - lexnfubHehl,
lwurzy ube|l le|slury
en1exlures1, &lhs1exlure->lexD),
relurn lhs1exlure,
}
Jako e opanowana ju zostaa umiejtno adowania tekstury, mona zapozna si z ko-
lejn funkcj, ktra moe zaadowa wszystkie tekstury uywane w programie i skonfi-
gurowa je tak, by moliwe byo ich wykorzystanie do tworzenia tekstur wielokrotnych.
Funkcja |oedAllTexture` aduje wszystkie tekstury, okrela ich parametry, tworzy mi-
pmapy i wie obiekty tekstur z jednostkami tekstur.
buu |uadA1exlures)
{
adue perwsza le|slure
sne1ex - |uad1exlure|e'snebnp'),
f sne1ex -- NU||)
relurn fase,
adue drua le|slure
chec|er1ex - |uad1exlure|e'chessbnp'),
f chec|er1ex -- NU||)
relurn fase,
lwurzy npnapy z flruwanen nuwyn da perwsze le|slury
Bnd1exlure|_1EX1URE_?D, sne1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
246 Cz II Korzystanie z OpenGL
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
uBud?D|pnaps|_1EX1URE_?D, |_RB, sne1ex->wdlh, sne1ex->hehl,
|_RB, |_UNSNED_B\1E, sne1ex->dala),
lwurzy npnapy z flruwanen nuwyn da drue le|slury
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_|DU|A1E),
uBud?D|pnaps|_1EX1URE_?D, |_RB, chec|er1ex->wdlh, chec|er1ex->hehl,
|_RB, |_UNSNED_B\1E, chec|er1ex->dala),
wybera perwsza ednusl|e le|slury
Aclve1exlureARB|_1EX1URED_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, sne1ex->lexD), wae ednusl|e z perwsza le|slura
wybera drua ednusl|e le|slury
Aclve1exlureARB|_1EX1URE1_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD), wae ednusl|e z drua le|slura
relurn lrue,
}
Funkcja Irtelze` inicjuje dane programu:
vud nlaze)
{
CearCuurDDf, DDf, DDf, DDf), lu w czarnyn |uurze
Shade|ude|_S|1H), cenuwane ad|e
Enabe|_DEP1H_1ES1), usuwane u|rylych puwerzchn
Enabe|_CU||_|ACE), bra| ubcze da newducznych slrun weu|aluw
|runl|ace|_CCu), newduczne slruny pusadaa purzade| werzchu|uw
przecwny du |erun|u ruchu ws|azuwe| zeara
Enabe|_1EX1URE_?D), wacza le|slury dwuwynaruwe
nl|ul1ex),
|uadA1exlures),
}
Szecian narysowa mona za pomoc rozbudowanej wersji funkcji DrewCube` znanej
z poprzednich przykadw. Bdzie ona korzysta z funkcji glMultTexCoord2` w miej-
sce funkcji glTexCoord2` w celu zdefiniowania wsprzdnych jednostek tekstur dla
kadego wierzchoka szecianu:
vud DrawCubefual xPus, fual yPus, fual zPus)
{
Push|alrx),
1ransalefxPus, yPus, zPus),
Ben|_UADS),
Nurna8fDDf, 1Df, DDf), urna cana
Rozdzia 9. Zaawansowane odwzorowania tekstur 247
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8fD5f, D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8fD5f, D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8f-D5f, D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8f-D5f, D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, DDf, 1Df), przedna cana
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8fD5f, D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8f-D5f, D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8f-D5f, -D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8fD5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8f1Df, DDf, DDf), prawa cana
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8fD5f, D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8fD5f, -D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8fD5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8fD5f, D5f, -D5f),
End),
Ben|_UADS),
Nurna8f-1Df, DDf, DDf), ewa cana
248 Cz II Korzystanie z OpenGL
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8f-D5f, D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8f-D5f, D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8f-D5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8f-D5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, -1Df, DDf), duna cana
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8f-D5f, -D5f, D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8f-D5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8fD5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8fD5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, DDf, -1Df), lyna cana
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, DDf),
Verlex8fD5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, DDf),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, DDf),
Verlex8f-D5f, -D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, 1Df, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, 1Df, 1Df),
Verlex8f-D5f, D5f, -D5f),
|ul1exCuurd?fARB|_1EX1URED_ARB, DDf, 1Df),
|ul1exCuurd?fARB|_1EX1URE1_ARB, DDf, 1Df),
Verlex8fD5f, D5f, -D5f),
End),
Pup|alrx),
}
Rozdzia 9. Zaawansowane odwzorowania tekstur 249
Wikszo kodu funkcji |erder` znana jest z poprzednich przykadw. Okrela ona po-
oenie kamery i rysuje szecian.
vud Render)
{
radans - fualP*ane-9DDf)1BDDf),
wyznacza puuene |anery
caneraX - uu|X + snradans)*nuuse\,
caneraZ - uu|Z + cusradans)*nuuse\,
canera\ - uu|\ + nuuse\ ?Df,
wyceuwue |anere w pun|l D,D,D)
uu|X - DDf,
uu|\ - DDf,
uu|Z - DDf,
upruna bufury e|ranu eb
Cear|_C|R_BU||ER_B1 | |_DEP1H_BU||ER_B1),
|uaddenlly),
uneszcza |anere
u|uu|AlcaneraX, canera\, caneraZ, uu|X, uu|\, uu|Z, DD, 1D, DD),
s|aue szecan du ruznaruw 15x15x15
Scaef15Df, 15Df, 15Df),
rysue szecan u rud|u w pun|ce D,D,D)
DrawCubeDDf, DDf, DDf),
SwapBuffers_HDC), przeacza bufury
}
Po umieszczeniu omwionych funkcji w szkielecie standardowej aplikacji systemu Win-
dows uzyskany zostanie program, ktrego dziaanie ilustruje rysunek 9.3.
Rysunek 9.3.
Przykad
zastosowania
tekstury wielokrotnej
250 Cz II Korzystanie z OpenGL
Tekstury wielokrotne mog by rdem doskonaych efektw i dlatego z pewnoci
warto z nimi poeksperymentowa troch wicej. Pora jednak na omwienie kolejnego
doskonaego narzdzia tworzenia zaawansowanych efektw graficznych: odwzorowania
otoczenia.
Odwzorowanie otoczenia
Odwzorowanie otoczenia polega na stworzeniu obiektu, ktrego powierzchnia wydaje
si odbiciem jego otoczenia. Na przykad doskonale wypolerowana srebrna kula odbija
bdzie na swojej powierzchni elementy otaczajcego j wiata. Wanie taki efekt mona
uzyska stosujc odwzorowanie otoczenia. W tym celu nie trzeba jednak wcale tworzy
obrazu odbicia otoczenia na powierzchni efektu. W OpenGL wystarczy jedynie utwo-
rzy tekstur reprezentujc otoczenie obiektu, a OpenGL automatycznie wygeneruje
odpowiednie wsprzdne tekstury. Zmiana pooenia obiektu wymaga wyznaczenia
nowych wsprzdnych tekstury, by mona byo uzyska efekt odbicia zmieniajcego si
razem z poruszajcym si obiektem.
Najlepszy efekt zastosowania odwzorowania otoczenia uzyska mona uywajc tekstur
utworzonych za pomoc rybiego oka. Zastosowanie takich tekstur nie jest absolutnie
konieczne, ale znacznie zwiksza realizm odwzorowania otoczenia. Wsprzdne tek-
stury mona te oblicza indywidualnie, jednak zmniejsza to zwykle efektywno two-
rzenia grafiki.
Aby skorzysta w OpenGL z moliwoci odwzorowania otoczenia, niezbdny jest po-
niszy fragment kodu:
1exenf|_S, |_1EX1URE_EN_|DE, |_SPHERE_|AP),
1exenf|_1, |_1EX1URE_EN_|DE, |_SPHERE_|AP),
Enabe|_1EX1URE_EN_S),
Enabe|_1EX1URE_EN_1),
naslepne wybera le|slure uluczena rysue ube|l
I to wszystko! Teraz naley przeanalizowa przykad zastosowania moliwoci odwzo-
rowania otoczenia.
Torus na niebie
Omwiony teraz zostanie przykad zastosowania moliwoci odwzorowania otoczenia
w programie, ktry rysowa bdzie torus pokryty tekstur otoczenia. Rysunek 9.4 przed-
stawia kocowy efekt dziaania programu.
Tekstur otoczenia utworzy mona na podstawie tekstury nieba, do ktrej zastosowany
zostanie efekt rybiego oka za pomoc dowolnego edytora obrazw dysponujcego tak
moliwoci. Rysunek 9.5 przedstawia otrzyman tekstur otoczenia.
Rozdzia 9. Zaawansowane odwzorowania tekstur 251
Rysunek 9.4.
Torus pokryty
tekstur otoczenia
Rysunek 9.5.
Tekstura otoczenia
uzyskana
na podstawie
tekstury nieba
Teraz naley przyjrze si kodowi programu. Poniej przedstawione zostay jego frag-
menty zwizane z tworzeniem tekstur i rysowaniem grafiki:
lypedef slrucl
{
nl wdlh, szeru|uc le|slury
nl hehl, wysu|uc le|slury
unsned nl lexD, ube|l le|slury
unsned char *dala, dane le|slury
} lexlure_l,

fual ane - DDf, |al ubrulu lurusa


lexlure_l *env1ex, le|slura uluczena
lexlure_l *s|y1ex, le|slura neba

buu |uadA1exlures)
{
adue ubraz le|slury uluczena
env1ex - |uad1exlure|e's|y-spherebnp'),
f env1ex -- NU||)
relurn fase,
s|y1ex - |uad1exlure|e's|ybnp'),
f s|y1ex -- NU||)
relurn fase,
252 Cz II Korzystanie z OpenGL
lwurzy npnapy z flruwanen nuwyn da le|slury uluczena
Bnd1exlure|_1EX1URE_?D, env1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
uBud?D|pnaps|_1EX1URE_?D, |_RB, env1ex->wdlh, env1ex->hehl,
|_RB, |_UNSNED_B\1E, env1ex->dala),
lwurzy npnapy z flruwanen nuwyn da le|slury neba
Bnd1exlure|_1EX1URE_?D, s|y1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
uBud?D|pnaps|_1EX1URE_?D, |_RB, s|y1ex->wdlh, s|y1ex->hehl,
|_RB, |_UNSNED_B\1E, s|y1ex->dala),
relurn lrue,
}

vud Render)
{
zwe|sza |al ubrulu
f ane > 8GDDf)
ane - DDf,
ane - ane + D?f,
upruna bufury e|ranu eb
Cear|_C|R_BU||ER_B1 | |_DEP1H_BU||ER_B1),
|uaddenlly),
Bnd1exlure|_1EX1URE_?D, s|y1ex->lexD),
Ben|_UADS),
1exCuurd?fDDf, DDf),
Verlex8f-?DDDf, -?DDDf, -1?DDf),
1exCuurd?f1Df, DDf),
Verlex8f?DDDf, -?DDDf, -1?DDf),
1exCuurd?f1Df, 1Df),
Verlex8f?DDDf, ?DDDf, -1?DDf),
1exCuurd?fDDf, 1Df),
Verlex8f-?DDDf, ?DDDf, -1?DDf),
End),
udsuwa ube|l ubraca u wzeden wszysl|ch us u|adu wspurzednych
1ransalefDDf, DDf, -1DDDf),
Rulalefane, 1Df, DDf, DDf),
Rulalefane, DDf, 1Df, DDf),
Rulalefane, DDf, DDf, 1Df),
|unfurue udwzuruwane uluczena
1exenf|_S, |_1EX1URE_EN_|DE, |_SPHERE_|AP),
1exenf|_1, |_1EX1URE_EN_|DE, |_SPHERE_|AP),
Enabe|_1EX1URE_EN_S),
Enabe|_1EX1URE_EN_1),
Rozdzia 9. Zaawansowane odwzorowania tekstur 253
wybera le|slure uluczena
Bnd1exlure|_1EX1URE_?D, env1ex->lexD),
rysue lurus u prunenu wewnelrznyn ruwnyn 1D ednusle|
prunenu zewnelrznyn ?D ednusle|
auxSud1urus1DDf, ?DDf),
|ush),
SwapBuffers_HDC), przeacza bufury
}
Jak atwo zauway, stosowanie odwzorowania otoczenia w OpenGL jest niezwykle
proste, o ile pozwoli si maszynie OpenGL automatycznie wyznacza wsprzdne tek-
stury. Wsprzdne te mona oblicza indywidualnie, aby uzyska inne efekty specjalne,
ale zagadnienie to nie bdzie tutaj omawiane.
Macierze tekstur
W rozdziale 5. omwione zostay sposoby wykonywania przeksztace wierzchokw,
takich jak przesunicie, obrt i skalowanie za pomoc macierzy modelowania. Przed-
stawiona zostaa take koncepcja stosu macierzy umoliwiajca hierarchiczne tworzenie
grafiki.
Takie same moliwoci w przypadku tekstur OpenGL udostpnia za pomoc macierzy
tekstur i stosu macierzy tekstur. Na przykad funkcj glTrerlete` mona zastosowa
do przesunicia tekstury na odpowiedni powierzchni. Podobnie funkcj gl|otete`
mona wykorzysta do obrotu ukadu wsprzdnych tekstury i uzyska w efekcie obrt
tekstury. Gra American McGees Alice firmy Electronic Arts and Rogue Entertain-
ment jest najlepszym przykadem niezwykych efektw, jakie mona osign poprzez
manipulacje macierz tekstur.
Wykonywanie operacji na macierzach tekstur jest bardzo atwe. Stosuje si w tym celu
udostpniane przez OpenGL funkcje glMultMetrx`, glPu|Metrx`, glPopMetrx`
oraz funkcje przeksztace. Najpierw jednak trzeba poinformowa maszyn OpenGL,
e wykonywane bd operacje na macierzy tekstur:
|alrx|ude|_1EX1URE),
Od tego momentu na macierzy tekstur i stosie macierzy tekstur mona wykonywa do-
wolne operacje. Po ich zakoczeniu naley poleci maszynie OpenGL powrt do ma-
cierzy modelowania, aby zamiast tekstur przeksztaca obiekty.
Poniej zaprezentowany zosta fragment kodu ilustrujcy sposb wykonywania obrotu
tekstury:
upruna bufury e|ranu eb
Cear|_C|R_BU||ER_B1 | |_DEP1H_BU||ER_B1),
|uaddenlly),
wybera lryb uperac na nacerzy le|slur
|alrx|ude|_1EX1URE),
|uaddenlly),
254 Cz II Korzystanie z OpenGL
Rulalefane, DDf, DDf, 1Df), ubraca le|slure
przywraca lryb uperac na nacerzy nudeuwana
|alrx|ude|_|DE|VEu),
Bnd1exlure|_1EX1URE_?D, lexD), wybera le|slure
rysue czwuru|al pu|ryly le|slura
Ben|_UADS),
1exCuurd?fDDf, DDf),
Verlex8f-?DDf, -?DDf, -4DDf),
1exCuurd?f1Df, DDf),
Verlex8f?DDf, -?DDf, -4DDf),
1exCuurd?f1Df, 1Df),
Verlex8f?DDf, ?DDf, -4DDf),
1exCuurd?fDDf, 1Df),
Verlex8f-?DDf, ?DDf, -4DDf),
End),
Kod ten wybiera najpierw macierz tekstury jako biec macierz. Nastpnie aduje do
niej macierz jednostkow, zanim zastosuje do biecej macierzy funkcj obrotu gl|ote
te`. Na skutek jej uycia tekstura zostaje obrcona o pewien kt wzgldem osi z. Po
wykonaniu obrotu wybiera macierz modelowania jako biec macierz i rysuje czworo-
kt pokryty obrcon tekstur. Proste, prawda?
Gdyby po czworokcie zostay narysowane kolejne obiekty, to take zostayby one po-
kryte obrcon tekstur. Rozwizanie tego problemu zaprezentowane zostao poniej:
upruna bufury e|ranu eb
Cear|_C|R_BU||ER_B1 | |_DEP1H_BU||ER_B1),
|uaddenlly),
wybera lryb uperac na nacerzy le|slur
|alrx|ude|_1EX1URE),
|uaddenlly),
Rulalefane, DDf, DDf, 1Df), ubraca le|slure
przywraca lryb uperac na nacerzy nudeuwana
|alrx|ude|_|DE|VEu),
Bnd1exlure|_1EX1URE_?D, lexD), wybera le|slure
rysue czwuru|al pu|ryly le|slura
Ben|_UADS),
1exCuurd?fDDf, DDf),
Verlex8f-?DDf, -?DDf, -4DDf),
1exCuurd?f1Df, DDf),
Verlex8f?DDf, -?DDf, -4DDf),
1exCuurd?f1Df, 1Df),
Verlex8f?DDf, ?DDf, -4DDf),
1exCuurd?fDDf, 1Df),
Verlex8f-?DDf, ?DDf, -4DDf),
End),
reselue nacerz le|slur da naslepnych ube|luw
|alrx|ude|_1EX1URE),
|uaddenlly),
|alrx|ude|_|DE|VEu),
rysue naslepne ube|ly

Rozdzia 9. Zaawansowane odwzorowania tekstur 255


Wystarczy jedynie zaadowa macierz jednostkow do macierzy tekstur, aby wykonane
przeksztacenia tekstury nie miay wpywu na sposb rysowania tekstur na kolejnych
obiektach. Warto wyprbowa rne przeksztacenia tekstur i uzyska nowe, ciekawe
efekty, ktre mona bdzie zastosowa w grach.
Mapy owietlenia
Zadaniem map owietlenia jest symulacja statycznego owietlenia powierzchni. Mapa
owietlenia jest tekstur, ktra opisuje sposb owietlenia powierzchni. Mapy owietle-
nia znajduj coraz powszechniejsze zastosowanie dziki wprowadzeniu sprztowej ob-
sugi tekstur wielokrotnych. Cho mapy owietlenia stosowane s gwnie w celu uzy-
skania efektu statycznego owietlenia, mona je wykorzysta take do tworzenia cieni.
Rysunek 9.6 przedstawia map owietlenia symulujc efekt strumienia wiat padaj-
cego na powierzchni pod ktem prostym. Jeli pokryty ni zostanie wielokt, to uzyskany
zostanie efekt owietlenia strumieniem wiata prostopadym do jego powierzchni.
Rysunek 9.6.
Przykad mapy
owietlenia
Mapy owietlenia s teksturami wykorzystujcymi jedynie odcienie szaroci. Aby uzy-
ska efekt owietlenia, map tak naley poczy z tekstur pokrywajc wielokt.
Stosowanie map owietlenia
Map owietlenia stosuje si na przykad do uzyskania efektu owietlenia szecianu po-
krytego tekstur szachownicy. Trzeba naoy j na kad ze cian szecianu, by uzy-
ska efekt pokazany na rysunku 9.7.
Rysunek 9.7.
Zastosowanie
mapy owietlenia
256 Cz II Korzystanie z OpenGL
adujc map owietlenia z pliku naley zadba o to, by jej piksele opisane byy za po-
moc odcieni szaroci. Poniej zamieszczona zostaa zmodyfikowana wersja funkcji |o
edOtepFle` adujcej map owietlenia z 24-bitowego pliku BMP jako obraz w od-
cieniach szaroci:
unsned char *|uadrayBlnapchar *fenane, B1|APN|HEADER *blnapnfuHeader)
{
||E *fePlr, ws|an| puzyc p|u
B1|AP||EHEADERblnap|eHeader, nauwe| p|u
unsned char*blnapnae, dane ubrazu
nlnaedx - D, czn| p|se
unsned charlenpRB, znenna zanany s|aduwych
unsned char *raynae, ubraz w udcenach szaruc
nl raydx, czn| p|se w udcenach szaruc
ulwera p| w lrybe 'read bnary'
fePlr - fupenfenane, 'rb'),
f fePlr -- NU||)
relurn NU||,
wczylue nauwe| p|u
fread&blnap|eHeader, szeufB1|AP||EHEADER), 1, fePlr),
sprawdza, czy esl lu p| furnalu B|P
f blnap|eHeaderbf1ype - B1|AP_D)
{
fcusefePlr),
relurn NU||,
}
wczylue nauwe| ubrazu
freadblnapnfuHeader, szeufB1|APN|HEADER), 1, fePlr),
uslawa ws|an| puzyc p|u na puczal|u danych ubrazu
fsee|fePlr, blnap|eHeaderbfffBls, SEE|_SE1),
przydzea panec bufuruw ubrazu
blnapnae - unsned char*)naucblnapnfuHeader->bSzenae),
przydzea panec pulrzebna du przechuwana ubrazu
w udcenach szaruc,
lrzy razy nnesza n ruznar ubrazu RB
raynae - unsned char*)naucblnapnfuHeader->bSzenae 8),
sprawdza, czy udau se przydzec panec
f blnapnae)
{
freeblnapnae),
fcusefePlr),
relurn NU||,
}
wczylue dane ubrazu
freadblnapnae, 1, blnapnfuHeader->bSzenae, fePlr),
Rozdzia 9. Zaawansowane odwzorowania tekstur 257
sprawdza, czy dane zuslay wczylane
f blnapnae -- NU||)
{
fcusefePlr),
relurn NU||,
}
raydx - D,
fur naedx - D, naedx < blnapnfuHeader->bSzenae, naedx+-8)
{
raynae[raydx] - blnapnae[naedx],
raydx++,
}
freeblnapnae),
zany|a p| zwraca ws|an| bufura zaweraaceu wczylany ubraz
fcusefePlr),
relurn raynae,
}
Po zaadowaniu mapy owietlenia mona posugiwa si ni jak zwyk tekstur z jedn
rnic: format jej trzeba zawsze definiowa jako C|_|UMI|A|CL, a nie jako C|_|CO. A oto
przykad:
napa uwelena a|u npnapa
uBud?D|pnaps|_1EX1URE_?D, |_|U|NANCE, wdlh, hehl, |_|U|NANCE,
|_UNSNED_B\1E, hlnapDala),
ub puedyncza le|slura
1exnae?D |_1EX1URE_?D, D, |_|U|NANCE, wdlh, hehl, D, |_|U|NANCE,
|_UNSNED_B\1E, hlnapDala),
Aby zastosowa map owietlenia, naley posuy si mechanizmem tekstur wielo-
krotnych i wczy tryb nakadania tekstury C|_M0DU|ATL. Trzeba zatem przyjrze si naj-
istotniejszym fragmentom kodu tego programu:
lypedef slrucl
{
nl wdlh, szeru|uc le|slury
nl hehl, wysu|uc le|slury
unsned nl lexD, ube|l le|slury
unsned char *dala, dane le|slury
} lexlure_l,
le|slury
lexlure_l *chec|er1ex, napa uwelena
lexlure_l *hlnap1ex, le|slura szachuwncy
fun|ce lwurzena le|slur weu|rulnych
P|N||U|11EXCRD?|ARBPRC |ul1exCuurd?fARB - NU||,
P|N|AC1VE1EX1UREARBPRC Aclve1exlureARB - NU||,
P|N|C|EN1AC1VE1EX1UREARBPRC CenlAclve1exlureARB - NU||,
nl nax1exlureUnls - D,
buu nl|ul1ex)
{
char *exlensunSlr, sla duslepnych ruzszerze
258 Cz II Korzystanie z OpenGL
exlensunSlr - char*)elSlrn|_EX1ENSNS),
f exlensunSlr -- NU||)
relurn fase,
f slrslrexlensunSlr, '|_ARB_nullexlure'))
{
pubera dupuszczana czbe ednusle| le|slur
elnleerv|_|AX_1EX1URE_UN1S_ARB, &nax1exlureUnls),
pubera adresy fun|c lwurzena le|slur weu|rulnych
|ul1exCuurd?fARB - P|N||U|11EXCRD?|ARBPRC)
welPrucAddress'|ul1exCuurd?fARB'),
Aclve1exlureARB - P|N|AC1VE1EX1UREARBPRC)
welPrucAddress'Aclve1exlureARB'),
CenlAclve1exlureARB - P|N|C|EN1AC1VE1EX1UREARBPRC)
welPrucAddress'CenlAclve1exlureARB'),
relurn lrue,
}
ese
relurn fase,
}
Funkcja IrtMultTex` sprawdza dostpno mechanizmu tworzenia tekstur wielokrot-
nych dla danej implementacji OpenGL. Tym razem wykorzystuje ona funkcj trtr`,
ktra zwraca warto |U||, jeli drugi z jej parametrw nie jest podacuchem pierwszego.
Kolejn z funkcji jest omwiona wczeniej funkcja adowania mapy owietlenia z pliku:
unsned char *|uadrayBlnapchar *fenane, B1|APN|HEADER *blnapnfuHeader)
{
||E *fePlr, ws|an| puzyc p|u
B1|AP||EHEADERblnap|eHeader, nauwe| p|u
unsned char*blnapnae, dane ubrazu
nlnaedx - D, czn| p|se
unsned charlenpRB, znenna zanany s|aduwych
unsned char *raynae, ubraz w udcenach szaruc
nl raydx, czn| p|se w udcenach szaruc
ulwera p| w lrybe 'read bnary'
fePlr - fupenfenane, 'rb'),
f fePlr -- NU||)
relurn NU||,
wczylue nauwe| p|u
fread&blnap|eHeader, szeufB1|AP||EHEADER), 1, fePlr),
sprawdza, czy esl lu p| furnalu B|P
f blnap|eHeaderbf1ype - B1|AP_D)
{
fcusefePlr),
relurn NU||,
}
Rozdzia 9. Zaawansowane odwzorowania tekstur 259
wczylue nauwe| ubrazu
freadblnapnfuHeader, szeufB1|APN|HEADER), 1, fePlr),
uslawa ws|an| puzyc p|u na puczal|u danych ubrazu
fsee|fePlr, blnap|eHeaderbfffBls, SEE|_SE1),
przydzea panec bufuruw ubrazu
blnapnae - unsned char*)naucblnapnfuHeader->bSzenae),
przydzea panec pulrzebna du przechuwana ubrazu
w udcenach szaruc,
lrzy razy nnesza n ruznar ubrazu RB
raynae - unsned char*)naucblnapnfuHeader->bSzenae 8),
sprawdza, czy udau se przydzec panec
f blnapnae)
{
freeblnapnae),
fcusefePlr),
relurn NU||,
}
wczylue dane ubrazu
freadblnapnae, 1, blnapnfuHeader->bSzenae, fePlr),
sprawdza, czy dane zuslay wczylane
f blnapnae -- NU||)
{
fcusefePlr),
relurn NU||,
}
raydx - D,
fur naedx - D, naedx < blnapnfuHeader->bSzenae, naedx+-8)
{
raynae[raydx] - blnapnae[naedx],
raydx++,
}
freeblnapnae),
zany|a p| zwraca ws|an| bufura zaweraaceu wczylany ubraz
fcusefePlr),
relurn raynae,
}
Nastpna funkcja, |oed|g|tep`, przypomina funkcj |oedTextureFle` z poprzed-
nich przykadw, ale korzysta z usug funkcji adowania mapy owietlenia |oedCrey
Otep`:
lexlure_l *|uad1exlure|echar *fenane)
{
B1|APN|HEADER lexnfu,
lexlure_l *lhs1exlure,
260 Cz II Korzystanie z OpenGL
przydzea panec slru|lurze lypu lexlure_l
lhs1exlure - lexlure_l*)naucszeuflexlure_l)),
f lhs1exlure -- NU||)
relurn NU||,
adue ubraz le|slury sprawdza puprawne wy|unane le uperac
lhs1exlure->dala - |uadrayBlnapfenane, &lexnfu),
f lhs1exlure->dala -- NU||)
{
freelhs1exlure),
relurn NU||,
}
uneszcza nfurnace u szeru|uc wysu|uc le|slury
lhs1exlure->wdlh - lexnfubudlh,
lhs1exlure->hehl - lexnfubHehl,
lwurzy ube|l le|slury
en1exlures1, &lhs1exlure->lexD),
relurn lhs1exlure,
}
Rwnie funkcja |oedAllTexture`, ktra prezentowana jest poniej, zostaa zmodyfi-
kowana pod ktem uycia mapy owietlenia, dla ktrej w odrnieniu od zwykych
tekstur naley zastosowa wartoci C|_|UMI|A|CL i C|_M0DU|ATL:
buu |uadA1exlures)
{
adue le|slure szachuwncy
chec|er1ex - |uad1exlure|e'chessbnp'),
f chec|er1ex -- NU||)
relurn fase,
adue nape uwelena
hlnap1ex - |uad|hlnap'napbnp'),
f hlnap1ex -- NU||)
relurn fase,
lwurzy le|slure szachuwncy
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
uBud?D|pnaps|_1EX1URE_?D, |_RB, chec|er1ex->wdlh, chec|er1ex->hehl,
|_RB, |_UNSNED_B\1E, chec|er1ex->dala),
lwurzy nape uwelena
Bnd1exlure|_1EX1URE_?D, hlnap1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_|DU|A1E),
uBud?D|pnaps|_1EX1URE_?D, |_|U|NANCE, hlnap1ex->wdlh,
hlnap1ex->hehl, |_|U|NANCE, |_UNSNED_B\1E, hlnap1ex->dala),
Rozdzia 9. Zaawansowane odwzorowania tekstur 261
wybera perwsza ednusl|e le|slury
Aclve1exlureARB|_1EX1URED_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD), wae le|slure szachuwncy
wybera drua ednusl|e le|slury
Aclve1exlureARB|_1EX1URE1_ARB),
Enabe|_1EX1URE_?D),
Bnd1exlure|_1EX1URE_?D, hlnap1ex->lexD), wae nape uwelena
relurn lrue,
}
Pozostaa cz kodu jest identyczna z pierwszym przykadem programu tworzenia tek-
stur wielokrotnych.
Wieloprzebiegowe tekstury wielokrotne
Brak obsugi mechanizmu tekstur wielokrotnych przez konkretn implementacj OpenGL
nie oznacza, e nie mona uzyska takich efektw innym sposobem. Rozwizanie polega
na symulacji tekstur wielokrotnych za pomoc doboru odpowiednich funkcji czenia
i tworzeniu kocowego efektu w wielu przebiegach rysowania grafiki. Metoda ta jest
zwykle wolniejsza od tekstur wielokrotnych, ktre coraz czciej obsugiwane s sprz-
towo, ale umoliwia uzyskanie podobnych efektw.
Wieloprzebiegowe tworzenie sceny polega na odpowiedniej zmianie zawartoci bufora
gbi i trybw czenia kolorw w kolejnych przebiegach. Aby uzyska taki efekt jak
w przypadku tekstur wielokrotnych, naley wykona poniszy fragment kodu:
perwszy przebe rysuwana
Bnd1exlure|_1EX1URE_?D, lex1),
Draw1exluredCubeDDf, DDf, DDf),
dru przebe rysuwana
Enabe|_B|END), wacza aczene |uuruw
Deplh|as||_|A|SE), wyacza zaps du bufura eb
Deplh|unc|_EUA|),
Bend|unc|_ZER, |_SRC_C|R),
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
Draw1exluredCubeDDf, DDf, DDf),
przywraca puprzedn slan naszyny pen|
Deplh|as||_1RUE),
Deplh|unc|_|ESS),
Dsabe|_B|END),
Poprzez zmian sposobu czenia kolorw uzyska mona efekt tekstury wielokrotnej.
Ponisze fragmenty kodu pokazuj, w jaki sposb mona uzyska w wielu przebiegach
taki sam efekt jak w przypadku pierwszego przykadu tekstur wielokrotnych:
262 Cz II Korzystanie z OpenGL
buu |uadA1exlures)
{
adue ubraz perwsze le|slury
sne1ex - |uad1exlure|e'snebnp'),
f sne1ex -- NU||)
relurn fase,
adue ubraz drue le|slury
chec|er1ex - |uad1exlure|e'chessbnp'),
f chec|er1ex -- NU||)
relurn fase,
lwurzy perwsza le|slure
Bnd1exlure|_1EX1URE_?D, sne1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_REP|ACE),
uBud?D|pnaps|_1EX1URE_?D, |_RB, sne1ex->wdlh, sne1ex->hehl,
|_RB, |_UNSNED_B\1E, sne1ex->dala),
lwurzy drua le|slure
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|A_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_|N_||1ER, |_|NEAR),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_S, |_REPEA1),
1exParaneler|_1EX1URE_?D, |_1EX1URE_uRAP_1, |_REPEA1),
1exEnv|_1EX1URE_ENV, |_1EX1URE_ENV_|DE, |_|DU|A1E),
uBud?D|pnaps|_1EX1URE_?D, |_RB, chec|er1ex->wdlh, chec|er1ex->hehl,
|_RB, |_UNSNED_B\1E, chec|er1ex->dala),
relurn lrue,
}
vud Draw1exluredCubefual xPus, fual yPus, fual zPus)
{
Push|alrx),
1ransalefxPus, yPus, zPus),
Ben|_UADS),
Nurna8fDDf, 1Df, DDf), urna cana
1exCuurd?f1Df, DDf),
Verlex8fD5f, D5f, D5f),
1exCuurd?f1Df, 1Df),
Verlex8fD5f, D5f, -D5f),
1exCuurd?fDDf, 1Df),
Verlex8f-D5f, D5f, -D5f),
1exCuurd?fDDf, DDf),
Verlex8f-D5f, D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, DDf, 1Df), przedna cana
1exCuurd?f1Df, 1Df),
Verlex8fD5f, D5f, D5f),
Rozdzia 9. Zaawansowane odwzorowania tekstur 263
1exCuurd?fDDf, 1Df),
Verlex8f-D5f, D5f, D5f),
1exCuurd?fDDf, DDf),
Verlex8f-D5f, -D5f, D5f),
1exCuurd?f1Df, DDf),
Verlex8fD5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8f1Df, DDf, DDf), prawa cana
1exCuurd?fDDf, 1Df),
Verlex8fD5f, D5f, D5f),
1exCuurd?fDDf, DDf),
Verlex8fD5f, -D5f, D5f),
1exCuurd?f1Df, DDf),
Verlex8fD5f, -D5f, -D5f),
1exCuurd?f1Df, 1Df),
Verlex8fD5f, D5f, -D5f),
End),
Ben|_UADS),
Nurna8f-1Df, DDf, DDf), ewa cana
1exCuurd?f1Df, 1Df),
Verlex8f-D5f, D5f, D5f),
1exCuurd?fDDf, 1Df),
Verlex8f-D5f, D5f, -D5f),
1exCuurd?fDDf, DDf),
Verlex8f-D5f, -D5f, -D5f),
1exCuurd?f1Df, DDf),
Verlex8f-D5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, -1Df, DDf), duna cana
1exCuurd?f1Df, DDf),
Verlex8f-D5f, -D5f, D5f),
1exCuurd?f1Df, 1Df),
Verlex8f-D5f, -D5f, -D5f),
1exCuurd?fDDf, 1Df),
Verlex8fD5f, -D5f, -D5f),
1exCuurd?fDDf, DDf),
Verlex8fD5f, -D5f, D5f),
End),
Ben|_UADS),
Nurna8fDDf, DDf, -1Df), lyna cana
264 Cz II Korzystanie z OpenGL
1exCuurd?fDDf, DDf),
Verlex8fD5f, -D5f, -D5f),
1exCuurd?f1Df, DDf),
Verlex8f-D5f, -D5f, -D5f),
1exCuurd?f1Df, 1Df),
Verlex8f-D5f, D5f, -D5f),
1exCuurd?fDDf, 1Df),
Verlex8fD5f, D5f, -D5f),
End),
Pup|alrx),
}
vud Render)
{
radans - fualP*ane-9DDf)1BDDf),
wyznacza puuene |anery
caneraX - uu|X + snradans)*nuuse\,
caneraZ - uu|Z + cusradans)*nuuse\,
canera\ - uu|\ + nuuse\ ?Df,
wyceuwue |anere w pun|l D,D,D)
uu|X - DDf,
uu|\ - DDf,
uu|Z - DDf,
upruna bufury e|ranu eb
Cear|_C|R_BU||ER_B1 | |_DEP1H_BU||ER_B1),
|uaddenlly),
uneszcza |anere
u|uu|AlcaneraX, canera\, caneraZ, uu|X, uu|\, uu|Z, DD, 1D, DD),
s|aue szecan du ruznaruw 15x15x15
Scaef15Df, 15Df, 15Df),
perwszy przebe rysuwana
Bnd1exlure|_1EX1URE_?D, sne1ex->lexD),
Draw1exluredCubeDDf, DDf, DDf),
dru przebe rysuwana
Enabe|_B|END), wacza aczene |uuruw
Deplh|as||_|A|SE), wyacza zaps du bufura eb
Deplh|unc|_EUA|),
Bend|unc|_ZER, |_SRC_C|R),
Bnd1exlure|_1EX1URE_?D, chec|er1ex->lexD),
Draw1exluredCubeDDf, DDf, DDf),
przywraca puprzedn slan naszyny pen|
Deplh|as||_1RUE),
Deplh|unc|_|ESS),
Dsabe|_B|END),
|ush),
SwapBuffers_HDC), przeacza bufury
}
Rozdzia 9. Zaawansowane odwzorowania tekstur 265
Efekt uzyskany w wyniku wieloprzebiegowego tworzenia tekstur nie bdzie si rni
od efektw uzyskanych za pomoc tekstur wielokrotnych. Zwykle jednak tworzony b-
dzie wolniej, poniewa mechanizm tekstur wielokrotnych korzysta z moliwoci ich
sprztowej obsugi. Jednak tworzenie tekstur wielokrotnych w wielu przebiegach po-
zwala na dodatkowe eksperymentowanie z rnymi efektami uzyskiwanymi przez zmian
funkcji czenia kolorw.
Podsumowanie
OpenGL umoliwia pokrycie powierzchni wielokta sekwencj tekstur tworzc tekstur
wielokrotn.
W procesie tworzenia tekstur wielokrotnych wyrni mona cztery etapy: sprawdzenie
dostpnoci tekstur wielokrotnych, uzyskanie wskanikw funkcji rozszerzenia, stwo-
rzenie jednostki tekstury i okrelenie wsprzdnych tekstur.
Odwzorowanie otoczenia pozwala rysowa obiekty odbijajce otaczajcy je wiat na po-
dobiestwo wypolerowanej srebrnej kuli.
Stos macierzy tekstur umoliwia wykonywanie przesuni, obrotw i skalowa tekstur.
Przeksztacenia tekstur umoliwiaj uzyskanie ciekawych efektw.
Mapy owietlenia su do symulacji statycznego owietlenia obiektu za pomoc odpo-
wiedniej tekstury reprezentujcej wiato padajce na dan powierzchni.