You are on page 1of 690

Spis treci

O
autorach...............................................................................................................
21
Przedmowa
..............................................................................................................23
Wprowadzenie......................................................................................................
.... 25
Dla kogo jest ta ksika?............................................................................................................26
System wymagany dla OpenGL.................................................................................................26
Jzyk...........................................................................................................................................26
Kompilatory ...............................................................................................................................27
Co znajdziesz w tej ksice........................................................................................................27
Cz I: Wprowadzenie do OpenGL....................................................................................28
Cz II: Uywanie OpenGL ...............................................................................................28
Cz III: Tematy zaawansowane i efekty specjalne............................................................29
Cz IV: OpenGL i... .........................................................................................................30
Dodatki..............................................................................................:..................................31
Pytka CD-ROM doczona do ksiki.......................................................................................31
Do dziea!...................................................................................................................................32

Cz l
Wprowadzenie do OpenGL.................................................................. 33
Rozdzia 1.
Co to jest OpenGL?.................................................................................................. 35
O OpenGL..................................................................................................................................36
Historia OpenGL..................................................................................................................36
Dalszy rozwj OpenGL........................................................................................................37
Jak dziaa OpenGL.....................................................................................................................37
OpenGL w Windows..................................................................................................................38
Architektura graficzna: oprogramowanie kontra sprzt .......................................................38
Ograniczenia oglnej implementacji....................................................................................40
Dalsze perspektywy OpenGL w Windows.................................................................................40
Rozdzia 2.
Podstawy grafiki
3D................................................................................................. 41
Postrzeganie w trzech wymiarach ..............................................................................................41
2D + Perspektywa = 3D.......................................................................................................42
Usuwanie niewidocznych linii .............................................................................................43
Kolory i cieniowanie............................................................................................................43
wiata i cienie.....................................................................................................................44
OpenGL - ksiga eksperta

Ukady wsprzdnych ...............................................................................................................44


Dwuwymiarowe wsprzdne kartezjaskie ........................................................................45
Obcinanie wsprzdnych....................................................................................................46
Widoki, twoje okna na trjwymiarowy wiat....................................................................... 46
Rysowanie prymityww....................................................................................................... 47
Trjwymiarowe wsprzdne kartezjaskie ......................................................................... 48
Rzuty, podstawa grafiki 3D........................................................................................................48
Rzuty rwnolege ................................................................................................................. 49
Rzuty perspektywiczne........................................................................................................ 50
Podsumowanie ...........................................................................................................................50
Rozdzia 3.
Nauka OpenGL z uyciem biblioteki AUX
................................................................... 51
OpenGL: API, nie jzyk............................................................................................................. 5 1
Podzia pracy w OpenGL..................................................................................................... 52
Typy danych OpenGL.......................................................................................................... 53
Konwencje nazw funkcji.. .................................................................................................... 55
Biblioteka AUX.......................................................................................................................... 56
Niezaleno od platformy................................................................................................... 57
AUX = wejcie/wyjcie w prosty sposb............................................................................. 57
Analiza krtkiego programu OpenGL........................................................................................ 58
Cz nagwkowa............................................................................................................... 59
Ciao programu ....................................................................................................................60
Tryb wywietlania: pojedynczy bufor.................................................................................. 60
Pozycjonowanie okna.. ........................................................................................................ .60
Tworzenie okna OpenGL..................................................................................................... 62
Czyszczenie okna (wypenianie kolorem). ........................................................................ ...62
Samoczyszczenie okna.. ............................. ...................................................................... ....64
Oprnienie zawartoci kolejki............................................................................................ 64
Rysowanie ksztatw za pomoc OpenGL .................................................................................65
Funkcja renderujca............................................................................................................. 66
Rysowanie prostokta ..........................................................................................................66
Inicjowanie........................................................................................................................... 67
Skalowanie do rozmiarw okna .................................................................................................68
Ustawianie widoku i bryy obcinania................................................................................... 68
Definiowanie widoku........................................................................................................... 7 1
Definiowanie bryy obcinania.............................................................................................. 72
Aby kwadrat by kwadratem ................................................................................................73
Animacja przy uyciu biblioteki AUX... .................................................................................... 74
Podwjne buforowanie......................................................................................................... 77
W kocu troch trzeciego wymiaru!..... ...................................................................................... 78
Podsumowanie ...........................................................................................................................79
Podrcznik.. ........................................................................................................................... .....79
aux!dleFunc..........................................................................................................................79
auxnitDisplayMode...... .................................................................................................... ...80
aux!nitPosition ..................................................................................................................... 8 1

aiucReshapeFunc ............................................................................................................... ...85


auxSetOneColor. ............................................................................................................... ...85
auxSolidBox.. ....................................................................................................................... 86
Spis treci

auxSolidCube.... ............................................................................................................... ....87


AuxSolidCylinder ................................................................................................................ 87
auxSolidDodecahedron. ..................................................................................................... ..88

auxSolidSphere .................................................................................................................... 89
auxSolidTeapot .................................................................................................................... 89
auxSolidTetrahedron.. ..................................................................................................... .....90

auxWireCone ....................................................................................................................... 9 1
auxWireCube ..................................................................................................................... ..92

auxWire!cosahedron ............................................................................................................93
auxWireOctahedron ............................................................................................................. 94
auxWireSphere.....................................................................................................................94
auxWireTeapot.. ................................................................................................................ ...95
auxWireTetrahedron ............................................................................................................95
auxWireTorus. ...................................................................................................................... 95

glYiewport...........................................................................................................................97
glRect...................................................................................................................................98
Rozdzia 4.
OpenGL for Windows: OpenGL + Win32 = Wiggle..................................................... 101
Rysowanie w oknach Windows................................................................................................ 102
Konteksty urzdze GDI....................................................................................................102
Konteksty renderowania OpenGL......................................................................................l 05
Korzystanie z funkcji Wiggle................................................................................................... 106
Tworzenie i wybieranie kontekstu renderowania............................................................... 106
Rysowanie przy uyciu OpenGL........................................................................................ 106
Przygotowanie okna dla OpenGL.............................................................................................l 08
Style okien .........................................................................................................................108
Formaty pikseli ..................................................................................................................108
Powrt odbijajcego si kwadratu............................................................................................ 111
Skalowanie do okna........................................................................................................... 114
Tykniciatimera.................................................................................................................ll4
wiata, kamera, akcja!................................................................................................
15
Podsumowanie. 16 16 16 18 GetPixelFormat
Podrcznik........ ..................................................................................................................
ChoosePixelFormat... 122
DescribePixelFormat. SetPixelFormat.. ......................................................................................
........................... 122
SwapBuffers.... ............................................................................................................... ....123
wglCreateContext...........................................................................................,...................124
wglDeleteContext.. ............................................................................................................. 125
wglGetCurrentContext.. ................................................................................................... ..125
wglGetCurrentDC .............................................................................................................. 126
wglGetProcAddress..... .................................................................................................. .....126
10______________________________________OpenGL - ksiga eksperta

wglMakeCurrent.....................................................................................................
........... 127
wglShareLists..........................................................................................................
........... 128
wglUseFontBitmaps...............................................................................................
............ 129
wglUseFontOutlines.............................................................................................
..............130
Rozdzia 5.
Bdy i inne komunikaty
OpenGL............................................................................. 133
Gdy dobremu programowi przydarzaj si ze przygody
........................................................134
Kim jestem i co potrafi?
.........................................................................................................135
Rozszerzenia
OpenGL........................................................................................................ 136
Udzielanie wskazwek za pomoc funkcji
glHint................................................................... 137
Podsumowanie
.........................................................................................................................138
Podrcznik...................................................................................................................
............. 138
glGetLastError.....................................................................................................
..............138
glGetLastError.......................................................................................................
............ 138
glGetString...........................................................................................................
..............139
glHint......................................................................................................................
........... 140
gluErrorString......................................................................................................
..............141
gluGetString...........................................................................................................
............141

Cz II
Uywanie OpenGL............................................................................ 143
Rozdzia 6.
Rysowanie w trzech wymiarach: linie, punkty i
wielokaty.........................................145
Rysowanie punktw w przestrzeni
trjwymiarowej................................................................ 146
Przygotowanie trjwymiarowej
osnowy............................................................................ 146
Trjwymiarowy punkt: wierzchoek
.................................................................................. 148
Narysujmy co!
..................................................................................................................149
Rysowanie
punktw...........................................................................................................14
9
Ustalanie rozmiaru
punktu................................................................................................. 152
Rysowanie linii w trzech
wymiarach........................................................................................ 155
amane i amane
zamknite............................................................................................... 156
Przyblianie krzywych
odcinkami..................................................................................... 157
Ustalanie gruboci
linii...................................................................................................... 158
Linie
przerywane.............................................................................................................
... 160
Rysowanie trjktw w przestrzeni
3D.................................................................................... 162
Trjkt: twj pierwszy
wielokt......................................................................................... 162
Kierunek.................................................................................................................
............ 163
Paski
trjktw..............................................................................................................
.....164
Wachlarze
trjktw..........................................................................................................
165
Budowanie jednolitych
obiektw............................................................................................. 166
Ustawianie kolorw
wieloktw........................................................................................ 169
Korzystanie z bufora
gbokoci........................................................................................ 169
Ukrywanie niewidocznych
powierzchni............................................................................ 171
Tryby
wieloktw.............................................................................................................
. 173
Inne prymitywy
........................................................................................................................174
Czworokty
........................................................................................................................174
Paski
czworoktw........................................................................................................
.....l75
Oglne
wielokty.............................................................................................................
..l75
Wypenianie
wieloktw....................................................................................................l75
Reguy konstruowania
wieloktw.................................................................................... 179
Podzia
wielokta...............................................................................................................
181
Podsumowanie
.........................................................................................................................183
Spis treci

Podrcznik. ........................................................................................................................... ....l 84


glBegin.. ............................................................................................................................. 184
glCullFace............,.............................................................................................................185
glEdgeFlag. ..................................................................................................................... ...186
glEnd...... .......................................................................................................................... ..188
glFrontFace........................................................................,...............................................188
glGetPolygonStipple .......................................................................................................... 1 89
glLineStipple.. ................................................................................................................ ....190

glPolygonMode. ............................................................................................................... ..194


glPolygonStipple. .............................................................................................................. .195
glVertex................................................,.............................................................................196
Rozdzia 7.
Manipulowanie przestrzeni 3D: transformacje wsprzdnych
.................................199
Czy to jest ten rozdzia z matematyk? ....................................................................................200
Przeksztacenia.........................................................................................................................200
Wsprzdne obserwatora..................................................................................................201
Przeksztacenia punktu obserwacji.. ............................................................................... ....202
Przeksztacenia modelu...................................................................................................... 202
Dwoisto widoku modelu.................................................................................................204
Przeksztacenia rzutowania................................................................................................205
Przeksztacenia okna. ......................................................................................................... 206
Ach, te macierze........ .......................................................................................................... .....206
Co to jest macierz?... ..................................................................................................... .....206
Kolejka przeksztace ........................................................................................................207
Macierz widoku modelu.... ................................................................................................. 208
Macierz tosamociowa ..................................................................................................... 2 1 1
Stosy macierzy ...................................................................................................................2 1 3
Atomowy przykad.............................................................................................................214
Rzutowania.. ............................................................................................................................. 21 6
Rzutowanie rwnolege......................................................................................................217
Rzutowanie perspektywiczne.............................................................................................218
Przykad daleko-blisko.. ................................................................................................ .....220
Zaawansowane operacje na macierzach ...................................................................................223
adowanie macierzy ..........................................................................................................223
Tworzenie wasnych przeksztace .................................................................................... 224
Inne przeksztacenia.. .................................................................................................... .....224
Podsumowanie .........................................................................................................................224
Podrcznik. ............................................................................................................................ ...225
glFrustum...........................................................................................................................225
glLoadldentity... ............................................................................................................. ....226
glLoadMatrix ..................................................................................................................... 226
glMatrixMode . ................................................................................................................. ..227

glPopMatrix ....................................................................................................................... 228

glTranslate.... .................................................................................................................... ..23 1


gluLookAt...... .................................................................................................................. ..23 1
gluOrtho2D........................................................................................................................232
gluPerspective. ................................................................................................................... 233
12______________________________________OpenGL - ksiga eksperta

Rozdzia 8.
Kolory i
cieniowanie...............................................................................................
235
Czym jest kolor?.......................................................................................................................236
wiato jako fala.................................................................................................................236
wiato jako czsteczka......................................................................................................237
Twj osobisty wykrywacz fotonw....................................................................................237
Komputer jako generator fotonw .....................................................................................238
Sprzt grafiki kolorowej...........................................................................................................239
Tryby graficzne w komputerach osobistych............................................................................241
Rozdzielczoci ekranu........................................................................................................241
Gboko koloru...............................................................................................................241
Kolor 4-bitowy...................................................................................................................242
Kolor 8-bitowy................................................................................................................... 242
Kolor 24-bitowy.................................................................................................................242
Inne gbokoci koloru.......................................................................................................242
Wybr koloru...........................................................................................................................243
Kostka kolorw..................................................................................................................243
Ustalanie koloru rysowania................................................................................................245
Cieniowanie .......................................................................................................................246
Ustawianie trybu cieniowania ............................................................................................248
Palety Windows........................................................................................................................249
Dopasowywanie kolorw.............,.....................................................................................249
Dithering............................................................................................................................250
Korzyci ze stosowania palety w trybie 8-bitowym ...........................................................251
Tworzenie palety......................................................................................................................253
Czy potrzebujesz palety?....................................................................................................254
Struktura palety..................................................................................................................254
Paleta 3-3-2........................................................................................................................255
Tworzenie i usuwanie palety..............................................................................................258
Pewne ograniczenia..................:.........................................................................................259
Tryb indeksu koloru .................................................................................................................259
Kiedy uywa trybu indeksu koloru?.................................................................................259
Uycie trybu indeksu koloru ..............................................................................................260
Podsumowanie .........................................................................................................................262
Podrcznik................................................................................................................................ 263
glClearIndex.......................................................................................................................263
glColor...............................................................................................................................263
glColorMask......................................................................................................................265
gllndex...............................................................................................................................265
gl!ndexMask.......................................................................................................................266
glLogicOp..........................................................................................................................267
glShadeModel....................................................................................................................268
Rozdzia 9.
Owietlenie i rda
wiata.................................................................................... 271
wiato w rzeczywistym wiecie..............................................................................................272
wiato otaczajce..............................................................................................................273
wiato rozproszone...........................................................................................................273
wiato odbyskw.............................................................................................................273
Zmy to razem ................................................................................................................274
Materiay w rzeczywistym wiecie...........................................................................................275
Waciwoci materiau .......................................................................................................275
Owietlanie materiaw......................................................................................................275
Spis treci

Obliczanie efektw wiata otaczajcego... ................................................................... .....276


Efekty wiata rozpraszajcego i odbyskw......................................................................277
Umieszczenie wiata w scenie... ............................................................................................. .277
Wczanie owietlenia........................................................................................................ 277
Przygotowanie modelu owietlenia.................................................................................... 278
Przygotowanie waciwoci materiau ...............................................................................279
Uywanie rda wiata...........................................................................................................28 1
Gdzie jest gra?.... ............................................................................................................. .282
Normalne do powierzchni. ............................................................................................ .....283
Okrelanie normalnej .........................................................................................................283
Normalne jednostkowe.. .................................................................................................... .285
Znajdowanie normalnej...................................................................................................... 286
Przygotowanie rda wiata............................................................................................. 288
Przygotowanie waciwoci materiau ...............................................................................289
Rysowanie wieloktw ...................................................................................................... 289
Efekty owietlenia.. ................................................................................................................ ..29 1
Odbyski.............................. ............................................................................................... 291
wiato odbyskw..................... ....................................................................................... .29 1
Waciwoci odbyskw materiau..................................................................................... 292
Stopie poyskliwoci ........................................................................................................293
Urednianie normalnych ....................................................................................................294
wiata punktowe..................................................................................................................... 298
Tworzenie wiata punktowego. .................................................................................... .....299
Rysowanie wiata punktowego .................................................................................... .....30 1
Cienie .......................................................................................................................................302
Czym jest cie? .................................................................................................................. 303
Kod zgniatajcy".............................................................................................................. 304
Przykad cienia................................................................................................................... 305
Owietlenie i tryb indeksu koloru............................................................................................. 308
Podsumowanie .........................................................................................................................308
Podrcznik................................................................................................................................ 309

glLightModel ..................................................................................................................... 3 15
glMaterial.................................................................................................................... ....... 3 17
glNormal ............................................................................................................................ 3 18
Rozdzia 10.
Modelowanie i kompozycja obiektw 3D
................................................................. 321
Okrelenie zadania ................................................................................................................... 32 1
Wybr rzutowania.............................................................................................................. 322
Wybr owietlenia i waciwoci materiau .......................................................................323
Wywietlanie rezultatu....................................................................................................... 324
Konstruowanie modelu po kawaku .........................................................................................325
Gwka............................................................................................................................... 325
Trzpie................................................................................................... ............................ 328
Gwint ................................................................................................................................. 332
Skadanie modelu w cao ................................................................................................335
Test szybkoci.......................................................................................................................... 336
14 _____________________________________ OpenGL - ksiga eksperta

Poprawianie wydajnoci........................................................................................................... 340


Tworzenie listy wywietlania............................................................................................. 340
Podsumowanie .........................................................................................................................343
Podrcznik.. ........................................................................................................................... ...343

glDeleteLists ...................................................................................................................... 345

gllsList .............................................................................................................................. .347


glListBase .......................................................................................................................... 348
glNewList...........................................................................................................................349
Rozdzia 11.
Grafika rastrowa
....................................................................................................351
Rysowanie bitmap....................................................................................................................351
Czcionki bitmapowe...........................................................................................................355
Budowanie prostej biblioteki czcionek ..............................................................................355
Pixmapy: bitmapy z kolorem.. .................................................................................................. 359
Rysowanie pixmap.............................................................................................................359
Remapowanie kolorw....................................................................................................... 360
Tablice odwzorowa kolorw.. .......................................................................................... 361
Skalowanie pixmapy. ......................................................................................................... 362
Wykrawanie obszarw........ .......................................................................................... .....362
Odczytywanie pixmap z ekranu .........................................................................................363
Kopiowanie pixmap ....................................................................................................... ....366
Przegldarka plikw bitmap.. ................................................................................................ ...366
Pliki bitmap w Windows... ............................................................................................ .....367
Odczyt plikw .BMP.......................................................................................................... 368
Zapis pliku .BMP............................................................................................................... 370
Drukowanie bitmap............................................................................................................ 372
Wywietlanie bitmapy........................................................................................................375
Podsumowanie......................................................................................................................... 377
Podrcznik................................................................................................................................ 377

glPixelMap. ........................................................................................................................ 379


glPixelStore. ....................................................................................................................... 380
glPixelTransfer.. ................................................................................................................. 382
glPixelZoom. ................................................................................................................... ...383
glReadPixels ...................................................................................................................... 384
Rozdzia 12.
Mapowanie tekstur
................................................................................................387
Podstawy nakadania tekstur. ................................................................................................... 388
Definiowanie obrazw tekstur.................................................................................................. 389
Definiowanie tekstur ID.. .................................................................................................. 389
Definiowanie tekstur 2D ............................................................................................... .....391
Rysowanie wieloktw z naoon tekstur... ...................................................................... ...392
Mipmapy. ................................................................................................................................. 394
Program ogldania terenu....... .................................................................................................. 397
Definiowanie terenu.. ......................................................................................................... 397
Rysowanie terenu... ....................................................................................................... .....397
Rysowanie sceny................................................................................................................ 400
Spis treci _______________________________________________ 15

Automatyczne generowanie wsprzdnych tekstur........ ............................................... ....401


Lot nad terenem .................................................................................................................402
Podsumowanie .........................................................................................................................402
Podrcznik................................................................................................................................429
glTexCoord. ...................................................................................................................... .429

glTexImagelD ................................................................................................................ ...43 1


glTex!mage2D ................................................................................................................... 432
glTexParameter.. ........................................................................................................... .....433
Rozdzia 13.
Kwadryki: sfery, cylindry i dyski.
......................................................................... ....435
Tworzenie kwadryk..................................................................................................................436
Zmiana sposobu rysowania kwadryki ......................................................................................436
Rysowanie cylindrw............................................................................................................... 437
Rysowanie stokw............................................................................................................438
Teksturowanie cylindrw................................................................................................... 438
Rysowanie dyskw................................................................................................................... 438
Teksturowanie dysku .........................................................................................................439
Rysowanie czciowych dyskw .......................................................................................439
Rysowanie sfer.. ....................................................................................................................... 439
Teksturowanie sfer. ........................................................................................................... .440
Rysowanie owka................................................................................................................... 440
Podsumowanie .........................................................................................................................442
Podrcznik.... ............................................................................................................................ 45 1
gluCylinder ........................................................................................................................451
gluDeleteQuadric ............................................................................................................... 452

gluQuadricDrawStyle.......... ........................................................................................... ....454

gluQuadricTexture .............................................................................................................456
gluSphere ...................................................................................................................... .....456

Cz III
Tematy zaawansowane i efekty specjalne......................................... 459
Rozdzia 14.
Maszyna stanu OpenGL
.......................................................................................... 461
Podstawowe zmienne stanu OpenGL....................................................................................... 46 1
Zachowywanie i odtwarzanie zmiennych stanu .......................................................................462
Stan rysowania.. ................................................................................................................. 464
Stan bufora gbokoci. ...................................................................................................... 465
Stan bufora szablonu.......................................................................................................... 465
Stan owietlenia ............................................................................................................ .....465
Stan teksturowania............. .............................................................................................. ..466
Stan pikseli...... ............................................................................................................... ....467
Podrcznik.............. ................................................................................................................. .468
glDisable/glEnable...... ................................................................................................. ....468
gllsEnabled ................................................................................................................... .....470
16 _________________________________________ OpenGL - ksiga eksperta

glPopAttrib... ................................................................................................................... ...470


glPushAttrib.. ..................................................................................................................... 470
Rozdzia 15.
Bufory: nie tylko do animacji
.................................................................................473
Czym s bufory?. ................................................................................................................. .....473
Konfigurowanie buforw................................................................................................... 474
Bufor koloru. ........................................................................................................................... .477
Podwjne buforowanie.. ................................................................................................. ....477
Buforowanie stereo ............................................................................................................478
Przerzucanie buforw.. ..................................................................................................... ..478
Bufor glbokoci......................................................................................................................479
Porwnywanie gbokoci.. ............................................................................................ ....479
Wartoci gbokoci........................................................................................................... 481
Zastosowania bufora gbokoci ........................................................................................481
Inne zastosowanie bufora gbokoci................................................................................. 484
Wycinanie fragmentw sceny ............................................................................................485
Bufor szablonu .........................................................................................................................489
Korzystanie z bufora szablonu ...........................................................................................489
Funkcje bufora szablonu. ............................................................................................... ....489
Rysowanie w buforze szablonu.......................................................................................... 490
Bufor akumulacji........ .............................................................................................................. 494
Uycie bufora akumulacji w celu zasymulowania rozmycia ruchu.. ................................. 495
Uycie bufora akumulacji do antyaliasingu .......................................................................498
Podrcznik................................................................................................................................ 499
glAccum.............................................................................................................................499
glClearColor............................................. .......................................................................... 500
glClearDepth. .................................................................................................................. ...500

glDepthRange...... .............................................................................................................. .503


Rozdzia 16.
Efekty specjalne: przezroczysto i mga.
............................................................. ...505
Blending...................................................................................................................................505
Efekt przezroczystoci przez czenie kolorw.................................................................. 507
czenie kolorw przy antyaliasingu................................................................................. 51 1
czenie kolorw w programach rysunkowych.. .......................................................... .....51 1
Mga......................................................................................................................................... 520
Rysowanie imbrykw cieniowanych w zalenoci od gbokoci ....................................521
Inne rodzaje mgy............................................................................................................... 524
Gboko mgy .................................................................................................................524
Powrt do programu przegldania terenu................................................................................. 525
Podsumowanie .........................................................................................................................530
Podrcznik................................................................................................................................ 530
glBlendFunc.. .................................................................................................................. ...530
............................................................................................................................
Rozdzia 17.
Krzywe i powierzchnie: co to jest NURBS?!!
............................................................ 533
Krzywe i powierzchnie............................................................................................................. 534
Reprezentacja parametryczna..... ....................................................................................... .534
Punkty kontrolne................................................................................................................ 53 5
Spis treci ______________________________________________ 17

Cigo............... .............................................................................................................. 536


Obliczenia. ............................................................................................................................ ...537
Dwu wymiarowa krzywa .................................................................................................... 537
Obliczanie krzywej............................................... .............................................................. 540
Powierzchnia trjwymiarowa.... ........................................................................................ .541
Owietlenie i normalne ..........................................................................................544
NURBS .................................................................................................................................... 545
Od krzywych Beziera do krzywych B-sklejanych.. ...... ................... ...................... .....,,. 545
Wzy ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................,.,.............,....,,,, 546
Tworzenie powierzchni NURBS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 546 Waciwoci obiektw
NURBS ,,...................,..,,.......,.......,.............,..,,...,, 547
Definiowanie powierzchni ,,.,,...,..,...,..........,,,,,,,,.....,,,..,,...,....,......,..,,,, 547
Wycinanie,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 549
Podsumowanie ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,551
Podrcznik,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 55 1
glEvalCoord,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.551
glEvalMesh ...... .................................... ....................... ............................ ....... ..,,,, ,..,,552
glEvaIPoint.., ....... ...... ............................................................................................ ,,553
glGetMap .................... ........... ............................................................... ....... ...... ,....., .,.553
glMap,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,555
glMapGrid............... ,,,,,,,...,...,,.,....,,,..,..,,,,... ........... ...... ......... ............. ,.,,558
gluBeginCurve. ......,,....,,,,,,...,,.,.....,,.,,......,,,.,,,,,,...,,, ...... ,,,.,.,,,..,,, 559
gluBeginSurface.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,560
gluBeginTrim.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,560 gluDeleteNurbsRenderer, ..,..,
,..,,,... ...,,.................,..,..,,....,.,,,,,.,....,,,,, .56 1
gluEndCurve,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,562
gluEndSurface,., ...... ...... .,,,,,...,.,.,.............,..,.,..,,....................,,,,,,,,.... .,563
gluEndTrim.,, ,,,.,,,,,...,,,,,...,,.,,,,,.,,,.,,,,,..,,,,,,,,,..,....,,,,,,,,,., 563
gluGetNurbsProperty ......,,.........,,,,.,,,,.,,..,,,,,,,,,,,,,,,..,.,..,,,,.,.,,,...,563
gluLoadSamplingMatrices .,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 564
gluNewNurbsRenderer.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,565
gluNurbsCallback...................... ........ ............. ,,,,,,,,,,,,,,,,.,,,,,, 566

gluNurbsProperty ....,,,....,,,,....,..,.,,,,......,,...,.....,.....,.,.,....,,...,,.,,..., 569


gluNurbsSurface.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,571 gluPwlCurve
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 572
Rozdzia 18.
Podzia wieloktw..
.............................................................................................. .575
Zoone wielokty,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 575 Rysowanie wieloktw
wklsych.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,, 576 Rysowanie wieloktw zoonych
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.577 Funkcje zwrotne, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. 58
1 Podsumowanie ,,,,,,,,,,,,,,,,,,,,,,,.........,,,.........,..,,,............,..,,,.,.,,,,.,,, 582
Podrcznik,,, ,..,..,.,,...,.,,,...,,....,,,,.,,....,,,,......,,., ,,,,,, ........,, 583
gluBeginPolygon..... ,.,.,....,,. ...... ,..,.....,,...... ...... ,...., ...... .............................. ...,583
gluDeleteTess......................... ............... ,..,.....,,.......,,........,.........,......,,......,583
gluEndPolygon. ...... ...... ........................................................ ....... .,.,..,...,...., ....... .583
gluNewTess.,,,,....,......,...........................,,,,.,,,,,,,,,,.,,,,584
gluNextContour.....,,...... ........................ ,...., ,....................,.,..,.., 584
gluTessCallback. ,..........,....................................,...... ,,,.., 585
gluTessVertex .,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,, 585
18 ______________________________________ OpenGL - ksiga eksperta

Rozdzia 19.
Grafika interaktywna
.............................................................................................. 587
Selekcja. .............................................................................................................................. .....588
Nazywanie prymityww ....................................................................................................588
Praca w trybie selekcji.. ................................................................................................. .....590
Bufor selekcji ..................................................................................................................... 590
Wybieranie. ....................................................................................................................... .592
Wybr hierarchiczny.......................................................................................................... 594
Sprzenie zwrotne................................................................................................................... 598
Bufor sprzenia zwrotnego. .............................................................................................. 598
Dane sprzenia zwrotnego................................................................................................ 599
Znaczniki uytkownika ......................................................................................................600
Przykad.................................................................................................................................... 600
Nadawanie obiektom etykiet na potrzeby sprzenia zwrotnego ......................................601
Krok 1: wybranie obiektu................................................................................................... 602
Krok 2: pobieranie informacji o narysowanych obiektach. ............................................... 603
Podsumowanie .........................................................................................................................605
Podrcznik..:................................ ............................................................................................. 605

gllnitNames. ................................................................................................................... ....607

glSelectBuffer ................................................................................................................... .612


gluPickMatrix..... .............................................................................................................. ..613
Rozdzia 20.
OpenGL w Sieci: VRML
........................................................................................... 615
Na styku dwch wiatw.... .................................................................................................. ....61 5
Dwuwymiarowa nawigacja................................................................................................ 61 6

Instalacja............................................................................................................................ 61 8
Tryb spacerowy.................................................................................................................. 61 8
Tryb ogldania .................................................................................................................. .620
Open Inventor i VRML . ........................................................................................................ ...622
Podsumowanie .........................................................................................................................622

Cz IV
OpenGL i... ..................................................................................... 625
Rozdzia 21.
OpenGL i MFC....................................
............................................................... .....627
Wydzielenie kodu zwizanego z OpenGL. .............................................................................. .628
Zaczynamy od AppWizarda... ................................................................................................ ..629
Budowanie szkieletu .......................................................................................................... 629
Dodawanie bibliotek ..........................................................................................................630
Przygotowanie klasy widoku dla OpenGL...............................................................................631
Format pikseli i kontekst renderowania... .............................................................................. ...632
Usuwanie kontekstu renderowania.. ............................................................................... ....634
Obsuga zmiany rozmiaru okna. ............................................................................................... 634
. Spis treci_______________________________________________19

Renderowanie sceny.................................................................................................................634
7 Unikanie niepotrzebnego czyszczenia
okna.......................................................................635
8 Obsuga
palety..........................................................................................................................635
8
Podsumowanie............................................................................................................
.............639
O
O Rozdzia 22.
2 OpenGL i OWL........................................................................................................ 641
^ Wydzielenie kodu zwizanego z OpenGL........................................
8 Zaczynamy od AppExperta...............................................................
8 Budowanie szkieletu ......................................................................
3 Dodawanie nagwkw..................................................................
3 Dodawanie procedur obsugi komunikatw..................................
3 Wypenianie szkieletu aplikacji.........................................................
l Przygotowanie klasy widoku dla OpenGL....................................
l Format pikseli i kontekst renderowania............................................
j Usuwanie kontekstu renderowania.................................................
; Obsuga zmiany rozmiaru okna.........................................................
; Renderowanie sceny..........................................................................
i Unikanie niepotrzebnego czyszczenia okna...................................
j Niech si krci................................................................................
i Obsuga palety...................................................................................
! Podsumowanie..................................................................................
' Rozdzia 23.
, OpenGL w Visual Basic i
4GL..................................................................................657
, Wymagany dostp niskiego
poziomu.......................................................................................657
'. Magia
obiektw........................................................................................................................658
Pug and
Play.....................................................................................................................
659
Wydzielenie kodu
OpenGL................................................................................................659
l Dziaanie i sposb uycia kontrolki
WaiteGL.OCX.................................................................659
Znaczniki
OpenGL.............................................................................................................6
60
i Instalacja i uycie kontrolki WaiteGL w Yisual Basicu
6.0.....................................................661
Instalowanie
kontrolki........................................................................................................661
Przykad w Yisual Basicu
..................................................................................................662
Malowanie w oknie OpenGL
.............................................................................................663
Troch
ruchu....................................................................................................................
..664
Wykorzystanie kontrolki OCX w Delphi 2.0
..........................................................................665
Instalowanie
kontrolki........................................................................................................665
Przykad w
Delphi..............................................................................................................665
Malowanie w oknie
OpenGL.............................................................................................667
Troch
ruchu....................................................................................................................
..667
Par uwag na temat kodu
rdowego......................................................................................668
Podsumowanie
.........................................................................................................................669
Rozdzia 24.
Przyszo OpenGL w Windows ...............................................................................
671
Wnioski....................................................................................................................................674

Dodatki........................................................................................... 677
Dodatek A
Poprawianie wydajnoci OpenGL w
Windows........................................................... 679
Listy
wywietlania......................................................................................................
.......679
Operacje na macierzach .....................................................................................................680
20______________________________________OpenGL - ksiga eksperta

Operacje zwizane z
owietleniem.....................................................................................680
Konstruowanie
obiektw....................................................................................................680
Inne rady
............................................................................................................................6
81
Dodatek B
Dalsza
lektura........................................................................................................6
83
Ksiki na temat programowania
Windows.......................................................................683
Ksiki i materiay na temat
OpenGL................................................................................684
Ksiki komputerowe na temat programowania grafiki (w szczeglnoci
3D)..................684
Serwery FTP i WWW zwizane z
OpenGL.......................................................................684
Skadnice
VRML...............................................................................................................685
Dodatek C
OpenGL wersja 1.1.................................................................................................687

Dodatek D
Sownik..................................................................................................................689

Skorowidz....................................................................................................
.......... 695
>erta

.68 O autorach
0
.68
0
.681

583
683
684
684
684
685

Richard S. Wright jr pracuje dla Yisteon Corporation w Maitland na Florydzie, opraco-


89 wujc aplikacje Windows dla suby zdrowia. Richard programowania uczy si
w smej klasie, w 1978 roku, przy papierowym terminalu. Gdy mia szesnacie lat, ro-
dzice pozwolili mu kupi komputer zamiast samochodu; niecay rok pniej sprzeda
swj pierwszy program. Gdy skoczy szko redni, jego pierwsz prac byo naucza
nie programowania w lokalnej prywatnej szkole. Studiowa na Wydziale Elektrycznym
i Nauk Komputerowych Uniwersytetu w Louisville, ale na ostatnim roku, kiedy studia
rzucajc si w wir kariery. Urodzony w Louisville w Kentucky, obecnie wraz z on
i trjk dzieci mieszka w sonecznym Lak Marry na Florydzie. Gdy nie programuje
i nie ciga huraganw, zajmuje si po amatorsku astronomi, wyleguje si na play
i uczy w szkce niedzielnej.

Michael Sweet pracuje dla Chesapeake Test Rang w Patuxent River w stanie Maryland; jest
take wspwacicielem Easy Software Products, maej firmy programistycznej
specjalizujcej si w tworzeniu grafiki komputerowej na stacjach roboczych Silicon
Graphics. Przy komputerze pierwszy raz zasiad w wieku szeciu lat, za pierwszy program
sprzeda, gdy mia lat dwanacie. Pod koniec studiw w SUNY Institute of Technology w
Nowym Jorku Michael pracowa jako konsultant do spraw grafiki komputerowej. Tu
po studiach przenis si do Marylandu. W wolnych chwilach uwielbia jedzi na
rowerze, fotografowa i gra na trbce.
Przedmowa
Z powodu bardzo duych wymaga co do sprztu i mocy obliczeniowej, trjwymiarowa
grafika komputerowa dotd bya dostpna jedynie na specjalizowanych stacjach robo-
czych, mimp e sama technologia jej tworzenia jest znana od dziesitek lat. Dzisiejsze
komputery osobiste stay si jednak na tyle wydajne, e z powodzeniem mona ich uywa
do tworzenia trjwymiarowej grafiki. Obecnie przecitny komputer jest wydajniejszy ni
stacja graficzna sprzed kilku lat, kosztujc jednoczenie duo mniej.
OpenGL to standard, ktry powsta w celu umoliwienia przeniesienia grafiki kompute-
rowej, tradycyjnie dostpnej jedynie na stacjach graficznych, do zwykego komputera
osobistego. Gdy tylko powstaa ta technologia, uzyskaa znaczne wsparcie ze strony
Microsoftu.

Obecnie platforma Windows oferuje rnorodne aplikacje OpenGL, od przegldarek


VRML do programw CAD/CAM i pakietw do animacji. Jest take pierwsz platform,
na ktrej zostanie zaimplementowana nowa wersja OpenGL, wersja 1.1.

Richard Wright ju od dawna by popularyzatorem technologii Win32 i OpenGL. Jest


aktywnym uczestnikiem grupy dyskusyjnej comp.graphics.api.opengl i pomaga innym w
rozwizywaniu problemw programistycznych. Sam regularnie wymieniam si z nim
pomysami i uwagami. Ciesz si, e w tej ksice Richard zechcia podzieli si swoim
latami zdobywanym dowiadczeniem i jestem pewien, e przeczytanie jej z pewnoci
bardzo pomoe ci w tworzeniu wasnych aplikacji OpenGL dla Windows.

Hock San Lee


OpenGL Development Manager
Microsoft Corporation Czerwiec 1996
Wprowadzenie
Witamy w wiecie grafiki OpenGL! Pierwszy raz o OpenGL usyszaem w 1992 roku na
Win32 Developers Conference w San Francisco. Windows NT 3.1 byy dopiero we
wczesnej wersji beta (czy te pnej alfa) i obecnych byo wielu producentw, zapowia-
dajcych swoje wsparcie dla tej nowej, ekscytujcej platformy. Midzy innymi obecna
bya take firma Silicon Graphics, Inc. (SGI). Prezentowaa swoje nowe stacje graficzne i
odtwarzaa fragmenty popularnych filmw, w ktrych zastosowano efekty specjalne
tworzone na jej komputerach. NT dziaay na procesorach MIPS - obecnie posiadanych
przez SGI -jednak gwnym celem pokazu bya promocja nowego, trjwymiarowego
standardu graficznego o nazwie OpenGL. By on oparty na wasnym standardzie IRIS GL
firmy SGI i wtedy stanowi zupen nowo. Co wane, take Microsoft ju wtedy
zapowiedzia wsparcie dla OpenGL w swoich Windows NT.

Jednak na pierwsze blisze zetknicie si z OpenGL musiaem czeka a do momentu


ukazania si wersji beta systemu Windows NT 3.5. Zawarte w nich, oparte na OpenGL
wygaszacze ekranu stanowiy jedynie wierzchoek gry lodowej, zaledwie zapowiadajc
to, co mona osign za pomoc tej biblioteki graficznej. Jak wiele innych osb,
przedzieraem si przez pliki pomocy Microsoftu, kupiem take ksik OpenGL Pro-
gramming Guide" (zwan obecnie po prostu Czerwon Ksig). W tej ksice starannie
unikano zagadnie zwizanych z platformami i we wszystkich przykadach korzystano z
pomocniczej biblioteki AUX (Auxilary), niezalenej od platformy biblioteki funkcji
przeznaczonych do uruchamiania aplikacji OpenGL.

W tym czasie Czerwona Ksiga bya jedyn pozycj zwizan z nauk OpenGL. Mimo e
zawieraa dokadny opis funkcji OpenGL, brakowao jej dwch wanych elementw. Po
pierwsze, nie bya dla pocztkujcych. Moe takie byy intencje autorw, lecz do lektury tej
ksiki potrzebna bya oglna wiedza o grafice trjwymiarowej. Drug wad bya jej
niezaleno od platformy. Jako programista Windows, potrzebowaem odpowiedzi na
pewne wane pytania, na przykad takie, jak wykorzysta pliki .BMP jako tekstury, jak
w OpenGL stworzy palet przeznaczon do wykorzystania na 8-bitowej karcie
graficznej, czy jak korzysta z dorzuconych przez Microsoft funkcji wiggle".

Niniejsza ksika wypenia te luki. Chciaem w niej zawrze wprowadzenie do grafiki


trjwymiarowej i programowania w OpenGL, poczonych w jedn cao. Poza tym
zaprezentowaem to w kontekcie pojedynczego systemu operacyjnego, najpopularniej-
szego systemu wszechczasw, Microsoft Windows. Dodatkowo, na kocu kadego roz-
dziau zamieciem podrcznik, zawierajcy syntetyczny opis omawianych funkcji.
26______________________________________OpenGL - ksiga eksperta

Dla kogo jest ta ksika?


Ta pozycja jest przeznaczona dla szerokiego grona programistw OpenGL i Windows.
Mog korzysta z niej zarwno programici Windows, chccy zaj si grafik trjwy-
miarow i OpenGL, jak i dowiadczeni twrcy trjwymiarowej grafiki w Windows,
chccy dowiedzie si czego wicej na temat zastosowa tej biblioteki. Ta ksika jest
cenn pozycj take dla dowiadczonych programistw OpenGL, ktrzy ju zdobyli
praktyk w pracy ze stacjami graficznymi i chc si zaj tworzeniem aplikacji przezna-
czonych rwnie dla platformy Microsoft Windows.

System wymagany dla OpenGL


OpenGL nie jest dostpne dla 16-bitowych wersji Windows (3.1, 3.11 itd.). Microsoft
doczy OpenGL do Windows NT 3.5, a take do Windows 95, poprzez oddzielnie roz-
prowadzane biblioteki DLL (Te biblioteki s dostpne na serwerze FTP i stronach WWW
Microsoftu, moesz take je znale na pytce CD.-ROM doczonej do tej ksiki, w
kartotece Windows 95).

W naszej ksice nie s opisywane inne biblioteki OpenGL, przeznaczone dla 32- lub
16-bitowych systemw. Od strony programowej, OpenGL uywane w Windows 95 nie
rni si od swojego odpowiednika dla Windows NT. Pierwszy zestaw bibliotek DLL
wydany przez Microsoft dla Windows NT obejmuje wszystkie funkcje OpenGL 1.0; s
one dostpne w Windows NT 3.5 i 3.51. Do Windows NT 4.0 zostay dodane funkcje
OpenGL 1.1, a w momencie gdy ta ksika znajdzie si na rynku, powinny by ju do-
stpne takie funkcje rwnie dla Windows 95. Najwiesze informacje znajdziesz w pliku
readme.txt na pytce CD-ROM doczonej do ksiki.

Wszystkie przykady zaprezentowane w ksice powinny dziaa poprawnie ju na


szybkim komputerze 486 (tzn. prawdziwym" 486, z wbudowanym koprocesorem ma-
tematycznym!) z co najmniej omioma megabajtami pamici RAM. Nie s to due wy-
magania; wikszo pakietw programistycznych wymaga obecnie lepszego sprztu.
Jeli jeste zainteresowany, cay kod w ksice i na pytce zosta opracowany i dziaa
poprawnie na komputerze Pentium 90 MHz z 32 MB RAM i 16/24-bitow kart graficzn.
Bdziesz potrzebowa karty graficznej mogcej wywietli co najmniej 256 kolorw (co
najmniej karty 8-bitowej). Jeli moesz pracowa w trybie graficznym z wiksz iloci
kolorw, tym lepiej. Najlepsze wyniki daje praca w trybach z 65 tysicami lub
szesnastoma milionami kolorw.

Jzyk
Z wyjtkiem dwch rozdziaw powiconych pakietom klas C++, cay kod rdowy
zosta napisany w C. Wybr pomidzy C a C++ moe prowadzi niemal do krucjaty re-
Wprowadzenie

ligijnej pomidzy dwoma zwalczajcymi si obozami programistw. Mona jednak za-


oy, e kady kompetentny programista C++ swobodnie analizuje dobrze zorganizo-
wany kod C, co nie zawsze jest prawd w sytuacji odwrotnej. Istnieje popularna biblioteka
C++ dla OpenGL, zwana Open Inventor; w zwizku z tym kada prba utworzenia wasnej
biblioteki klas poredniczcych C++ dla OpenGL byaby jedynie powieleniem wykonanej
ju dobrej pracy, a poza tym wykraczaoby to poza ramy tej ksiki.

Gdy ju mamy wybrany jzyk, zajmijmy si potrzebnymi narzdziami.

Kompilatory
Cay kod rdowy by oryginalnie opracowywany przy pomocy Microsoft Yisual C++
4.0. (Tak, z jego pomoc mona kompilowa take programy C!) Przy kadym przy-
kadzie znajdziesz pliki projektu Yisual C++.

Poniewa wszystkie przykady s napisane w C i nie korzystaj z adnych bibliotek spe-


cyficznych dla innych producentw, nie powiniene napotka adnych problemw przy
budowie projektw przy pomocy innych 32-bitowych kompilatorw. Zakadam, e
znasz, ktrego uywasz kompilator, i wiesz, jak dodawa do projektw biblioteki i pliki
nagwkowe.

Dla programistw wolcych biblioteki klas C++, takie jak MFC czy OWL, doczono
rozdziay dotyczce wanie tych bibliotek. Dodatkowo, wiele przykadw C zostao
doczonych take w wersji MFC (Yisual C++) oraz OWL (Borland C++). Te przykady
mona znale w kartotekach \MFC i \OWL na pytce CD-ROM. Pliki projektw do tych
przykadw przygotowano take w wersji dla kompilatora Borlanda (za pomoc Borland
C++ 5.0).

Uwag powicono take uytkownikom narzdzi Borlanda: pytka CD-ROM zawiera


specyficzn dla Borlanda wersj biblioteki AUX OpenGL. Ta biblioteka nie jest czci
oficjalnej specyfikacji OpenGL, ale zwykle, tak jak OpenGL, jest implementowana na
rnych platformach. Z nieznanych powodw Borland doczy pliki nagwkowe tej
biblioteki, ale nie sam bibliotek, za wersja biblioteki AUX dostarczana z narzdziami
Microsoftu nie jest zgodna z Borland C++. Dodatkowe uwagi na temat uywania
kompilatora Borland C++ z przykadami z tej ksiki znajdziesz w kartotece \Borland na
pytce CD-ROM.

Co znajdziesz w tej ksice


Caa ksika zostaa podzielona na cztery czci. Cz pierwsza stanowi wprowa-
dzenie do OpenGL i podstaw jej uywania w Microsoft Windows. W czci drugiej po-
znamy podstawy programowania w OpenGL. Bdzie mowa o prymitywach, widokach,
modelowaniu transformacji, owietleniu i mapowaniu tekstur. W czci trzeciej zagbimy
si w bardziej zaawansowane tematy zwizane z bibliotek OpenGL - poznamy
28_________________________________________OpenGL - ksiga eksperta

maszyn stanu OpenGL, efekty specjalne, bardziej szczegowo zajmiemy si buforami,


zaawansowanym generowaniem powierzchni oraz pewnymi zagadnieniami grafiki
interaktywnej. W czci czwartej poznamy dodatkowe informacje zwizane z
wykorzystaniem OpenGL w innych rodowiskach programowania (MFC, OWL i Vi-sual
Basic). Na koniec pokrtce omwimy przyszo OpenGL w Windows.

Cz I: Wprowadzenie do OpenGL
Rozdzia 1. - Co to jest OpenGL?
W tym rozdziale przedstawimy na przykadach, czym jest OpenGL, skd si wzio i
dokd zmierza. Omwimy take waniejsze rnice i zgodnoci OpenGL z systemem
graficznym Microsoft Windows.

Rozdzia 2. - Podstawy grafiki 3D


Ten rozdzia jest przeznaczony dla nowicjuszy w dziedzinie trjwymiarowej grafiki.
Wprowadzimy w nim podstawowe koncepcje i czsto stosowane wyraenia.

Rozdzia 3. - Nauka OpenGL z uyciem biblioteki AUX


W tym rozdziale zaczniesz pisa programy uywajce OpenGL. Pocztkujcym ua-
twiamy ycie dziki wykorzystaniu biblioteki AUX. Ta prosta biblioteka narzdziowa jest
niezalena od platformy i systemu okien. Poza tym poznamy konwencje nazywania funkcji
i zmiennych OpenGL, a take DLL-e i biblioteki zawierajce poszczeglne grupy funkcji
OpenGL.

Rozdzia 4. - OpenGL for Windows: OpenGL + Win32 = Wiggle


W tym rozdziale zaczniesz pisa prawdziwe programy Windows (posiadajce ptl ko-
munikatw) uywajce OpenGL. Poznasz tzw. funkcje wiggle" Microsoftu, spajajce
kod graficzny OpenGL z kontekstami urzdze Windows. Powiemy take par sw o
tym, na jakie komunikaty Windows naley reagowa i w jakim celu.

Rozdzia 5. - Bdy i inne komunikaty OpenGL


Poznamy metody, jakich OpenGL uywa do zgaszania bdw; powiemy take o spo-
sobach odczytywania numeru wersji i nazwy twrcy biblioteki.

Cz II: Uywanie OpenGL


Rozdzia 6. - Rysowanie w trzech wymiarach: linie, punkty i
wielokty
Tutaj dowiesz si, jak z dwuwymiarowych prymityww s skadane trjwymiarowe
obiekty. Zostan omwione wszystkie prymitywy OpenGL, a take sposoby ukrywania
niewidocznych powierzchni.
Wprowadzenie_____________________________________________29

Rozdzia 7. - Manipulowanie przestrzeni 3D: transformacje


wsprzdnych
W tym rozdziale nauczysz si przesuwa obiekty i widok sceny. Dowiesz si, jak obraca,
przesuwa i skalowa obiekty. Opowiemy sobie o dziaaniach na macierzach, dziki czemu
bdziesz mg ich uywa, nawet jeli wczeniej nie miae o nich adnego pojcia.

Rozdzia 8. - Kolory i cieniowanie


Tutaj dowiesz si, jak tchn ycie w obiekty uzupeniajc je o kolory. Gdy przeczytasz ten
rozdzia, cieniowanie obiektw z jednego koloru w inny bdzie dla ciebie dziecinn
zabaw. Zobaczysz take, dlaczego musisz konstruowa palet 3-3-2, gdy twj program
dziaa na 256-kolorowej karcie graficznej.

Rozdzia 9. - Owietlenie i rda wiata


OpenGL obsuguje do omiu niezalenych rde wiata w scenie. Nauczysz si uywa
tych rde, ustawia ich parametry i waciwoci, a take dowiesz si, jak wspdziaaj
one z odbijajcymi waciwociami materiaw przypisywanych obiektom.

Rozdzia 10. - Modelowanie i kompozycja obiektw 3D


i
l W tym rozdziale zaczniemy tworzy zoone trjwymiarowe obiekty, skadajc je z pro-
f stych, mniej skomplikowanych obiektw 3D. Poznamy take listy wywietlania OpenGL,
l stanowice metod przyspieszania rysowania obiektw skadajcych si z wielu czci.

Rozdzia 11. - Grafika rastrowa


i
i
j W tym rozdziale dowiesz si, jak w bibliotece OpenGL manipulowa bitmapami. Dotyczy
[ to take odczytywania plikw .BMP Windows i wywietlania ich w scenach OpenGL.

Rozdzia 12. - Mapowanie tekstur


j Mapowanie tekstur jest jedn z najuyteczniejszych waciwoci kadej biblioteki 3D.
Nauczysz si owija" bitmapy wok wieloktw, a take korzysta z automatycznej
generacji wsprzdnych tekstury.

Rozdzia 13. - Kwadryki: kule, cylindry i dyski


W tym rozdziale omwimy funkcje biblioteki glu (OpenGL Utility Library), przezna-
czone do szybkiego tworzenia pewnych standardowych ksztatw.

Cz III: Tematy zaawansowane i efekty specjalne


Rozdzia 14. - Maszyna stanu OpenGL
Wiele globalnych ustawie i parametrw OpenGL jest zarzdzanych przez Maszyn
stanu OpenGL. W tym rozdziale poznamy ten mechanizm, a take kilka uoglnionych
funkcji przeznaczonych do ustawiania i odczytywania rnych parametrw.
30______________________________________OpenGL - ksiga eksperta

Rozdzia 15. - Bufory: nie tylko do animacji

W tym rozdziale poznamy wiele dodatkowych szczegw na temat buforw w OpenGL.


Przekonasz si, e nie su wycznie do przeczania ekranw.
Rozdzia 16. - Efekty specjalne: przezroczysto i mga

W tym rozdziale zajmiemy si kilkoma innymi efektami specjalnymi. Nale do nich


przezroczysto kanau alfa oraz efekt mgy, stosowane do uzyskania wraenia gbi.
Rozdzia 17. - Krzywe i powierzchnie: co to jest NURBS?!!

W tym rozdziale omawiamy funkcje narzdziowe suce do generowania krzywych i


powierzchni Beziera i NURBS. Moesz ich uy przy tworzeniu zoonych ksztatw
ma iloci kodu.
Rozdzia 18. - Podzia wieloktw

Tutaj poznasz sposoby podziau zoonych lub niewypukych wieloktw na mniejsze,


wygodniejsze elementy.
Rozdzia 19. - Grafika interaktywna
W tym rozdziale wyjanimy dwie cechy biblioteki OpenGL: selekcj i funkcje zwrotne.
Dziki tym dwum grupom funkcji uytkownik moe operowa obiektami sceny. Moesz
take otrzymywa szczegowe informacje na temat kadego obiektu w scenie.
Rozdzia 20. - OpenGL w Sieci: VRML

W tym rozdziale poznamy jzyk VRML (Yirtual Reality Modeling Language) oraz jego
histori w OpenGL. Omwimy take klasy biblioteki Open Inventor oraz ich powizania z
OpenGL i VRML.

Cz IV: OpenGL i...


Rozdzia 21. - OpenGL i MFC

Ten rozdzia jest przeznaczony dla programistw C++ uywajcych biblioteki klas
MFC Microsoftu. Pokaemy, jak uywa OpenGL w aplikacjach MFC oraz jak doda
moliwoci renderowania OpenGL do okien wyprowadzonych z klasy CWnd.
Rozdzia 22. - OpenGL i OWL
Ten rozdzia jest przeznaczony dla programistw C++ uywajcych biblioteki klas
OWL Borlanda. Pokaemy, jak doda moliwoci renderowania OpenGL do okien OWL
wyprowadzonych z klasy TWindow.
>erta Wprowadzenie

Rozdzia 23. - OpenGL w Visual Basic i 4GL


pen- W tym rozdziale poznamy kontrolk OCX, zawierajc wikszo funkcji i polece
OpenGL. Dziki niej mona atwo tworzy programy OpenGL w jzyku Yisual Basic
(4.0 lub nowszym) albo w dowolnym 32-bitowym rodowisku obsugujcym biblioteki
OCX. Przedstawimy przykady dla Yisual Basic 4.0 i Delphi 2.0.
nich Rozdzia 24. - Przyszo OpenGL w
Windows
W tym rozdziale zastanowimy si nad przyszoci grafiki 3D i OpenGL w Windows.
Omwimy konsekwencje pynce z powstania DirectX API Microsoftu, do ktrego nale
DirectDraw, Direct Sound, Direct Play, Direct Input oraz Direct 3D, zawierajce
y
s 3D API firmy Reality Labs.
tw

Dodatki
3ze Dodatek A - Polepszanie wydajnoci OpenGL w Windows
Znajdziesz tutaj kilka oglnych rad dotyczcych poprawy szybkoci dziaania OpenGL w
Windows NT i Windows 95.

:ne. t Dodatek B - Przydatna literatura


W tym dodatku znajduje si lista dalszych ksiek i materiaw zawierajcych informacje
zwizane z tematami omawianymi w tej ksice.

Dodatek C - OpenGL wersja 1.1


W trakcie powstawania tej ksiki powstawao rwnie OpenGL l. l. W treci ksiki nie
zostay omwione nowe funkcje i elementy tej wersji biblioteki; omwiono je oglnie
dopiero w tym dodatku. Na pytce CD-ROM znajduj si najaktualniejsze i uzu-
penione informacje o nowych funkcjach i moliwociach dodanych do Windows NT
4.0; znajdziesz na niej take par przykadowych programw.

Dodatek D - Sownik
las Sownik popularnych terminw zwizanych z OpenGL i grafik trjwymiarow.
la

Pytka CD-ROM doczona do ksiki


as
Wraz z t ksik otrzymujesz pytk CD-ROM, do granic moliwoci wypenion
przykadami i innymi rzeczami zwizanymi z OpenGL. W gwnym katalogu pytki,
w kartotece o nazwie Book, znajdziesz cay kod rdowy zaprezentowany w ksice.
Oprcz tego na pytce jest wiele przykadw demonstrujcych koncepcje prezentowane
w kadym z rozdziaw, nie opisywanych w treci ksiki.
32______________________________________OpenGL - ksiga eksperta

Kady rozdzia posiada wasn kartotek wewntrz kartoteki Book. W kadej kartotece
rozdziau znajduj si dodatkowe kartoteki, dla kadego przykadu osobno. Na przykad,
program odbijajcego si prostokta z rozdziau trzeciego znajduje si w kartotece
X:\Book\R03\bounce (gdzie X oznacza liter twojego napdu CD-ROM).

Niektre z kartotek rozdziaw zawieraj podkartotek o nazwie \Tank. Zawiera ona


program symulacji czogu i robota, rozwijany wraz z poznawaniem materiau zawartego z
kolejnych rozdziaach. Cho ten program nie jest analizowany rozdzia po rozdziale, w
miar poznawania kolejnych funkcji i elementw OpenGL, symulacja staje si coraz
bardziej zoona. Szczegy dotyczce tworzenia tego programu znajdziesz w pliku re-
adme.txt w kartotece kadego rozdziau.

Niektre z przykadowych programw z kadego rozdziau zostay przepisane take w


C++ przy uyciu MFC lub OWL. Mona je znale w kartotekach X:\MFC\ lub
X:\OWLV Take w tym przypadku, wewntrz kartotek MFC i OWL znajduj si osobne
kartoteki dla kadego rozdziau.

Dwie nastpne gwne kartoteki na pytce to \Borland i \OpenGLl 1. Kartoteka \Borland


zawiera specyficzn dla Borlanda wersj biblioteki AUX. Szczegy dotyczce uywania
funkcji tej biblioteki znajdziesz w pliku readme.txt w tej kartotece. Kartoteka
\OpenGLll zawiera dokument opisujcy dodatkowe elementy biblioteki OpenGL 1.1,
ktre Microsoft zawar w systemie Windows NT 4.0. Ponadto znajdziesz tam kilka do-
datkowych programw demonstrujcych te nowe moliwoci.

Pamitaj, aby sprawdzi zawarto pliku readme.txt w gwnej kartotece w celu po-
znania najbardziej aktualnych informacji o zawartoci pytki CD-ROM. Ten plik zawiera
take peny listing wszystkich plikw i programw zawartych na tej pytce.

Do dziea!
Jeli dopiero zaczynasz poznawa grafik trjwymiarow lub bibliotek OpenGL, szczerze
ci zazdroszcz. Nic nie daje wikszej satysfakcji i zwykej radoci ni poznawanie nowej
technologii lub narzdzia. Cho OpenGL ma korzenie w naukowym modelowaniu i
symulacji, nie musisz by naukowcem, aby je opanowa. Szczegowe, krok po kroku
opisywane przykady zawarte w tej ksice poprowadz ci na nowy poziom
umiejtnoci programowania.

Nauka OpenGL jest porwnywalna z nauk SQL przy programowaniu baz danych. Zanim
poznaem SQL, nawet nie wyobraaem sobie, jak potg moe wada programista baz
danych. Jeli tylko po amatorsku zajmowae si trjwymiarow grafik lub po prostu
chciaby j pozna, przekonasz si, jak wiele w tym wzgldzie ma do zaoferowania
biblioteka OpenGL!

RichardS. Wrightjr.
Wprowadzenie do OpenGL
Pierwsza cz tej ksiki zawiera wprowadzenie do trjwymiarowej grafiki i programowania w OpenGL.
Zaczniemy j od krtkiego omwienia biblioteki OpenGL, jej pochodzenia, przeznaczenia oraz sposobu
dziaania. Nastpnie, zanim przystpimy do pisania kodu, pomwimy oglnie o grafice 3D w komputerach,
wyjanimy, jak i dlaczego widzimy w trzech wymiarach oraz jak okrela si pooenie i orientacj obiektu w
trjwymiarowej przestrzeni. W ten sposb zapoznasz si z podstawowymi zagadnieniami i wyraeniami
wykorzystywanymi w caej dalszej czci ksiki.
W rozdziale trzecim rozpoczniesz tworzenie swoich pierwszych programw OpenGL. Poznasz wymagane
biblioteki i pliki nagwkowe, a take konwencje nazw bibliotek i funkcji OpenGL. Na pocztku poznamy
bibliotek AUX, stanowic zestaw narzdzi do nauki OpenGL niezalenie od platformy programowej i
sprztowej. Dopiero pniej, w rozdziale czwartym, przejdziemy do pisania programw uywajcych OpenGL
bezporednio w Windows 95 i Windows NT. Poznamy rozszerzenia interfejsu GDI w Windows, umoliwiajce
uycie OpenGL w Windows; opiszemy take sposoby ich wykorzystania. W rozdziale pitym uzyskasz
konieczne informacje dotyczce obsugi i zgaszania bdw. Dowiesz si, jak od pyta bibliotek AUX o jej
tosamo i twrc, a take jak poprawi jej wydajno. Posiadajc t wiedz, bdziesz dobrze przygotowany
do opanowania wiedz^z czci drugiej, w ktrej przykady bd znacznie bardziej skomplikowane!
(zdzia 1.
o to jest OpenGL?
OpenGL mona zdefiniowa jako programowy interfejs sprztu graficznego". Jest to
biblioteka przeznaczona do tworzenia trjwymiarowej grafiki, bardzo szybka i atwo
przenaszalna pomidzy rnymi systemami. Uywajc OpenGL moesz tworzy ele-
ganck i interesujc grafik 3D, o jakoci nie ustpujcej programom typu ray-trace.
Najwiksz zalet korzystania z biblioteki OpenGL jest jej szybko dziaania, o rzdy
wielkoci wysza od programw typu ray-trace. W OpenGL zastosowano algorytmy
opracowane i dopieszczone przez Silicon Graphics (SGI), niekwestionowanego lidera w
dziedzinie animacji i grafiki komputerowej.

OpenGL jest przeznaczone do uywania w komputerach wyposaonych w sprzt zapro-


jektowany i zoptymalizowany pod ktem wywietlania i operowania grafik 3D. Je-
dynie programowe, oglne" implementacje OpenGL take s moliwe; nale do nich
wanie implementacje w Windows NT i Windows 95. Jednak ta sytuacja wkrtce moe si
zmieni, poniewa coraz wicej producentw kart graficznych uzupenia swoje produkty o
akceleratory grafiki trjwymiarowej. Cho s one przeznaczone gwnie do wykorzystania w
grach, z tym cile wie si, rozwj coraz szybszych kart 2D, optymalizujcych operacje takie
jak rysowanie odcinkw czy wypenianie i manipulowanie bitmapami. Tak jak dzi ju nikt nie
wyobraa sobie zastosowania w nowym komputerze Windows zwykej karty VGA, tak
wkrtce standardem stan si karty graficzne z akceleratorem 3D.

Graficzne interfejsy API w Windows


Na pocztku byo GDI (Graphics Device Interface), dziki
ktremu moliwe byo pisanie programw graficznych
niezalenych od sprztu -jednak za cen szybkoci. Twrcy
kart graficznych zaczli pisa zoptymalizowane sterowniki GDI,
znacznie przyspieszajce dziaanie tego interfejsu. Nastpnie,
specjalnie z myl o twrcach gier, Microsoft zaproponowa
bibliotek WinG. WinG zawieraa jedynie kilka funkcji
pozwalajcych na szybkie wywietlanie bitmap, ale i one nie
byy wystarczajco sprawne. Po pewnym czasie Microsoft
opracowa nowy
36 Cz l * Wprowadzenie do OpenGL

interfejs, Direct Draw API, umoliwiajcy naprawd


niskopoziomowy dostp do sprztu. Direct Draw rozwin si
do caego zestawu interfejsw, zwanych cznie pakietem
DirectX, umoliwiajcym bezporedni dostp do sprztu,
dziki ktremu pisanie gier stao si o wiele atwiejsze, za
same gry mog dziaa szybciej. Po jakim czasie czci
pakietu sta si rwnie interfejs 3DDI, wspierajcy
trjwymiarow grafik w grach i innych aplikacjach
multimedialnych. Na temat powiza Windows z
akceleratorami trzeciego wymiaru powiemy sobie nieco wicej
w rozdziale 24.

OpenGL jest uywane do rnych celw, od programw typu CAD, przez aplikacje ar-
chitektoniczne a do generowania komputerowych dinozaurw w najnowszych filmach.
Wprowadzenie przemysowego API 3D na masowy rynek systemw operacyjnych, takich
jak Microsoft Windows, take obiecuje pewne ekscytujce moliwoci. Gdy powszechna
stanie si akceleracja sprztowa i szybkie procesory, grafika 3D wkrtce stanie si
typowym skadnikiem kadej aplikacji i nie bdzie ju stanowi domeny gier i aplikacji
naukowych.

Kto jeszcze pamita czasy, kiedy arkusze kalkulacyjne mogy prezentowa dane w postaci
paskiego, dwuwymiarowego wykresu? Jeli sdzisz, e dodanie trzeciego wymiaru do
zwykej aplikacji jest ekstrawagancj, przypomnij sobie firmy, ktre pierwsze
zastosoway ten pomys w praktyce. Quattro Pro, jedna z pierwszych aplikacji pozwala-
jcych na atwe tworzenie trjwymiarowych wykresw, niemal cakowicie zdominowaa
rynek arkuszy kalkulacyjnych. Obecnie paska, dwuwymiarowa grafika nie moe
zapewni sukcesu adej powanej aplikacji.

Nie chodzi o to, e OpenGL suy wycznie tworzeniu wykresw w aplikacjach biuro-
wych. Zastosowa jest mnstwo. Sukces lub poraka produktu czsto w ogromnym
stopniu zaley od jego wygldu, mimo e we wszystkich innych aspektach program nie
ustpuje lub nawet wyprzedza konkurencj. A dobra grafika 3D moe znacznie po-
dnie walory wizualne programu!

O OpenGL
Powiedzmy sobie teraz par sw na temat pochodzeniu biblioteki OpenGL, jej twrcach
oraz o jej zastosowaniach i perspektywach. Poznamy take podstawowe aspekty
implementacji OpenGL.

Historia OpenGL
OpenGL jest wzgldnie nowym standardem przemysowym, opracowanym zaledwie
kilka lat temu, jednak ju powszechnie zaakceptowanym. Przodkiem OpenGL by wasny
jzyk GL firmy Silicon Graphics. IRIS GL" byo interfejsem API grafiki 3D dla stacji
roboczych IRIS tej samej firmy. Te komputery nie miay jedynie oglnego prze-
Rozdzia 1. * Co to jest OpenGL?__________________________________37

znaczenia, lecz posiaday specjalny sprzt zoptymalizowany pod ktem wywietlania


rozbudowanej grafiki. Ten sprzt pozwala midzy innymi na superszybkie
wykonywanie oblicze macierzowych (stanowicych podstaw wszelkiej grafiki 3D),
wspiera operacje na buforach gbokoci i na kilka innych sposobw przyspiesza
obliczenia graficzne. Jednak gdy SGI podjo prb przeniesienia biblioteki IRIS GL na
inne platformy sprztowe, pojawiy si problemy.
OpenGL jest rezultatem prac firmy SGI nad popraw przenaszalnoci biblioteki IRIS
GL. Nowy jzyk oferuje moc biblioteki GL, lecz jest przy tym otwarty", pozwalajc na
atw adaptacj dla rnych platform sprztowych i systemw operacyjnych. (SGI wci
sprzedaje IRIS GL, jednak poza usuwaniem bdw nie rozbudowuje go o nowe funkcje i
elementy).
W lipcu 1992 roku powstaa wersja 1.0 specyfikacji OpenGL. Ju pi dni pniej, na
pierwszej konferencji programistw Win32, SGI zaprezentowaa bibliotek OpenGL
dziaajc na komputerze IRIS Indigi. Wstawki wideo z filmw takich jak Terminator 2
oraz wizualizacje aplikacji medycznych przycigay ywe zainteresowanie publicznoci.
Ju w tym czasie Microsoft i SGI wsppracoway ze sob, planujc zamieszczenie
OpenGL w przyszych wersjach Windows NT.

Dalszy rozwj OpenGL


Otwarty standard nie moe by w rzeczywistoci otwarty", jeli kontroluje go tylko jedna
firma. W zwizku z tym wszelkie rozszerzenia OpenGL s zatwierdzane przez
OpenGL Architecture Review Board (ARB), ktrej czonkami zaoycielami s SGI,
Digital Euipment Corporation, IBM, Intel i Microsoft. OpenGL ARB zbiera si dwa
razy w roku.
Te spotkania s otwarte dla publicznoci i niezrzeszone firmy take mog bra udzia w
dyskusji (cho nie mog gosowa). O pozwolenie na udzia w obradach trzeba ubiega si
o wiele... wczeniej, gdy w celu zwikszenia produktywnoci spotkania odbywaj si w
niewielkim gronie. Czonkowie ARB czsto uczestnicz w grupie dyskusyjnej
comp.graphics.api.opengl. Mona do niej wysya wasne pytania i uwagi.
W grudniu 1995 roku ARB ratyfikowao kocow wersj specyfikacji wersji 1.1 biblioteki
OpenGL. Wiele z rozszerze i zmian w stosunku do wersji l .0 dotyczy poprawienia
wydajnoci; zostay one zebrane w Dodatku A.

Jak dziaa OpenGL


OpenGL jest jzykiem1 raczej proceduralnym ni opisowym. Zamiast opisywania samej
sceny oraz jej wygldu, programista opisuje kroki konieczne do osignicia okrelonego
1
W treci ksiki mona natrafi na terminy biblioteka OpenGL i jzyk OpenGL. O ile termin bi-
blioteka odnosi si do caego produktu w oglnoci, o tyle o jzyku mona mwi raczej w kontekcie
specyficznych wywoa funkcji zawartych w bibliotece, (przyp. tumacza)
38_________________________________Cz l Wprowadzenie do OpenGL

wygldu lub efektu. Te kroki" stanowi wywoania funkcji wysoce przenaszalnego in-
terfejsu API, zawierajcego okoo 120 polece i funkcji. Su one rysowaniu prymityww
graficznych, takich jak punkty, odcinki i wielokty w trzech wymiarach. Ponadto OpenGL
obsuguje owietlenie i cieniowanie, mapowanie tekstur, animacj oraz dodatkowe efekty
specjalne.
OpenGL nie zawiera adnych funkcji przeznaczonych do zarzdzania oknami, interakcji z
uytkownikiem czy operacji wejcia/wyjcia. Kade systemowe rodowisko (takie jak
Microsoft Windows) posiada do tego celu wasne funkcje i jest odpowiedzialne za za-
pewnienie sposobw przeniesienia rysunkw OpenGL do okna lub na bitmap.

OpenGL w Windows
OpenGL zadebiutowa w Windows NT 3.51. Wkrtce po powstaniu Windows 95 pojawi
si rwnie zestaw bibliotek DLL umoliwiajcych korzystanie z OpenGL take w tym
systemie. Ta ksika odnosi si wanie do tej oglnej implementacji OpenGL. Ty,
programista, zostaniesz w niej poprowadzony przez podstawy grafiki trjwymiarowej, a
nastpnie dowiesz si, jak kompilowa i czy programy OpenGL w Windows NT i
Windows 95. Przechodzc dalej, omwimy funkcje dostarczone przez Microsoft -
stanowice spoiwo umoliwiajce dziaanie OpenGL z interfejsem GDI Microsoftu. Od
tego momentu zaczniesz poznawa pozostae elementy OpenGL API, wszystko to w
kontekcie Microsoft Windows NT i Windows 95.

Architektura graficzna: oprogramowanie kontra sprzt


Uycie OpenGL nie jest tym samym, co uycie GDI przy rysowaniu w oknie. W rze-
czywistoci, biecy wybr pdzli, pir, czcionek i innych obiektw GDI nie ma a-
dnego wpywu na OpenGL. Tak jak GDI uywa kontekstu urzdzenia do sterowania
rysowaniem w oknie, tak OpenGL uywa tzw. kontekstu renderowania (tworzenia grafiki).
Kontekst renderowania jest powizany z kontekstem urzdzenia, ktry z kolei jest
powizany z oknem - i voila - OpenGL renderuje do okna. Szczegy mechaniki tego
procesu zostan opisane w rozdziale czwartym.
Jak ju wspomnielimy, OpenGL jest przeznaczony do pracy w systemach z akceleracj
sprztow. Coraz czciej producenci kart graficznych uzupeniaj je o obsug tej biblioteki.
Poprawnie napisana aplikacja OpenGL nie powinna zauwaa rnic pomidzy
renderowaniem ze wsparciem ze strony sprztu a renderowaniem czysto programowym.
Jednak uytkownik z pewnoci zauway rnic, polegajc na znacznym wzrocie
wydajnoci w przypadku zastosowania akceleratora.
Rysunek 1.1 ilustruje akceleracj sprztow w Windows, wcznie ze zwyk akceleracj
GDI i akceleracj Direct Draw, a take akceleracj OpenGL. Po lewej stronie widzimy, jak
aplikacje korzystaj z normalnych wywoa GDI, kierowanych poprzez bibliotek
WINSRV.DLL do interfejsu Win32 Device Driver Interface. Interfejs Win32 DDI
ozdzia 1. * Co to jest OpenGL? 39

nastpnie komunikuje si bezporednio ze sterownikiem karty graficznej i dopiero tam


odbywa si sprztowa akceleracja wywoa GDI.

Rysunek 1.1.
Schemat dziaania
akceleracji
sprztowej \v
Windows

Direct Draw jest zoptymalizowany pod ktem dostpu do sprztu graficznego. Cakowicie
pomija GDI i komunikuje si bezporednio z kart graficzn, by moe za porednictwem
cienkiej warstwy HAL (Hardware Abstraction Layer - warstwy abstrakcji sprztu) i
oprogramowania emulujcego funkcje nieobsugiwane przez sprzt. Direct Draw jest
zwykle uywany w grach, umoliwiajc bezporednie manipulacje w pamici graficznej w
celu osignicia ultraszybkiej grafiki i animacji 2D.
Po prawej stronie rysunku 1.1 znajduj si wywoania OpenGL i innych API 3D, prze-
kazywane poprzez interfejs sterownika grafiki trjwymiarowej (3D DDI). 3D DDI jest
opracowany tak, aby umoliwi producentom sprztu akceleracj OpenGL i innych trj-
wymiarowych API, takich jak Reality Labs API. (Dyskusja na temat OpenGL i API firmy
Reality Labs zostaa zawarta w rozdziale 24). Oprcz tego, dostawcy akceleratorw
40_________________________________Cz l Wprowadzenie do OpenGL

sprztowych przeznaczonych specjalnie dla OpenGL (takich jak chipset GLINT) mog
instalowa wasne sterowniki klienta OpenGL, a take specjalizowane sterowniki interfejsu
producenta.

Ograniczenia oglnej implementacji


O ile nie zostanie wsparta przez sprzt, oglna implementacja OpenGL zastosowana
przez Microsoft podlega pewnym ograniczeniom. Zalicza si do nich brak wsparcia dru-
kowania grafiki OpenGL na monochromatycznych drukarkach lub drukarkach koloro-
wych o mniej ni czterech bitplanach kolorw (mniej ni szesnastu kolorach). Nie s take
obsugiwane palety sprztowe dla poszczeglnych okien. Zamiast tego, Windows posiada
pojedyncz palet sprztow, ktr musi dzieli pomidzy poszczeglne aplikacje.

Na koniec, pewne elementy OpenGL nie zostay zaimplementowane; nale do nich


obrazy stereoskopowe, pomocnicze bufory oraz plany bitowe alfa. Jednak te elementy
mog, lecz nie musz, by implementowane przez sprzt. Zanim zechcesz skorzysta z
nich w swojej aplikacji, zawsze najpierw sprawd ich dostpno (wicej na ten temat w
rozdziale pitym).

Dalsze perspektywy OpenGL w Windows


Wprowadzenie OpenGL do rodziny systemw operacyjnych Windows otwiera cakiem
nowe, ekscytujce moliwoci. Gdy miliony komputerw osobistych bd mogy korzysta
z OpenGL, Windows stanie si najpopularniejsz platform dla aplikacji tego typu. Na
pocztku bd to gwnie aplikacji naukowe i inynieryjne, przeznaczone do modelowania
i wizualizacji, jednak z czasem z pewnoci powstanie take ogromna liczba gier,
programw rozrywkowych i aplikacji biurowych wykorzystujcych trjwymiarow
grafik.

Nawet w przypadku producentw tworzcych aplikacje OpenGL dla innych platform,


implementacje dla Microsoft Windows mog sta si znaczc pozycj. Stacje robocze
oparte na Windows stanowi atrakcyjn alternatyw dla drogich, specjalistycznych stacji
graficznych, przy tym mona na nich korzysta z przeogromnej oferty rnorodnych
istniejcych programw i aplikacji.
Rozdzia 2.
Podstawy grafiki 3D
W tym rozdziale dowiesz si:

Jak oczy postrzegaj trzeci wymiar;


W jaki sposb dwuwymiarowy obraz moe udawa trzeci wymiar;
Jak wsprzdne kartezjaskie okrelaj pooenie obiektu;
Jak widok wpywa na rozmiar obrazka;
W jaki sposb tworzy si trjwymiarowe obiekty z dwuwymiarowych prymityww;
Jak pracowa z rzutami rwnolegymi i perspektywicznymi.

Zanim zajmiemy si specyfik OpenGL, powimy nieco czasu poznaniu podstawo-


wego sownictwa trjwymiarowej grafiki. W tym celu zaprezentujemy fundamentalne
koncepcje grafiki 3D i ukadw wsprzdnych. Dowiesz si take, w jaki sposb mona
tworzy (pozornie) trjwymiarow grafik na paskim, dwuwymiarowym ekranie.
Czytelnicy dowiadczeni w grafice 3D lub po prostu palcy si do napisania pierwszego
programu OpenGL, mog po prostu na razie pomin ten rozdzia.

Postrzeganie w trzech wymiarach


Trjwymiarowa grafika komputerowa" to w rzeczywistoci dwuwymiarowe obrazy na
paskim ekranie komputera, sprawiajce wraenie posiadania gbokoci czy trzeciego"
wymiaru. Aby mc rzeczywicie oglda obraz trjwymiarowy, musisz oglda obiekt
oboma oczami lub dostarczy kademu oku oddzielny, nieco inny obraz obiektu. Rzu
okiem na rysunek 2.1. Kade oko widzi dwuwymiarowy obraz bdcy jakby tymczasow
fotografi na siatkwce (na tylnej czci oka). Te dwa obrazy s nieco rne, gdy kade
oko patrzy na obiekt pod nieco innym ktem (wanie w tym celu nasze oczy s od
siebie oddalone). Dopiero mzg czy te dwa nieco rne obrazy w jeden,
trjwymiarowy obraz w mzgu.
42 Cz l Wprowadzenie do OpenGL

Rysunek 2.1.
Jak oczy widz'
trzeci wymiar

Pierwszy obraz Drugi obraz


na siatkwce na siatkwce

Na rysunku 2.1 kt 9 pomidzy obrazami staje si tym mniejszy, im bardziej obiekt oddala si
od oczu. W zwizku z tym efekt trjwymiarowoci zwiksza si wraz ze wzrostem kta
pomidzy dwoma obrazami. Stereoskopy (te rczne przegldarki trjwymiarowych
slajdw, ktrymi z pewnoci bawie si w dziecistwie) i trjwymiarowe kina wyko-
rzystuj wanie ten efekt, przekazujc kademu z oczu odmienny obraz, czy to przez
oddzielne soczewki, czy te przez kolorowe okulary przepuszczajce wybrane fragmenty
obrazu. W tych obrazach zwykle stosuje si wikszy kt pomidzy oboma widokami, w
celu osignicia wyraniejszego efektu trjwymiarowoci.

Co si stanie gdy zakryjesz jedno oko? By moe mylisz, e dalej bdziesz widzia
trjwymiarowo, ale sprbuj przeprowadzi taki oto eksperyment: Umie szklank lub
jaki inny obiekt na wycignicie rki, po lewej stronie od siebie. Praw rk zaso
prawe oko i sprbuj sign po ten przedmiot. (Powiniene uy plastikowej szklanki!)
Zwr uwag e tym razem masz duo wicej trudnoci z signiciem i trafieniem w
szklank. Teraz odkryj prawe oko i jeszcze raz sprbuj chwyci szklank; przekonasz si,
jaka jest rnica. Wanie z tego powodu ludzie, ktrzy stracili jedno oko, czsto maj
problemy z ocen odlegoci.

2D + Perspektywa = 3D
Powd, dla ktrego po zasoniciu jednego oka wiat nie staje si natychmiast paski,
wynika z faktu, e wiele z efektw wiata trjwymiarowego obowizuje take w wiecie
dwch wymiarw. Najoczywistszym z nich jest to, e obiekty blisze wydaj si
wiksze od obiektw pooonych dalej. Ten efekt jest nazywany perspektyw. Za per-
spektywa plus zmiany w barwie, teksturze, owietleniu, cieniowaniu i rnych intensy-
wnociach koloru (w zwizku z owietleniem) cznie tworz wraenie trjwymiarowoci.

Ju sama perspektywa wystarczy do stworzenia wraenia trzeciego wymiaru. Rysunek 2.2


przedstawia prosty szkieletowy szecian. Nawet bez kolorowania i cieniowania, ten
szecian wydaje si obiektem trjwymiarowym. Jednak gdy bdziesz patrzy na niego
wystarczajco dugo, przd i ty szecianu nagle zamieni si miejscami. Dzieje si tak,
Rozdzia 2. * Podstawy grafiki 3D 43

poniewa mzgowi brakuje jakiej dodatkowej paszczyzny odniesienia, kontekstu


okrelajcego rzeczy wista posta obiektu.

Rysunek 2.2.
Ten prosty
szkieletowy szecian
demonstruje efekt
perspektywy

Usuwanie niewidocznych linii


Rysunek 2.2 zawiera jedynie tyle informacji, aby da wraenie trzech wymiarw, nie
umoliwia jednak okrelenia, gdzie jest przd, a gdzie ty obiektu. Ogldajc rzeczywisty
obiekt, skd wiesz, gdzie jest jego ty, a gdzie przd? To proste - ty jest przesonity przez
przd. Gdyby szecian z rysunku 2.2 by wypeniony, nie mgby ujrze jego tylnego
wierzchoka i w zwizku z tym nie mgby pomyli go z wierzchokiem przednim. Nawet
jeliby szecian by zrobiony z drutu, czci drutu z przodu przesaniaaby czci drutu z
tyu. Aby zasymulowa to na dwuwymiarowym rysunku, naley usun linie zasaniane
przez powierzchnie przednich cian szecianu. Ta technika nazywa si usuwaniem
niewidocznych linii i zostaa zastosowana w przypadku kostki z rysunku 2.3.

Rysunek 2.3.
Ta sama kostka po
usuniciu
niewidocznych linii

Kolory i cieniowanie
Rysunek 2.3 wci nie daje wraenia rzeczywistego obiektu. cianki kostki maj dokadnie
ten sam kolor, co to, za wszystko, co wida, to przednie cianki. Rzeczywista kostka
miaaby pewien kolor i tekstur; na przykad w drewnianej kostce widoczne byyby kolor i
tekstura drewna. W komputerze (lub na papierze), jeli jedynie pokolorujemy kostk i
narysujemy j w dwch wymiarach, otrzymamy rysunek podobny do rysunku 2.4.
Wrcilimy wic do obiektu wygldajcego na paski i dopki nie narysujemy krawdzi
innym kolorem, w ogle nie osigniemy efektu trjwymiarowoci. Aby odzyska
wraenie trzech wymiarw (bez rysowania krawdzi w innym kolorze), kad z trzech
widocznych cianek musimy zamalowa innym kolorem lub tym samym kolorem o rnym
nateniu, co daje wraenie owietlenia obiektu. Na rysunku 2.5 widzimy obiekt, w
ktrym cianki zostay zamalowane rnymi kolorami lub odcieniami.
44 Cz l 4 Wprowadzenie do OpenGL

Rysunek 2.4.
Pokolorowana
kostka, ale bez
cieniowania

Rysunek 2.5.
Kostka ze ciankami
zamalowanymi
rnymi kolorami

wiata i cienie
Musimy powiedzie take par sw o owietleniu. Owietlenie daje dwa wane efekty w
przypadku obiektw ogldanych w trzech wymiarach. Po pierwsze, powoduje, e po-
wierzchnie o jednakowym kolorze, po owietleniu z boku, wydaj si mie rne cienio-
wanie. Po drugie, obiekty nie przepuszczajce wiata (czyli wikszo wypenionych
obiektw) po owietleniu rzucaj cie (rysunek 2.6).
Rysunek 2.6.
Kostka owietlona
pojedynczym
rdem wiata

Na nasz trjwymiarowy obiekt maj wpyw dwa rda wiata. wiato otoczenia, po-
zbawione kierunku, to po prostu jednolite owietlenie mogce powodowa efekt cieniowania
na jednolitych obiektach; wiato otoczenia powoduje, e bardziej odlege krawdzie
wydaj si ciemniejsze. Drugim rdem wiata moe by na przykad lampa. Lampy w
grafice trjwymiarowej s uywane do zmiany cieniowania jednolitych obiektw oraz
uzyskiwania efektw cienia.

Ukady wsprzdnych
Gdy wiesz ju, jak oko moe postrzega trzy wymiary na dwuwymiarowej paszczynie
(ekranie komputera), zastanwmy si, jak narysowa obiekty na tym ekranie. Gdy rysujesz
punkty, linie czy inne ksztaty na ekranie, zwykle okrelasz ich pooenie w odnie-
Rozdzia 2. 4 Podstawy grafiki 3D 45

siniu do wierszy i kolumn. Na przykad, na standardowej karcie VGA na ekranie mieci si


640 punktw w poziomie i 480 punktw w pionie. Aby narysowa punkt na rodku
ekranu, nakazujesz narysowanie punktu o wsprzdnych (320, 240) - czyli 320
punktw od lewej krawdzi i 240 punktw od grnej krawdzi.

W OpenGL, gdy tworzysz okno przeznaczone do rysowania, musisz okreli take


ukad wsprzdnych, ktrego chcesz uy, oraz sposb odwzorowania wsprzdnych
tego ukadu na fizyczne piksele ekranu. Zanim zajmiemy si trzema wymiarami, zoba-
czmy, jak wyglda to w ukadzie dwch wymiarw.

Dwuwymiarowe wsprzdne kartezjaskie


Najpopularniejszym ukadem w dwuwymiarowych rysunkach jest kartezjaski ukad
wsprzdnych. Wsprzdne kartezjaskie s okrelane przez wsprzdne x i y. Wsp-
rzdna x okrela pooenie w poziomie, za wsprzdna y - w pionie.

Pocztek kartezjaskiego ukadu wsprzdnych znajduje si w punkcie x = O, y = 0.


Wsprzdne kartezjaskie s zapisywane jako pary, w nawiasach, w ktrych wsprzdna
x jest zapisywana jako pierwsza, za wsprzdna y jako druga, oddzielona przecinkiem.
Na przykad pocztek ukadu mona zapisa jako (O, 0). Rysunek 2.7 opisuje
kartezjaski ukad wsprzdnych w dwch wymiarach. Linie x i y ze znacznikami s
nazywane osiami i biegn od minus nieskoczonoci do plus nieskoczonoci. Zwr
uwag, e na tym rysunku wida po prostu zwyky ukad wsprzdnych, z jakim nieraz
zetkne si w szkole. W Windows istnieje jednak moliwo zastosowania innych (a
waciwie zmodyfikowanych) ukadw odwzorowania, w ktrych jednostki i kierunki
mog by interpretowane inaczej. W dalszej czci ksiki zobaczymy, jak na rne
sposoby mona odwzorowa ten prawdziwy ukad wsprzdnych na rne ukady
wsprzdnych okna.
Rysunek 2.7.
Kartezjaski uklad
(-7,6)
wsprzdnych
. . _ _ _ _ _j (5,4)
"' Pzqtek '
(0,0) !
i M i I-3.-2) l l l l l l l
"--

-y

Osie x i y s do siebie prostopadle (przecinaj si pod ktem prostym) i razem tworz


paszczyzn xy. Paszczyzna jest, mwic w duym uproszczeniu, pask powierzchni. W
kadym ukadzie wsprzdnych, para osi przecinajcych si pod ktem prostym tworzy
paszczyzn. W systemie zawierajcym jedynie dwie osie, istnieje oczywicie tylko jedna
paszczyzna.
46 Cz l * Wprowadzenie do OpenGL

Obcinanie wsprzdnych
Okno jest mierzone fizycznie w pikselach. Zanim zaczniesz rysowa w oknie punkty,
odcinki i inne ksztaty, musisz najpierw poinformowa OpenGL, jak ma zamienia podane
pary wsprzdnych na fizyczne wsprzdne okna. Odbywa si to poprzez okrelenie
regionu przestrzeni kartezjaskiej zajmowanego przez okno; ten region nosi nazw obszaru
obcinania. W dwuwymiarowej przestrzeni obszar obcinania jest okrelony przez
minimalne i maksymalne wartoci wsprzdnych x i y punktw nalecych do okna.
Mona spojrze na to take inaczej, okrelajc pooenie pocztku w stosunku do okna.
Rysunek 2.8 przedstawia dwa przykady obszarw obcinania.

Rysunek 2.8.
Dwa obszary
obcinania
100
Obszar
roboczy
okna

(0,0) 150

W pierwszym przykadzie, po lewej stronie rysunku 2.8, wsprzdne x w oknie nale do


zakresu od O do +150 (od lewej do prawej), za wsprzdne y nale do zakresu od O do
100 (od dou do gry). Punkt na rodku ekranu miaby wsprzdne (75, 50). W
drugim przykadzie widzimy obszar obcinania ze wsprzdnymi x nalecymi do
zakresu od -75 do +75, za wsprzdnymi y nalecymi do zakresu od -50 do 50. W
tym przykadzie punkt w rodku ekranu pokrywa si z pocztkiem ukadu (O, 0).
Istnieje take moliwo uycia funkcji OpenGL (lub zwykych funkcji rysunkowych
GDI Windows) w celu odwrcenia ukadu wsprzdnych do gry nogami" lub za-
miany strony lewej z praw. W rzeczywistoci, domylnym odwzorowaniem w oknach
Windows jest o pionowa biegnca od gry do dou okna. Cho jest to uyteczne podczas
wypisywania tekstu od dou do gry, takie odwzorowanie jest inne ni to, do ktrego
przywyklimy w szkole.

Widoki, twoje okna na trjwymiarowy wiat


Rzadko wysoko i szeroko obszaru obcinania dokadnie odpowiadaj szerokoci i wy-
sokoci okna w pikselach. W zwizku z tym ukad wsprzdnych musi zosta odwzo-
rowany z logicznych wsprzdnych kartezjaskich na fizyczne wsprzdne pikseli
okna. To odwzorowanie jest okrelane przez tak zwany widok. Widok jest obszarem
wewntrz obszaru roboczego okna, ktry zostanie uyty do rysowania obszaru roboczego.
Widok po prostu odwzorowuje obszar obcinania w okrelony obszar okna. Zwykle
Rozdzia 2. * Podstawy grafiki 3D 47

widok jest zdefiniowany jako cale okno, ale nie jest to wymagane - na przykad moesz
zechcie rysowa tylko w dolnej czci okna.

Rysunek 2.9 przedstawia due okno, 300 x 200 pikseli, z widokiem obejmujcym cay
obszar roboczy. Gdyby obszar obcinania dla tego okna zostaby ustawiony na od O do
150 w osi x i od O do 100 w osi y, to wsprzdne logiczne byyby odwzorowane na
wiksze wsprzdne ekranowe okna. Kade zwikszenie wsprzdnej logicznej powo-
dowaoby dwukrotne zwikszenie odpowiedniej wsprzdnej (wsprzdnej piksela) w
oknie.

Rysunek 2.9.
Widok zdefiniowany
jako dwukrotne
powikszenie Obszot roboczy okna
obszaru obcinania 300x200 pikseli
Widok = 300x200

Dla odrnienia, na rysunku 2.10 pokazano widok odpowiadajcy obszarowi obcinania.


Okno ma jednak w dalszym cigu wymiary 300 x 200 pikseli, co powoduje, e obszar
widoku zajmuje jedynie lew doln cz okna.

Rysunek 2.10.
Widok o tych samych
rozmiarach, co
obszar obcinania

Moesz uywa widokw do zmniejszania lub powikszania obrazw wewntrz okna


oraz do wywietlania jedynie czci obszaru obcinania, poprzez ustawienie widoku wi-
kszego ni obszar roboczy okna.

Rysowanie prymityww
Zarwno w dwch, jak i w trzech wymiarach, gdy rysujesz obiekt, w rzeczywistoci
skadasz go z serii mniejszych ksztatw, zwanych prymitywami. Prymitywy to proste
obiekty, takie jak punkty, odcinki i paskie wielokty skadane w przestrzeni 3D w celu
utworzenia trjwymiarowych obiektw. Na przykad, trjwymiarowa kostka z rysunku 2.5
skada si z szeciu dwuwymiarowych kwadratw, z ktrych kady jest umie-
48 Cz l * Wprowadzenie do OpenGL

szczony na osobnej ciance. Kady rg prostokta (i kadego innego prymitywu) jest


nazywany wierzchokiem. Wierzchoki posiadaj okrelone wsprzdne w przestrzeni
dwu- lub trjwymiarowej. O prymitywach wystpujcych w OpenGL oraz sposobach ich
wykorzystania dowiesz si w rozdziale 6.

Trjwymiarowe wsprzdne kartezjaskie


Sprbujmy teraz uzupeni nasz dwuwymiarowy ukad wsprzdnych o trzeci wymiar,
dodajc do niego gboko. Rysunek 2.11 przedstawia ukad wsprzdnych kartezja-
skich z now osi, osi z. O z jest prostopada zarwno do osi x, jak i osi y. Reprezentuje
lini biegnc prostopadle ze rodka ekranu w kierunku ogldajcego. (Obrcilimy nasz
ukad z rysunku 7.7 wok osi y, a nastpnie wok osi x. Gdybymy tego nie zrobili, o z
biegaby prosto w naszym kierunku i nie moglibymy jej ujrze). Wsprzdne w takiej
trjwymiarowej przestrzeni okrelamy przy pomocy trzech wsprzdnych: x, y i z. Na
rysunku 2.11 dla jasnoci zaznaczono punkt (-4, 4, 4).
Rysunek 2.11.
Wsprzdne
kartezjaskie w
trzech wymiarach (-4,4,4) z

Rzuty, podstawa grafiki 3D


Wiesz ju, jak przy pomocy wsprzdnych kartezjaskich mona okreli pooenie w
przestrzeni 3D. Jednak bez wzgldu na to, jak bdziesz wytrzeszcza oczy, piksele na
ekranie maj tylko dwa wymiary. Jak OpenGL tumaczy wsprzdne kartezjaskie na
dwuwymiarowe wsprzdne, ktre mona przedstawi na ekranie? Krtka odpowied
brzmi: dziki trygonometrii i prostych manipulacjach macierzami. Prostych? C, moe nie
do koca - moglibymy teraz powici wiele stron i licznych czytelnikw, ktrzy nie
lubi algebry liniowej, objaniajc te proste" zagadnienia. Wicej informacji na ten temat
znajdzie si jednak w rozdziale 7, za gbsze omwienie mona znale w dodatku B. Na
szczcie, aby uywa OpenGL do tworzenia grafiki, nie trzeba si zna na matematyce.

Wszystko, czego w rzeczywistoci potrzeba do zrozumienia wikszoci materiau w tej


ksice, to pojcie rzutu. Wsprzdne 3D s rzutowane na dwuwymiarow paszczyzn (to
okna). Przypomina to rysowanie pisakiem na szybie konturw jakiego trjwymia-
Rozdzia 2. * Podstawy grafiki 3D 49

rowego obiektu w oddali. Gdy usuniemy obiekt lub przeniesiemy szyb, w dalszym cigu
pozostaj na niej kontury obiektu. Na rysunku 2.12 dom w tle jest rzutowany na paski
kawaek szka. Okrelajc rzutowanie, okrelasz bryle obcinania (pamitasz obszary
obcinania?), ktr chcesz wywietli w oknie, a take sposb przeksztacania jej
wsprzdnych.

Rysunek 2.12.
Trjwym iarowy
obiekt rzutowany na
pask szyb (ekran)

Rzuty rwnolege
W OpenGL zwykle bdziesz mia do czynienia z dwoma gwnymi rodzajami rzutw.
Pierwszy rodzaj to rzuty rwnolege. Tego typu rzutowanie okrela si stosujc prosto-
ktn lub szecienn bry rzutowania. Nic, co znajduje si poza t bry, nie jest rzuto-
wane. Co wicej, wszystkie obiekty o tych samych rozmiarach s rysowane w tych
samych rozmiarach, bez wzgldu na to, czy znajduj si dalej czy bliej. Ten rodzaj
rzutowania (przedstawiony na rysunku 2.13) jest czsto uywany w projektowaniu ar-
chitektonicznym i programach CAD (Computer Aided Design - projektowanie wspo-
magane komputerem).

Rysunek 2.13. Grna


Brya obcinania
rzutu rwnoleglego Dalsza

Prawa

Blisza
Dolna

Bry obcinania rzutu rwnolegego okrela si podajc blisz, dalsz, lew, praw,
grn oraz doln paszczyzn obcinania. Obiekty znajdujce si wewntrz takiej bryy
obcinania s wywietlane (z wziciem pod uwag ich orientacji) na dwuwymiarowym
obrazie wywietlanym na ekranie.
50 Cz l * Wprowadzenie do OpenGL

Rzuty perspektywiczne
Drugim, popularniejszym typem rzutowania s rzuty perspektywiczne. To rzutowanie po-
woduje postanie efektu zmniejszenia rozmiarw bardziej odlegych obiektw. Brya widzenia
(rysunek 2.14) przypomina piramid ze citym wierzchokiem. Obiekty bdce bliej
paszczyzny rzutowania maj rozmiary zblione do oryginalnych, podczas gdy obiekty znaj-
dujce si dalej, wraz ze wzrostem oddalenia maj coraz mniejsze rozmiary. Ten rodzaj rzu-
towania odgrywa najwaniejsz rol w nadawaniu realizmu symulacjom i animacjom 3D.

Rysunek 2.14. Dalsza


Brya obcinania w
rzutowaniu
perspektywicznym
Grna

Prowa

Podsumowanie
W tym rozdziale zapoznalimy si z podstawami trjwymiarowej grafiki. Wiesz ju, e aby
zobaczy prawdziwy trjwymiarowy widok, musisz widzie dwa obrazy tego samego
obiektu, nieco przesunite wzgldem siebie. Widziae take, jak tworzy si iluzj
trjwymiarowoci paskich obiektw, przez dodanie perspektywy, usunicie niewidocznych
linii, pokolorowanie, wycieniowanie oraz owietlenie. Zapoznae si z kartezjaskim
ukadem dwu- i trjwymiarowych wsprzdnych, poznae take dwie metody stosowane
przez OpenGL do rzutowania trjwymiarowych scen na dwuwymiarow powierzchni.

Celowo nie omawialimy szczegw zwizanych z osigniciem tych efektw w OpenGL. W


nastpnych rozdziaach powiemy, jak stosowa te techniki oraz jak maksymalnie wy-
korzysta potg tej biblioteki. Na doczonej do ksice pytce CD-ROM znajdziesz
odnoszcy si do rozdziau drugiego program CUBE, demonstrujcy koncepcje omawiane w
pierwszej czci tego rozdziau. Po uruchomieniu programu moesz wciska spacj
przechodzc kolejno od siatkowego szecianu do w peni owietlonego jednolitego klocka z
cieniem. By moe w tym momencie nie rozumiesz kodu programu, ale nie jest to teraz
potrzebne do zrozumienia samego zagadnienia. Zanim skoczysz lektur tej ksiki,
bdziesz umia tworzy takie przykady samodzielnie i od zera.
Rozdzia 3.
Nauka OpenGL
z uyciem biblioteki AUX
W tym rozdziale dowiesz si:

Jakie biblioteki i pliki nagwkowe skadaj si na bibliotek OpenGL;


Jak biblioteka AUX zapewnia podstawowe funkcje zarzdzania oknami, dostpne dla
prawie wszystkich platform;
Jak uy OpenGL do stworzenia okna i rysowania w nim;
Jak uy domylnego ukadu wsprzdnych OpenGL;
Jak tworzy zoone kolory uywajc komponentw RGB (Red, Green i Blue);
Jak widok wpywa na rozmiary obrazu;
Jak przeskalowa rysunek, aby dopasowa si do rozmiarw okna;
Jak stworzy prost animacj z uyciem podwjnego bufora;
Jak rysowa predefiniowane obiekty.

Gdy zostae wprowadzony do OpenGL i znasz podstawy grafiki trjwymiarowej, nad-


szed czas, aby samemu zaj si tworzeniem programw. Ten rozdzia rozpoczynamy od
omwienia uywania OpenGL z kompilatorem; przy okazji poznasz take konwencje
nazw zmiennych i funkcji. Jeli pisae ju jakie aplikacje OpenGL, w pewnoci wiele
szczegw odkrye ju samodzielnie. Jeli tak jest rzeczywicie, moesz pomin
pierwsz sekcj i przej bezporednio do opisu biblioteki AUX.

OpenGL: API, nie jzyk


OpenGL nie jest jzykiem programowania; jest to interfejs API (Application Program-
ming Interface - interfejs programowania aplikacji). Gdy mwimy, e program jest na-
52_________________________________Cz l Wprowadzenie do OpenGL

pisany w OpenGL lub jest aplikacj OpenGL, rozumiemy przez to, e jest napisany w
jakim jzyku programowania (takim jak C czy C++) i wywouje funkcje jednej lub kilku
bibliotek OpenGL. Nie twierdzimy, e programy uywaj OpenGL wycznie do rysowania,
gdy mona w nich czy wybrane elementy rnych pakietw graficznych. Mona te
uywa OpenGL wycznie do specyficznych zada, za grafiki specyficznej dla systemu
(na przykad Windows GDI) do innych.

Jako API, biblioteka OpenGL jest zgodna z konwencj wywoa funkcji C. To oznacza, e
programy w C mog wprost wywoywa funkcje OpenGL, poniewa albo sama funkcja jest
napisana w C, albo posiada specjaln funkcj poredni C do kodu napisanego w asemblerze
lub jakim innym jzyku. W tej ksice programy s pisane w C lub C++ i s przeznaczone
do pracy w rodowisku Windows NT lub Windows 95. Programy C++ mog atwo
korzysta z funkcji C i interfejsu API, wymaga to jedynie wprowadzenia bardzo drobnych
poprawek. Inne jzyki programowania -midzy innymi tak zwane 4GL-e (j?zyki czwartej
generacji), na przykad Yisual Basic - mogce wywoywa funkcje w bibliotekach C, take
mog korzysta z OpenGL. Wicej szczegw na ten temat znajduje si w rozdziale 23.

Wywoywanie funkcji C z C++


Z wyjtkiem rozdziaw dotyczcych specyficznych bibliotek
klas C++ lub jzykw czwartej generacji, wszystkie przykady w
rozdziaach zostay stworzone w C. Na doczonej do ksiki
pytce CD-ROM wiele przykadw zostao przepisanych w C++ i
przygotowanych do uycia z dwoma popularnymi bibliotekami
klas C++ (MFC i OWL). Moesz przejrze te programy, aby
zobaczy, jak zastosowano w nich makra preprocesora w celu
zachowania w jzyku C wikszoci kodu rysunkowego
OpenGL.

Podzia pracy w OpenGL


OpenGL API zostao podzielone na trzy osobne biblioteki; s one zebrane w tabeli 3.1.

Tabela 3.1.
Biblioteki i pliki nagwkowe OpenGL

NlN.HM* 5KS E*-*


Auxiliary (pomocnicza) glaux.lib glaux.h aux
OpenGL lub gl opengl32.dll gl.h gl
Narzdziowa lub glu glu32.dll glu.h glu

Pierwsza z nich, opisywana w tym rozdziale, to biblioteka Auxiliary (pomocnicza),


zwana w skrcie AUX (czasem nazywa si j bibliotek narzdziow"),
glaux.lib. Deklaracje dla tej biblioteki s zawarte w pliku nagwkowym
glaux.h. Funkcje zawarte w bibliotece nie s w rzeczywistoci czci spe-
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX_______________________53

cyfikacji OpenGL, lecz raczej zestawem narzdzi zapewniajcych niezalen od


platformy osnow dla wywoywania funkcji OpenGL. Jeli producent twojego
kompilatora nie dostarczy tych plikw, moesz je otrzyma jako cz Win32
SDK Microsoftu. Nazwy wszystkich funkcji z tej biblioteki rozpoczynaj si od
przedrostka aux.
+ Funkcje rzeczywicie zdefiniowane w specyfikacji OpenGL, zatwierdzonej przez
OpenGL Architecture Review Board, s zawarte w bibliotece opengl32.dll oraz jej
pliku nagwkowym, gl.h. Nazwy funkcji w tej bibliotece s poprzedzone
przedrostkiem g/.
* Na koniec, istnieje take biblioteka narzdziowa OpenGL, glu32.dll, wraz z
plikiem nagwkowym glu.h. Ta biblioteka zawiera pomocnicze funkcje ua-
twiajce wykonywanie powszechnych operacji, takich jak rysowanie ku, dyskw
czy cylindrw. Ta biblioteka jest napisana przy uyciu funkcji OpenGL, przez
co jest gwarantowane, e bdzie dziaaa na wszystkich platformach ob-
sugujcych specyfikacj OpenGL. Nazwy funkcji w tej bibliotece s poprze-
dzone przedrostkiem glu.

Gdy jako podstawy dla aplikacji uywasz biblioteki AUX (a wanie na tym skupimy si
w tym rozdziale), masz do dyspozycji take wszystkie funkcje bibliotek opengI32.dll i
glu32.dll. W ten sposb bdziesz mg pozna podstawy OpenGL, a take kilka polece z
biblioteki gl.

Uwaga na temat bibliotek


Z pewnoci zauwaye, e biblioteka AUX jest bibliotek
statycznie czon z aplikacj. Pozostae biblioteki OpenGL
s jednak zaimple-mentowane jako biblioteki DLL. Biblioteki
importowe potrzebne dla tych DLL-i to openg!32.lib oraz
glu32.lib. Zwykle s dostarczane wraz z kompilatorem; mona
take otrzyma je wraz z Win32 SDK Microsoftu. Jeli
uywasz Borland C++, powiniene stworzy wasne biblioteki
eksportowe, przy pomocy programu implib.exe Borlanda.

Typy danych OpenGL


Aby uatwi przenoszenie kodu OpenGL pomidzy rnymi platformami, OpenGL de-
finiuje wasne typy danych. Te typy odnosz si do normalnych typw danych C, ktrych
take moesz uywa, jeli zajdzie taka potrzeba. Jednak rne kompilatory i
rodowiska rzdz si odmiennymi reguami co do rozmiaru i uoenia zmiennych C w
pamici. Uywajc typw danych zdefiniowanych w OpenGL, moesz uniezaleni si od
tego rodzaju rnic.

Tabela 3.2 zawiera list typw danych OpenGL, odpowiadajcych im typw danych C w
32-bitowym rodowisku Windows (Win32) oraz odpowiednie przyrostki dla nazw
zmiennych. W tej ksice kada zmienna posiada odpowiedni przyrostek; przekonasz
si, e takie przyrostki posiada take wiele nazw funkcji OpenGL.
54 Cz l Wprowadzenie do OpenGL

Tabela 3.2.
Typy zmiennych OpenGL oraz odpowiadajce im typy zmiennych w C
Typ danych w OpenGL Wewntrzna reprezentacja Zdefiniowane jako Przyrostek nazwy
typ C zmiennej w C
GLbyte 8-bitowa liczba cakowita signed char b
GLshort 16-bitowa liczba cakowita short s
GLint, GLsizei 32-bitowa liczba cakowita long 1
GLfloat, GLclampf 32-bitowa liczba float f
zmiennoprzecinkowa
GLdouble, GLclampd 64-bitowa liczba double ub
zmiennoprzecinkowa
GLubyte, GLboolean 8-bitowa liczba cakowita bez unsigned char us
znaku
GLushort 1 6-bitowa liczba cakowita bez unsigned short ui
znaku
GLuint, GLenum, GLbitfield 32-bitowa liczba cakowita bez unsigned long
znaku

Wszystkie typy danych rozpoczynaj si od GL, co oznacza zmienn OpenGL. Wie- !


kszo posiada take przyrostek okrelajcy odpowiedni typ danych C (byte, short, int, ;
float itd.). Niektre posiadaj take liter u, co oznacza typ bez znaku, na przykad uby- j
te oznacza unsigned byte. W pewnych przypadkach stosowana jest bardziej opisowa ;
nazwa, na przykad size do podania wartoci dugoci czy gbokoci. Na przykad :
GLsizei to zmienna OpenGL oznaczajca parametr rozmiaru, reprezentowany jako li
czba cakowita. Sowo c lamp jest uywane przy skadaniu kolorw i stanowi skrt od
color amplitud (amplituda koloru). Ten typ danych wystpuje cznie z przyrostkami/;
i d, oznaczajcymi typy float i double. Zmienne GLboolean s uywane do okrelania j
warunkw typu Prawda i Fasz (True i False), GLenum dla zmiennych wyliczeniowych, i
za GLbitfield dla zmiennych zawierajcych binarne pola bitowe. f

Wskaniki i tablice nie s traktowane w aden specjalny sposb. Tablica zmiennych ty-f
pu GLshort moe zosta zadeklarowana po prostu jako: [
GLshort shorts[10];

za tablica dziesiciu wskanikw do zmiennych GLdouble jako [


GLdouble *doubles[ 1 0 ] ; \
j
Pewne inne rodzaje wskanikw s uywane dla powierzchni NURBS i kwadryk. Zaj-;
mierny si nimi w dalszych rozdziaach ksiki.
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 55

Konwencje nazw funkcji


Wszystkie funkcje OpenGL zostay nazwane zgodnie z okrelon konwencj, informujc o
bibliotece, z ktrej pochodzi funkcja, oraz o rodzaju i typie jej argumentw. Nazwy
wszystkich funkcji posiadaj rdze, okrelajcy odpowiadajce funkcji polecenie
OpenGL. Na przykad rdzeniem nazwy funkcji glColor3f() jest Color. Przedrostek gl
reprezentuje bibliotek gl (tabela 3.1), za przyrostek 3f oznacza, e funkcja wymaga
przekazania trzech argumentw zmiennoprzecinkowych (float). Wszystkie funkcje
OpenGL maj nastpujcy format:

<Przedrostek biblioteki><Rdze polecenia><Opcjonalnie liczba argumentw><Op-


cjonalnie typ argumentw>

Elementy nazwy funkcji OpenGL ilustruje rysunek 3.1. Ta prosta funkcja z przyrostkiem 3f
wymaga podania trzech argumentw zmiennoprzecinkowych. Inne odmiany wymagaj
podania trzech liczb cakowitych (glColor3i()), trzech liczb podwjnej precyzji
(glColor3d()) itd. Ta konwencja dodawania na kocu nazwy funkcji iloci i typu argu-
mentw bardzo uatwia zapamitanie listy argumentw danej funkcji, bez koniecznoci
zagldania do dokumentacji. Pewne wersje funkcji glColor wymagaj podania czterech
argumentw; dodatkowy argument oznacza skadnik alfa.

Rysunek 3.1.
Elementy nazwy
funkcji OpenGL
glColor3f(...)
nazwy Liczba Typ
argumentw argumentw

W podrczniku na kocu rozdziau rodziny" funkcji s wymienione wedug przedro-


stkw bibliotek i rdzeni nazw. Tak wic wszystkie wariacje funkcji glColor (glColor3f,
glColor4f, glColor3i etc.) s opisane jako pojedyncza pozycja - glColor.

Czysto kodu
Wiele kompilatorw C/C++ zakada, e literay
zmiennoprzecinkowe s typu double, chyba e przy pomocy
przyrostka jawnie okreli si inny typ. Gdy jako argumentw
zmiennoprzecinkowych uyjesz literaw i nie okrelisz, e te
literay s typu float, a nie double, kompilator zgosi
ostrzegawczy komunikat, informujc o moliwej utracie
precyzji w wyniku konwersji. W miar wzrostu objtoci
programu OpenGL, ilo ostrzee zaczyna i w setki i
trudno jest wrd nich spostrzec rzeczywiste bdy skadni.
Moesz wyczy ostrzeenia uywajc odpowiedniej opcji
kompilatora -jednak nie zalecamy tego rozwizania.
56 Cz l Wprowadzenie do OpenGL

Duo lepiej jest od pocztku tworzy czysty, przenony kod.


Pozbd si wic ostrzee o konwersji typw (w tym wypadku
o konwersji na typ float) - zamiast wycza potencjalnie
uyteczne ostrzeenia.
Z drugiej strony, jeli nie chcesz si zajmowa jawnym
oznaczaniem literaw jako liczb typu float, moe ci skusi
stosowanie tych wersji funkcji, ktre akceptuj argumenty
zmiennoprzecinkowe o podwjnej precyzji (typ double). Jednak
OpenGL wewntrznie korzysta z typu float, wic stosowanie
funkcji innych ni funkcje z argumentami pojedynczej precyzji
powoduje dodanie pewnego narzutu, zwizanego ze wstpn
konwersj argumentw na typ float.

Biblioteka AUX
W pozostaej czci rozdziau zajmiemy si bibliotek Auxiliary (AUX), znacznie ua-
twiajc opanowanie OpenGL. Ta biblioteka zostaa stworzona w celu umoliwienia
nauki pisania programw OpenGL bez koniecznoci zawracania sobie gowy szczegami
dotyczcymi danego rodowiska systemowego, czy to bdzie UNIX, czy Windows czy
cokolwiek innego. Przy uyciu biblioteki AUX nie pisze si finalnego" kodu; uywa si
jej gwnie we wstpnej fazie, do przetestowania swoich pomysw. Brak podstawowych
elementw graficznego interfejsu uytkownika uniemoliwia zastosowanie tej biblioteki
przy tworzeniu bardziej uytecznych aplikacji.

Zestaw gwnych funkcji biblioteki AUX jest dostpny w prawie wszystkich implemen-
tacjach OpenGL. Te funkcje obsuguj tworzenie okien i manipulowanie nimi, a take
wejciem ze strony uytkownika. Pozostae funkcje rysuj pewne kompletne obiekty
3D, w postaci szkieletowej lub jednolitej. Uywajc biblioteki AUX do stworzenia i
obsugi okna oraz OpenGL w celu rysowania w tym oknie, mona tworzy programy
tworzce nawet bardzo skomplikowane rysunki. Po przekompilowaniu moesz bez wi-
kszych problemw przenosi te programy do innych rodowisk.

Oprcz gwnych funkcji, kade rodowisko implementujce bibliotek AUX imple-


mentuje take pewne funkcje pomocnicze, umoliwiajce wykonywanie operacji specy-
ficznych dla systemu, takich jak przeczanie buforw czy adowanie obrazw. Im
bardziej twj kod bdzie si opiera na tych pomocniczych funkcjach, w tym mniejszym
stopniu bdzie przenony. Z drugiej strony, dziki penemu wykorzystaniu tych funkcji
moesz tworzy fantastyczne sceny, ktre zadziwi rodzin i przyjaci - bez konie-
cznoci poznawania wszystkich zoonych szczegw programowania Windows.

Niestety, mao prawdopodobne jest, aby wikszo funkcji uytecznej aplikacji spro-
wadzaa si wycznie do rysowania trjwymiarowych scen, nie moesz wic uywa
biblioteki AUX do wszystkiego. Jednak mimo wszystko, ta biblioteka jest niezastpiona
jeli chodzi o nauk i opanowywanie OpenGL, a w przypadku pewnych programw, zanim
stworzysz pen aplikacj, moesz uy biblioteki AUX do dopieszczenia kodu zajmujcego
si samym rysowaniem.
Rozdzia 3. 4 Nauka OpenGL z uyciem biblioteki AUX_______________________57

Niezaleno od platformy
OpenGL to wydajne i wymylne API przeznaczone do tworzenia trjwymiarowej grafiki, z
ponad 300 poleceniami, umoliwiajcymi okrelenie wszystkich elementw sceny, od
ustawienia koloru i waciwoci materiau, a po przeprowadzanie obrotw i innych
zoonych transformacji obiektw. By moe zdziwi ci to, e OpenGL nie posiada po-
jedynczej funkcji czy polecenia zwizanego z zarzdzaniem oknem czy ekranem. Nie
ma take funkcji przeznaczonych do odczytu klawiatury czy pooenia myszki. We jednak
pod uwag, e jednym z gwnych zaoe twrcw tego systemu bya jego niezaleno
od platformy. Tworzenie i otwieranie okna przebiega zupenie inaczej na rnych
platformach. Nawet gdyby OpenGL zawierao polecenie otwierajce okno, uyby wanie
jego, czy raczej specjalizowanej funkcji wbudowanej w system operacyjny?

Kolejnym zagadnieniem zwizanym z platform jest obsuga klawiatury i myszy. Jeliby


kade rodowisko obsugiwao je w ten sam sposb, musielibymy martwi si tylko
jednym rodowiskiem i niepotrzebne byoby ju otwarte" API. Poniewa jednak kady
system operacyjny jest inny, niezaleno OpenGL od platformy uzyskuje si kosztem
braku pewnych funkcji zwizanych z urzdzeniami wejciowymi i graficznym interfejsem
uytkownika.

AUX = wejcie/wyjcie w prosty sposb


Biblioteka AUX pocztkowo zostaa stworzona jako zestaw narzdzi przeznaczonych do
nauki OpenGL bez koniecznoci zagbiania si w szczegy zwizane z systemem
operacyjnym i interfejsem uytkownika. Aby to osign, AUX zawiera podstawowe
funkcje do tworzenia okna oraz odczytywania zdarze wywoywanych przez klawiatur i
mysz. Wewntrznie, biblioteka AUX wykorzystuje mechanizmy danego systemu ope-
racyjnego, jednak funkcje udostpniane przez ni pozostaj takie same na wszystkich
platformach.

Biblioteka AUX zawiera tylko kilka funkcji przeznaczonych do obsugi okien, klawiatury i
myszy, jednak i tak oszczdza ci znacznego kopotu zwizanego z ich obsug w
czystym C/C++ lub przez API Windows. Biblioteka zawiera take funkcje przeznaczone
do rysowania kilku stosunkowo prostych trjwymiarowych obiektw, takich jak okrg,
szecian, torus czy nawet imbryk do herbaty. Przy bardzo maym wysiku moesz uy
biblioteki AUX do wywietlenia okna i wykonania w nim kilku operacji OpenGL.
Cho biblioteka AUX w rzeczywistoci nie stanowi czci specyfikacji OpenGL,
wyglda na to, e zostaa zaimplementowana dla wszystkich platform, dla ktrych
zaimplementowano OpenGL. Windows take nie stanowi wyjtku, za kod rdowy
biblioteki AUX jest dostpny za darmo jako cz Win32 SDK Microsoftu.
58 Cz l * Wprowadzenie do OpenGL

Analiza krtkiego programu OpenGL


Aby lepiej zrozumie bibliotek AUX, rzumy okiem na jeden z najkrtszych w wiecie
programw OpenGL, stworzony wanie za pomoc tej biblioteki. Listing 3.1 prezentuje
program shortest.c, za wynik jego dziaania zosta pokazany na rysunku 3.2.

Rysunek 3.2.
Wynik dziaania
programu shortest.c

Listing 3.1. Najkrtszy w wiecie program OpenGL

// shortest.c
// N a j k r t s z y w wiecie program OpenGL

finclude <windows.h> // Standardowy nagwek Windows wymagany we


wszystkich programach
tinclude <conio.h> // Funkcje I/ O konsoli tinclude
< gl\ gl .h > // Funkcje OpenGL tinclude < gl\gl a ux. h >
// Funkcje biblioteki AUX

void main(void)

// Funkcje AOX suce do przygotowania okna


auxInitDisplayMode (AUX_SINGLE | AUX_RGBA) ;
aux!nitPosition(100, 100,250,250) ;
aux!nitWindow("Mj pierwszy program OpenGL");

// Funkcje OpenGL wykonujce co w oknie


glClearColor(O.Of, O . O f , l.O f, l . O f ) ;
glClear (GL_COLOR_BUFFER_BIT) ;
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX_______________________59_

glFlushO ;

// Zatrzymanie i oczekiwanie na wcinicie klawisza


cprintf("Wcinij jaki klawisz, aby zamkn okno\n");
getch();

Tryby konsoli
Aplikacja konsoli to program Win32 dziaajcy w oknie trybu
tekstowego. Taki program bardzo przypomina program DOS-a
uruchomiony w Windows NT lub Windows 95, z tym e jest w
peni 32-bitowa aplikacja i ma dostp do caego API Win32.
Programy konsoli nie s ograniczone do trybu tekstowego. W
rzeczywistoci mog tworzy wasne okienka (w powyszym
programie sprbuj uy funkcji MessageBox() z wartoci
IMULL podan w miejscu uchwytu okna), za aplikacje GUI
(Graphics User Interface - graficzny interfejs uytkownika)
mog w razie potrzeby tworzy okna konsoli. Biblioteka AUX
umoliwia atwe pisanie programw konsoli, zawierajcych
funkcj main(), ktra tworzy pomocnicze okno GUI dla rysunku
tworzonego w OpenGL.

Aby zbudowa ten program, musisz ustawi opcje kompilatora i linkera tak, aby po-
wstaa aplikacja konsoli Win32. Musisz doczy bibliotek AUX, glaux.lib, oraz bi-
bliotek importow OpenGL, openg!32.1ib. Szczegowe instrukcje na temat kompilacji i
czenia programw znajdziesz w dokumentacji kompilatora.

Program shortest.c nie czyni zbyt wiele. Gdy uruchomisz go w linii polece, tworzy
standardowe okno GUI z tytuem Mj pierwszy program OpenGL" oraz czystym nie-
bieskim tem. Nastpnie w oknie konsoli wywietla komunikat Wcinij jaki klawisz,
aby zamkn okno". Okno GUI nie reaguje na klawiatur ani mysz; to okno konsoli
oczekuje na wcinicie jakiego klawisza w celu zakoczenia dziaania (musisz w tym
celu przeczy si z powrotem do okna konsoli). Nie moesz take przesun okna
OpenGL ani zmieni jego rozmiaru, za samo okno nawet si nie odrysowuje. Jeli
przesonisz okno, a nastpnie je odsonisz, przekonasz si, e obszar roboczy sta si
czarny.

Ten prosty program zawiera trzy funkcje biblioteki AUX (poprzedzone przedrostkiem
aux) oraz trzy prawdziwe" funkcje OpenGL (poprzedzone przedrostkiem gl). Przej-
rzyjmy ten program linia po linii, a nastpnie przejdmy do omwienia innych funkcji,
poprawiajcych dziaanie naszego programu.

Cz nagwkowa
S do niej wczone nastpujce pliki:
tfinclude <windows.h>
#include <conio.h>
include <gl\gl.h>
tinclude <gl\glaux.h>
60_________________________________Cz l Wprowadzenie do OpenGL

Te pliki nagwkowe zawieraj definicje wszystkich prototypw funkcji uywanych


przez program. Pliku windows.h wymagaj wszystkie aplikacje GUI w Windows; cho
nasz program jest programem konsoli, biblioteka AUX tworzy okno GUI, w ktrym od-
bywa si rysowanie. Plik conio.h zawiera deklaracje funkcji wejcia/wyjcia konsoli.
Musielimy go doczy, gdy korzystamy z funkcji cprintf() w celu wywietlenia ko-
munikatu oraz z funkcji getch() w celu oczekiwania na wcinicie klawisza koczcego
dziaanie programu. Plik gl.h definiuje funkcje OpenGL poprzedzone przedrostkiem gl,
za plik glaux.h zawiera wszystkie funkcje konieczne dla biblioteki AUX.

Ciao programu
Nastpnie mamy do czynienia z gwn czci programu:
void main(void) {

Programy konsoli napisane w C i C++ zawsze rozpoczynaj dziaanie od funkcji main().


Jeli jeste dowiadczonym programist Windows, by moe zastanawiasz si, gdzie w
tym przykadzie wystpuje funkcja WinMain(). Nie ma jej, a to dlatego, e na pocztku
uruchamiamy aplikacj konsoli, nie musimy wic tworzy okna z ptl komunikatw.
W przypadku Win32 istnieje moliwo tworzenia okien graficznych z poziomu aplikacji
konsoli, tak jak moliwe jest tworzenie okien konsoli z poziomu aplikacji GUI. Tymi
szczegami zajmuje si sama biblioteka AUX (jak pamitasz, wanie taki by cel jej
powstania).

Tryb wywietlania: pojedynczy bufor


Nastpna linia kodu
auKlnitDisplayMode(AUX_SINGLE | AUX_RGBA);

informuje bibliotek AUX o trybie wywietlania, jaki ma zosta uyty podczas tworzenia
okna. Zastosowane przez nas znaczniki nakazuj uycie okna z pojedynczym buforem
(AUX_SINGLE) oraz trybu kolorw RGBA (AUX_RGBA). Okno z pojedynczym
buforem oznacza, e wszystkie polecenia rysowania s wykonywane bezporednio w
wywietlanym oknie. Alternatyw stanowi okno z podwjnym buforem, w ktrym
polecenia rysowania s realizowane w niewidocznym buforze, ktry nastpnie jest
szybko przerzucany do okna na ekranie. Ta technika jest stosowana najczciej przy
tworzeniu animacji, co zademonstrujemy w dalszej czci rozdziau. Tryb koloru RGBA
oznacza, e wartoci kolorw s podawane jako oddzielne wartoci barw skadowych:
czerwonej, zielonej i niebieskiej (ang. red, green i blue) - wicej informacji na ten
temat znajdziesz w rozdziale 8.

Pozycjonowanie okna
Po ustawieniu trybu wywietlania, musimy poinformowa bibliotek AUX o pooeniu i
rozmiarach okna. Suy do tego nastpna linia kodu:
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 61

aux!nitPosition(100,100,250,250);

Parametry reprezentuj pooenie lewego grnego rogu okna oraz jego szeroko i wy-
soko. Powysza linia nakazuje umieszczenie lewego grnego rogu okna w miejscu o
wsprzdnych (100, 100) oraz nadanie oknu szerokoci 250 pikseli i wysokoci take 250
pikseli. Przy standardowej rozdzielczoci VGA (640 x 480), okno zajmie do du cz
ekranu. Przy rozdzielczociach Super VGA (800 x 600 i wyszych) okno zajmie mniej
miejsca, gdy ilo pikseli pozostanie taka sama (250 x 250).

Oto prototyp tej funkcji:


auxInitPosition(GLint x, GLint y, GLsizei width, GLsizei height);

Typy danych GLint i GLsizei s zdefiniowane jako liczby cakowite (zostay one om-
wione w sekcji dotyczcej typw danych we wczeniejszej czci rozdziau). Parametr x
okrela ilo pikseli liczonych od lewej krawdzi ekranu, za parametr y - ilo pikseli
liczonych od grnej krawdzi. Wanie tak Windows domylnie konwertuje wsprzdne
ekranu na wsprzdne fizyczne. Domylna metoda liczenia wsprzdnej x w OpenGL jest
taka sama; jednak w przypadku wsprzdnej y jest ona liczona od dolu do gry - przeciwnie
do kierunku wzrostu tej wsprzdnej w Windows. Spjrz na rysunki 3.3 oraz 3.4.

Rysunek 3.3.
Domylne Wsprzdne ektranu w Windows
odwzorowanie
wsprzdnych Kierunek dodatni
ekranu \v Windows (100,100)

Kierunek dodatni

/ }dwzorowanie wsprzdnych w oknie OpenGL


Kierunek dodatni
i
Rysunek 3.4.
Domylne
odwzorowanie
wsprzdnych okna (100,100) Kierunek dodatni
w OpenGL
62 __ __ ______Cz l Wprowadzenie do OpenGL

Uwaga na temat przenonoci kodu


O ile Windows odwzorowuje wsprzdne ekranu tak, jak
pokazano na rysunku 3.3, o tyle system X Windows
odwzorowuje wsprzdne tak samo jak OpenGL na rysunku
3.4. Jeli przenosisz program korzystajcy z biblioteki AUX z
innego rodowiska, by moe bdziesz musia zmodyfikowa
wywoanie funkcji auxlnitPosition().

Tworzenie okna OpenGL


Ostatnie wywoanie funkcji z biblioteki AUX wie si z samym utworzeniem okna na
ekranie. Kod
auxlnitwindow("Mj pierwszy program O p e n G L " ) ;

tworzy okno oraz nadaje mu tytu Mj pierwszy program OpenGL". Oczywicie, poje-
dynczym argumentem tej funkcji jest wanie tytu okna. Gdybymy zatrzymali si w
tym miejscu, program stworzyby puste okno (domylnie o czarnym tle) z podanym
tytuem, a nastpnie zakoczyby dziaanie natychmiast zamykajc okno OpenGL. Do-
danie ostatniej instrukcji getch() zabezpieczy nas przed zamkniciem okna, jednak w
dalszym cigu w samym oknie nie dzieje si nic interesujcego.

Czyszczenie okna (wypenianie kolorem)


Trzy omwione dotd linie kodu s zwizane z bibliotek AUX i wystarczaj do zaini-
cjowania i stworzenia okna, w ktrym bdzie rysowa OpenGL. Od tego momentu,
wszystkie wywoania polece i funkcji OpenGL bd operowa wanie w tym oknie.
Nastpna linia kodu
glClearColor( O . O f , O . O f , l.Of, l . O f ) ;

to twoje pierwsze wywoanie prawdziwej funkcji OpenGL. Ta funkcja ustala kolor uy-
wany podczas czyszczenia okna. Jej prototyp to:
void glClearColor (GLclampf red, GLclampf green, GLclampf blue,
OGLclampf alpha) ;

GLclampf w wikszoci implementacji OpenGL jest zdefiniowane jako liczba zmienno-


przecinkowa typu float. W OpenGL pojedynczy kolor jest reprezentowany jako mieszanina
czerwonej, zielonej i niebieskiej barwy skadowej. Zakres kadego ze skadnikw naley
do przedziau od 0,0 do 1,0. Wystpuje tu podobiestwo do sposobu okrelania koloru w
Windows, przy pomocy makra RGB tworzcego warto COLORREF. (Szczegy
znajdziesz w kadej ksice powiconej programowaniu w Windows). Rnica polega
na tym, e w Windows kady komponent koloru naley do przedziau od O do 255, co
daje w sumie 256 x 256 x 256 dostpnych kolorw - czyli ponad 16 milionw kolorw.
W OpenGL wartoci kadej barwy skadowej moe by dowolna poprawna warto z
przedziau od 0,0 do 1,0, co teoretycznie daje nieskoczon liczb potencjalnych kolorw.
W praktyce, OpenGL wewntrznie reprezentuje kolory jako
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX

wartoci 32-bitowe, czyli maksymalna ilo reprezentowalnych kolorw wynosi


4294967296 (w przypadku niektrych kart graficznych odpowiada to trybowi TrueCo-
lor). W efekcie kada barwa skadowa moe zmienia si z 0,0 na 1,0, z krokiem
wynoszcym w przyblieniu 0,00006.

Naturalnie zarwno Windows, jak i OpenGL konwertuj otrzyman warto koloru na


najblisz warto moliw do zaprezentowania na zainstalowanym sprzcie i ewen-
tualnie w danej palecie. Bliej zajmiemy si tym w rozdziale 8.

Tabela 3.3 zawiera list niektrych czciej wykorzystywanych kolorw oraz odpowia-
dajce im wartoci poszczeglnych barw. Te wartoci mog by uyte we wszystkich
funkcjach OpenGL zwizanych z kolorem.

Tabela 3.3.
Stosunki barw skadowych czciej uywanych kolorw
Kolor wynikowy Barwa czerwona Barwa zielona Barwa niebieska
Czarny 0,0 0,0 0,0
Czerwony 1,0 0,0 0,0
Zielony 0,0 1,0 0,0
ty 1,0 1,0 0,0
Niebieski 0,0 0,0 1,0
Fioletowy 1,0 0,0 1,0
Bkitny 0,0 1,0 1,0
Ciemny szary 0,25 0,25 0,25
Jasny szary 0,75 0,75 0,75
Brzowy 0,60 0,40 0,12
Pomaraczowy 0,98 0,625 0,12
Rowy 0,98 0,04 0,70
Purpura 0,60 0,40 0,70
Biay 1,0 1,0 1,0

Ostatnim argumentem funkcji flClearColor() jest skadnik alfa. Skadnik alfa jest uy-
wany przy przezroczystoci oraz przy efektach specjalnych takich jak przejrzysto.
Przejrzysto odnosi si do waciwoci obiektu umoliwiajcej wiatu przechodzenie
przez obiekt. Przypumy, e prezentujesz kawaek czerwonego witrau, lecz owietlonego
niebieskim wiatem. Niebieskie wiato wpynie na wygld czerwieni w szkle
(czerwony + niebieski = fioletowy). Moesz uy skadnika alfa w celu uczynienia
koloru niebieskiego pprzejrzystym, tak aby wyglda na przykad jak warstwa wody,
ukazujca znajdujce si pod ni obiekty. Na temat tego rodzaju efektw mona po-
wiedzie o wiele wicej ni tylko o wartoci alfa; w rozdziale 16 napiszemy przykadowy
program demonstrujcy te zagadnienia, a na razie pozostaw t warto jako 1.
64 Cz l Wprowadzenie do OpenGL

Samoczyszczenie okna
Gdy poinformowalimy OpenGL o kolorze, jakiego ma uy do czyszczenia, moemy
uy instrukcji wykonujcej samoczyszczenie. Suy do tego linia
glClear(GL_COLOR_BUFFER_BIT);

Funkcja glClear() czyci dany bufor lub kombinacj buforw. Bufor to miejsce, gdzie
przechowywana jest informacja o obrazie. Skadniki czerwony, zielony i niebieski po-
siadaj wewntrznie osobne bufory, jednak w caoci traktujemy je jako pojedynczy
bufor kolorw.
Bufory to bardzo uyteczny element OpenGL; szczegowo omwimy je w rozdziale 15.
Przed lektur nastpnych kilku rozdziaw jedyne, co musimy zapamita o buforze ko-
lorw, to informacja e jest w nim wewntrznie przechowywany rysowany obraz, za
wyczyszczenie bufora funkcj glClear() powoduje usunicie rysunku z okna.

Oprnienie zawartoci kolejki


Oto wywoanie ostatniej z trzech funkcji OpenGL:
glFlushO ;

Ta linia powoduje wykonanie wszystkich niewykonanych dotd polece OpenGL - w tym


momencie mamy dwa takie polecenia: glClearColor() oraz glClear().
Wewntrznie, OpenGL uywa tzw. kanau renderowania, kolejno przetwarzajcego po-
lecenia. Funkcje i polecenia OpenGL czsto s umieszczane w kolejce i oczekuj w niej do
momentu, a serwer OpenGL przetworzy kilka da" naraz. To znacznie poprawia
wydajno, szczeglnie w przypadku konstruowania zoonych obiektw. Nastpuje
przyspieszenie rysowania, gdy dostp do stosunkowo wolnego sprztu graficznego w celu
wykonania danego zestawu instrukcji rysunkowych odbywa si rzadziej. (Gdy
opracowywano Win32, zastosowano t sam koncepcj dla Windows GDI, w celu przy-
spieszenia operacji graficznych w Windows NT). W naszym krtkim programie funkcja
glFlush() po prostu informuje OpenGL, aby przetworzy dostarczone dotd polecenia
graficzne, nie czekajc na nastpne instrukcje rysunkowe.
Ostatni fragment kodu w tym przykadzie
// Zatrzymanie i oczekiwanie na wcinicie klawisza
cprintf("Wcisnij jaki klawisz aby zamkn o k n o \ n " ) ;
getch() ; >

wywietla komunikat w oknie konsoli i zatrzymuje dziaanie programu do momentu na-


cinicia jakiego klawisza; w tym momencie program koczy dziaanie i nastpuje
zamknicie okna.
Program w obecnej wersji nie jest zbyt interesujcy, jednak demonstruje podstawowy
sposb utworzenia okna oraz wyczyszczenia go przy uyciu okrelonego koloru. Spr-
Rozdzia 3. Nauka OpenGL z uyciem biblioteki AUX

bujmy go teraz rozbudowa dodajc kilka dodatkowych funkcji bibliotek AUX i


OpenGL.

Rysowanie ksztatw za pomoc OpenGL


Program shortest.c tworzy puste okno o bkitnym tle. Sprbujmy teraz co w nim na-
rysowa. Ponadto chcemy, aby okno mogo zmienia rozmiary i przemieszcza si, tak jak
prawdziwe okno Windows. Przy okazji zrezygnujemy take z uywania funkcji
getch() w celu wychwycenia momentu zakoczenia dziaania programu. Zmodyfikowany
program przedstawiono na listingu 3.2.

listing 3.2. Bardziej przyjazny program OpenGL________________________________

// friendly.c
// Bardziej przyjazny program OpenGL

linclude <windows.h> // Standardowy nagwek dla Windows


tfinclude <gl\gl.h> // Biblioteka OpenGL
tinclude <gl\glaux.h> // Biblioteka AUX

// Wywoywane przez bibliotek AUX w celu narysowania sceny


void CALLBACK RenderScene(void)
{
// Kolor ta: Niebieski
glClearColor(O.Of, O.Of, l.Of, l . O f ) ;
// Wyczyszczenie okna
glClear(GL_COLOR_BUFFER_BIT);
// Kolor rysowania czerwony
//
R G
B
glColor3f( l . O f , O.Of, O . O f ) ;
// Narysowanie prostokta wypenionego biecym kolorem
glRectf(lOO.Of, 150.Of, 150.Of, 100.O f ) ;
glFlushO ;

void main(void) {
// Przygotowanie trybu rysowania i okna za pomoc biblioteki AUX
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
aux!nitPosition(100,100,250,250); auxlnitWindow("Mj drugi program
OpenGL");

// Przygotowanie funkcji wywoywanej w momencie, gdy konieczne // jest


odwieenie okna auxMainLoop(RenderScene);
66_________________________________Cz l * Wprowadzenie do OpenGL

Pierwsza zmiana dotyczy plikw nagwkowych. Nie ma tu pliku conio.h, gdy nie
uywamy ju funkcji getch() ani cprintf().

Funkcja renderujca
W programie wystpuje nowa funkcja, RenderScene().
// Wywoywane przez bibliotek AUX w celu narysowania sceny void
CALLBACK RenderScene(void)

W tej funkcji umiecilimy cay kod odpowiedzialny za rysowanie w oknie. Proces ry-
sowania w OpenGL czsto jest nazywany renderowaniem, uylimy wic adekwatnej do
tego nazwy funkcji. W nastpnych przykadach wikszo kodu rysunkowego znajdzie si
wanie w tej funkcji.

Zwr uwag na instrukcj CALLBACK w deklaracji funkcji. Jest ona wymagana,


gdy mamy zamiar poinformowa bibliotek AUX, aby wywoywaa t funkcj za kadym
razem, gdy okno bdzie wymaga odwieenia. Funkcje zwrotne (ang. callback) to zwyke
funkcji, ktre bez naszego udziau wywouje biblioteka AUX. O tym, jak to dziaa,
powiemy sobie nieco pniej.

Rysowanie prostokta
Poprzednim razem wszystkie dziaania programu sprowadzay si jedynie do wyczy-
szczenia ekranu. Teraz do kodu rysunkowego dodalimy dwie ponisze linie:
// Kolor rysowania czerwony
//
R G
B
glColor3f( l . O f , O . O f , O . O f ) ;

// Narysowanie prostokta wypenionego biecym kolorem


glRectf(lOO.Of, 150.Of, 150.Of, 100.O f ) ;

Pierwsza linia ustawia kolor uywany w nastpnych operacjach rysowania (linii i wy-
penie); suy do tego funkcja glColor3f(). Druga linia, wywoujca funkcj glRectf(),
suy do narysowania wypenionego prostokta.

Funkcja glColor3f() wybiera kolor w ten sam sposb, co glClearColor(), z tym e nie
trzeba podawa wartoci skadnika alfa:
void glColor3f(GLfloat red, GLfloat green, GLfloat blue);

Funkcja glRectf() wymaga parametrw typu float, o czym informuje kocowa litera f
nazwie funkcji. W tym wypadku w nazwie nie ujmuje si iloci argumentw, gdy
wszystkie odmiany tej funkcji wymagaj podania czterech argumentw. Cztery argu-
menty funkcji glRectf():
void glRectf(GLfloat xl, GLfloat yl, GLfloat x2, GLfloat y 2 ) ;
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX_______________________67

reprezentuj dwie pary wsprzdnych: (xl, yl) oraz (x2, y2). Pierwsza para reprezentuje
lewy grny rg prostokta, za druga para - rg prawy dolny. Jeli chcesz sobie
przypomnie odwzorowanie wsprzdnych w OpenGL, spjrz na rysunek 3.4.

Inicjowanie
Gwna funkcja programu friendly.c rozpoczyna si tak samo jak w naszym pierwszym
przykadzie:
void main(void) {
// Przygotowanie trybu rysowania i okna za pomocy biblioteki AUX
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
auxInitPosition(100,100,250,250); aux!nitWindow("Mj drugi program
OpenGL");
// Przygotowanie funkcji wywoywanej w razie koniecznoci //
odwieenia okna auxMainLoop(RenderScene); }

Jak wczeniej, trzy wywoania auxlnito* przygotowuj i tworz okno, w ktrym bdzie si
odbywa rysowanie. W ostatniej linii funkcji auxMainLoop() znajduje si nazwa funkcji,
ktra bdzie uywana do rysowania, funkcji RenderScene(). Funkcja Main-Loop()
biblioteki AUX po prostu podtrzymuje dziaanie programu do momentu, a uytkownik
zamknie okno. Pojedynczym argumentem funkcji jest wskanik do innej funkcji, ktra ma
by wywoywana za kadym razem, gdy okno wymaga aktualizacji. Ta funkcja zwrotna
zostanie wywoana podczas pierwszego wywietlenia okna, gdy zostanie ono przesunite
lub przeskalowane, a take gdy zostanie odsonite przez inne okno.
// Wywoywane przez bibliotek AUX w celu narysowania sceny void
CALLBACK RenderScene(void)
{
// Kolor ta: Niebieski
glClearColor( O . O f , O.Of, l . O f , l . O f ) ;
// Wyczyszczenie okna
glClear(GL_COLOR_BUFFER_BIT);

// Kolor rysowania czerwony


//
R G
B
glColor3f( l . O f , O.Of, O . O f ) ;

// Narysowanie prostokta wypenionego biecym kolorem


glRectf(lOO.Of, 150.Of, 150.Of, 100.O f ) ;

glFlushf) ; }

W tym momencie program wywietli czerwony kwadrat na rodku niebieskiego okna,


gdy tak wanie na stae ustawilimy pooenie prostokta. Gdy powikszysz okno,
kwadrat pozostanie na swoim miejscu w stosunku do lewego dolnego rogu okna. Gdy
zmniejszysz okno, kwadrat moe nie zmieci si w obszarze roboczym. Dzieje si tak,
poniewa, na skutek zmiany rozmiaru okna zmieniana si rozmiary obszaru rysowania,
lecz kod rysunkowy w dalszym cigu umieszcza prostokt w tym samym miejscu
68_________________________________Cz l * Wprowadzenie do OpenGL

o wsprzdnych (100, 150, 150, 100). W oryginalnym oknie byo to dokadnie na rodku;
w oknie wikszym te wsprzdne wskazuj lewy dolny rg okna (rysunek 3.5).

Rysunek 3.5.
Efekty zmiany rozmiaru okna

250

Skalowanie do
rozmiarw okna
W praktycznie wszystkich rodowiskach okienkowych uytkownik moe w dowolnej
chwili zmieni rozmiary okna. Gdy tak si dzieje, okno zwykle odpowiada odrysowaniem
swej zawartoci, biorc pod uwag nowy rozmiar. Czasem zechcesz po prostu obci
obraz do nowych wymiarw lub wywietli cay obraz w wikszym oknie. Do naszych
celw zwykle jednak zechcemy tak przeskalowa rysunek, aby w peni mieci si w
oknie, bez wzgldu na rozmiar rysunku lub okna. Tak wic bardzo mae okno bdzie
zawierao peny, lecz bardzo may rysunek, za wiksze okno bdzie zawierao podobny,
lecz wikszy rysunek. Wida to w wikszoci programw rysunkowych, gdy zmniejszasz
okno, lecz nie powikszasz samego rysunku. Zmniejszenie okna zwykle nie zmienia
rozmiaru rysunku, jednak powikszenie rysunku zwykle zwiksza rozmiar okna.

Ustawianie widoku i bryy obcinania


W rozdziale 2 omawialimy wpyw widokw i bry obcinania na zakres wsprzdnych
oraz skalowanie dwu- i trjwymiarowych rysunkw w dwuwymiarowych oknach na
ekranie komputera. Teraz zajmiemy si ustawieniami widoku i wsprzdnymi bryy
obcinania w OpenGL. Gdy tworzymy okno wywoaniem funkcji
auKlnitPosition(100,100,250,250);

biblioteka AUX domylnie tworzy widok dokadnie dopasowany do rozmiarw okna


(0,0, 250, 250). Brya obcinania jest domylnie ustawiana tak, aby wypeniaa pierwszy
kwadrant kartezjaskiej przestrzeni, z osiami x i y wyznaczajcymi szeroko i wysoko
okna. O z biegnie prostopadle do obserwatora, przez co obiekty rysowane na paszczynie
xy sprawiaj wraenie dwuwymiarowych. Graficznie ilustruje to rysunek 3.6.
Rozdzia 3. + Nauka OpenGL z uyciem biblioteki AUX 69

Rysunek 3.6.
Widok i brya
obcinania dla (250,250,-!)
program u friendly. c

(250,250,1)
(100,150,0)

(150,100,0

Cho nasz rysunek skada si z paskiego, dwuwymiarowego prostokta, w rzeczywistoci


rysujemy w trjwymiarowej przestrzeni kartezjaskiej. Funkcja glRectf() rysuje prostokt
na paszczynie xy o wsprzdnej z = 0. Poniewa patrzymy w d osi z, widzimy paski
prostokt.
Gdy tylko zmienia si rozmiar okna, widok i brya obcinania musz zosta przedefmio-
wane odpowiednio do nowych rozmiarw. W przeciwnym razie zobaczymy efekt
przedstawiony na rysunku 3.5, kiedy to odwzorowanie ukadu wsprzdnych sceny na
ukad wsprzdnych okna pozostaje takie samo, bez wzgldu na rozmiar okna.
Poniewa zmiany wymiarw okna s wykrywane i obsugiwane rnie w rnych ro-
dowiskach, biblioteka AUX dostarcza funkcji auxReshapeFunc(), ktra rejestruje funkcj
zwrotn, wywoywan przez bibliotek AUX przy kadej zmianie wymiarw okna. Funkcja
przekazywana w wywoaniu auxReshapeFunc() ma nastpujcy prototyp:
void CALLBACK ChangeSize(GLsizei w, GLsizei h ) ;

Nazw ChangeSize (zmie rozmiar) wybralimy jako nazw opisow i bdziemy si jej
trzyma take w nastpnych przykadach.
Funkcja ChangeSize() otrzymuje now szeroko i wysoko okna za kadym razem,
gdy zmienia si ktry z wymiarw okna. Moemy uy tej informacji do zmodyfiko-
wania odwzorowania naszego ukadu wsprzdnych na ukad wsprzdnych ekranu, za
pomoc dwch funkcji OpenGL: glViewport() oraz glOrtho(). Listing 3.3 przedstawia
nasz poprzedni przykad modyfikowany tak, aby bra pod uwag zmian rozmiaru okna.
Na listingu zostaa przedstawiona jedynie zmodyfikowana funkcja main() oraz nowa
funkcja ChangeSize().
70_________________________________Cz l Wprowadzenie do OpenGL

Listing 3.3. Skalowanie w


OpenGL_______________________________________
// Scal.c
// Skalowanie okna OpenGL

// Wywoywana przez bibliotek AUX w momencie zmiany rozmiaru okna


void CALLBACK ChangeSize(GLsizei w, GLsizei h)
{
// Zabezpieczenie przed dzieleniem przez zero
i f ( h == 0) h =
1;

// Ustawienie widoku na wymiary okna


glViewport( O , O, w, h ) ;
// Wyzerowanie ukadu wsprzdnych
glLoadldentity();
// Ustalenie bryy obcinania ( l e w a , prawa, dolna, grna, blisza, //
dalsza) if (w <= h)
glOrtho ( O . O f , 250.Of, O . O f , 250.0f*h/w, 1 . 0 , - 1 . 0 ) ;
else
glOrtho ( O . O f , 250.0f*w/h, O . O f, 250.Of, 1 . 0 , - 1 . 0 ) ;
}
void main(void) {
// Przygotowanie trybu rysowania i okna za pomoc biblioteki AUX
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
aux!nitPosition(100,1 0 0 , 2 5 0 , 2 5 0 ) ;
auxlnitwindow("Skalowanie o k n a " ) ;
// Przygotowanie funkcji wywoywanej w momencie zmiany rozmiaru
// okna
auxReshapeFunc(ChangeSize);
// Przygotowanie funkcji wywoywanej w momencie koniecznoci //
odwieenia okna auxMainLoop(RenderScene);

Teraz, gdy zmienisz wymiary okna, prostokt take zmieni swj rozmiar. Znacznie wiksze
okno bdzie zawierao duo wikszy prostokt, za o wiele mniejsze okno bdzie
zawierao znacznie mniejszy prostokt. Jeli wyduysz okno w poziomie, prostokt zostanie
wyrodkowany w pionie, daleko na lewo od rodka. Jeli wyduysz okno w pionie,
prostokt zostanie wyrodkowany w poziomie, bliej dou okna. Zwr uwag e
prostokt zawsze pozostaje kwadratem. Aby zobaczy jak zmienia si rozmiar prostokta
wraz z rozmiarami okna, spjrz na rysunki 3.7a i 3.7b.
Rozdzia 3. Nauka OpenGL z uyciem biblioteki AUX 71

Rysunek 3.7a.
Obraz
przeskalowany do
wymiarw okna

Rysunek 3.7b.
Prostokt zmienia
rozmiar wraz
z wymiarami okna

Definiowanie widoku
Aby zrozumie, jak definiuje si widok, przyjrzyjmy si bliej funkcji ChangeSize(). Na
pocztku wywouje ona funkcj glViewport() z now szerokoci i wysokoci okna.
Funkcja glViewport() jest zdefiniowana jako
void glviewport(GLint x, GLint y, GLint width, GLint h e i g h t ) ;

Parametry x i y okrelaj prawy dolny rg widoku wewntrz okna, za parametry width i


height okrelaj szerokoci i wysoko widoku w pikselach. Zwykle x i y przyjmuj
warto O, jednak mona uy widokw do przedstawiania kilku rysunkw w rnych
obszarach okna. Widok definiuje obszar wewntrz okna, okrelajc wsprzdne ekra-
nowe, w zakresie ktrych bdzie mogo rysowa OpenGL (rysunek 3.8). Nastpnie bieca
brya obcinania jest odwzorowywana na nowy widok. Jeli okrelisz widok
mniejszy ni wsprzdne okna, rysunek take zostanie odpowiednio zmniejszony, tak jak
przedstawiono na rysunku 3.8.
72 Cz l * Wprowadzenie do OpenGL

Rysunek 3.8.
Odwzorowanie
widoku na okno
GrViewport(0,0,125,125)
125X
glVjewport(0,0,250,250)

11
250 N- 250
-H
-H
Widok i okno maj te same rozmiary
Widok stanowi poow rozmiaru okna

Definiowanie bryy obcinania


Ostatni czynnoci w naszej funkcji ChangeSize() jest przedefiniowanie bryy obcinania,
tak aby stosunek wsprzdnych pozosta bez zmian. Stosunek wsprzdnych (ang. aspect
rati) to stosunek iloci pikseli odpowiadajcych jednostce osi pionowej do iloci pikseli
odpowiadajcych jednostce osi poziomej. Stosunek wsprzdnych o wartoci 1,0 oznacza,
e jednostkom obu osi odpowiadaj rwne iloci pikseli (stosunek prostoktny). Stosunek o
wartoci 0,5 oznacza e na kade dwa piksele w osi poziomej przypada jeden piksel w osi
pionowej.

Jeli widokowi zostanie przypisany stosunek wsprzdnych rny od 1,0 i widok zo-
stanie odwzorowany w prostoktn bry obcinania, spowoduje to, e obrazy bd znie-
ksztacone. Na przykad, widok dostosowany do wymiarw okna, lecz odwzorowany w
prostoktn bry obcinania spowoduje, e obrazy bd wskie i wysokie w wskich i
wysokich oknach, a niskie i szerokie w niskich i szerokich oknach. W naszym przypadku
kwadrat tylko wtedy byby kwadratowy, gdyby samo okno byo kwadratowe.

W naszym przykadzie dotyczcym bryy obcinania stosujemy rzutowanie rwnolege


(patrz rozdzia 2). Poleceniem OpenGL sucym do utworzenia takiego rzutowania jest
glOrtho():
void glOrtho(GLdouble lewa, GLdouble prawa, GLdouble dolna, GLdouble ^gorna,
GLdouble blisza, GLdouble dalsza);

W trjwymiarowej przestrzeni kartezjaskiej, wartoci lewa i prawa okrelaj minimaln i


maksymaln wsprzdn wywietlan wzdu osi x; wartoci dolna i grna odnosz si do
osi y. Wartoci blisza i dalsza okrelaj zakres wywietlanych wsprzdnych osi z, na
ktrej wartoci malej w gb ekranu (rysunek 3.9).

Tu przed wywoaniem funkcji glOrtho() z pewnoci zauwaye pojedyncze wywoanie


funkcji glLoad!dentity(). Jest ono konieczne, gdy OpenGL nie ustanawia nowej bryy
obcinania, lecz modyfikuje bry ju istniejc. Mnoy macierz opisujc biec bry
obcinania przez macierz opisujc bry obcinania okrelon przez argumenty
wywoania funkcji glOrtho(). Jednak dyskusj na temat operacji macierzowych i prze-
ksztacania wsprzdnych odoymy a do rozdziau 7. W tym momencie powiniene
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 73

jedynie wiedzie, e funkcja glLoad!dentity() po prostu zeruje" ukad wsprzdnych


przed kadym zastosowaniem funkcji glOrtho(); nastpne wywoanie funkcji gOrtho()
bez wyzerowania ukadu wsprzdnych zmodyfikowaoby bry obcinania nawet do tego
stopnia, e nasz prostokt mgby nawet nie ukaza si w oknie.

Rysunek 3.9.
Przestrze
kartezjaska

Aby kwadrat by kwadratem


To, e nasz kwadrat" pozostaje kwadratowy, jest zasug poniszego kodu:
if (w <= h)
glOrtho ( O . O f , 250.Of, O . O f , 250.0f*h/w, 1.0, -1.0);
else
glOrtho ( O . O f , 250.0f*w/h, O . O f , 250.O f , 1.0, -1.0);
Rysunek 3.10.
250
Region obcinania L t 111l
dla trzech rnych -' S ii1
i __
CNI
ksztatw okna
.:
J
">
11

250 1
11,
' . _ _ _ _ _ _ _ - !
1
,T
s
Cl
r 500
H

H
250

Nasza brya obcinania (widoczna cz przestrzeni wsprzdnych) jest modyfikowana


tak, e jej lewa strona znajduje si zawsze w punkcie x = 0. Prawa strona rozciga si o
250 jednostek w prawo, chyba e okno ma wiksz szeroko ni wysoko. W takim
wypadku prawa strona jest mnoona przez stosunek wsprzdnych okna. Dolna pa-
szczyzna zawsze znajduje si w punkcie y = O, za grna paszczyzna jest przesunita o
250 jednostek w gr, chyba e okno ma wiksz wysoko ni szeroko. W takim
74_________________________________Cz l Wprowadzenie do OpenGL

przypadku pooenie grnej paszczyzny jest mnoone przez stosunek wsprzdnych


okna. Dziki temu zawsze pozostaje nam do dyspozycji region 250 x 250 jednostek, bez
wzgldu na ksztat okna. Dziaanie tego mechanizmu przedstawia rysunek 3.10.

Animacja przy uyciu biblioteki AUX


Jak dotd, omawialimy podstawy zastosowania biblioteki AUX przy tworzeniu okna.
Omawialimy take polecenia OpenGL suce do rysowania. Czsto zaley nam je-
dnak, aby obraca lub przemieszcza obiekty, tworzc efekt animacji. Jako punkt wyjcia
wemy poprzedni przykad, rysujcy kwadrat, i sprawmy, aby ten kwadrat zacz
odbija si od krawdzi okna. Mgby stworzy ptl, ktra w nieskoczono zmie-
niaaby wsprzdne obiektu i wywoywaaby funkcj RenderScene(), co powodowaoby,
e kwadrat kryby wok okna.

Jednak biblioteka AUX zawiera o wiele wygodniejsz funkcj uatwiajc tworzenie


prostych animowanych sekwencji. Ta funkcja, aux!dleFunc(), jako argumentu oczekuje
nazwy funkcji, ktra ma by okresowo wywoywana w czasie bezczynnoci okna. Wy-
woywana funkcja ma nastpujcy prototyp:
void CALLBACK IdleFunction(void);

Ta funkcja jest cay czas regularnie wywoywana przez bibliotek AUX, chyba e okno
jest akurat przemieszczane lub skalowane.

Gdy zmienimy zaszyte w program wartoci okrelajce pooenie kwadratu na wartoci


przechowywane w zmiennych, a nastpnie stale bdziemy je modyfikowa wewntrz
funkcji IdleFunction(), kwadrat zacznie si porusza w obrbie okna. Spjrzmy na
przykad tego rodzaju animacji. Listing 3.4 stanowi zmodyfikowan wersj listingu 3.3, tak
e kwadrat zmienia pooenie w obrbie okna, odbijajc si od jego krawdzi. Musimy
przy tym ledzi pooenie i rozmiar kwadratu, a take bra pod uwag wszelkie zmiany
w rozmiarze okna.

Listing 3.4. Animowany odbijajcy si kwadrat____________________________________

// bounce.c
// Odbijajcy si kwadrat

#include <windows.h> // Standardowy nagwek dla Windows


include <gl\gl.h> // Biblioteka OpenGL
Sinclude <gl\glaux.h> // Biblioteka AUX

// Pocztkowa pozycja i wymiary kwadratu


GLfloat xl = 100.O f ; GLfloat yl = 150.O f ;
GLsizei rsize = 50;
Rozdziaf 3. * Nauka OpenGL z uyciem biblioteki AUX ______________________ 75

// Dugo kroku w kierunku x i y


// (ilo pikseli, o ktre trzeba si za kadym razem przesun)
GLfloat xstep = l . O f ;
GLfloat ystep = l.Of;

// Przechowanie informacji o zmianach rozmiarw okien


GLfloat windowWidth; GLfloat windowHeight;

// Wywoywana przez bibliotek AUX w momencie zmiany rozmiaru okna


void CALLBACK ChangeSize (GLsizei w, GLsizei h)
{
// Zabezpieczenie przed dzieleniem przez zero, gdy okno jest zbyt
// niskie (nie mona tak zmniejszy okna, aby miao zerow
// wysoko) .
i f ( h == 0) h
= 1;

// Ustawienie widoku na wymiary okna


glviewport ( O , O, w, h ) ;

// Wyzerowanie ukadu wsprzdnych przed modyfikacj


glLoadldentity ( ) ;

// Niech kwadrat bdzie kwadratem, tym razem przechowujemy //


obliczon szeroko i wysoko do pniejszego uytku if (w <=
h)
{
windowHeight = 250.0f*h/w;
windowWidth = 250. Of;

else

windowWidth = 250.0f*w/h;
windowHeight = 250. Of;

// Ustalenie bryy obcinania


glOrtho ( O . O f , windowWidth, O . O f , windowHeight, l . O f , - l . O f ) ;

// Wywoywane przez bibliotek AUX w celu narysowania sceny


void CALLBACK RenderScene (void)
{
// Kolor ta: Niebieski
glClearColor ( O . O f , O.Of, l.Of, l . O f ) ;

// Wyczyszczenie okna biecym kolorem ta


glClear (GL_COLOR_BUFFER_BIT) ;

// Kolor rysowania czerwony; Narysowanie prostokta //


wypenionego biecym kolorem glColorSf ( l . O f , O.Of,
O . O f ) ; glRectf(xl, y l , xl+rsize, yl+rsize);

glFlush() ;
76 _________________________________ Cz l * Wprowadzenie do OpenGL

// Wywoywana przez bibliotek AUX w czasie wolnym (okno nie //


jest przesuwane ani skalowane) void CftLLBACK IdleFunction (void) {
// Odwrcenie kierunku w momencie osignicia lewej lub prawej
// krawdzi
if(xl > windowWidth-rsize || xl < 0)
xstep = -xstep;
// Odwrcenie kierunku w momencie osignicia grnej lub dolnej //
krawdzi
if(yl > windowHeight-rsize l l yl < 0)
ystep = -ystep;

// Sprawdzenie zakresu. Robimy to na wypadek zmniejszenia okna, //


kiedy kwadrat mgby si znale poza bry obcinania if(xl >
windowWidth-rsize)
xl = windowWidth-rsize-1;
if(yl > windowHeight-rsize)
yl = windowHeight-rsize-1;

// Samo przesunicie kwadratu xl


+= xstep; yl += ystep;
// Narysowanie sceny z nowymi wsprzdnymi
RenderScene () ;

// Gwna funkcja programu


void main(void)
{
// Przygotowanie trybu rysowania i okna za pomoc biblioteki AUX
aux!nitDisplayMode (AUX_SINGLE | AUX_RGBA) ;
aux!nitPosition(100, 100,250,250);
auxlnitwindow( "Prosta animacja 2 D " ) ;
// Przygotowanie funkcji wywoywanej w momencie zmiany wymiarw //
okna auxReshapeFunc(ChangeSize) ;
// Przygotowanie funkcji wywoywanej w momencie bezczynnoci okna
aux!dleFunc (IdleFunction) ;
// Przygotowanie gwnej ptli programu
auxMainLoop (RenderScene) ;

Animacja tworzona przez ten przykad jest kiepska, nawet w bardzo szybkim komputerze.
Poniewa przed narysowaniem prostokta jest czyszczona zawarto caego okna, cay
czas kwadrat migocze i wyranie wida, e w rzeczywistoci jest rysowany jako dwa
trjkty. Aby stworzy pynniejsz animacj, musimy wykorzysta mechanizm zwany
podwjnym buforowaniem.
Rozdzia 3. Nauka OpenGL z uyciem biblioteki AUX __ __ 77

Podwjne buforowanie
Jedn z najwaniejszych cech kadego pakietu graficznego jest obsuga podwjnego bu-
forowania. Ta funkcja umoliwia tworzenie rysunku w niewidocznym buforze, a na-
stpnie byskawiczne przerzucenie zawartoci tego bufora do okna na ekranie.

Podwjne buforowanie suy dwu celom. Po pierwsze, rysowanie zoonych rysunkw


moe trwa do dugo, a nie yczysz sobie, aby na ekranie by widoczny kady etap
tworzenia obrazu. Uywajc podwjnego bufora, moesz skomponowa obraz i wywietli
go dopiero wtedy, gdy bdzie w caoci gotowy. W ten sposb uytkownik nigdy nie
widzi fragmentw sceny, lecz dopiero cay obraz po przerzuceniu go na ekran.

Drugim zastosowaniem podwjnego buforowania jest animacja. Kada klatka animacji


jest rysowana w niewidocznym buforze, a nastpnie, gdy ju jest gotowa, zostaje prze-
rzucona na ekran. Biblioteka AUX zapewnia w tym celu podwjnie buforowane okna.
Aby skorzysta z tej techniki i uzyska w naszym programie znacznie pynniejsz ani-
macj, do pliku bounce.c musimy wprowadzi jedynie dwie drobne zmiany. Po pierwsze,
zmienimy lini w funkcji main() inicjujc tryb wywietlania, nakazujc wczenie po-
dwjnego buforowania:
auKlnitDisplayMode(AUX_DOUBLE | AUX_RGBA);

Spowoduje to, e cae rysowanie odbywa si bdzie w niewidocznym buforze.

Nastpnie dodamy pojedyncz lini na kocu funkcji RenderScene():


auxSwapBuffers();

Funkcja auxSwapBuffers() powoduje przerzucenie na ekran zawartoci niewidocznego bufora.


(Peny kod tego programu znajdziesz w kartotece BOUNCE2 na pytce CD-ROM). W
wyniku otrzymujemy bardzo pynn animacj czerwonego kwadratu obijajcego si
wewntrz niebieskiego okna (rysunek 3.11).
Rysunek
3.11.
Odbijajcy si
78_________________________________Cz l * Wprowadzenie do OpenGL

W kocu troch trzeciego wymiaru!


Jak dotd wszystkie omawiane przykady przedstawiay czerwony prostokt na rodku
niebieskiego okna, ewentualnie przeskalowany lub odbijajcy si od krawdzi okna. W
tym momencie sam moesz obija si o ciany, niecierpliwie oczekujc, e w kocu
pojawi si co trjwymiarowego. Nie czekaj duej!

Jak ju wspomniano, cay czas rysowalimy obiekty w przestrzeni 3D, jednak rzut pro-
stokta by prostopady do bryy obcinania. Gdybymy mogli po prostu obrci bry
obcinania w stosunku do obserwatora, by moe ujrzelibymy jakie elementy trzeciego
wymiaru. W tym momencie jednak, a do rozdziau 7, nie mamy zamiaru zagbia si w
obroty i transformacje wsprzdnych. A nawet gdybymy sprbowali tego teraz,
kwadrat, nawet obrcony, nie jest zbyt ciekawy.

Aby ujrze gboko, musimy narysowa obiekt, ktry nie jest paski. Biblioteka AUX
zawiera prawie tuzin trjwymiarowych obiektw - od kuli a po imbryk na herbat - ktre
mona stworzy jednym wywoaniem funkcji. Te funkcje maj posta auxSolidrra:() lub
auxWirexxx;e(), gdzie xxxx oznacza, nazw jednolitego lub szkieletowego obiektu, ktry
ma zosta stworzony. Na przykad, ponisze polecenie rysuje szkieletowy imbryk do kawy
o rednicy wynoszcej, w przyblieniu, 50 jednostek:
auxWireTeapot( 5 0 . Of);

Jeli bymy zdefiniowali bry obcinania na zakres od -100 do 100 we wszystkich trzech
osiach, otrzymalibymy imbryk do kawy przedstawiony na rysunku 3.12. Imbryk do
kawy jest w tym momencie chyba najlepszym przykadem, poniewa pozostae obiekty
ogldane w rzucie rwnolegym nadal sprawiaj wraenie paskich. Program rysujcy
ten imbryk do herbaty znajduje si w osobnym podrozdziale na pytce CD-ROM, w
pliku teapot.c.

Rysunek 3.12.
Szkieletowy imbryk do herbaty

Jeliby zamieni szkieletowy imbryk na imbryk


jednolity poleceniem
auxWireTeapot(50.Of);

zobaczyby jedynie sylwetk imbryka. Aby ujrze


wypuko jednolicie pokolorowa- nego obiektu, musiaby
zastosowa cieniowanie i owietlenie,
wykorzystujc do tego polecenia OpenGL, ktre poznasz dopiero w rozdziale 9 i
nastpnych.
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX_______________________79

Aby lepiej pozna trjwymiarowe obiekty biblioteki AUX, zajrzyj do przykadw


AUXWIRE i AUXSOLID na pytce CD-ROM, w podrozdziaach biecego rozdziau. W
tych przykadach zostaa wykorzystana funkcja glRotatef() (opisana w rozdziale 7),
obracajca obiekty wok wszystkich trzech osi bryy widzenia. Niektre z obiektw
wykorzystuj bibliotek narzdziow, wic pamitaj, aby przy samodzielnym modyfi-
kowaniu przykadw poczy kod z bibliotek glu32.1ib.

Podsumowanie
W tym rozdziale zostalimy wprowadzeni do narzdziowej biblioteki AUX oraz pozna-
limy podstawy pisania programw korzystajcych z OpenGL. Uylimy biblioteki
AUX do pokazania najprostszego sposobu utworzenia okna i rysowania w nim przy
pomocy polece OpenGL. Nauczye si uywa biblioteki AUX do tworzenia okien,
ktre mog zmienia rozmiary, a take prezentowa w nich proste animacje. Oprcz
tego znasz ju proces uywania OpenGL przy rysowaniu - komponowanie i wybieranie
kolorw, czyszczenie ekranu, rysowanie prostokta, a take ustawianie widoku oraz
bryy obcinania tak, aby dopasowa je do rozmiaru okna. Omwilimy take rne typy
danych, jak rwnie pliki nagwkowe i biblioteki wymagane przy budowie programw
OpenGL.

Biblioteka AUX zawiera jeszcze wiele innych funkcji obsugujcych take klawiatur i
mysz. Implementacja biblioteki stworzona przez Microsoft zawiera specyficzne dla
Windows funkcje umoliwiajce dostp do uchwytw okien i kontekstw urzdze.
Przejrzyj umieszczon poniej sekcj podrcznika, aby samemu odkry pozostae ele-
menty i zastosowania biblioteki AUX. Przejrzyj take inne przykady do rozdziau trze-
ciego, zamieszczonych na pytce CD-ROM doczonej do ksiki.

Podrcznik
auxldleFunc
Przeznaczenie Ustawia funkcj zwrotn wywoywan w czasie bezczynnoci.
Plik nagwkowy <glaux.h>
Skadnia void aux!dleFunc(AUXIDLEPROC func);
Opis Okrela, e funkcja bezczynnoci func() bdzie regularnie wywoywana
w momencie braku innej aktywnoci okna. Gdy program nie jest zajty
renderowaniem sceny, funkcja zmienia pewne parametry uywane przez
funkcje rysunkowe przy tworzeniu nastpnego obrazu.
80 Cz l Wprowadzenie do OpenGL

Parametry
func Prototypem tej funkcji jest
Zwracana void CALLBACK IdleFunc(void);
Definiowana przez uytkownika funkcja regularnie wywoywana w
warto czasie bezczynnoci programu. Przekazanie wartoci NULL jako
Przykad Patrz adresu funkcji zatrzymuje przetwarzanie czasu wolnego.
take Brak.
Przykady BOUNCE i BOUNCE2 do tego rozdziau.
auxSwapBuffers, auxMainLoop, auxReshapeFunc

auxlnitDisplayMode
Przeznaczenie Inicjuje tryb wywietlania biblioteki AUX dla okna OpenGL.
Plik <glaux.h>
nagwkowy void auxInitDisplayMode(GLbitfield mask);
Skadnia Opis To pierwsza funkcja, jaka musi by wywoana w programie korzystajcym z
biblioteki AUX. Suy do przygotowania okna OpenGL. Ta funkcja ustala
charakterystyk okna uywanego przez OpenGL w operacjach
rysunkowych.
Parametry
mask GLbitfield: Maska lub kombinacja bitowa masek z tabeli 3.4. Te wartoci
masek mog by czone przy pomocy bitowego operatora OR. Na
Zwracana przykad, aby przygotowa okno posiadajce podwjny bufor i korzystajce
warto z indeksowanego trybu kolorw, wywoaj
Przykad Patrz aux!nitDisplayMode(AUX_DOUBLE | AUX_INDEX)

take Brak.
Kady przykadowy program w tym rozdziale.
aux!nitPosition, aux!nitWindow

Tabela 3.4.
Wartoci masek dla rnych charakterystyk okna

Warto maski Znaczenie

AUX_SINGLE Wcza tryb pracy z pojedynczym buforowaniem


AUX_DOUBLE Wcza tryb pracy z podwjnym buforowaniem
AUX_RGBA Wcza tryb RGBA
AUX_INDEX Wcza tryb koloru indeksowanego
AUX DEPTH Wcza 32-bitowy bufor gbokoci
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 81

Tabela 3.4.
Wartoci masek dla rnych charakterystyk okna cig dalszy
Warto maski Znaczenie

AUX_DEPTH16 Wcza 16-bitowy bufor gbokoci


AUX_STENCIL Wcza bufor szablonu
AUX_ACCUM Wcza bufor akumulacji
AUX_ALPHA Wcza bufor ALFA
AUX FIXED 332 PAL Wcza dla okna sta palet 3-3-2

auxlnitPosition
Przeznaczenie Ustala pozycj okna przygotowanego przez aux!nitWindow().
Plik nagwkowy <glaux.h>
Skadnia void aux!nitPosition(GLint x, GLint y, GLsizei width, GLsizei height);
Opis Ta funkcja informuje bibliotek AUX o miejscu, gdzie ma zosta otwarte
gwne okno graficzne.
Paramet
ry x GLint: Odlego lewego grnego rogu okna od lewej krawdzi ekranu,
mierzona w pikselach.

y GLint: Odlego lewego grnego rogu okna od grnej krawdzi ekranu,


mierzona w pikselach.
width GLsizei: Pocztkowa szeroko obszaru roboczego okna, mierzona w
pikselach.
height GLsizei: Pocztkowa wysoko obszaru roboczego okna, mierzona w
pikselach.
Zwracana warto Brak.
Przykad Kady przykadowy program w tym rozdziale.
Patrz take aux!nitDisplayMode, aux!nitWindow

auxlnitWindow
Przeznaczenie Inicjuje i wywietla okno renderowania OpenGL.
Plik <glaux.h>
nagwkowy void aux!nitWindow(BYTE *titleString);
82 Cz l Wprowadzenie do OpenGL

Opis Ta funkcja otwiera okno, ktre bdzie uywane przez OpenGL przy
operacjach graficznych.
Przed wywoaniem okna naley okreli jego charakterystyk za pomoc
funkcji aux!nitDisplayMode() oraz aux!nitPosition().
Parametry
titleString GLBYTE: Wskanik do acucha znakw, ktry zostanie uyty jako tytu
okna, wywietlany na belce tytuowej.
Zwracana warto Brak.
Przykad Kady przykadowy program w tym rozdziale.
Patrz take aux!nitDisplayMode, aux!nitPosition

auxKeyFunc
Przeznaczenie Wie funkcj zwrotn z wciniciem danego klawisza.
Plik <glaux.h>
nagwkowy void auxKeyFunc(GLint key, void(*function(void));
Skadnia Opis Ustala funkcj zwrotn {function), ktra bdzie wywoywana przez
bibliotek AUX za kadym razem, gdy zostanie wcinity klawisz
o numerze key. Po przetworzeniu klawisza nastpuje odwieenie okna.
Parametry
key GLint: Numer klawisza, jaki ma by powizany z dan funkcj. Moe to
by jedna z wartoci z tabeli 3.5.
function Ta funkcja zwrotna ma nastpujcy prototyp: void
Zwracana CALLBACK KeyFunc(void);
warto Ta funkcja jest wywoywana przez bibliotek AUX za kadym razem, gdy
Przykad zostanie wcinity dany klawisz. Gdy jako ten parametr zostanie
przekazana warto NULL, nastpuje wstrzymanie wywoywania funkcji
zwrotnej.
Patrz take
Brak.
Dodatkowy przykadowy program KEYMOYE na pytce CD-ROM, w
folderze tego rozdziau.
auxMouseFunc
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 83

Tabela 3.5.
Definicje klawiszy w bibliotece A UX

Warto Opis
AUX_ESCAPE Klawisz Esc Klawisz spacji Klawisz
AUX_SPACE Enter Klawisz kursor w lewo
AUX_RETURN Klawisz kursor w prawo Klawisz
AUX_LEFT kursor w gr Klawisz kursor w d
AUX_RJGHT Klawisze od A do Z (wielkie litery)
AUX_UP Klawisze od a do z (mae litery)
AUX_DOWN Klawisze numeryczne od O do 9
AUX_A do AUX_Z
AUX_a do AUX_z
AUX OdoAUX 9

auxMainLoop
Przeznaczenie Okrela funkcj, ktra powinna zosta uyta do odwieenia zawartoci okna
OpenGL,
Plik nagwkowy <glaux.h>
Skadnia void auxMainLoop(AUXMAINPROC func);
Opis Ta funkcja jest uywana do okrelenia funkcji, ktra ma by wywoywana za
kadym razem, gdy okno OpenGL wymaga aktualizacji. Ta funkcja nie
zwraca sterowania a do momentu zamknicia okna OpenGL.
Parametry
func Ta funkcja ma nastpujcy prototyp
Zwracana warto void CALLBACK MainFunc(void);
Ta funkcja jest uywana do aktualizacji zawartoci okna i powinna zawiera
Przykad Patrz instrukcje rysunkowe.
take Brak.
Kady przykadowy program w tym rozdziale.
aux!dleFunc, auxReshapeFunc
84 Cz l Wprowadzenie do OpenGL

auxMouseFunc
Przeznaczenie Wie funkcje zwrotn z klikniciami przyciskw myszy
Plik nagwkowy <glaux.h>
Skadnia Opis void auxMouseFunc(int button, int mod, AUXMOUSEPROC func);
Suy do ustawienia funkcji/Mc jako funkcji wywoywanej w momencie
kliknicia lub zwolnienia przycisku myszy. Przycisk myszy jest okrelany
przez jedn z podanych niej wartoci. Tryb wywoywania okrela, czy
funkcja ma by wywoywana w momencie, gdy przycisk jest wciskany lub
zwalniany.
Parametry
button int: Przycisk, z ktrym ma by powizana funkcja zwrotna; moe to by
mod jedna z nastpujcych wartoci: AUX_LEFTBUTTON (lewy),
func AUX_MIDDLEBUTTON (rodkowy) lub AUX_RIGHTBUTTON (prawy).
int: Tryb wywoywania funkcji zwrotnej. Moe nim by
AUX_MOUSEDOWN (funkcja jest wywoywana w momencie klinicia
przyciskiem myszy) lub AUX_MOUSEUP (funkcja jest wywoywana w
momencie zwolnienia przycisku myszy).
Ta funkcja ma nastpujcy prototyp
void CALLBACK MouseFunc(AUX_EVENTREC *event); Struktura event
zawiera wsprzdne wskanika myszy w momencie wystpienia
zdarzenia.
typedef struct _AUX_EVENTREC {
GLint event;
GLINT data [ 4 ] ; }
AUX_EVENTREC;
event: GLint: Okrela zdarzenie, jakie nastpio (AUX_MOUSEUP lub
AUX_MOUSEDOWN)
data[4]\ GLint: zawiera dane specyficzne dla zdarzenia
data[AUX_MOUSEX] = pozioma wsprzdna wskanika myszy
data[AUX_MOUSEY] = pionowa wsprzdna wskanika myszy
data[MOUSE_STATUS] = przycisk myszy (z parametru button)
Brak.
Zwracana warto Program MBOUNCE na pytce CD-ROM, w folderze tego rozdziau.
Przykad Patrz auxKeyFunc
take
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 85

auxReshapeFunc
Przeznaczenie Ustanawia funkcj, ktra bdzie wywoywana w momencie, gdy zmieni si
rozmiar okna.
Plik nagwkowy <glaux.h>
Skadnia void auxReshapeFunc(AUXRESHAPEPROC func);
Opis Ta funkcja jest uywana do okrelenia funkcji, ktra ma by wywoywana za
kadym razem, gdy zmieni si rozmiar okna OpenGL. Zwykle w tej funkcji
Parametry s modyfikowane ustawienia widoku i bryy obcinania tak, aby prawidowo
func przeskalowa obraz.

Ta funkcja ma nastpujcy prototyp


Zwracana warto void CALLBACK Reshape(GLsizei width, GLsizei height);
Przykad Patrz Funkcja otrzymuje now szeroko i wysoko okna.
take Brak.
Przykad SCAL w tym rozdziale.
aux!dleFunc, auxMainLoop

auxSetOneColor
Przeznaczenie Plik Ustala pojedynczy kolor w indeksowanej palecie kolorw
nagwkowy <glaux.h>
Skadnia Opis void auxSetOneColor(int index, float red, float green, float blue);
Parametry Ta funkcja jest uywana w indeksowanych trybach kolorw. W takim trybie,
zamiast okrelania koloru za pomoc wartoci RGB, tworzona jest paleta
index kolorw. Kolory s przypisywane obiektom przez podanie indeksu w
red palecie. Ta funkcja ustala wartoci RGB koloru reprezentowanego przez
dany indeks palety.
green
blue Zwracana
int: Indeks w palecie kolorw.
warto
float: Czerwona skadowa danego koloru.
float: Zielona skadowa danego koloru.
float: Niebieska skadowa danego koloru.
Brak.
86_________________________________Cz l * Wprowadzenie do OpenGL

Przykad Uzupeniajcy przykad COLORDX na pytce CD-ROM, w folderze tego


rozdziau. Zwr uwag, e ten przykad naley uruchomi
w indeksowanym trybie wywietlania (dostpnym w wikszoci
256-kolorowych kart, jednak przy nie wicej ni 8-bitach koloru).
Patrz take getColorMapSize, auxSetRGBMap

auxSolidBox________________________
Przeznaczenie Rysuje jednolity prostopadocian.
Plik nagwkowy <glaux.h>
Skadnia void auxSolidBox(GLdouble width, GLdouble height, GLdouble depth);
Opis Rysuje jednolity prostopadocian ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Alternatywn form tej funkcji jest
auxSolidCube. Uywana gwnie do demonstracji.
Parametry
width GLdouble: Szeroko prostopadocianu.
height GLdouble: Wysoko prostopadocianu.
depth GLdouble: Gboko prostopadocianu.
Zwracana warto Brak.
Przykad Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
Patrz take auxWireBox, auxSolidCube

auxSolidCone_______________________
Przeznaczenie Rysuje jednolity stoek.
Plik nagwkowy <glaux.h>
Skadnia void auxSolidCone(GLdouble radius, GLdouble height);
Opis Rysuje jednolity stoek ze rodkiem w centrum ukadu wsprzdnych
(O, O, 0). Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie podstawy stoka.
height GLdouble: Wysoko stoka.
Zwracana warto Brak.
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 87

Przykad Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego


Patrz take rozdziau. Umieszczony tam program zawiera przykady tworzenia
wszystkich predefmiowanych jednolitych obiektw z biblioteki AUX.
auxWireCone

auxSolidCube
Przeznaczenie Plik Rysuje jednolity szecian.
nagwkowy <glaux.h>
Skadnia Opis void auxSolidCube(GLdouble width);
Rysuje jednolity szecian ze rodkiem w centrum ukadu wsprzdnych
(O, O, 0). Alternatywna forma funkcji auxSolidBox Uywana gwnie do
Parametry demonstracji.
width
Zwracana warto GLdouble: Dugo krawdzi szecianu.
Przykad Brak.
Patrz take Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze
dotyczcym tego rozdziau. Umieszczony tam program zawiera przykady
tworzenia wszystkich predefmiowanych jednolitych obiektw z biblioteki
AUX.
auxWireCube, auxSolidBox

AuxSolidCylinder
Przeznaczenie Plik Rysuje jednolity cylinder.
nagwkowy <glaux.h>
Skadnia Opis void auxSolidCylinder(GLdouble radius, GLdouble height);
Rysuje jednolity cylinder ze rodkiem w centrum ukadu wsprzdnych (O,
Parametry O, 0). Uywana gwnie do demonstracji.
radius
height GLdouble: Promie podstawy cylindra.
Zwracana warto GLdouble: Wysoko cylindra. Brak.
Przykad Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
wszystkich predefmiowanych jednolitych obiektw.z biblioteki AUX.
Patrz take auxWireCylinder
88 Cz l * Wprowadzenie do OpenGL

auxSolidDodecahedron
Przeznaczenie Plik Rysuje jednolity dwunastocian.
nagwkowy <glaux.h>
Skadnia Opis void auxSolidDodecahedron(GLdouble radius);
Rysuje jednolity dwunastocian foremny ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). cianki dwunastocianu s picioktami foremnymi.
Parametry Uywana gwnie do demonstracji.
radius
Zwracana warto GLdouble: Promie dwunastocianu.
Przykad Brak.
Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Patrz take wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWireDodecahedron

auxSolidlcosahedron
Przeznaczenie Plik Rysuje jednolity dwudziestocian.
nagwkowy <glaux.h>
Skadnia Opis void auxSolid!cosahedron(GLdouble radius);
Rysuje jednolity dwudziestocian foremny ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). cianki dwudziestocianu s trjktami
Parametry rwnobocznymi. Uywana gwnie do demonstracji.
radius
Zwracana warto GLdouble: Promie dwudziestocianu.
Przykad Brak.
Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Patrz take wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWire!cosahedron

auxSolidOctahedron
Przeznaczenie Rysuje jednolity omiocian.
Plik nagwkowy <glaux.h>
Skadnia void auxSolidOctahedron(GLdouble radius);
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 89

Opis Rysuje jednolity omiocian foremny ze rodkiem w centrum ukadu


wsprzdnych (O, O, 0). cianki omiocianu s trjktami
rwnobocznymi. Uywana gwnie demonstracji.
Parametry
radius GLdouble: Promie omiocianu.
Zwracana Brak.
warto Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWireOctahedron

auxSolidSphere
Przeznaczenie Rysuje jednolit kul.
Plik <glaux.h>
naglwkowy void auxSolidSphere(GLdouble radius);
Skadnia Opis Rysuje jednolit kul ze rodkiem w centrum ukadu wsprzdnych
(O, O, 0). Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie kuli.
Zwracana Brak.
warto Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWireSphere

auxSolidTeapot
Przeznaczenie Rysuje jednolity imbryk do herbaty.
Plik <glaux.h>
nagwkowy void auxSolidTeapot(GLdouble radius);
Skadnia Opis Rysuje jednolity imbryk do herbaty ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Uywana gwnie demonstracji.
Parametry
radius Gldouble: Promie imbryka (w przyblieniu).

Zwracana Brak.
90 Cz l * Wprowadzenie do OpenGL

Przykad Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego


rozdziau. Umieszczony tam program zawiera przykady tworzenia
wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
Patrz take auxWireTeapot

auxSolidTetrahedron
Przeznaczenie Plik Rysuje jednolity czworocian foremny.
nagwkowy <glaux.h>
Skadnia Opis void auxSolidTetrahedron(GLdouble radius);
Rysuje jednolity czworocian foremny ze rodkiem w ukadu
wsprzdnych (O, O, 0). cianki czworocianu s trjktami
Parametry rwnobocznymi. Uywana gwnie do demonstracji.
radius
Zwracana warto GLdouble: Promie omiocianu.
Przykad Brak.
Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia wszystkich
Patrz take predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWireTetrahedron

auxSolidTorus
Przeznaczenie Rysuje jednolity torus (dtk).
Plik nagwkowy <glaux.h>
Skadnia Opis void auxSolidTorus(GLdouble innerRadius, GLdouble outerRadius);
Rysuje jednolity torus ze rodkiem w centrum ukadu wsprzdnych (O, O, 0).
Torus ma ksztat dtki. Promie wewntrzny to promie dtki, za promie
zewntrzny to promie koa. Uywana gwnie do demonstracji.

Parametry
GLdouble: Wewntrzny promie torusa.
innerRadius
GLdouble: Zewntrzny promie torusa. Brak.
outerRadius
Uzupeniajcy przykad AUXSOLID na pytce CD-ROM, w folderze tego
Zwracana warto rozdziau. Umieszczony tam program zawiera przykady tworzenia wszystkich
Przykad
predefiniowanych jednolitych obiektw z biblioteki AUX.
auxWireTorus

Patrz take
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 91

auxSwapBuffers
Przeznaczenie Przerzuca rysunek z niewidocznego bufora do okna podczas rysowania z
podwjnym buforowaniem.
Plik <glaux.h>
nagwkowy void auxSwapBuffers(void);
Skadnia Ta funkcja jest uywana przy rysowaniu i animacji z wykorzystaniem
podwjnego buforowania. Wywoanie funkcji powoduje przerzucenie
Opis sceny tworzonej w niewidocznym buforze do okna.
Brak.
Zwracana Przykad BOUNCE2 w tym rozdziale.
warto aux!nitDisplayMode, aux!dleFunc

auxWireBox
Przeznaczenie Rysuje szkieletowy prostopadocian.
Plik <glaux.h>
nagwkowy void auxWireBox(GLdouble width, GLdouble height, GLdouble depth);
Skadnia Opis Rysuje szkieletowy prostopadocian ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Alternatywn form tej funkcji jest auxWireCube.
Uywana gwnie do demonstracji.
Parametry
width GLdouble: Szeroko prostopadocianu.
height GLdouble: Wysoko prostopadocianu.
depth GLdouble: Gboko prostopadocianu.
Zwracana Brak.
warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidBox, auxWireCube

auxWireCone
Przeznaczenie Rysuje szkieletowy stoek.
Plik nagwkowy <glaux.h>
Skadnia void auxWireCone(GLdouble radius, GLdouble height);
92 Cz l * Wprowadzenie do OpenGL

Opis Rysuje szkieletowy stoek ze rodkiem w centrum ukadu wsprzdnych


(O, O, 0). Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie podstawy stoka.
height GLdouble: Wysoko stoka. Brak.
Zwracana warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidCone
Patrz take

auxWireCube
Przeznaczenie Rysuje szkieletowy szecian.
Plik nagwkowy <glaux.h>
Skadnia void auxWireCube(GLdouble width);
Opis Rysuje szkieletowy szecian ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Alternatywna forma funkcji auxWireBox
Parametry
Uywana gwnie do demonstracji.
width
Zwracana warto
GLdouble: Dugo krawdzi szecianu.
Przykad
Brak.
Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Patrz take
wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidCube, auxWireBox

auxWireCylinder
Przeznaczenie Rysuje szkieletowy cylinder.
Plik nagwkowy <glaux.h>
Skadnia Opis void auxWireCylinder(GLdouble radius, GLdouble height);
Rysuje szkieletowy cylinder ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Uywana gwnie do demonstracji.
Rozdzia 3. + Nauka OpenGL z uyciem biblioteki AUX 93

Parametry
radius GLdouble: Promie podstawy cylindra.
height GLdouble: Wysoko cylindra. Brak.
Zwracana warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefmiowanych jednolitych obiektw z biblioteki AUX.
auxSolidCylinder
Patrz take

auxWireDodecahedron
Przeznaczenie Plik Rysuje szkieletowy dwunastocian.
nagwkowy <glaux.h>
Skadnia Opis void auxWireDodecahedron(GLdouble radius);
Rysuje szkieletowy dwunastocian foremny ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). cianki dwunastocianu s picioktami
Parametry foremnymi. Uywana gwnie do demonstracji.
radius
Zwracana warto GLdouble: Promie dwunastocianu.
Przykad Brak.
Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Patrz take wszystkich predefmiowanych jednolitych obiektw z biblioteki AUX.
auxSolidDodecahedron

auxWirelcosahedron
Przeznaczenie Plik Rysuje szkieletowy dwudziestocian.
nagwkowy <glaux.h>
Skadnia Opis void auxWire!cosahedron(GLdouble radius);
Rysuje szkieletowy dwudziestocian foremny ze rodkiem w centrum
ukadu wsprzdnych (O, O, 0). cianki dwudziestocianu s trjktami
Parametry rwnobocznymi. Uywana gwnie do demonstracji.
radius Zwracana
warto GLdouble: Promie dwudziestocianu.
Brak.
94 Cz l * Wprowadzenie do
OpenGL

Przykad Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego


rozdziau. Umieszczony tam program zawiera przykady tworzenia
wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
Patrz take auxSolid!cosahedron

auxWireOctahedron
Przeznaczenie Rysuje szkieletowy omiocian.
Plik <glaux.h>
nagwkowy void auxWireOctahedron(GLdouble radius);
Skadnia Opis Rysuje szkieletowy omiocian foremny ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). cianki omiocianu s trjktami rwnobocznymi.
Uywana gwnie do demonstracji.
Parametry GLdouble: Promie omiocianu. Brak.
radius Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
Zwracana warto rozdziau. Umieszczony tam program zawiera przykady tworzenia wszystkich
predefiniowanych jednolitych obiektw z biblioteki AUX.
Przykad
auxSolidOctahedron

Patrz take auxWireSphere


Przeznaczenie Rysuje szkieletow kul.
Plik <glaux.h>
nagwkowy void auxWireSphere(GLdouble radius);
Skadnia Opis Rysuje szkieletow kul ze rodkiem w centrum ukadu wsprzdnych (O,
O, 0). Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie kuli.
Zwracana Brak.
warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidSphere
Rozdzia 3. Nauka OpenGL z uyciem biblioteki AUX 95

auxWireTeapot
Przeznaczenie Rysuje szkieletowy imbryk do herbaty.
Plik <glaux.h>
nagwkowy void auxWireTeapot(GLdouble radius);
Skadnia Opis Rysuje szkieletowy imbryk do herbaty ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie imbryka (w przyblieniu).
Zwracana Brak.
warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidTeapot

auxWireTetrahedron
Przeznaczenie Rysuje szkieletowy czworocian foremny.
Plik <glaux.h>
nagwkowy void auxWireTetrahedron(GLdouble radius);
Skadnia Opis Rysuje szkieletowy czworocian foremny ze rodkiem w centrum ukadu
wsprzdnych (O, O, 0). cianki czworocianu s trjktami
rwnobocznymi. Uywana gwnie do demonstracji.
Parametry
radius GLdouble: Promie omiocianu.
Zwracana Brak.
warto Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze tego
rozdziau. Umieszczony tam program zawiera przykady tworzenia
Przykad wszystkich predefiniowanych jednolitych obiektw z biblioteki AUX.
auxSolidTetrahedron

auxWireTorus
Przeznaczenie Rysuje szkieletowy torus (dtk).
Plik nagwkowy <glaux.h>
Skadnia void auxWireTorus(GLdouble innerRadius, GLdouble outerRadius);
96 Cz l * Wprowadzenie do OpenGL

Opis Rysuje szkieletowy torus ze rodkiem w centrum ukadu wsprzdnych


(O, O, 0). Torus ma ksztat dtki. Promie wewntrzny to promie dtki, za
promie zewntrzny to promie koa. Uywana gwnie do demonstracji.
Parametry GLdouble: Wewntrzny promie
innerRadius torusa. GLdouble: Zewntrzny
outerRadius Zwracana promie torusa.
warto Brak.
Przykad Uzupeniajcy przykad AUXWIRE na pytce CD-ROM, w folderze
Patrz take tego rozdziau. Umieszczony tam program zawiera przykady
tworzenia wszystkich predefiniowanych jednolitych obiektw z biblioteki
AUX.
auxSolidTorus

glCIearColor
Przeznaczenie Plik Ustala wartoci barw skadowych i kanau alfa dla buforw kolorw.
nagwkowy
Skadnia void glClearColor(GLclampf red, GLclampf green, GLclampf blue,
GLclampf alpha);
Opis Ustala wartoci uywane podczas czyszczenia buforw dla barw czerwonej,
zielonej i niebieskiej oraz dla skadnika alfa. Podane wartoci s obcinane
do przedziau [O.Of, 1.0].
Parametry
red GLclampf: Czerwony skadnik koloru wypenienia.
green GLclampf: Zielony skadnik koloru wypenienia.
blue GLclampf: Niebieski skadnik koloru wypenienia.
alpha GLclampf: Skadnik alfa koloru wypenienia.
Zwracana warto Brak.
Przykad Przykad SHORTEST w tym rozdziale.

glFIush
Przeznaczenie Wykonuje funkcje i polecenia OpenGL oczekujce w kolejce.
Plik nagwkowy
Skadnia void glFlush(void);
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX 97

Opis Polecenia OpenGL czsto s umieszczane w kolejce w celu pniejszego


Przyka przetworzenia wszystkich naraz, co owocuje popraw wydajnoci. Zaley to
take od sprztu, sterownikw i samej implementacji OpenGL. Polecenie
d glFlush powoduje wykonanie wszystkich oczekujcych w kolejce polece.
Wszystkie przykady w tym rozdziale.

glOrtho
Przeznaczenie Ustala lub modyfikuje zakres bryy obcinania..
Plik
nagwkowy void glOrtho(GLdouble left, GLdouble right, GLdouble bottom,
GLdouble top, GLdouble near, GLdouble far);
Skadnia
Ta funkcja okrela rwnoleg bry obcinania. W rzutowaniu tego typu
obiekty znajdujce si dalej od obserwatora nie wydaj si mniejsze ni
obiekty umieszczone bliej (w przeciwiestwie do rzutowania
perspektywicznego). Wyobra sobie bry obcinania umieszczon w
przestrzeni kartezjaskiej; w takim przypadku lewa i prawa paszczyzna
wyznaczaj minimaln i maksymaln warto osi x, paszczyzny dolna i
grna wyznaczaj minimaln i maksymaln warto osi y, za paszczyzny
blisza i dalsza wyznaczaj minimaln i maksymaln warto osi z.
Parametry
left GLdouble: Wsprzdna lewej paszczyzny obcinania.
right GLdouble: Wsprzdna prawej paszczyzny obcinania.
bottom GLdouble: Wsprzdna dolnej paszczyzny obcinania.
top GLdouble: Wsprzdna grnej paszczyzny obcinania.
near GLdouble: Wsprzdna bliszej paszczyzny obcinania.
far GLdouble: Wsprzdna dalszej paszczyzny obcinania.
Zwracana Brak.
warto Przykad SCAL w tym rozdziale.
Przykad Patrz glYiewport

giyiewport
Przeznaczenie Ustala obszar okna (widok), przeznaczony do wykorzystania przez
OpenGL.

Plik nagwkowy
98 Cz l * Wprowadzenie do OpenGL

Skadnia Opis void glViewport(GLint x, GLint x, GLsizei width, GLsizei height);


Ustala region wewntrz okna (widok), ktry ma zosta uyty do
odwzorowania wsprzdnych bryy obcinania na fizyczne wsprzdne
Parametry x okna.
wldth
height GLint: Odlego lewej krawdzi widoku od lewej krawdzi okna,
mierzona w pikselach.
Zwracana warto
GLint: Odlego grnej krawdzi widoku od grnej krawdzi okna,
Przykad Patrz mierzona w pikselach.
take GLsizei: Szeroko widoku w pikselach.
GLsizei: Wysoko widoku w pikselach.
Brak.
Przykad SCAL w tym rozdziale.
glOrtho

gIRect
Przeznaczenie Rysuje paski prostokt.
Plik nagwkowy <gl.h>
Odmiany void gIRectd(GLdouble xl, GLdouble yl, GLdouble x2, GLdouble y2);
void glRectf(GLfloat xl, GLfloat yl, GLfloat x2, GLfloat y2);
void glRecti(GLint xl, GLint yl, GLint x2, GLint y2);
void glRects(GLshort xl, GLshort y l, GLshort x2, GLshort y2);
void glRectdv(const GLdouble *vl, const GLdouble *v2);
void glRectfv(const GLfloat *vl, const GLfloat *v2);
void glRectiv(const GLint *vl, const GLint *v2);
void glRectsv(const GLshort *vl, const GLshort *v2);
Opis Ta funkcja stanowi efektywn metod tworzenia prostokta przez podanie
wsprzdnych dwch przeciwlegych wierzchokw. Prostokt jest
rysowany na paszczynie xy o wsprzdnej z = 0.
Parametry
xl, y l Okrelaj lewy grny wierzchoek prostokta.
x2,y2 Okrelaj prawy dolny wierzchoek prostokta.
*vl Tablica dwch wartoci okrelajcych lewy grny wierzchoek
prostokta. Moe by opisany take jako v l [2].
Rozdzia 3. * Nauka OpenGL z uyciem biblioteki AUX_______________________99

*v2 Tablica dwch wartoci okrelajcych prawy dolny wierzchoek


prostokta. Moe by opisany take jako v2[2].
Zwracana warto Brak.
Przykad Przykad FRIENDLY w tym rozdziale.
Rozdzia 4.
OpenGL for Windows:
OpenGL + Win32 = Wiggle
W tym rozdziale:

Obsuga okna bez porednictwa biblioteki AUX: Uywane funkcje


* Tworzenie i korzystanie z kontekstw * wglCreateContext,
renderowania wglDeleteContext,
wglMakeCurrent
* danie i wybieranie formatu pikseli * ChoosePixelFormat,
SetPixelFormat
* Reagowanie na komunikaty okienkowe WM_PAINT, WM_CREATE,
WM_DESTROY, WM_SIZE
* Uycie podwjnego buforowania w Windows * SwapBuffers

OpenGL to czysto graficzne API, wic obsuga okien i interakcji z


uytkownikiem spoczywa na barkach systemu operacyjnego. Aby
zapewni poprawn wspprac, kady system operacyjny zwykle
posiada odpowiednie rozszerzenia, sklejajce" OpenGL z wasnymi
funkcjami wejcia/wyjcia i zarzdzania oknami. Te rozszerzenia to kod
wicy polecenia rysunkowe OpenGL z konkretnym oknem. Oprcz
tego, potrzebne s take funkcje ustawiajce tryb buforw, gboko
koloru oraz inne charakterystyki graficzne.
W przypadku Microsoft Windows kod czcy wystpuje w postaci
szeciu nowych funkcji OpenGL (tzw. funkcji wiggle, gdy ich nazwy
zaczynaj si od przedrostka wgl, a nie g/) oraz piciu nowych funkcji
Win32 dodanych do GDI w Windows NT i 95. W tym rozdziale
omwimy wanie te czce funkcje, rezygnujc jednoczenie z wyrczania
si funkcjami biblioteki AUX.
W rozdziale 3 biblioteki AUX uywalimy do nauki podstaw
programowania OpenGL w C. Dowiedziae si, jak rysowa par dwu- i
trjwymiarowych obiektw oraz jak
102________________________________Cz l Wprowadzenie do OpenGL

okrela ukad wsprzdnych i sposb rzutowania, nie wgbiajc si w adne szcze-goty


programowana Windows. Nadszed wJec czas, aby odej od tego bezokienko-wegp"
podejcia do OpenGL i sprbowa prawdziwej pracy w rodowisku Windows. fett nie
zadawafa ci pojedyncze okno, drak menu, brak moliwoci drukowania, brak okien
dialogowych oraz kilku innych elementw nowoczesnego interfejsu uytkownika,
powiniene nauczy si uywa OpenGL we wasnych aplikacjach Win32.

Poczynajc od tego rozdziau, bdziemy budowa w peni funkcjonalne aplikacje Win-


dows, potrafice korzysta ze wszystkich elementw systemu operacyjnego. Dowiesz si,
jak charakterystyk musi posiada okno Windows, aby mogo suy do prezentowania
grafiki tworzonej w OpenGL. Zapoznasz si z komunikatami okienkowymi, na jakie
powinien reagowa dobrze napisany program OpenGL, powiemy take par sw na
temat sposobw obsugi tych komunikatw. Koncepcje omawiane w tym rozdziale s
wprowadzane stopniowo, w trakcie budowania modelowego programu OpenGL w C, ktry
bdzie stanowi punkt wyjcia dla wszystkich nastpnych przykadw.

A do teraz, do lektury tej ksiki nie bya wymagana adna wiedza na temat trjwy-
miarowej grafiki, wymagana bya jedynie podstawowa umiejtno programowania w
C. Jednak od tego momentu zakadamy, e znasz przynajmniej podstawy pisania pro-
gramw dla Windows. (W przeciwnym wypadku musielibymy napisa ksik dwa
razy grubsz, ktrej wiksza cz dotyczyaby zagadnie programowania Windows ni
programowania w OpenGL). Jeli jeste nowicjuszem w Windows lub przywyke do
korzystania z ktrego z pakietw Application Framework (na przykad MFC czy
OWL) i nie znasz si na procedurach okienkowych, przekazywaniu komunikatw itd.,
przed zagbieniem si w dalszy tekst powiniene zapozna si z ktr z pozycji wy-
mienionych w dodatku B, dotyczcym dalszej lektury zwizanej z tematem programo-
wania w OpenGL.

Rysowanie w oknach Windows


Przy korzystaniu z biblioteki AUX mielimy do dyspozycji tylko jedno okno, wic
OpenGL zawsze wiedzia, w ktrym oknie ma rysowa (bo gdzieby indziej?). Jednak
aplikacje Windows zwykle posiadaj znacznie wicej okien. W rzeczywistoci okna
dialogowe, kontroIki i nawet menu na podstawowym poziomie s oknami. Skd wic
OpenGL, podczas wykonywania kodu rysunkowego, wie, gdzie ma rysowa? Zanim
sprbujemy odpowiedzie na to pytanie, spjrzmy najpierw, jak normalnie przebiega
rysowanie w oknie, bez korzystania z OpenGL.

Konteksty urzdze GDI


Aby narysowa co w oknie bez uycia OpenGL, powiniene uy funkcji GDI (Graphics
Device Interface) - graficznego interfejsu uytkownika. Kade okno posiada tzw. kontekst
urzdzenia, okrelajcy graficzny charakter okna, za kada funkcja GDI jako jednego z
argumentw wymaga podania uchwytu kontekstu urzdzenia, wskazujcego
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle_________________103

okno, w ktrym ma odbywa si rysowanie. Moesz korzysta z wielu kontekstw


urzdze, ale tylko po jednym dla kadego z okien.

Przykadowy program WINRECT na doczonej do ksiki pytce CD-ROM tworzy


standardowe okno z niebieskim tem i czerwonym kwadratem w rodku. Wynik dziaania
tego programu, przedstawiony na rysunku 4.l, wyglda znajomo. To ten sam obraz, jaki
otrzymalimy w naszym drugim programie OpenGL w rozdziale 3., programie
friendly.c. Jednak w odrnieniu od tamtego przykadu, program WINRECT zosta
stworzony z wykorzystaniem wycznie Windows API. Kod tego programu praktycznie nie
rni si od oglnego schematu programw Windows. Wystpuje w nim funkcja
WinMain, przeprowadzajca standardowe inicjowanie i zawierajca ptl komunikatw, a
take funkcja WndProc, obsugujca komunikaty skierowane do gwnego okna.

Rysunek 4.1.
Odpowiednik programu friendly. c z rozdziau 3.,
napisany bez uycia OpenGL

Twoja znajomo programowania Windows powinna


obejmowa take szczegy doty- czce tworzenia i
wywietlania okna, z tego programu omwimy wic jedynie
kod odpowiedzialny za rysowanie ta i kwadratu.

Najpierw musimy utworzy niebieski i czerwony


pdzel dla ta i kwadratu. Uchwyty tych pdzli s zadeklarowane globalnie:
// Uchwyty pdzli GDI uywanych do rysowania
HBRUSH hBlueBrush,hRedBrush;

Same pdzle s tworzone w funkcji WinMain, przy uyciu makra RGB w celu utworzenia
jednolitych pdzli, niebieskiego i czerwonego.
// Utworzenie niebieskiego i czerwonego pdzla do wypeniania //
i rysowania
// Czerwony, zielony, niebieski
hBlueBrush = CreateSolidBrush(RGB( O, O, 255));
hRedBrush = CreateSolidBrush(RGB( 255, O, 0));

W momencie okrelania stylu okna wskazujemy take, e to ma by malowane przy


uyciu niebieskiego pdzla.
wc.hbrBackground = hBlueBrush; // Niebieski pdzel dla ta

Pooenie i rozmiary okna (poprzednio okrelane przy pomocy funkcji aux!nitPosition) s


ustalane w momencie tworzenia okna.
104 ________________________________ Cz l * Wprowadzenie do OpenGL

// Utworzenie gwnego okna aplikacji hWnd =


CreateWindow(
IpszAppName,
IpszAppName,
WS_OVERLAPPEDWINDOW,
100, 100, // Pooenie i wymiary
// okna
250, 250, NULL, NULL, hlnstance,

Na koniec, samo rysowanie zawartoci okna odbywa si wewntrz procedury obsugi


komunikatu WM_PAINT wewntrz funkcji WndProc.
case WM_PAINT: (
PAINTSTRUCT ps;
HBRUSH hOldBrush;

// Rozpoczcie rysowania
BeginPaint (hWnd, &ps) ;
// Wybranie czerwonego pdzla
hOldBrush = SelectObject (ps .hdc,hRedBrush) ;

// Narysowanie prostokta aktualnie wybranym pdzlem


Rectangle (ps.hdc, 100, 100, 150, 150) ;
// Odoenie pdzla SelectObject
(ps .hdc, hOldBrush) ;
// Koniec rysowania
EndPaint (hWnd, sps) ;
} break;

Wywoanie funkcji BeginPaint() przygotowuje okno do rysowania oraz przypisuje polu


hdc struktury PAINTSTRUCT uchwyt kontekstu urzdzenia uywanego do rysowania w
tym oknie. Uchwyt kontekstu urzdzenia jest przekazywany jako pierwszy parametr
waciwie wszystkich funkcji GDI, identyfikujc okno, do ktrego ma si odnosi dziaanie
danej funkcji. Nasz kod nastpnie wybiera do operacji rysowania czerwony pdzel, po
czym rysuje czerwony, wypeniony prostokt o wsprzdnych (100, 100, 150, 150). Po
narysowaniu prostokta pdzel jest odkadany, za funkcja EndPaint() zajmuje si
wykonaniem kocowych porzdkw.

Zanim wycigniesz wniosek, e OpenGL dziaa tak samo, przypomnij sobie, e GDI jest
mechanizmem specyficznym dla Windows. Inne rodowiska nie posiadaj kontekstw
urzdze, uchwytw okien itp. Z drugiej strony, OpenGL zosta zaprojektowany tak, aby
by cakowicie przenony pomidzy rnymi rodowiskami i platformami
sprztowymi. Dodanie kontekstu urzdzenia do funkcji OpenGL sprawioby, e kod
OpenGL staby si bezuyteczny w kadym rodowisku innym ni Windows.
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 105

Konteksty renderowania OpenGL


W celu zapewnienia przenonoci rdzennych funkcji OpenGL, kade rodowisko musi
posiada jaki sposb na wskazanie okna, w ktrym OpenGL bdzie rysowa. W Win-
dows, rodowisko OpenGL jest osadzone w czym, co nosi nazw kontekstu rendero-
wania. Podobnie jak kontekst urzdzenia zapamituje informacje o trybie rysowania i
poleceniach GDI, tak kontekst renderowania zapamituje ustawienia i polecenia
OpenGL.

W swojej aplikacji moesz posiada wicej ni jeden kontekst renderowania - na przykad


moesz korzysta z dwch okien uywajcych rnych trybw rysowania, rzutw itd.
Jednak aby polecenia OpenGL wiedziay" w ktrym oknie maj dziaa, w poje-
dynczym wtku w danym momencie tylko jeden kontekst renderowania moe by biecy.
Gdy kontekst renderowania staje si biecym, jest wizany take z kontekstem
urzdzenia, czyli konkretnym oknem. W tym momencie OpenGL wiej ju, w ktrym
oknie ma rysowa. T koncepcj ilustruje rysunek 4.2, pokazujc, jak polecenia OpenGL
s porednio powizane z oknem przez biecy kontekst renderowania.
Rysunek 4.2.
W jaki sposb
polecenia OpenGL
odnajduj swoje
okno

Rada dotyczca wydajnoci


Biblioteka OpenGL jest bezpieczna ze wzgldu na wtki, co
oznacza, e moesz korzysta jednoczenie z kilku wtkw
rysujcych w swoich oknach lub na swoich bitmapach. W
przypadku systemw wieloproce-sorowych moe to
powodowa duy wzrost wydajnoci. Wtki mog by
uyteczne take w systemach jednoprocesorowych, na
przykad kiedy jeden wtek zajmuje si rysowaniem, za drugi
obsug interakcji z uytkownikiem. Mona take zastosowa
kilka wtkw rysujcych obiekty w ramach tego samego
kontekstu renderowania. Na pytce CD-ROM doczonej do
ksiki, w folderze tego rozdziau, znajduje si program
GLTHREAD, stanowicy przykad uywania wtkw w OpenGL.
106 ________________________________ Cz l Wprowadzenie do OpenGL

Korzystanie z funkcji Wiggle


Kontekst renderowania nie jest wasn koncepcj OpenGL, lecz raczej dodatkiem do
API Windows stworzonym w celu wsparcia OpenGL. W rzeczywistoci, nowe funkcje
wiggle zostay dodane do Win32 API specjalnie w celu umoliwienia OpenGL dziaania w
oknach. Trzema najczciej uywanym funkcjami zwizanymi z kontekstem renderowania
s
HGLRC wglCreateContext (HDC h D C ) ; BOOL
wglDeleteContext (HGLRC h r c ) ; BOOL
wglMakeCurrent(HDC hDC, HGLRC h r c ) ;

Tworzenie i wybieranie kontekstu renderowania


Zwr uwag na nowy typ danych, HGLRC, reprezentujcy uchwyt kontekstu rendero-
wania. Funkcja wglCreateContext() otrzymuje uchwyt kontekstu urzdzenia GDI i zwraca
uchwyt kontekstu renderowania OpenGL. Podobnie jak kontekst urzdzenia GDI, kontekst
renderowania musi zosta zniszczony, gdy ju nie bdzie potrzebny. Suy do tego funkcja
wglDeleteContext(), jako jedynego parametru oczekujca uchwytu kontekstu
renderowania, ktry ma zosta zniszczony.

Gdy kontekst renderowania jest tworzony dla danego kontekstu urzdzenia, mwi si, e
jest odpowiedni do rysowania w tym kontekcie urzdzenia. Gdy kontekst renderowania
staje si biecy (w wyniku wywoania funkcji wglMakeCurrent()), nie jest konieczne
podawanie kontekstu urzdzenia uytego przy tworzeniu tego kontekstu
renderowania. Jednak wskazany przy tym kontekst urzdzenia musi mie t sam chara-
kterystyk, co kontekst urzdzenia wskazany podczas tworzenia kontekstu renderowania.
Musz zgadza si liczba kolorw, definicje buforw itd., czyli te informacje, ktre okrela
si mianem formatu pikseli.

Aby kontekst renderowania mg sta si biecym dla kontekstu urzdzenia rnego od


kontekstu urzdzenia uytego przy tworzeniu kontekstu renderowania, oba konteksty
urzdze musz mie taki sam format pikseli. Moesz odoy biecy kontekst ren-
derowania albo przez wybranie innego kontekstu renderowania, albo przez wywoanie
funkcji wglMakeCurrent z parametrem NULL w miejscu uchwytu kontekstu rende-
rowania. (Wybr i ustawianie formatu pikseli zostanie omwione za chwil).

Rysowanie przy uyciu OpenGL


Jeli niezbyt czsto programowae z wykorzystaniem GDI, ledzenie zarwno kontekstu
urzdzenia, jak i kontekstu renderowania moe wydawa si do kopotliwe, jednak gdy
raz tego sprbujesz, przekonasz si, e to bardzo atwe. W dawnych czasach
programowania w 16-bitowych Windows, konieczne byo pobieranie kontekstu urz-
dzenia, szybkie wykorzystanie i jeszcze szybsze zwrcenie - gdy cay system Win-
dows mia do dyspozycji jedynie pi kontekstw naraz. Teraz, w czasach 32-bitowych
Windows te ograniczenia odeszy w niepami. Nie oznacza to, e moemy by nieu-
wani, lecz e wystpuje mniej ogranicze w tworzeniu okien z prywatnym kontekstem
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle _________________ 107

urzdzenia (przy uyciu stylu okna WS_OWNDC) i pozostawaniu przy nim przez cay
czas ycia okna. Co wicej, poniewa wikszo naszych przykadw bdzie animowana,
moemy unikn cigych (i kosztownych) wywoa funkcji GetDC() za kadym razem,
gdy chcemy kontekst renderowania uczyni biecym. Kolejna oszczdno czasu polega na
jednokrotnym uczynieniu kontekstu renderowania biecym i pozostawieniu go biecym
przez cay czas dziaania programu. Jeli tylko jedno okno w wtku korzysta z OpenGL,
nigdy nie spowoduje to problemw, zaoszczdzi za nam koniecznoci regularnego
wywoywania funkcji wglMakeCurrent.

Jedynie dwa komunikaty okienkowe wymagajjakiegokolwiek kodu zwizanego z two-


rzeniem i usuwaniem kontekstu renderowania: WM_CREATE oraz WM_DESTROY.
Naturalnie, kontekst renderowania jest tworzony w odpowiedzi na komunikat WM_
CREATE, za niszczony w odpowiedzi na komunikat WM_DESTROY. Ponisza szkie-
letowa sekcja z procedury okna korzystajcego z OpenGL ilustruje schemat tworzenia i
usuwania kontekstu renderowania:
LRESULT CALLBACK WndProc (HWND hWnd, . . . { static HGLRC hRC;
// Przechowuje kontekst renderowania pomidzy
// wywoaniami
static HDC hDC; // Przechowuje kontekst urzdzenia pomidzy //
wywoaniami

switch (message) {
case WM_CREATE:
hDC = GetDC(hWnd) ;

hRC = wglCreateContext (hDC) ;


wglMakeCurrent (hDC, hRC);
break;
case WM_DESTROY:
wglMakeCurrent (hDC, NULL) ;
wglDeleteContext (hRC) ;

PostQuitMessage ( 0 ) ;
break;

Rysowanie w oknie w dalszym cigu odbywa si w procedurze obsugi komunikatu


WM_PAINT, z tym e tym razem zawiera polecenia rysunkowe OpenGL. W procedurze
obsugi tego komunikatu moesz ju zrezygnowa z sekwencji BeginPaint/ EndPaint. (Te
funkcje czyciy okno, ukryway punkt wstawiania na czas rysowania oraz zatwierdzay
obszar roboczy okna po rysowaniu). W OpenGL musisz jedynie zatwierdzi obszar ro-
boczy okna, aby w dalszym cigu mc otrzymywa komunikaty WM_PAINT. Oto
szkielet procedury obsugi komunikatu WM_PAINT:
case WM_PAINT:

// Wywoanie kodu rysunkowego OpenGL


RenderScene () ;
108________________________________Cz l * Wprowadzenie do OpenGL

// Zatwierdzenie odmalowanego obszaru


ValidateRect(hWnd,NULL); > ^ break;

Sztuczki programistyczne
W dalszym cigu, po narysowaniu sceny przez OpenGL, moesz
uywa do rysowania polece GDI. Wedug dokumentacji
Microsoftu, takie dziaanie jest w peni obsugiwane, z wyjtkiem
okien o podwjnym buforowaniu. Moesz jednak uywa
wywoa GDI take w oknach z podwjnym buforowaniem - jeli
tylko wywoujesz funkcje GDI ju po przerzuceniu buforw. W
rzeczywistoci nie s obsugiwane wywoania GDI dziaajce na
tylnym buforze podwjnie buforowanych okien. Najlepiej unika
takich wywoa, gdy gwnym przeznaczeniem podwjnego
buforowania jest zapobieganie migotaniu oraz pynna
aktualizacja ekranu.

Przygotowanie okna dla OpenGL


W tym momencie moe si niecierpliwisz chcc szybko zabra si za pisanie programu, w ktrym
uyjesz poznanego kodu i funkcji z poprzedniego rozdziau, umieszczajc je w procedurze obsugi
komunikatu WM_PAINT. Jednak poczekaj jeszcze moment. Musisz pozna jeszcze dwa wane
wstpne kroki, zanim bdziesz mg skorzysta z kontekstu renderowania.

Style okien
Aby OpenGL mg rysowa w oknie, okno musi zosta utworzone z ustawionymi stylami
WS_CLIPCHILDREN oraz WS_CLIPSIBLINGS, natomiast nie moe zawiera stylu
CS_PARENTDC. Powodem tego jest fakt, e kontekst renderowania nadaje si jedynie do rysowania
w oknach, dla ktrych zosta stworzony (okrelonych przez kontekst urzdzenia w funkcji
wglCreateContext) lub w oknach o dokadnie takim samym formacie pikseli. Style
WS_CLIPCHILDREN oraz WS_CLIPSIBLINGS zabezpieczaj funkcj rysunkow przed prb
aktualizacji wszelkich okien potomnych. Styl CS_PARENTDC (powodujcy, e okno dziedziczy
kontekst urzdzenia swojego okna nadrzdnego) jest niedozwolony, poniewa kontekst
renderowania moe by powizany z tylko jednym kontekstem urzdzenia i oknem. Jeli te style nie
zostan okrelone, nie bdziesz mg ustawi formatu pikseli okna - ostatniego szczegu, jakim
musimy si zaj przed przejciem do naszego pierwszego programu OpenGL w Windows.

Formaty pikseli
Rysowanie w oknie przez OpenGL wymaga take ustawienia formatu pikseli. Podobnie jak kontekst
renderowania, format pikseli nie jest w rzeczywistoci czci OpenGL ja-
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle_________________109

ko takiego. Stanowi raczej rozszerzenie Win32 API (a konkretnie GDI) przeznaczone do


wsparcia funkcjonowania OpenGL. Format pikseli ustala waciwoci kontekstu ren-
derowania OpenGL, takie jak ilo kolorw i gboko bufora, a take to, czy okno jest
podwjnie buforowane. Zanim bdziesz mg uy kontekstu urzdzenia do stworzenia
kontekstu renderowania, musisz ustawi dla tego kontekstu urzdzenia format pikseli. Oto
dwie funkcje, ktrych bdziesz potrzebowa:
int ChoosePixelFormat(HDC hDC, PIXELFORMATDESCRIPTOR *ppfd)
BOOL SetPixelFormat(HDC hDC, int iPixelFormat, PIXELFORMATDESCRIPTOR
0*ppfd)

Ustawienie formatu pikseli przebiega w trzech krokach. Po pierwsze, wypeniasz struktur


PIXELFORMATDESCRIPTOR zgodnie z charakterystyk i zachowaniem okna, jakie
chcesz osign (poznamy je za chwil). Nastpnie przekazujesz t struktur funkcji
ChoosePixelFormat. Funkcja ChoosePixelFormat zwraca indeks (bdcy liczb cakowit)
formatu pikseli dostpnego dla wskazanego kontekstu urzdzenia. Na koniec ten indeks
jest przekazywany funkcji SetPixelFormat. Caa sekwencja wyglda mniej wicej tak:
PIXELFORMATDESCRIPTOR pixelFormat;
int nFormat!ndex; HDC hDC;

// inicjowanie struktury pixelFormat;

nFormat!ndex = ChoosePixelFormat(hDC, spixelFormat);


SetPixelFormat( h D C , nPixelFormat, spixelFormat);

Funkcja ChoosePixelFormat prbuje dopasowa obsugiwany format pikseli do infor-


i macji otrzymanych w strukturze PIXELFORMATDESCRIPTOR. Zwracany indeks sta-
1
nowi identyfikator formatu pikseli. Na przykad, moesz zada formatu pikseli
! posiadajcego 16 milionw kolorw, lecz sprzt obsuguje jedynie 256 kolorw jedno
czenie. W takim przypadku format pikseli bdzie najbliszym z moliwych - w tym
; przypadku formatem pikseli z 256 kolorami. Ten indeks jest przekazywany funkcji
SetPixelFormat.
Dokadny opis struktury PIXELFORMATDESCRIPTOR znajdziesz w sekcji podrcznika
na kocu rozdziau, w punkcie dotyczcym funkcji DescribePixelFormat. Listing 4.1
przedstawia funkcj z przykadowego programu GLRECT, w ktrej nastpuje wypenienie
tej struktury, a nastpnie ustalenie formatu pikseli dla kontekstu urzdzenia.

Listing 4.1. Funkcja ustalajca format pikseli dla danego kontekstu urzdzenia_______________

// Wybranie formatu pikseli dla danego kontekstu urzdzenia void


SetDCPixelFormat(HDC hDC)
{
int nPixelFormat;
Static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIKELFORMATDESCRIPTOR), // Rozmiar tej struktury
l, // Wersja struktury
PFD_DRAW_TO_WINDOW | // Rysowanie w oknie (nie na
// bitmapie)
110________________________________Cz l Wprowadzenie do OpenGL

PFD_SUPPORT_OPENGL | // Obsuga wywoa OpenGL


// w tym oknie
PFD_DOUBLEBOFFER, // Tryb podwjnego buforowania
PFD_TYPE_RGBA, // Tryb kolorw RGBA
8, // Chcemy 8-bitowego koloru
0,0,0,0,0,0, // Nieuywane przy wybieraniu
// trybu
0,0, // Nieuywane przy wybieraniu
// trybu
0,0,0,0,0, // Nieuywane przy wybieraniu
// trybu
16, // Rozmiar bufora gbokoci
O, // Nieuywane przy wybieraniu
// trybu
O, / // Nieuywane przy wybieraniu
// trybu
PFD_MAIN_PLANE, // Rysowanie na gwnym planie
O, // Nieuywane przy wybieraniu
// trybu
0 , 0 , 0 }; // Nieuywane przy wybieraniu
// trybu
// Wybranie formatu pikseli najbardziej zblionego do wskazanego
// w pfd
nPixelFormat = ChoosePixelFormat(hDC, ipfd);
// Ustawienie formatu pikseli dla kontekstu urzdzenia
SetPixelFormat( h D C , nPixelFormat, Spfd);

Jak wida w tym przykadzie, nie wszystkich pl struktury PIXELFORMATDESCRIP-TOR


dotyczy wybieranie formatu pikseli. Tabela 4. l zawiera list pl ustawianych przez kod z
listingu 4.1. Pozostae pola mog w tym momencie otrzyma warto 0.

Tabela 4.1.
Pola struktury PKELFORMA TDSCRIPTOR uywane podczas dania formatu pikseli

Pole Opis
nSize Rozmiar struktury, ustawiany na sizeof(PIXELFORMATDESCRIPTOR)
nYersion Wersja tej struktury danych, ustawiana na l.
dwFlags Znaczniki okrelajce waciwoci bufora pikseli, ustawiane na
(PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL
PFD_DOUBLEBUFFER). Wskazuj one, e kontekst urzdzenia nie jest
kontekstem bitmapy (pamiciowym), do rysowania zostanie uyty OpenGL
oraz e okno powinno by podwjnie buforowane.
iPixelType Typ danych pikseli. Informuje OpenGL, aby uyo trybu RGBA lub
indeksowanego trybu kolorw. Aby uy trybu RGBA, uyj staej
PFD_TYPE_RGBA.
cColorBits Ilo bitw na kolor, w tym wypadku 24 bity. Jeli sprzt nie obsuguje 24-
bitowego
koloru, zostanie wybrana maksymalna obsugiwana ilo bitw na kolor.
cDepthBits Ilo bitw bufora gbokoci (z-bufora). Ustawiane na 32 dla maksymalnej
dokadnoci, jednak czsto wystarcza 16 bitw (zajrzy] do sekcji podrcznika).
iLayerType Rodzaj warstwy. W przypadku Microsoft Windows dozwolona jest
jedynie staa PFD MAIN PLANE.
GL Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle_________________111

Powrt odbijajcego si kwadratu


a
W kocu mamy wystarczajc ilo informacji, aby utworzy okno Windows uywajce
OpenGL bez podpierania si bibliotek AUX. Program pokazany na listingu 4.2
zawiera wymagany kod Windows oraz funkcje rysujce z przykadu BOUNCE2 z rozdziau
3. Jak wida z dugoci kodu programu, biblioteka AUX oszczdza nam wiele wysiku.

Funkcje RenderScene, ChangeSize i IdleFunction praktycznie zostay ywcem przeniesione


z przykadu z rozdziau trzeciego i w zwizku z tym nie bdziemy ich tutaj omawia. Te
funkcje, razem z funkcj z listingu 4.1, tworz przykadowy program GLRECT. Rysunek 4.3
przedstawia znajomy odbijajcy si kwadrat. Listing 4.2 przedstawia funkcj WinMain,
tworzc okno, oraz funkcj WndProc, obsugujc poszczeglne komunikaty skierowane do
okna.

Rysunek 4.3.
Odbijajcy si kwadrat w wersji dla Windows

Listing 4.2. Program animowanego kwadratu, bez uycia biblioteki A


UX___________

// Punkt wejcia wszystkich


programw Windows int
APIENTRY WinMain(
HINSTANCE hlnstance,
HINSTANCE
hPrev!nstance, LPSTR IpCmdLine, int
nCmdShow) {
MSG msg; // Struktura komunikatu
WNDCLASS we; // Struktura klasy okna
HWND hWnd; // Uchwyt gwnego okna

// Okrelenie klasy okna


w e . style = CS_HREDRAW l CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
we.hlnstance = hlnstance;
wc.hlcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC ARROW);
112________________________________Cz l Wprowadzenie do OpenGL

// W przypadku okna OpenGL nie potrzeba pdzla ta


wc.hbrBackground = NULL;

wc.lpszMenuName = NULL;
wc.lpszClassName = IpszAppName;

// Zarejestrowanie klasy okna


if(RegisterClasst&wc) == 0)
return FALSE;

// Utworzenie gwnego okna aplikacji


hWnd = CreateWindow(
IpszAppName,
IpszAppName,
// OpenGL wymaga WS_CLIPCHILDREN i WS_CLIPSIBLINGS
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
OWS_CLIPSIBLINGS,
// Pooenie i wymiary okna
100, 100,
250, 250,
NULL,
NULL,
hlnstance,
NULL);
// Wyjcie, jeli nie powiodo si utworzenie okna
ifthWnd == NULL) return FALSE;

// Wywietlenie okna
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
// Przetwarzanie komunikatw a do momentu zakoczenia
// dziaania aplikacji
while( GetMessage(smsg, NULL, O, 0 ) )
{
TranslateMessage(smsgi;
DispatchMessage(imsg); }
return msg.wParam;
}
// Procedura okna, ktra obsuguje wszystkie komunikaty skierowane do
// tego okna
LRESULT CALLBACK WndProc( HWND hWnd,
UINT message, WPARAM wParam, LPARAM
IParam) {
static HGLRC hRC; // Stay kontekst renderowania static
HDC hDC; // Prywatny kontekst urzdzenia GDI
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle_________________113

switch (message)
{
// Utworzenie okna, przygotowanie dla OpenGL
case WM_CREATE:
// Przechowanie kontekstu urzdzenia
hDC = GetDC(hWnd);
// Wybranie formatu pikseli
SetDCPixelFormat(hDC);
// Utworzenie kontekstu renderowania i uczynienie go
// biecym
hRC = wglCreateContext( h D C ) ;
wglMakeCurrent(hDC, hRC);

// Utworzenie timera odpalanego co milisekund


SetTimer(hWnd,101,l,NULL);
break;
// Okno jest niszczone, wic robimy porzdki
case WM_DESTROY:
// Usunicie utworzonego timera
KillTimer(hWnd,101);
// Odoenie biecego kontekstu renderowania i usunicie
// go
wglMakeCurrent( h D C , NULL);
wglDeleteContext( h R C ) ;
// Poinformowanie aplikacji o zakoczeniu dziaania
PostQuitMessage( 0 ) ; break;
// Zmieniaj si wymiary okna
case WM_SIZE:
// Wywoanie naszej funkcji modyfikujcej bry obcinania
// i widok
ChangeSize(LOWORD(IParam), HIWORD(IParam));
break;
// Timer, ktry przesuwa i odbija prostokt, po prostuO //
wywoujemynasz poprzedni funkcj Onldle, a nastpnie //
uniewaniamy okno,aby zostao odrysowane case WMJTIMER:
{
IdleFunction();
InvalidateRect(hWnd,NULL,FALSE);
}
break;
// Funkcja rysujca. Ten komunikat jest wysyany przez Windows //
za kadym razem, gdy okno wymaga odwieenia case WM_PAINT:
(
// Wywoanie kodu rysunkowego OpenGL
RenderScene();
// Wywoanie funkcji przerzucajcej bufory
SwapBuffers(hDC);
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle_________________115

LION). Gdy funkcja WndProc otrzyma komunikat WM_TIMER, wykonywany jest poniszy
kod:
case WMJTIMER: {
IdleFunctionO ;

IiwalidateRect (hWnd, NULL, FALSE) ;


}
break;

Funkcja IdleFunction jest identyczna z funkcj z przykadu BOUNCE2, z jednym wy-


jtkiem: nie zawiera wywoania funkcji RenderScene(). Zamiast niej wywoywana jest
funkcja InvalidateRect, powodujca wysanie przez system komunikatu WM_PAINT do
okna, czyli w efekcie odmalowanie jego zawartoci.

wiata, kamera, akcja!


Wszystko ju jest na swoim miejscu, nadszed wic czas na prawdziwe dziaania. Kod
OpenGL przeznaczony do rysowania sceny jest wywoywany z wntrza procedury obsugi
komunikatu WM_PAINT. Procedura wywouje funkcj RenderScene (take zapoyczon z
przykadu BOUNCE2), przerzuca zawarto buforw oraz zatwierdza obszar roboczy okna
(w celu zablokowania nadmiarowych komunikatw WM_PAINT).
case WM_PAINT: {
// Wywoanie kodu rysunkowego OpenGL
RenderScene();

// Wywoanie funkcji przerzucajcej bufory


SwapBuffers( h D C ) ;
// Zatwierdzenie odmalowanego obszaru
YalidateRect(hWnd,NULL);
}
break;

Wystpuje tu nowa funkcja GDI Windows, SwapBuffers. Ta funkcja peni t sam rol, co
auxSwapBuffers - w oknie z podwjnym buforowaniem przerzuca do okna zawarto
niewidocznego (tylnego) bufora. Jednym parametrem funkcji jest kontekst urzdzenia.
Zwr uwag, e ten kontekst urzdzenia musi posiada format pikseli z ustawionym
znacznikiem PFD_DOUBLEBUFFER; w przeciwnym razie dziaanie funkcji si nie
powiedzie.

I ju! W tym momencie posiadasz szkielet kodu, w ktry moesz wstawi wasn, dowoln
procedur renderujc OpenGL. Bdzie ona korzystaa z prawdziwego okna Windows,
z wszystkimi jego cechami (skalowaniem, przenoszeniem, zamykaniem itd.). Co wicej,
moesz oczywicie uy tego kodu do utworzenia okna OpenGL stanowicego cz
rozbudowanej aplikacji, zawierajcej inne okna, menu itd.
116 ____ ____ ____ ___ ____ Cz l Wprowadzenie do OpenGL

Brakujcy kod obsugi palety


Gdy porwnasz zamieszczony w ksice kod programu GLRECT
z kodem programu na doczonej do ksiki pytce CD-ROM, w
tym drugim zauwaysz procedury obsugi dwch dodatkowych
komunikatw. Te dwa komunikaty: WM_QUERYPALETTE i
WM_PALETTECHANGED obsuguj odwzorowanie palety
Windows. Kolejna funkcja, GetOpenGL-Palette, tworzy dla
nas palet kolorw. Palety s zem koniecznym, jeli mamy
zamiar korzysta z kart graficznych potraficych wywietli
maksymalnie 256 kolorw. Bez tego kodu moglibymy nie
otrzyma kolorw o ktre poprosilibymy funkcj glColor, za w
przypadku pewnych kolorw, nie otrzymalibymy nawet ich
przyblienia. Palety i kolory w Windows stanowi wany temat,
ktrym zajmiemy si szczegowo w rozdziale 8. To kolejne
irytujce zagadnienie, ktrego roztrzsania staraa si nam
oszczdzi biblioteka AUX!

Podsumowanie
Po przeczytaniu tego rozdziau powiniene zdawa sobie spraw, o ilu uciliwych
szczegach nie musimy pamita korzystajc z biblioteki AUX. Poznae koncepcj
kontekstw renderowania, wprowadzon do Windows GDI po to, aby OpenGL wie-
dziao, w ktrym oknie ma wykonywa operacje graficzne. Wiesz ju, jak wybr i usta-
wienie formatu pikseli przygotowuje kontekst urzdzenia przed wykorzystaniem go do
stworzenia kontekstu renderowania. Oprcz tego dowiedziae si, na ktre komunikaty
okienkowe i w jaki sposb powinien odpowiada program OpenGL w Windows.

W poniszej sekcji podrcznika znajdziesz usystematyzowane informacje o funkcjach opi-


sywanych w tym rozdziale oraz dodatkowe informacje o funkcjach jeszcze nie omawianych,
gdy to wymagaoby poznania pewnych zagadnie i koncepcji, ktre jeszcze nie byy
poruszane. Przykady zastosowania tych funkcji znajdziesz na pytce CD-ROM doczonej do
ksiki. Zachcamy do samodzielnej analizy i modyfikowania tych przykadw.

Podrcznik
ChoosePixel Format
Przeznaczenie Wybiera format pikseli najbardziej zbliony do formatu zadanego
w strukturze PIXELFORMATDESCRIPTOR, dostpny dla danego
kontekstu urzdzenia.
Plik nagwkowy <wingdi.h>
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 117

Skadnia int ChoosePixelFormat(HDC hDC, const


PIXELFORMATDESCRIPTOR *ppfd);
Opis Ta funkcja jest uywana do wyznaczenia najlepszego formatu pikseli
dostpnego dla danego kontekstu urzdzenia. Wybr opiera si na
charakterystyce przekazanej w strukturze
PIXELFORMATDESCRIPTOR. Otrzymany indeks formatu jest
przekazywany funkcji SetPixelFormat.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia, dla ktrego funkcja wyszukuje
najbardziej dopasowany format pikseli.
PPfd PDCELFORMATDESCRIPTOR: Wskanik do struktury opisujcej idealny
dany format pikseli. Niektre pola struktury s zarezerwowane do
wykorzystania w przyszoci. Peny opis struktury
PIXELFORMATDESCRIPTOR zostanie podany przy opisie funkcji
DescribePixelFormat. Tutaj opiszemy jedynie te pola, ktre s
wykorzystywane przy wyborze formatu pikseli:
nSize WORD: Rozmiar struktury, zwykle ustawiany na
sizeof(PIXELFORMATDESCRIPTOR).
nYersion WORD: Numer wersji struktury, ustawiany na 1.
dwFlag DWORD: Zestaw znacznikw okrelajcych waciwoci bufora
pikseli.
iPixelType BYTE: Tryb kolorw (RGBA lub indeksowany).
cColorBits BYTE: Gboko bufora kolorw. cAlphaBits BYTE:
Gboko bufora alfa. cAccumBits BYTE: Gboko bufora
akumulacji. cDepthBits BYTE: Gboko bufora gbokoci.
cStencilBits BYTE: Gboko bufora szablonu.
cAuxBuffers BYTE: Ilo buforw pomocniczych (nieobsugiwane w
implementacji Microsoftu).
iLayerType BYTE: Rodzaj warstwy (nieobsugiwane w implementacji
Microsoftu).
Indeks formatu pikseli najbardziej zblionego do przekazanego formatu lub
warto zero, jeli nie powiodo si wyszukanie zblionego formatu.
Zwracana warto
Przykad Kod przykadu GLRECT w tym rozdziale demonstruje wybr formatu
pikseli:
int nPixelFormat;
static PIKELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),// Rozmiar tej
struktury
l, // Wersja struktury
118 Cz l * Wprowadzenie do OpenGL

// Wybranie formatu pikseli najbardziej


zblionego
// do wskazanego w pfd
nPixelFormat = ChoosePixelFormat(hDC, &pfd);

// Ustawienie formatu pikseli dla kontekstu


Patrz take urzdzenia SetPixelFormat(hDC, nPixelFormat,
&pfd);
DescribePixelFormat, GetPixelFormat, SetPixelFormat

DescribePixelFormat
Przeznaczenie Plik Zwraca szczegowe informacje o formacie pikseli.
nagwkowy <wingdi.h>
Skadnia int DescribePixelFormat(HDC hDC, int iPixelFormat, UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd);
Opis Ta funkcja wypenia struktur PIXELFORMATDESCRIPTOR informacjami
o formacie pikseli okrelonym dla danego kontekstu urzdzenia. Zwraca
take maksymalny indeks formatu pikseli dla danego kontekstu urzdzenia.
Jeli ppfd ma warto NULL, funkcja i tak zwraca maksymalny numer
indeksu formatu pikseli dla danego kontekstu urzdzenia. Niektre pola
struktury PIXELFORMATDESCRIPTOR nie s obsugiwane w oglnej
implementacji OpenGL Microsoftu, mog jednak by obsugiwane przez
poszczeglnych producentw sprztu.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia zawierajcego formaty pikseli.
tPixelFormat int: Indeks formatu pikseli, o ktrym chcemy otrzyma informacje.
nBytes UINT: Rozmiar struktury wskazywanej przez ppfd. Jeli ten parametr ma
warto zero, dane nie bd kopiowane do bufora. Powinien by ustawiony
na sizeof(PIXELFORMATDESCRIPTOR).
ppfd LPPIXELFORMATDESCRIPTOR: Wskanik do struktury
PIXELFORMATDESCRIPTOR, ktra zostanie wypeniona
szczegowymi informacjami o danym formacie pikseli. Struktura
PIXELFORMATDESCRIPTOR jest zdefiniowana nastpujco:
typedef struct tagPIKELFORMATDESCRIPTOR { // pfd
WORD nSize; WORD nVersion; DWORD dwFlags; BYTE
iPixelType; BYTE cColorBits; BYTE cRedBits; BYTE
cRedShift; BYTE cGreenBits; BYTE cGreenShift;
Rozdzia 4. OpenGL for Windows: OpenGL + Win32 = Wiggle_________________119

BYTE CBlueBits; BYTE


cBlueShift; BYTE cAlphaBits;
BYTE cAlphaShift; BYTE
cAccumBits; BYTE
cAccumRedBits; BYTE
cAccumGreenBits; BYTE
cAccumBlueBits; BYTE
cAccumAlphaBits; BYTE
cDepthBits; BYTE
cStencilBits; BYTE
cAuxBuffers; BYTE
iLayerType; BYTE bReserved;
DWORD dwLayerMask; DWORD
dwVisibleMask; DWORD
dwDamageMask; }
PIXELFORMATDESCRIPTOR;
nSize Zawiera rozmiar struktury. Zawsze powinno by ustawione na
sizeof(PIXELFORMATDESCRIPTOR).
nYersion Zawiera numer wersji struktury. Zawsze powinno by
ustawione na l.
dwFlags zawiera zestaw znacznikw bitowych (tabela 4.2) opisujcych
waciwoci formatu pikseli. Z pewnymi wyjtkami, te znaczniki nie
wykluczaj si wzajemnie.
iPixelType okrela typ danych pikseli, a dokadniej, okrela tryb wyboru
koloru. Moe to by jedna z wartoci z tabeli 4.3.
cColorBits ilo bitw koloru uywanych w buforze koloru,
z wyczeniem bitw alfa w trybie RGBA. W trybie indeksowanym
okrela ilo bitw indeksu koloru.
cRedBits okrela ilo bitw czerwieni w buforze koloru w trybie RGBA.
cRedShift okrela przesunicie bitw czerwieni w buforze koloru w trybie
RGBA.*
cGreenBits okrela ilo bitw zieleni w buforze koloru w trybie RGBA.
cGreenShift okrela przesunicie bitw zieleni w buforze koloru w trybie
RGBA.*
cBlueBits okrela ilo bitw bkitu w buforze koloru w trybie RGBA.
cBlueShift okrela przesunicie bitw bkitu w buforze koloru w trybie
RGBA.*
cAlphaBits okrela ilo bitw kanau alfa w buforze koloru w trybie
RGBA. Nieobsugiwane w implementacji Microsoftu.
cAlphaShift okrela przesunicie bitw kanau alfa w buforze koloru w
trybie RGBA. Nieobsugiwane w implementacji Microsoftu.
cAccumBits to czna gboko (ilo bitw) bufora akumulacji. Patrz
rozdzia 15.
120 Cz l Wprowadzenie do OpenGL

cAccumRedBits to ilo bitw czerwieni w buforze akumulacji.


cAccumGreenBits to ilo bitw zieleni w buforze akumulacji.
cAccumBlueBits to ilo bitw bkitu w buforze akumulacji.
cAccumAlphaBits to ilo bitw bufora alfa w buforze akumulacji.
cDepthBits okrela gboko bufora gbokoci. Patrz rozdzia 15.
cStencilBits okrela gboko bufora szablonu. Patrz rozdzia 15.
cAuxBuffers okrela ilo buforw pomocniczych. Nieobsugiwane w
implementacji Microsoftu.
iLayerType okrela rodzaj warstwy. Wartoci dostpne dla tego pola zawiera
tabela 4.4, lecz w implementacji Microsoftu dostpna jest jedynie warto
PFD_MAIN_PLANE.
bResenredJest zarezerwowane i nie powinno by modyfikowane.
dwLayerMask jest uywane w powizaniu z dwYisibleMask w celu
sprawdzenia, czy jedna warstwa nachodzi na inn. W biecej
implementacji Microsoftu warstwy nie s obsugiwane.
dwYisibleMask jest uywane w powizaniu z dwYisibleMask w celu
sprawdzenia, czy jedna warstwa nachodzi na inn. W biecej
implementacji Microsoftu warstwy nie s obsugiwane.
dwDamageMask wskazuje, czy wicej ni jeden format pikseli korzysta z tego
samego bufora ramki. Jeli iloczyn bitowy (AND) pl dwDamageMask dwch
formatw pikseli jest rny od zera, to korzystaj one z tego samego bufora
ramki.
*W rozdziale 8 wyjaniamy, jak odnosi si to do urzdze z palet
kolorw.
Zwracana warto Maksymalna ilo formatw pikseli obsugiwanych przez dany kontekst
urzdzenia lub zero w przypadku bdu.
Przykad Kod przykadu GLRECT na pytce CD-ROM doczonej do ksiki.
Sprawdzamy w nim, czy kontekst urzdzenia wymaga zdefiniowania
palety:
PIXELFORMATDESCRIPTOR pfd; // Deskryptor formatu pikseli int
nPixelFormat; // Indeks formatu pikseli

// Pobranie indeksu formatu pikseli oraz


// deskryptora formatu pikseli
nPixelFormat = GetPixelFormat( h D C ) ;
DescribePixelFormat(hDC, nPixelFormat, sizeof(PIKELFORMATDESCRIPTOR) ,
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 121

// Czy ten format pikseli wymaga palety? Jeli nie, po prostu nie //
twrz palety i zwr warto NULL if(!(pfd.dwFlags i
PFD_NEED_PALETTE)) return NULL;

// Stworzenie palety

Patrz take ChoosePixelFormat, GetPixelFormat, SetPixelFormat

Tabela 4.2.
Znaczniki pola dwFlags struktury PIXELFORMATDESCR1PTOR

Znacznik Opis

PFD_DRAW_TO_WINDOW Bufor jest uywany do rysowania w oknie lub na powierzchni


urzdzenia, takiego jak drukarka.
PFD_DRAW_TO_BITMAP Bufor jest uywany do rysowania na bitmapie w pamici.
PFD_SUPPORT_GDI Bufor obsuguje rysowanie GDI. Ten znacznik oraz znacznik
PFD_DOUBLEBUFFER wykluczaj si wzajemnie.
PFD_SUPPORT_OPENGL Bufor obsuguje rysowanie OpenGL.
PFD_GENERIC_FORMAT Format pikseli jest ogln implementacj (obsugiwan przez
emulacj GDI). Jeli ten znacznik nie jest ustawiony, format pikseli
jest obsugiwany przez sprzt lub sterownik urzdzenia.
PFD_NEED_PALETTE Format pikseli wymaga uycia palety logicznej.
PFD_NEED_SYSTEM_PALETTE Uywane w szczeglnych implementacjach obsugujcych tylko
jedn palet sprztow. Ten znacznik wymusza jednoznaczne
odwzorowanie palety sprztowej na palet logiczn.
PFD_DOUBLEBUFFER Ten format pikseli korzysta z podwjnego buforowania. Ten
znacznik i znaczniki PFD_SUPPORT GDI wykluczaj si
wzajemnie.
PFD_STEREO Bufor jest stereoskopowy. Jest to analogia do przedniego i tylnego
bufora w podwjnym buforowaniu, z tym e w tym przypadku
mamy do czynienia z buforem lewym i prawym. Nieobsugiwane w
implementacji OpenGL Microsoftu.
PFD_DOUBLE_BUFFER_DONTCARE Podczas wyboru formatu pikseli pozwalamy na wybranie
pojedynczego lub podwjnego buforowania, bez preferencji.
PFD STEREO DONTCARE Podczas wyboru formatu pikseli pozwalamy na wybranie trybu
stereoskopowego lub zwykego, bez preferencji.
122________________________________Cz l Wprowadzenie do OpenGL

Tabela 4.3.
Znaczniki pola iPixelType

Znacznik Opis
PFD_TYPE_RGBA Tryb koloru RGBA. Kolor kadego piksela jest okrelany przez
podanie skadowej czerwonej, zielonej, niebieskiej i alfa.
PFD_TYPE_COLORINDEX Indeksowany tryb koloru. Kolor kadego piksela jest okrelany
przez podanie indeksu w palecie (tablicy kolorw).

Tabela 4.4.
Znaczniki pola iLayerType

Znacznik Opis
PFD_MAIN_PLANE Warstwa jest gwnym planem.
PFD_O YERLA Y_PL ANE Warstwa j est nakadk.
PFD_UNDERLAY_PLANE Warstwa jest podkadk.

GetPixel Format______________________
Przeznaczenie Zwraca indeks formatu pikseli aktualnie wybranego w danym kontekcie
urzdzenia.
Plik nagwkowy <wingdi.h>
Skadnia int GetPixelFormat(HDC hDC);
Opis Ta funkcja zwraca format pikseli wybrany w danym kontekcie
urzdzenia. Zwracana warto jest indeksem formatu pikseli,
liczonym od l.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia.
Zwracana warto Indeks formatu pikseli wybranego w danym kontekcie urzdzenia lub warto
zero w przypadku bdu.
Przykad Spjrz na przykad dla funkcji DescribePixelFormat.
Patrz take DescribePixelFormat, ChoosePixelFormat, SetPixelFormat

Set Pixel Format______________________


Przeznaczenie Ustala format pikseli dla danego kontekstu urzdzenia.
Plik nagwkowy <wingdi.h>
Skadnia BOOL SetPixelFormat(HDC hDC, int nPixelFormat, const
PIXELFORMATDESCR1PTOR *ppfd);
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 123

Opis Ta ftmkcja ustawia format pikseli dla danego kontekstu urzdzenia. Gdy
format pikseli zostanie ustawiony dla danego kontekstu urzdzenia, nie
mona go ju modyfikowa, Ta funkcja musi by wywoana przed
utworzeniem kontekstu renderowania OpenGL dla tego urzdzenia.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia, dla ktrego chcemy ustawi format
pikseli.
nPixelFormat int: Indeks formatu pikseli do ustawienia.
PPfd LPPDCELFORMATDESCRIPTOR: Wskanik do struktury
PIXELFORMATDESCRIPTOR, zawierajcej deskryptor logicznego formatu
Zwracana pikseli. Ta struktura jest uywana wewntrznie do zapisu specyfikacji
warto logicznego formatu pikseli. Zawarto przekazywanej struktury nie wpywa
na dziaanie operacji.
Przykad TRUE, jeli podany format pikseli zosta ustawiony dla danego kontekstu
Patrz take urzdzenia, a FALSE w przypadku bdu.
Spjrz na przykad do funkcji ChoosePixelFormat.
DescribePixelFormat, GetPixelFormat, SetPixelFormat

SwapBuffers
Przeznaczenie Szybko kopiuje zawarto tylnego bufora do przedniego bufora
(widocznej powierzchni okna).
Plik <wingdi.h>
nagwkowy BOOL SwapBuffers(HDC hDC);
Skadnia Gdy jest wybrane podwjne buforowanie, okno posiada przedni bufor
(widoczny) oraz tylny bufor (niewidoczny). Polecenia rysunkowe s
wykonywane w tylnym buforze. Ta funkcja suy do skopiowania
zawartoci niewidocznego tylnego bufora do wywietlanego przedniego
bufora, w celu uzyskania pynnego rysowania scenki lub pynnej animacji.
Zwr uwag, e zawartoci bufora nie s wymieniane. Po zakoczeniu tej
operacji zawarto tylnego bufora jest niezdefiniowana.
Parametr
y hDC HDC: Uchwyt kontekstu urzdzenia okna, ktre posiada przedni i tylny
bufor.
Zwracana warto TRUE, jeli bufory zostay przerzucone.
Przykad Poniszy przykad przedstawia typowy kod procedury obsugi komunikatu
WM_PAINT. Wywoujemy w nim kod renderowania i jeli pracujemy z
podwjnym buforowaniem, przerzucamy zawarto tylnego bufora. Ten kod
wystpuje take w przykadzie GLRECT w tym rozdziale.
124 Cz l Wprowadzenie do OpenGL

// Funkcja rysujca. Ten komunikat jest wysyany //


przez Windows za kadym razem, gdy // okno wymaga
odwieenia case WM_PAINT:
// Wywoanie kodu rysunkowego OpenGL
RenderScene ();
// Wywoanie funkcji przerzucajcej bufory
SwapBuffers(hDC);
// Zatwierdzenie odmalowanego obszaru
ValidateRect(hWnd,NULL);
}
break

Patrz take glDrawBuffer

wglCreateContext
Przeznaczenie Tworzy kontekst renderowania odpowiedni do rysowania w podanym
kontekcie urzdzenia.
Plik <wingdi.h>
nagwkowy HGLRC wglCreateContext(HDC hDC);
Skadnia Tworzy kontekst renderowania OpenGL odpowiedni dla danego kontekstu
urzdzenia Windows. Format pikseli kontekstu urzdzenia powinien zosta
wybrany przed tworzeniem kontekstu renderowania. Gdy aplikacja
zakoczy korzystanie z kontekstu renderowania, powinna wywoa funkcj
wglDeleteContext.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia okna, w ktrym odbdzie si
rysowanie poprzez nowy kontekst renderowania.
Zwracana Uchwyt nowego kontekstu renderowania lub warto NULL w przypadku
bdu.
warto Poniszy przykad przedstawia pocztek procedury obsugi komunikatu
WM_CREATE. Pobieramy w nim kontekst urzdzenia dla biecego okna,
wybieramy format pikseli, a nastpnie tworzymy kontekst renderowania i
czynimy go biecym.
case WM_CREATE:
// Przechowanie kontekstu urzdzenia
hDC = GetDC(hWnd);

// Wybranie formatu pikseli


SetDCPixelFormat(hDC);
// Utworzenie kontekstu renderowania
// i uczynienie go biecym
hRC = wglCreateContext( h D C ) ;
wglMakeCurrent(hDC, hRC);
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 125

Patrz take wglDeleteContext, wglGetCurrentContext, wglMakeCurrent

wglDeleteContext
Przeznaczenie Plik Usuwa niepotrzebny ju kontekst renderowania.
nagwkowy <wingdi.h>
Skadnia Opis BOOL wglDeleteContext(HGLRC hglrc);
Usuwa kontekst renderowania OpenGL. Zwalniana jest pami i zasoby
Parametry zajmowane przez ten kontekst.
hglrc Zwracana
warto HGLRC: Uchwyt kontekstu renderowania, ktry ma zosta usunity.
TRUE, jeli kontekst renderowania zosta usunity, lub FALSE, jeli wystpi
bd. Bd wystpuje na przykad wtedy, gdy w jednym wtku prbujemy
Przykad usun biecy kontekst renderowania innego wtku.
Poniszy przykad przedstawia pocztek procedury obsugi komunikatu
WM_DESTROY. Zakadajc, e kontekst renderowania zosta utworzony w
momencie tworzenia okna, moemy w tym miejscu usun ten kontekst.
Zanim usuniesz kontekst, musisz uczyni go niebiecym.
case WM_DESTROY:
// Odoenie biecego kontekstu renderowania // i
usunicie go wglMakeCurrent( h D C , NULL);
wglDeleteContext(hRC);

// Poinformowanie aplikacji o zakoczeniu dziaania


PostOuitMessage( 0 ) ; break;

Patrz take wglCreateContext, wglGetCurrentContext, wglMakeCurrent

wglGetCurrentContext
Przeznaczenie Plik Zwraca uchwyt biecego kontekstu renderowania nalecego do wtku.
nagwkowy <wingdi.h>
Skadnia Opis HGLRC wglGetCurrentContext(void);
Kady wtek aplikacji moe mie wasny biecy kontekst renderowania. Ta
funkcja moe zosta uyta do sprawdzenia, ktry kontekst renderowania jest
Zwracana warto kontekstem biecym dla wtku.
Jeli wtek posiada biecy kontekst renderowania, funkcja zwraca uchwyt
tego kontekstu. W przeciwnym wypadku zwraca warto NULL.
126 Cz l Wprowadzenie do OpenGL

Przykad Zajrzyj do przykadowego programu GLTHREAD na pytce CD-ROM, w


folderze tego rozdziau.
Patrz take wglCreateContext, wglDeleteContext, wglGetCurrentDC,
wglMakeCurrent

wglGetCurrentDC
Przeznaczenie Zwraca uchwyt kontekstu urzdzenia powizanego z biecym
kontekstem renderowania OpenGL.
Plik nagwkowy <wingdi.h>
Skadnia HGLRC wglGetCurrentDC(void);
Opis Ta funkcja jest uywana do pobrania kontekstu uchwytu urzdzenia okna, z
Zwracana warto ktrym powizany jest biecy kontekst renderowania OpenGL. Zwykle
Przykad stosuje si j w celu poczenia rysunku OpenGL z rysunkiem tworzonym
Patrz take przy pomocy GDI.
Jeli wtek posiada biecy kontekst renderowania, funkcja zwraca uchwyt
kontekstu urzdzenia powizanego z tym kontekstem renderowania. W
przeciwnym wypadku zwraca warto NULL.
Zajrzyj do przykadowego programu GLTHREAD na pytce CD-ROM, w
folderze tego rozdziau.
wglGetCurrentContext

wglGetProcAddress
Przeznaczenie Zwraca adres funkcji rozszerzenia OpenGL, ktrej mona uy w danym
kontekcie renderowania.
Plik nagwkowy <wingdi.h>
Skadnia PROC wglGetProcAddress(LPCSTR IpszProc);
Opis Funkcje rozszerze to funkcje, ktre albo nie stanowijeszcze standardu
OpenGL, albo zostay wprowadzone do danej implementacji OpenGL, zwykle
w celu uzupenienia tej biblioteki o elementy specyficzne dla danej platformy.
Wiele rozszerze jest obsugiwanych w wicej ni jednej implementacji. Aby
uy tych funkcji, musisz wywoa funkcj wglGetProcAddress podajc
dokadn nazw funkcji rozszerzenia. W ten sposb moesz take sprawdzi
obecno danego rozszerzenia. Otrzymany adres funkcji moe by rny dla
rnych formatw pikseli, wic nie przechowuj go i nie prbuj uywa z
rnymi kontekstami renderowania, chyba e bdziesz pewien, i ich formaty
pikseli s identyczne. Moesz wywoa funkcj glString(GL_EXTENSION) w
celu otrzymania oddzielonego spacjami acucha zawierajcego wszelkie
dostpne rozszerzenia (szczegy znajdziesz w rozdziale 5).
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 127

Parametry
IpszProc LPCSTR: Nazwa funkcji rozszerzenia. Wielko liter i nazwa musz
dokadnie odpowiada wielkoci liter i nazwie funkcji rozszerzenia.
Zwracana warto Jeli funkcja rozszerzenia nie istnieje, zwracana jest warto NULL, w
przeciwnym wypadku zwracany jest adres funkcji rozszerzenia.
Przykad Poniszy przykad przedstawia sposb pobrania adresu specyficznej dla
Windows funkcji rozszerzenia glAddSwapHintRectWIN. To rozszerzenie
umoliwia przyspieszenie przerzucania buforw przez poinformowanie
OpenGL, e tylko okrelone regiony okna wymagaj odwieenia.
// Sprawdzenie, czy dane rozszerzenie jest obsugiwane
char *szBuffer;
szBuffer = (char*)glString(GL_EXTENSION);

// Jeli jest obsugiwane, pobierz adres funkcji


// i wywoaj j
if(strcmp(szBuffer,"GL_WIN_swap_hint") == 0)
{
PROC pSwapHint;
pSwapHint = wglGetProcAddress("glAddSwapHintRectWIN");

// Wywoaj t funkcje
pSwapHint(40.O f , 40.O f , 50.Of, 50.2 f ) ; )
else (
// Jeli nie jest obsugiwana, obsu to
// w inny sposb...

Patrz take glGetString

wglMakeCurrent
Przeznaczenie Biecy kontekst renderowania OpenGL czyni biecym dla danego
wtku i wie go z podanym kontekstem urzdzenia.
Plik <wingdi.h>
nagwkowy BOOL wglMakeCurrent(HDC hDC, HGLRC hglrc);
Skadnia Ta funkcja czyni podany kontekst renderowania biecym kontekstem
renderowania dla aktualnego wtku. Kontekst renderowania jest wizany ze
wskazanym kontekstem urzdzenia Windows. Kontekst urzdzenia nie musi
by kontekstem uytym w wywoaniu funkcji wglCreateContext przy
tworzeniu kontekstu renderowania, jednak jego format pikseli musi by
identyczny z formatem pikseli tamtego kontekstu urzdzenia, za oba
konteksty urzdze musz odnosi si do tego samego urzdzenia
fizycznego. Przed wybraniem nowego kontekstu renderowania, wszelkie
oczekujce w kolejce polecenia graficzne zostan zrzucone do poprzedniego
kontekstu renderowania. Gdy jako uchwyt kontekstu
128 Cz l * Wprowadzenie do OpenGL

renderowania zostanie podana warto NULL, aden kontekst nie bdzie


kontekstem biecym.
Parametry
hDC HDC: Uchwyt kontekstu urzdzenia, ktry ma zosta powizany z
nowym biecym kontekstem renderowania.
hglrc Zwracana HGLRC: Uchwyt kontekstu renderowania, ktry ma sta si biecym
kontekstem aktualnego wtku.
warto TRUE w przypadku powodzenia, a FALSE w przypadku bdu. Jeli
wystpi bd, biecy wtek nie bdzie mia biecego kontekstu
renderowania.
Przykad Patrz Spjrz na przykad przy opisie funkcji wglCreateContext.
take wglCreateContext, wglDeleteContext, wglGetCurrentContext,
wglGetCurrentDC

wglShareLists
Przeznaczenie Umoliwia kilku kontekstom korzystanie ze wsplnych list wywietlania.
Plik nagwkowy <wingdi.h>
Skadnia Opis BOOL wglShareLists(HGLRC hRCl, HGLRC hRC2);
Lista wywietlania to lista prekompilowanych" polece i funkcji OpenGL
(patrz rozdzia 10). Dla kadego kontekstu renderowania alokowana jest
pami na jego listy wywietlania. Gdy lista wywietlania zostanie
utworzona w ramach danego kontekstu renderowania, tylko ten kontekst ma
dostp do jej pamici. Ta funkcja umoliwia kilku kontekstom renderowania
dostp do wsplnej pamici list wywietlania. Jest to szczeglnie uyteczne
wtedy, gdy w kilku wtkach lub kontekstach renderowania korzysta si z
duych list wywietlania, gdy daje znaczne oszczdnoci pamici. Ze
wsplnej pamici list wywietlania moe korzysta dowolna liczba
kontekstw renderowania; pami nie zostanie zwolniona a do momentu
usunicia ostatniego kontekstu renderowania z niej korzystajcego. Podczas
uywania wsplnej pamici list wywietlania naley synchronizowa
tworzenie i wykorzystywania list wywietlania.
Parametry
hRCl HGLRC: Okrela kontekst renderowania, z ktrym bdzie dzielona
pami list wywietlania.
hRC2 HGLRC: Okrela kontekst renderowania, ktry bdzie dzieli pami list
wywietlania z kontekstem hRCl. A do momentu wywoania tej funkcji nie
naley tworzy adnych list wywietlania dla kontekstu hRC2.
Zwracana warto TRUE w przypadku powodzenia, a FALSE w przypadku bdu.
do Opendtozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 129

16
bdzie Przykad Zajrzyj do kartoteki symulacji czogu/robota (\TANK) na pytce CD-ROM,
Patrz take wewntrz foldera rozdziau 10. Ten program korzysta z kilku okien w celu
cym stworzenia jednoczenie kilku widokw tej samej sceny. Aby zaoszczdzi
pami, wszystkie konteksty renderowania tych okien korzystaj ze wsplnej
pamici list wywietlania.
gllsList, glNewList, glCallLists, glListBase, glDeleteLists, glEndList,
glGenLists

wglUseFontBitmaps
Przeznaczenie Tworzy zestaw list wywietlania bitmap dla aktualnie wybranej czcionki GDI.
<wingdi.h>
Plik nagwkowy
BOOL wglUseFontBitmaps(HDC hDC, DWORD dwFirst, DWORD
Skadnia dwCount, DWORD dwListBase);
Ta funkcja pobiera czcionk aktualnie wybran w kontekcie urzdzenia
Opis hDC i tworzy listy wywietlania bitmap dla dwCount znakw, poczynajc od
dwFirst. Listy wywietlania s tworzone w biecym kontekcie
renderowania i s identyfikowane przez numery rozpoczynajce si od
numeru dwListBase. Zwykle uywa si tej funkcji do rysowania tekstu w
podwjnie buforowanych scenach OpenGL, gdy Windows GDI nie dziaa w
trybie podwjnego buforowania. Ta funkcja jest uywana take do
nadawania etykietek obiektom OpenGL na ekranie.
HDC: Kontekst urzdzenia Windows, z ktrego pobierana jest definicja
Parametry czcionki. Uywana czcionka moe zosta zmieniona przez utworzenie
hDC nowej czcionki i wybranie jej w tym kontekcie urzdzenia.
DWORD: Warto ASCII pierwszego znaku czcionki, uywanej do
budowania list wywietlania.
dwFirst DWORD: Liczba tworzonych bitmap znakw, poczwszy od znaku
dwFirst.
dwCount DWORD: Warto bazowa identyfikatorw list wywietlania; zostanie
nadana licie wywietlania dla pierwszego znaku.
dwListBase TRUE jeli listy wywietlania mog zosta utworzone; FALSE w
przeciwnym wypadku.
Zwracana warto Poniszy kod demonstruje tworzenie zestawu list wywietlania dla
zestawu znakw ASCII. Ten zestaw list jest nastpnie uywany do
Przykad wypisania tekstu OpenGL" w biecej pozycji rastra.
//Utworzenie sylwetek znakw na podstawie czcionki //
wybran w kontekcie urzdzenia
130 Cz l * Wprowadzenie do OpenGL

wglUseFontBitmaps( h D C , // kontekst urzdzenia


O, // pierwszy znak 255, // liczba znakw
1000); // numer bazowy listy wywietlania

// Wyrysowanie napisu
glListBase(1000); glPushMatrix();
glCallLists ( 3 , GL_UNSIGNED__BYTE,
glPopMatrix(); "OpenGL") ,

Patrz take wglUseFontOutlines, gllsList, glNewList, glCallLists, glListBase,


glDeleteLists, glEndList, glGenLists

WglUseFontOutlines
Przeznaczenie Tworzy zestaw list wywietlania trjwymiarowych znakw dla aktualnie
wybranej czcionki GDI.
Plik nagwkowy <wingdi.h>
Skadnia BOOL wglUseFontOutlines(HDC hDC, DWORD dwFirst, DWORD
dwCount, DWORD dwListBase, FLOAT deviation, FLOAT extrusion, int
format, LPGLYPHMETRICSFLOAT Ipgmf);
Opis Ta funkcja pobiera czcionk TrueType aktualnie wybran w kontekcie
urzdzenia hDC i tworzy listy wywietlania trjwymiarowych sylwetek dla
dwCount znakw, poczynajc od znaku dwFirst. Listy wywietlania s
tworzone w biecym kontekcie renderowania i s identyfikowane przez
numery rozpoczynajce si od numeru dwListBase. Sylwetka moe by
tworzona z segmentw linii lub wieloktw; decyduje o tym parametr format.
Komrka znaku uywana dla czcionki ma szeroko i wysoko jednej
jednostki w poziomie i w pionie. Parametr extrusion wyznacza grubo
czcionki w ujemnym kierunku osi z. Parametr deviation, o wartoci O lub
wikszej, okrela odchylenie ukw od oryginalnych postaci znakw czcionki.
Ta funkcja dziaa wycznie z czcionkami typu TrueType. Dodatkowe dane
dotyczce znakw s przekazywane w tablicy /pgw/struktur
GLYPHMETRICSFLOAT.
Parametry
hDC HDC: Kontekst urzdzenia Windows, z ktrego pobierana jest definicja
czcionki.
dwFirst DWORD: Warto ASCII pierwszego znaku czcionki, uywanej do
budowania list wywietlania.
dwCoun DWORD: Liczba tworzonych znakw, poczwszy od znaku dwFirst.
Rozdzia 4. * OpenGL for Windows: OpenGL + Win32 = Wiggle 131

dwListBas DWORD: Warto bazowa identyfikatorw list wywietlania; zostanie


e nadana licie wywietlania dla pierwszego znaku.
FLOAT: Maksymalne odchylenie ukw znakw od ukw oryginalnych.
devaition FLOAT: Grubo czcionki; ronie w kierunku ujemnych wartoci osi z.
extrmion int: Okrela, czy znaki powinny by tworzone z segmentw linii czy
format wieloktw. Moe by jedn z poniszych wartoci:
Ipgmf WGL_FONT_LINES Znaki bd tworzone z segmentw linii.
WGL_FONT_POLYGONS Znaki bd tworzone z wieloktw.
LPGLYPHMETRICSFLOAT: Adres tablicy struktur, w ktrych znajd si
dane metryczne znakw. Kady element tablicy jest wypeniany danymi
odnoszcymi si do listy wywietlania danego znaku. Kada struktura jest
zdefiniowana nastpujco:
typedef struct _GLYPHMETRICSFLOAT { // gmf
FLOAT gmfBlackBoxX;
FLOAT gmfBlackBoxY;
POINTFLOAT gmfptGlyphOrigin;
FLOAT gmfCelllncK;
FLOAT gmfCelllncY;
} GLYPHMETRICSFLOAT;

Skadowe:
gmfBlackBoxX Szeroko najmniejszego prostokta cakowicie opisujcego znak.
gmfBlackBoxY Wysoko najmniejszego prostokta cakowicie opisujcego znak.
gmfptGfyphOrigi Wsprzdne x i y lewego grnego rogu prostokta cakowicie
opisujcego znak. Struktura POINTFLOAT jest zdefiniowana
n
nastpujco:
typedef struct _POINTFLOAT { // ptf
gmfCallIncX FLOAT x; // Wsprzdna pozioma punktu
FLOAT y; // Wsprzdna pionowa punktu }
POINTFLOAT;
gmfCalllncY
Odstp w poziomie od pocztku komrki biecego znaku do pocztku
komrki nastpnego znaku.
Zwracana warto
Odstp w pionie od pocztku komrki biecego znaku do pocztku
komrki nastpnego znaku.
Przykad
TRUE, jeli listy wywietlania mog zosta utworzone; FALSE w
przeciwnym wypadku.
Poniszy kod mona znale albo w przykadowym programie MFCGL w
rozdziale 21, albo w pliku glcode.c, w przykadowym programie OWLGL
w rozdziale 22. Te przykady ilustruj, jak czcionka zdefiniowana,
strukturze LOGFONT jest tworzona i wybierana w kontekcie urzdzenia,
a nastpnie jest uywana do utworzenia list wywietlania reprezentujcych
cay zestaw znakw ASCII tej czcionki.
hDC = (HDC)pData;
hFont = CreateFontlndirect(Slogfont);
132________________________________Cz l * Wprowadzenie do OpenGL

SelectObjectfhDC, hFont);
// Otworzenie list wywietlania dla znakw od O do 255,
// z gruboci 0 , 3 oraz domylnym odchyleniem.
// Numerowanie list wywietlania zaczyna si
// od 1000 (moe by dowolna liczba)
wglUseFontOutlines(hDC, O, 255, 1000, O . O f ,
0 . 3 f, WGL_FONT_POLYGONS, agmf);

DeleteObject(hFont);
Patrz take wglUseFontBitmaps, gllsList, glNewList, glCallLists, glListBase,
glDeleteLists, glEndList, glGenLists
Rozdzia 5.
Bdy i inne komunikaty
OpenGL
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Odczyta kod ostatniego bdu OpenGL * glGetError
+ Konwertowa kod bdu na tekstowy opis problemu * glErrorString
+ Odczyta numer wersji oraz informacji o twrcy OpenGL * glGetString, gluGetString
+ Poprawi wydajno z wykorzystaniem elementw * glHint
zalenych od implementacji

W kadym projekcie chcemy, aby tworzona aplikacja bya niezawodnym i dobrze dzia-
ajcym programem, poprawnie reagujcym na polecenia uytkownika i posiadajcym
pewn elastyczno. Nie s tu wyjtkiem take programy graficzne korzystajce z
OpenGL. Nie mamy zamiaru zmieni tego rozdziau w kurs inynierii oprogramowania i
kontroli jakoci, ale jeli chcesz, aby twoje programy dziaay sprawnie, musisz bra
pod uwag take bdy i nieoczekiwane sytuacje. OpenGL dostarcza dwch rnych
metod zapewnienia poprawnoci kodu.

Pierwszy z mechanizmw kontrolnych OpenGL dotyczy wykrywania bdw. Gdy wystpi


bd, musisz mie jaki sposb jego wychwycenia i wykrycia przyczyny. To jedyna
moliwo zapewnienia, e obraz Stacji Kosmicznej Freedom nie zamieni si w obraz
Stacji Kosmicznej Rozpuszczone Lody.

Drugi mechanizm OpenGL to proste rozwizanie powszechnie wystpujcego problemu -


czego, czemu od czasu do czasu winien jest kady programista, dobry i zy. Zamy, e
wiesz, i implementacja Microsoftu oglnej wersji biblioteki OpenGL umoliwia
rysowanie przy pomocy GDI w oknach z podwjnym buforowaniem, o ile tylko rysujesz w
przednim buforze. Nastpnie kupujesz jedn z najnowszych kart z akceleratorem 3D, a jej
producent dorzuca nowe sterowniki OpenGL. Co gorsza, przypumy, e
134 Cz l * Wprowadzenie do OpenGL

ktry z twoich klientw kupuje tak kart. Czy twj kod bdzie dalej dziaa? Czy te
zniszczy rysunek i wywietli psychodeliczn tcz? By moe masz powody, aby korzysta
z takich sztuczek optymalizacji; funkcja TextOut dziaa zdecydowanie szybciej ni funkcja
wglUseFontBitmaps. (Oczywicie, jeli masz tak super-hiper kart graficzn, TextOut
moe nie by ju najszybszym sposobem wywietlania napisw). Prostym sposobem
zabezpieczenia si przed tym rodzajem katastrof jest sprawdzenie wersji i producenta
biblioteki OpenGL. Jeli uywana implementacja to oglna implementacja Microsoftu,
moesz oszukiwa do woli; w przeciwnym razie lepiej pozosta przy udokumentowanych
metodach.

Podsumowujc, jeli chcesz skorzysta z moliwoci specyficznych dla wersji i producenta


biblioteki, powiniene sprawdza w programie, czy numer wersji i producent zgadzaj si z
t wersj biblioteki, dla ktrej tworzye program. Nieco pniej omwimy wskazwki
OpenGL, umoliwiajce poinstruowanie systemu graficznego aby powici uniwersalno
na rzecz szybkoci czy jakoci obrazu. Wanie taki jest zalecany sposb korzystania z
optymalizacji specyficznych dla producenta karty.

Gdy dobremu programowi


przydarzaj si ze przygody
Wewntrznie, OpenGL przechowuje zestaw szeciu znacznikw stanu bdw. Kady
znacznik reprezentuje odmienny rodzaj bdu. Za kadym razem, gdy wystpi bd,
ustawiany jest odpowiedni znacznik. Aby sprawdzi, czy ktry ze znacznikw jest
ustawiony, wywoaj funkcj glGetError:
GLenum glGetError(void);
Rysunek 5.1.
Okno dialogowe O
programie opisujce
biblioteki GL i
CU, a take
ostatnio wykryte
bdy
Rozdziaf 5. Bdy i inne komunikaty OpenGL__________________________135

Funkcja glGetError zwraca jedn z wartoci wymienionych w tabeli 5.1, zlokalizowanej w


sekcji podrcznika, przy opisie funkcji glGetError. Biblioteka GLU definiuje trzy
wasne bdy, ale te bdy s odwzorowywane dokadnie na dwa ju istniejce zna-
czniki. Jeli ustawiony jest wicej ni jeden z tych znacznikw, glGetError w dalszym
cigu zwraca tylko jedn warto. W momencie wywoania funkcji ta warto jest zero-
wana, za kolejne wywoanie funkcji zwraca warto kolejnego bdu lub sta GL_
NO_ERROR. Zwykle funkcja glGetError jest wic wywoywana w ptli, a do momentu
otrzymania wartoci GL_NO_ERROR.

Listing 5.1 stanowi fragment kodu z programu GLTELL, zawierajcy wanie tak ptl,
odczytujc kody kolejnych bdw. Zwr uwag, e opis bdu jest przekazywany
kontrolce w oknie dialogowym. Wynik dziaania programu GLTELL widzimy na
rysunku 5.1.

Listing 5.1. Przykad kodu odczytujcego wszystkie bdy______________________________

// Wywietlenie ostatnich komunikatw bdu i =


0; do {
glError = glGetError ();
SetDlgItemText( h D l g , IDC_ERRORl+i,gluErrorString(glError));
i++; } while(i < 6 && glError !=
GL_NO_ERROR) ;

Moesz take uy innej funkcji biblioteki GLU, gluErrorString, zwracajcej opis kodu
bdu:
const GLubyte* gluErrorString(GLenum errorCode);

Ta funkcja wymaga podania kodu bdu (otrzymanego od funkcji glGetError), za


zwraca statyczny acuch opisujcy bd. Na przykad, kod bdu GL_ INVALID_
ENUM zwraca acuch
nieprawidowe wyliczenie

Moesz by spokojny, e jeli bd zostanie spowodowany jakim poleceniem lub funkcj


OpenGL, to polecenie lub funkcja zostan zignorowane. By moe OpenGL nie wykona
wtedy tego, czego oczekujesz, ale w dalszym cigu bdzie dziaa. Jedynym wyjtkiem
jest bd GL_OUT_OF_MEMORY (lub GLU_OUT_OF_MEMORY, zreszt o tej samej
wartoci). Gdy wystpi ten bd, stan OpenGL jest niezdefiniowany - w rzeczywistoci
niezdefiniowany moe by stan twojego programu! W przypadku tego bdu najlepiej jest
posprzta, na ile to moliwe, i zakoczy dziaanie programu.

Kim jestem i co potrafi?


Jak wspomniano we wprowadzeniu do tej sekcji, istniej sytuacje, kiedy musisz wiedzie,
czy dane dziaanie jest dostpne w biecej implementacji. Jeli wiesz, e pro-
136________________________________Cz l * Wprowadzenie do OpenGL

gram dziaa z implementacj Microsoftu, za jej numer wersji jest taki sam jak numer
wersji biblioteki, z ktr testowae program, niczym niezwykym nie bdzie prba uycia
jakich sztuczek w celu poprawienia wydajnoci programu. Aby by pewnym, e
wykorzystywane moliwoci wystpuj w komputerze, w ktrym dziaa twj program,
musisz pozna sposb odpylania biblioteki OpenGL o nazw producenta i numer wersji
systemu graficznego. Zarwno biblioteka GL, jak i GLU potrafi zwrci swj numer
wersji oraz informacje o producencie.
W przypadku biblioteki GL moesz wywoa funkcj glGetString:
const GLubyte *glGetString(GLenum n a m e ) ;

Ta funkcja zwraca statyczny acuch opisujcy wskazany aspekt biblioteki GL. Dozwolone
parametry s podane przy opisie funkcji glGetString w sekcji podrcznika, cznie z
elementami biblioteki GL, do ktrych si odnosz.
Biblioteka GLU take posiada odpowiedni funkcj, gluGetString:
const GLubyte *gluGetString(GLenum n a m e ) ;

Ta funkcja zwraca statyczny acuch opisujcy wskazany aspekt biblioteki GLU. Do-
zwolone parametry s podane przy opisie funkcji gluGetString w sekcji podrcznika,
cznie z elementami biblioteki GLU, do ktrych si odnosz.
Listing 5.2 przedstawia fragment kodu z przykadowego programu GLTELL, zmodyfi-
kowanej wersji programu odbijajcego si kwadratu. Tym razem uzupenilimy program
o menu i okno dialogowe O programie. Okno O programie, pokazane na rysunku 5.1,
wywietla informacje o dostawcy i wersji obu bibliotek: GL oraz GLU. Dodatkowo
umiecilimy w kodzie bdn instrukcj, w celu utworzenia listy komunikatw bdw.

Listing 5.2. Przykad uycia funkcji glGetString i gluGetString_________________________

// glGetString demo
SetDlgItemText(hDlg,IDC_OPENGL_VENDOR,glGetString(GL_VENDOR));
SetDlgItemText(hDlg,IDC_OPENGL_RENDERER,glGetString(GL_RENDERER));
SetDlgItemText(hDlg, IDC_OPENGL_VERSION, glGetString(GL_VERSION));
SetDlgItemText(hDlg, IDC_OPENGL_EXTENSIONS, glGetString(GL_EXTENSIONS));

// gluGetString demo
SetDlgItemText(hDlg,IDC_GLU_VERSION,gluGetString(GLU_VERSION));
SetDlgItemText(hDlg,IDC_GLO_EXTENSIONS,gluGetString(GLU_EXTENSIONS));

Rozszerzenia OpenGL
Zwr szczegln uwag na znaczniki GL_EXTENSIONS oraz GLU_EXTENSIONS.
Niektrzy producenci (cznie z Microsoftem w ostatniej wersji OpenGL) oferuj roz-
szerzenia OpenGL umoliwiajce zastosowanie specyficznych optymalizacji lub pe-
wnych popularnych rozszerze, ktre jeszcze nie stay si czci standardu. Te
rozszerzenia mog znacznie poprawi wydajno twojej aplikacji. Jeli jednak korzystasz
z funkcji rozszerze, musisz sprawdzi, czy w systemie wystpuj rozszerzenia
Rozdzia 5. * Bdy i inne komunikaty OpenGL__________________________137

(uywajc GL_EXTENSIONS), a jeli nie s obecne, musisz zaimplementowa je w


jaki inny sposb.
Zwrcona lista rozszerze zawiera pozycje oddzielone spacjami. Musisz sam przetworzy
ten acuch w celu sprawdzenia obecnoci konkretnego rozszerzenia. Wicej informacji na
temat rozszerze OpenGL znajdziesz w opisie funkcji wglGetProcAddress w rozdziale 4
lub w dokumentacji swojej implementacji OpenGL. Rozszerzenia w implementacji
Microsoftu s omawiane i ilustrowane w dodatku A.

Udzielanie wskazwek za
pomoc funkcji glHint
Wspomnielimy o wykorzystywaniu znanych anomalii w bibliotekach OpenGL. Moesz
wykorzystywa take inne zachowanie specyficzne dla danego producenta. Moesz na
przykad renderowa obraz tak szybko, jak si da, w przypadku oglnej implementacji,
lecz przecza si do trybu sprztowego, jeli tylko karta na to pozwala. Nawet bez
korzystania z funkcji zalenych od producenta, moesz po prostu poleci bibliotece
OpenGL, aby pooya wikszy nacisk na szybko lub na jako obrazu, czyli na przykad
aby pomijajc pewne szczegy utworzya obraz bardzo szybko lub przeciwnie, aby
uwzgldnia wszystkie detale bez wzgldu na to, jak dugo rysunek miaby by
tworzony.
Funkcja glHint umoliwia wskazanie preferencji dotyczcych jakoci lub szybkoci dla
operacji rnych rodzajw. Funkcja jest zdefiniowana nastpujco:
void glHint(GLenum target, GLenum mod);

Parametr target umoliwia wskazanie rodzajw dziaania, ktre chcesz zmodyfikowa. Te


wartoci, wymienione przy opisie funkcji glHint w podrczniku, dotycz wskazwek dla mgy i
ustawie antyaliasingu. Parametr mod informuje bibliotek OpenGL, na czym bardziej
ci zaley - na krtszym czasie rysowania czy na adniejszym obrazie - lub e jest ci
wszystko jedno. Przykadem moe by rysowanie w maym oknie podgldu z mniejsz
dokadnoci w celu szybkiego otrzymania obrazu, przy pozostawieniu wyszej jakoci i
dokadnoci dla kocowego obrazu. Dozwolone wartoci parametru mod s wymienione
w opisie funkcji glHint w sekcji podrcznika.
W celu przeanalizowania tych ustawie dla rnych obrazw, zajrzyj do uzupeniajcego
przykadowego programu WINHINT na pytce CD-ROM, w folderze tego rozdziau.
Pamitaj, e nie wszystkie implementacje korzystaj z ustawie przekazanych w funkcji
glHint, akceptujc je bez zgaszania bdu. Oznacza to, e twoja wersja OpenGL moe
ignorowa pewne lub wszystkie wskazwki.
138 Cz l * Wprowadzenie do OpenGL

Podsumowanie
Nawet w tym niedoskonaym wiecie moemy przynajmniej wyapywa bdy i prbowa
jako im zaradzi. Moemy take odczytywa informacje o producencie i numerze wersji
biblioteki, dziki czemu mamy moliwo korzystania ze specyficznych rozszerze lub
wystrzegania si znanych bdw. W tym rozdziale dowiedziae si, jak zmaga si z
tym problemami. Wiesz ju, jak poinstruowa OpenGL, aby powicio jako obrazu na
rzecz szybkoci jego generowania, jednak efekt tych wskazwek take zaley od producenta i
szczegw implementacji biblioteki.

Podrcznik
gIGetError
Przeznaczenie Zwraca informacje o ostatnim bdzie.
Plik nagwkowy <gl.h>
Skadnia GLenum glGetError(void)
Opis OpenGL przechowuje pi znacznikw bdw, wymienionych w tabeli 5.1. Gdy wystpi
bd, odpowiedni znacznik bdu pozostaje ustawiony a do momentu wywoania funkcji
gIGetError. Jeli ustawionych zostanie kilka znacznikw bdw
jednoczenie, konieczne jest kilkakrotne wywoywanie funkcji gIGetError w
celu wyzerowana kolejnych znacznikw. Dobrym pomysem jest
wywoywanie tej funkcji w ptli, a do momentu otrzymania wartoci
GLJNO_ERROR. Jeli gIGetError bdzie wywoana pomidzy instrukcjami
glBegin i glEnd, zostanie ustawiony znacznik bdu
GL_INVALID_OPERATION.
Zwracana warto Jeden z kodw bdw z tabeli 5.1. We wszystkich przypadkach
z wyjtkiem GL_OUT_OF_MEMORY bdne polecenie jest ignorowane,
za stan zmiennych stanu OpenGL, buforw itd. nie zmienia si.
W przypadku bdu GL_OUT_OF_MEMORY, stan OpenGL jest
niezdefiniowany.
Przykad
Patrz przykad GLTELL z listingu 5.1 glErrorString
Patrz take

glGetlastError
Przeznaczenie Zwraca informacje o ostatnim bdzie.
Plik nagwkowy <gl.h>
Rozdzia 5. * Bdy i inne komunikaty OpenGL 139

Skadnia GLenum glGetError(void)


Opis OpenGL przechowuje sze znacznikw bdw, wymienionych w tabeli 5.1.
Gdy wystpi bd, odpowiedni znacznik bdu pozostaje ustawiony a do
momentu wywoania funkcji glGetError. Jeli ustawionych zostanie kilka
znacznikw bdw jednoczenie, konieczne jest kilkakrotne wywoywanie
funkcji glGetError w celu wyzerowania kolejnych znacznikw. Dobrym
pomysem jest wywoywanie tej funkcji w ptli, a do momentu otrzymania
wartoci GL_NO_ERROR. Jeli glGetError bdzie wywoana pomidzy
instrukcjami glBegin i glEnd, zostanie ustawiony znacznik bdu
GL_INVALID_OPERATION.
Zwracana warto Jeden z kodw bdw z tabeli 5.1. We wszystkich przypadkach
Przykad Patrz z wyjtkiem GL_OUT_OF_MEMORY bdne polecenie jest ignorowane,
za stan zmiennych stanu OpenGL, buforw itd. nie zmienia si.
take W przypadku bdu GL_OUT_OF_MEMORY, stan OpenGL jest
niezdefiniowany.
Patrz przykad GLTELL z listingu 5.1
glErrorString

Tabela 5.1.
Kody bdw zwracane przez funkcj glGetError

Warto Znaczenie

GL_N<D_ERROR Nie wystpi aden bd.


GLJNYALID ENUM Podano niewaciw warto argumentu typu wyliczeniowego.
GLU_INVALID_ENUM
GL_rNVALID_VALUE Argument liczbowy przekroczy dozwolony zakres.
GLU_INVALID_VALUE
GL_INVALID_OPERATION Prbowano wykona operacj niedozwolon w biecym stanie.
GL_STACK_OVERFLOW Prbowano wykona polecenie, ktre powoduje przepenienie stosu.
GL_STACK_UNDERFLOW Prbowano wykona polecenie, ktre powoduje niedopenienie stosu.
GL_OUT_OF_MEMORY GLU Brak pamici do wykonywania danej operacji.
OUT OF MEMORY

gIGetString
Przeznaczenie Zwraca acuch opisujcy wskazany aspekt implementacji OpenGL.
Plik nagwkowy <gl.h>
Skadnia const GLubyte *glGetString(GLenum name);
140 Cz l * Wprowadzenie do OpenGL

Opis Ta funkcja zwraca acuch opisujcy wskazany aspekt danej


implementacji OpenGL. acuch jest zdefiniowany statycznie, wic
zwracany adres nie moe by modyfikowany.

Parametry

name GLenum: Identyfikuje aspekt implementacji OpenGL, o ktrym chcemy


otrzyma informacj. Moe przyjmowa jedn z poniszych wartoci:
GL_VENDOR Zwraca nazw firmy, ktra stworzya dan implementacj.
GL_RENDERER Zwraca nazw renderera. Moe ona si zmienia
w zalenoci od konfiguracji sprztowej. Nazwa GDI Generic" okrela
programow emulacj OpenGL bez wsparcia ze strony sprztu.
GL_VERSION Zwraca numer wersji danej implementacji.
GL_EXTENSIONS Zwraca list obsugiwanych w tej wersji implementacji
rozszerze. Kada pozycja listy jest oddzielona spacj.
Zwracana warto acuch znakw opisujcy dany aspekt lub warto NULL w
przypadku uycia niewaciwego parametru.
Przykad Patrz Patrz przykad GLTELL z listingu 5.2
take gluGetString

glHint
Przeznaczenie Umoliwia programicie przekazanie wskazwek dotyczcych dziaania
biblioteki OpenGL.
Plik nagwkowy
Skadnia void glHint(GLenum target, GLenum mod);
Opis Pewne aspekty dziaania OpenGL mog si nieco rni w rnych
implementacjach. Ta funkcja umoliwia zasugerowanie bibliotece OpenGL,
aby powicia jako obrazu na rzecz szybkoci lub odwrotnie. Specyfikacja
OpenGL nie wymaga, aby funkcja glHint dawaa jaki efekt, wic moe by
ignorowana w rnych implementacjach.
Parametry
target GLenum: Okrela rodzaj dziaania, jakie ma by zmodyfikowane.
Parametr moe przyjmowa jedn z poniszych wartoci:
GL_FOG_HINT Wpywa na obliczenia zwizane z mg.
GL_LINE_SMOOTH_HINT Wpywa na rysowanie linii z
antyaliasingiem.
GL_PERSPECTIVE_CORRECTION_HINT Wpywa na jako koloru i
interpolacji tekstur.
Rozdzia 5. t Bdy i inne komunikaty OpenGL 141

GL_POINT_SMOOTH_HINT Wpywa na jako punktw rysowanych z


antyaliasingiem.
GL_POLYGON_SMOOTH_HINT Wpywa na jako wieloktw
rysowanych z antyaliasingiem.
mod GLenum: Okrela podany rodzaj dziaania. Parametr moe przyjmowa
jedn z poniszych wartoci:
Zwracana
warto GL_FASTEST da uycia najefektywniejszej i najszybszej metody.
GL_NICEST da uycia metody dajcej najlepszjako obrazu.
Przykad
GL_DONT_CARE Brak preferencji co do uywanej metody.
Brak
Poniszy kod zosta zaczerpnity z uzupeniajcego przykadu WINHINT na
pytce CD-ROM, z foldera tego rozdziau. Informuje bibliotek OpenGL,
aby rysowaa linie z antyaliasingiem tak szybko, jak to jest moliwe, nawet
kosztem jakoci obrazu.

gluErrorString
Przeznaczenie Zwraca acuch opisujcy dany kod bdu.
Plik <glu.h>
nagwkowy const GLubyte *gluErrorString(GLenum errorCode);
Skadnia Opis Ta funkcja zwraca acuch opisujcy wskazany kod bdu. acuch jest
zdefiniowany statycznie, wic zwracany adres nie moe by
Parametry modyfikowany. Zwracany acuch to acuch ANSI. Aby otrzyma acuch
errorCod ANSI lub UNICODE w zalenoci od rodowiska, uyj makra
glErrorStringWIN.
e

Zwracana GLenum: Kod bdu, ktrego opis chcemy uzyska. Moe by podana
dowolna warto z tabeli 5.1.
warto
acuch znakw opisujcy kod bdu.
Przykad Patrz
Patrz przykad GLTELL z listingu 5.2
take
gIGetError

gluGetString
Przeznaczenie Zwraca acuch zawierajcy dodatkowe informacje o bibliotece GLU.
Plik <glu.h>
nagwkowy const GLubyte *gluGetString(GLenum name);
142 Cz l * Wprowadzenie do OpenGL

Opis Ta funkcja zwraca acuch zawierajcy numer wersji lub informacje o


rozszerzeniach biblioteki GLU. acuch jest zdefiniowany statycznie, wic
zwracany adres nie moe by modyfikowany.
Parametry

name GLenum: Identyfikuje aspekt biblioteki GLU, o ktrym chcemy otrzyma


informacj. Moe przyjmowa jedn z poniszych wartoci:
GLU_VENDOR Zwraca nazw firmy, ktra stworzya dan
implementacj biblioteki GLU. Format tego acucha to:
<numer wersji><spacja>informacje o producencie>
GLU_EXTENSIONS Zwraca list rozszerze obsugiwanych w tej wersji
biblioteki GLU. Kada pozycja listy jest oddzielona spacj.
Zwracana warto acuch znakw opisujcy dany aspekt lub warto NULL w
przypadku uycia niewaciwego parametru.
Przykad Patrz Patrz przykad GLTELL z listingu 5.2
take glGetString
Uywanie OpenGL
Wyglda na to, e kady kurs programowania rozpoczyna si od tego samego gupiego przykadowego
programu, obliczajcego, ile litrw benzyny na sto kilometrw spali si jadc do okrelonego celu. Aby go
stworzy, trzeba nauczy si korzysta z terminala, potem edytora, kompilatora, linkera, pozna struktur
programu, a nastpnie skadni jzyka. Niestety, zanim zaczniemy chodzi, musimy nauczy si raczkowa i
OpenGL nie jest tu wyjtkiem.
W pierwszej czci ksiki poznalimy OpenGL, pewne zagadnienia trjwymiarowej grafiki, a take format
funkcji OpenGL. Nastpnie zaczlimy czy OpenGL z Windows API, budujc programy Windows rysujce
w oknach przy pomocy OpenGL. Nauczylimy si odczytywa kody bdw, interpretowa je oraz nie
korzysta z rozszerze, ktre nie s dostpne.
Teraz nadszed czas, aby od raczkowania przej do marszu na dwch nogach. W rozdziale 6 omwimy
prymitywy graficzne w OpenGL. Bdziesz uywa tych klockw tworzc wiksze i bardziej zoone
obiekty. Nastpnie dowiesz si, co mona zrobi z obiektem w trjwymiarowej przestrzeni: poznasz tran
slacje, obroty i inne przeksztacenia, cznie z przeksztaceniami ukadu wsprzdnych. Uzbrojony w te
informacje bdziesz mg przej do rozdziaw 8 i 9, w ktrych zajmiemy si kolorami, cieniowaniem
i innymi fotorealistycznymi efektami. Pozostae rozdziay dotycz zaawansowanych narzdzi manipulo
wania obiektami, technik onglowania obrazami i teksturami oraz kilku specjalnych trjwymiarowych
prymityww. ^^
Pamitaj, aby ledzi rozwj programu symulacji czotagpito^-llrego tworzenie rozpoczynamy ju od
najbliszego rozdziau. Ten specjalny przykadowy program nie jest opisywany w ksice i mona go znale
tylko na pytce CD-ROM, jednak jego kod rozwija si, w miar zdobywania wiadomoci z kolejnych rozdziaw.
Plik readme.txt opisuje kolejne etapy proc*M tworzena (Stogramu. Czy kto ma ju dosy odbijajcych i
kwadratw? Jejp^od razu przejdmy dalej!

ar
114________________________________Cz l 4 Wprowadzenie do OpenGL

// Zatwierdzenie odmalowanego obszaru


ValidateRect(hWnd,NULL);
}
break;

default: // Domylna obsuga wszystkich


// nieprzetwarzanych komunikatw return
(DefWindowProc(hwnd, message, wParam, IParam));

return ( O L ) ;

Jeli ledzie nasz wczeniejsz dyskusj, z pewnoci zrozumienie kodu w wersji dla
Windows nie sprawi ci problemu. Spjrzmy jednak na kilka miejsc, na ktre powiniene
zwrci szczegln uwag.

Skalowanie do okna
W naszym przykadzie z rozdziau trzeciego, opartym na bibliotece AUX, biblioteka AUX
wywoywaa zarejestrowan funkcj ChangeSize za kadym razem, gdy zmieniay si
wymiary okna. W naszym nowym przykadzie musimy w tym celu przechwy-tywa
komunikat WM_SIZE, wysyany przez Windows przy kadej zmianie wymiarw okna. W
procedurze obsugi tego komunikatu moemy sami wywoywa funkcj ChangeSize,
przekazujc LOWORD z parametru IParam, ktry zawiera now szeroko okna, oraz
HIWORD z IParam, zawierajc now wysoko okna.
// Zmieniaj si wymiary okna
case WM_SIZE:
// Wywoanie naszej funkcji modyfikujcej bry obcinania
/ / i widok
ChangeSize (LOWORD (IParam) , HIWORD (IParam) ) ;
break;

yknicia timera
Biblioteka AUX regularnie wywoywaa take nasz funkcj czasu wolnego, IdleFun-
ction. Ta funkcja bya wywoywana wtedy, gdy program nie mia nic lepszego do roboty (na
przykad nie musia odrysowywa zawartoci okna). Moemy atw.o zasymulowa to
dziaanie ustawiajc timer Windows dla naszego okna. Poniszy kod:
// Utworzenie timera odpalanego co milisekund
SetTimer(hWnd,101,1,NULL);

wywoywany w momencie tworzenia okna, uaktywnia timer Windows dla okna. W wyniku
tego, teoretycznie co milisekund okno OpenGL otrzyma komunikat WMJTIMER. W
praktyce komunikat bdzie wysyany tak czsto, jak czsto Windows bd w stanie go
wysa - w Windows 95 mniej wicej co 55 milisekund - i tylko wtedy, gdy w kolejce nie
bd oczekiwa inne komunikaty. (Wicej informacji na temat timera znajdziesz w
ksice Programming Windows 98 i NT, wydanej przez Wydawnictwo H-
Rozdzia 6.
Rysowanie
w trzech wymiarach:
linie, punkty i wielokty
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Rysowa punkty, linie i ksztaty * glBegin/glEnd/glVertex
* Rysowa ksztaty szkieletowe lub jednolite * glPolygonMode
* Ustala wielko rysowanych punktw * glPointSize
* Ustala grubo rysowanych linii * glLineWidth
* Ukrywa niewidoczne powierzchnie * glCullFace
* Ustala wzory linii przerywanych 4 glLineSample
4 Wypenia wielokty wzorem 4 glPolygonStipple

Jeli kiedykolwiek uczye si chemii (a nawet jeli si nie uczye), z pewnoci wiesz, e
wszystko dookoa skada si z atomw, za same atomy skadaj si jedynie z trzech
rzeczy: protonw, neutronw i elektronw. Wszystkie materiay i substancje, z ktrymi
kiedykolwiek miae kontakt - od kropel rosy po piasek na play - stanowi po prostu
rne uoenie tych trzech podstawowych klockw. Cho takie podejcie jest nieco
uproszczone z punktu widzenia kadego, kto skoczy trzeci czy czwart klas, przedstawia
jednak pewn generaln zasad: przy pomocy prostych elementw skadowych mona
tworzy bardzo zoone i pikne struktury.
Analogia jest oczywista. Obiekty i sceny tworzone w OpenGL take skadaj si z maych,
prostych ksztatw, uoonych i poczonych na rne i niepowtarzalne sposoby. W tym
rozdziale poznamy wanie te klocki, zwane prymitywami. Wszystkie prymity-
146_______________________________________Cz II Uywanie OpenGL

wy w OpenGL s jedno- lub dwuwymiarowymi obiektami, poczynajc od zwykych


punktw i linii, a koczc na skomplikowanych wieloktach. W tym rozdziale nauczysz si
wszystkiego, czego potrzeba, aby rysowa trjwymiarowe obiekty zoone z tych
prostszych ksztatw.

Rysowanie punktw
w przestrzeni trjwymiarowej
Uczc si cokolwiek rysowa w systemie komputerowym, zwykle zaczynamy od pi-kseli.
Piksel to najmniejszy element na monitorze komputera, ktry moe przyjmowa rne
kolory. Taka jest wanie grafika komputerowa w maksymalnym uproszczeniu:
narysowanie punktu w pewnym miejscu ekranu, z nadaniem mu okrelonego koloru.
Opierajc si na tej prostej koncepcji, uywajc ulubionego jzyka programowania, moesz
tworzy linie, wielokty, okrgi oraz wszelkie inne ksztaty i grafik. Moe nawet graficzny
interfejs uytkownika...

Jednak w przypadku OpenGL rysowanie na ekranie komputera przebiega zupenie inaczej.


Nie zajmujesz si wsprzdnymi fizycznymi i punktami na ekranie, ale raczej
wsprzdnymi w widocznym fragmencie przestrzeni trjwymiarowej. Do OpenGL
naley zamiana trjwymiarowych obiektw na dwuwymiarowy obraz wywietlany na
ekranie.
W tym i nastpnym rozdziale poznamy wikszo podstawowych zagadnie OpenGL i
innych pakietw grafiki trjwymiarowej. W nastpnym rozdziale zajmiemy si zaga-
dnieniami przeksztace przestrzeni trjwymiarowej na dwuwymiarowy obraz na ekranie
komputera oraz szczegami dotyczcymi manipulowania obiektami (obracaniem,
przesuwaniem i skalowaniem). Na razie zajmiemy si samym rysowaniem obiektw w
trjwymiarowym ukadzie wsprzdnych. By moe uznasz, e si nieco cofamy, ale jeli
najpierw dowiesz si jak rysowa obiekty, a dopiero potem jak nimi manipulowa,
materia w rozdziale sidmym stanie si ciekawszy i atwiejszy do opanowania. Gdy
porzdnie opanujesz prymitywy graficzne i przeksztacenia wsprzdnych, bdziesz
mg szybko opanowa kady jzyk lub bibliotek grafiki trjwymiarowej.

Przygotowanie trjwymiarowej osnowy


Rysunek 6. l przedstawia prost bry widzenia, ktrej bdziemy uywa w przykadach w
tym rozdziale. Obszar obejmowany przez t bry to przestrze kartezjaska rozcigajca
si od wartoci -100 do 100 we wszystkich trzech osiach, x, y i z. (Przestrze
kartezjaska zostaa omwiona w rozdziale 2). Potraktuj ten trjwymiarowy obszar jako
osnow, na ktrej bdzie opiera si dziaanie polece i funkcji OpenGL.
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokaty 147
i
t
/ +100 /
Rysunek 6.1.
Kartezjaska brya / /
widzenia o XlOO
wymiarach
200x200x200

- 0 / +100 l ]0

,
Kierunek
1 0

/ / inn /
/ +z /

Przygotowujemy t bry wywoaniem funkcji glOrtho(), podobnie jak to czynilimy w


poprzednich rozdziaach. Listing 6.1 przedstawia kod funkcji ChangeSize(), wywoywanej
w momencie zmiany rozmiaru okna (cznie z pocztkowym wymiarowaniem okna). Ten
kod nieco rni si od kodu, jaki poznalimy w poprzednich rozdziaach, gdy mona w
nim natrafi na kilka nieznanych funkcji (glMatrixMode, glLoadEntity). Powicimy im
wicej czasu w rozdziale 7, szczegowo wyjaniajc ich dziaanie i przeznaczenie.

Listing 6.1. Kod ustalajcy bry widzenia z rysunku 6. l ___

// Zmiana bryy widzenia i widoku.


// Wywoywane w momencie zmiany wymiaru okna
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.O f ;

// Zabezpieczenie przed dzieleniem przez O


i f ( h == 0) h = 1;
// Ustawienie widoku na wymiary okna
glYiewport( O , O, w, h ) ;

// Wyzerowanie stosu macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glLoadldentity();
// Ustanowienie bryy obcinania
// (lewa, prawa, dolna, grna, blisza, dalsza)
if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange,
^nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange,
^nRange);

// Wyzerowanie stosu macierzy widoku modelu


glMatrixMode(GL_MODELVIEW); glLoadldentity();
148 Cz II Uywanie OpenGL

Dlaczego zaczynamy od tego?


Gdy spojrzysz na kod rdowy w tym rozdziale, zauwaysz kilka
nowych wywoa wewntrz funkcji RenderScene(): glRotate(),
glPushMa-trix() i glPopMatrix(). Zostan one omwione w
rozdziale 7, lecz wprowadzamy je ju teraz. Robimy tak,
poniewa implementuj one kilka wanych elementw, ktre
chcemy wykorzysta tak szybko, jak tylko si da. Te funkcje
umoliwiaj rysowanie w przestrzeni 3D i pozwalaj na atw
wizualizacj rysunkw pod rnymi ktami. Wszystkie
przykady w tym rozdziale umoliwiaj obracanie scenek w
osiach x i y za pomoc klawiszy strzaek. Gdy spojrzysz na
trjwymiarowy rysunek prosto z gry, tj. wzdu osi z,
przekonasz si, e wyglda zupenie pasko. Jednak gdy nieco
obrcisz scenk, natychmiast ujrzysz gbi obiektw.
Wiele jeszcze musimy powiedzie o rysowaniu w
trjwymiarowej przestrzeni, a w tym rozdziale chcemy si
skupi tylko na tym. Dziki temu, e w kolejnych przykadach
zmienia si jedynie kod rysujcy, moesz ju teraz zacz
eksperymentowa z rysowaniem w trzech wymiarach osiga
interesujce rezultaty. Gdy ju to opanujesz, w nastpnym
rozdziale dowiesz si, jak manipulowa rysunkiem za pomoc
innych funkcji.

Trjwymiarowy punkt: wierzchoek


Aby narysowa punkt w trzech wymiarach, uywamy funkcji OpenGL glVertex - bez
wtpienia najczciej uywanej funkcji w OpenGL API. Jest to najmniejszy wsplny
dzielnik" wszystkich prymityww OpenGL: pojedynczy punkt w przestrzeni. Funkcja
glVertex moe przyjmowa od dwch do czterech parametrw dowolnego typu liczbowego,
od bajtw do liczb podwjnej precyzji, zgodnie z konwencj nazw omawian w
rozdziale 3.
Ponisza pojedyncza linia kodu nakazuje narysowanie punktu w naszym ukadzie
wsprzdnych, pooonego 50 jednostek wzdu osi x, 50 jednostek wzdu osi y i zero
jednostek wzdu osi z:
glVertex3f( 5 0 . O f , 50.O f , O . O f ) ;

Ten punkt jest przedstawiony na rysunku 6.2. Wybralimy reprezentacj wsprzdnych w


postaci liczb typu float, przy czym pozostaniemy take w pozostaej czci ksiki.
Podobnie, uywana przez nas forma funkcji glVertex() wymaga podania trzech parametrw,
okrelajcych wsprzdn x, y oraz z.
Dwie inne formy funkcji glVertex wymagaj podania dwch i czterech parametrw. Mo-
glibymy utworzy ten sam punkt, co na rysunku 6.2, wywoujc na przykad funkcj
glVertex2f(50.O f , 50.O f ) ;

Ta forma funkcji glVertex wymaga podania jedynie dwch parametrw, okrelajcych


wsprzdne x i y, przy zaoeniu, e wsprzdna z ma zawsze warto 0,0. Forma
Rozdzia 6. + Rysowanie w trzech wymiarach: linie, punkty i wielokty 149

funkcji glVertex wymagajca czterech parametrw, glVertex4f, uywa czwartej wartoci


wsprzdnej, w, uywanej w celu skalowania, Wicej na jej temat powiemy sobie w
rozdziale 7, ktrego wikszo powicimy przeksztaceniom wsprzdnych.

Rysunek 6.2.
Punkt (50, 50, 0)
okrelony funkcj
50 ' (50,50,0)
glVertex3f(50.0f,
SO.Of, O.Oj)
50

Narysujmy co!
Teraz wiemy ju, jak wskaza punkt w trjwymiarowej przestrzeni OpenGL. Co moemy
z nim zrobi i co moe zrobi z nim OpenGL? Czy wierzchoek jest punktem, ktry po
prostu powinien zosta narysowany? Czy jest to koniec odcinka lub wierzchoek szecianu?
Geometryczna definicja wierzchoka to nie tylko punkt w przestrzeni, ale raczej miejsce,
gdzie przecinaj si dwie linie lub krzywe. Na tym polegaj prymitywy.

Prymityw jest po prostu interpretacj zestawu lub listy wierzchokw tworzcych


ksztat rysowany na ekranie. W OpenGL wystpuje dziesi prymityww, od zwykych
punktw rysowanych w przestrzeni, po zamknite wielokty o dowolnej iloci krawdzi.
OpenGL rozpoczyna interpretacj listy wierzchokw tworzcych prymityw w momencie
napotkania instrukcji glBegin. Koniec interpretacji nastpuje w momencie napotkania
instrukcji glEnd. Jest to zgodne z intuicj, prawda?

Rysowanie punktw
Zacznijmy od pierwszego i najprostszego z prymityww: punktu. Spjrz na poniszy kod:
glBegin(GL_POINTS); // wybranie punktw jako
// prymitywu
glVertex3f (0 , 0f, 0,0f, 0 , 0 f ) ; // wskazanie punktu
glVertex3f (5 0 ,Of, 50,Of, 50,O f ) , // wskazanie innego punktu
glEnd() ; // koniec z rysowaniem punktw

Argument funkcji glBegin(), GL_POINTS, informuje OpenGL, e nastpujce po niej


wierzchoki maj zosta zinterpretowane jako punkty do narysowania. Na naszej licie
wystpuj dwa wierzchoki, czyli dwa punkty, ktre naley narysowa.

W tym momencie dochodzimy do wanej roli pary funkcji glBegin i glEnd: pomidzy tymi
wywoaniami moesz umieci dug list prymityww, jeli tylko nale do tego

L
150_______________________________________Cz II Uywanie OpenGL

samego typu. W ten sposb, w pojedynczej sekwencji glBegin/glEnd moesz zawrze


dowoln liczb prymityww.

Nastpny segment kodu jest bardzo rozrzutny i wykonuje si duo wolniej ni poprzedni
przykad:
glBegin(GL_POINTS); // wybranie punktu jako prymitywu
glVertex3f( 0 , 0 f , 0,0f, 0 , 0 f ) ;
glEnd();
glBegin(GL_POINTS); // wybranie punktu jako prymitywu
glVertex3f(50,O f , 50,O f , 50,O f ) ;
glEnd();

Wcicia w kodzie programu


Czy zwrcie uwag na wcicia uywane przy zapisie wywoa
funkcji glVertex()? Ta konwencja jest stosowana przez
wikszo programistw OpenGL, gdy znacznie uatwia
analiz kodu. Wcicia nie s wymagane, jednak uatwiaj
wyszukanie pocztkw i kocw list rysowanych prymityww.

Nasz pierwszy przykad


Kod przedstawiony na listingu 6.2 rysuje punkty w przestrzeni 3D. Uywa przy tym kilku
prostych wyrae trygonometrycznych w celu utworzenia spirali punktw biegncych w
gr osi z. Ten kod pochodzi z programu POINTS, zawartego na pytce CD-ROM w
folderze tego rozdziau. Wszystkie przykadowe programy korzystaj ze schematu, jaki
stworzylimy w rozdziaach 4 i 5. Zwr uwag na funkcj SetupRC(), w ktrej
ustawiamy kolor rysowania na zielony.

Listing 6.2. Kod rysunkowy tworzcy spiral punktw________________________________

// D e f i n i u j e sta o wartoci zblionej do PI


ttdefine GL_PI 3.1415f

// Ta funkcja odpowiada za i n i c j a l i z a c j kontekstu renderowania void


SetupRCO
// Czarne to
glClearColor( O . O f , O . O f , O . O f , l.Of );

// Kolor rysowania zielony


glColorSf( O . O f , l.Of, O . O f ) ; }
// Wywoywane w celu narysowania sceny
void RenderScene(void)
GLfloat x,y,z,angle; // Zmienne dla wsprzdnych i ktw

// Wyczyszczenie okna biecym kolorem ta


glClear(GL_COLOR_BUFFER_BIT);
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty____________151

// Zachowanie stanu macierzy i wykonanie obrotu


glPushMatrix();
glRotatef(xRot, l . O f , O . O f , O . O f ) ;
glRotatef(yRot, O . O f , l . O f , O . O f ) ;

// Wywoywane tylko raz dla wszystkich punktw


glBegin(GL_POINTS);

z = -50.Of;
for(angle = O . O f ; angle <= (2.Of*GL_PI)*3.Of; angle += O . l f )
{
x = 50.0f*sin(angle);
y = 50.Of*cos(angle);

// Okrelenie punktu i przesunicie si nieco w gr osi Z


glVertex3f( x , y, z ) ; z += 0 . 5 f; }

II Koniec rysowania punktw


glEnd();

// Odtworzenie transformacji
glPopMatrix();

// Zrzucenie polece graficznych

glFlushO ;

W tym \ w innych przykadach w tym rozdziale interesuje nas przede wszystkim kod
zawarty pomidzy wywoaniami glBegin i glEnd. Ten kod oblicza wsprzdne x i y dla
ktw od O do 360 dla trzech obrotw. (W programie wyraamy je w radianach, a nie w
stopniach; jeli nie znasz trygonometrii, musisz uwierzy na sowo. Jeli ci to
interesuje, zajrzyj do ramki Trygonometria radianw i stopni"). Za kadym razem, gdy
rysowany jest punkt, zwikszana jest nieco warto wsprzdnej z. Po uruchomieniu
programu wida jedynie zielony krg punktw, a to dla tego, e pocztkowo patrzymy w
d osi z. Aby lepiej widzie spiral, za pomoc klawiszy kursora obr scen dookoa osi x i
y. Ilustruje to rysunek 6.3.

Rysunek 6.3.
Efekt dziaania programu POINTS
152 Cz II Uywanie OpenGL

Nie wszystko od razu


Przypominamy, nie zajmujemy si teraz funkcjami, ktrych
jeszcze nie omawialimy (glPushMatrix, glPopMatrix ani
gIRotate). Te funkcje su do obracania obrazu, tak aby
lepiej widzia efekt trjwymiarowoci spirali rysowanej w
przestrzeni 3D. Szczegy przeksztace wsprzdnych
omwimy w rozdziale 7. Gdybymy nie uyli tych funkcji w tym
momencie, nie widziaby trzeciego wymiaru naszych
rysunkw i przykadowe programy nie byyby interesujce.
Take w pozostaych przykadach w tym rozdziale bdziemy
prezentowa jedynie kod zawarty pomidzy instrukcjami
gIBegin i glEnd.

Trygonometria radianw i stopni

x=sin(oc)
y=cos(ce)
Uy)

-> x

Rysunek w tej ramce przedstawia okrg narysowany na


paszczynie xy. Odcinek biegncy z pocztku ukadu
wsprzdnych (O, O) do dowolnego punktu okrgu tworzy kt a
z osi ox. Dla kadego kta a funkcje trygonometryczne cosinus
i sinus okrelaj wartoci wsprzdnych x i y punktu na
okrgu. Zwikszajc warto zmiennej reprezentujcej kt, tak
aby przesza przez cay okrg, moemy obliczy pooenie
punktw na caym obwodzie koa. Zwr uwag, e funkcje C
sin() i cos() wymagaj podania wartoci kta wyraonej w
radianach, a nie w stopniach. Peny kt odpowiada 2*PI
radianw, gdzie Pl to liczba niewymierna, wynoszca w
przyblieniu 3,1415 (poniewa to jest liczba niewymierna, po
przecinku wystpuje nieskoczona liczba cyfr).

Ustalanie rozmiaru punktu


Gdy rysujesz pojedynczy punkt, rozmiar tego punktu to domylnie jeden piksel. Moesz to
zmieni przy pomocy funkcji glPointSize:
void glPointSize(GLfloat s i z e ) ;
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokaty____________153

Funkcja gIPointSize wymaga pojedynczego parametru, okrelajcego przyblion re-


dnic (w pikselach) rysowanych punktw. Nie s dostpne wszystkie rednice punktw,
powiniene wic sprawdzi, ktre wartoci s obsugiwane. Uyj poniszego kodu, aby
sprawdzi zakres rozmiarw punktu oraz najmniejszy interwa pomidzy tymi war-
tociami:
GLfloat sizes[ 2 ] ; // Obsugiwany zakres wielkoci punktw GLfloat
step; // Obsugiwany przyrost wielkoci punktw

// Pobranie zakresu obsugiwanych wielkoci i przyrostu wielkoci


glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY,Sstep);

Tablica sizes bdzie zawieraa dwa elementy, okrelajce najmniejsz i najwiksz


warto argumentu funkcji gIPointSize. Dodatkowo, zmienna step bdzie zawieraa
najmniejsz dozwolon warto przyrostu wielkoci punktu. Specyfikacja OpenGL wymaga,
aby by obsugiwany przynajmniej jeden rozmiar punktu, 1,0. Implementacja OpenGL
Microsoftu obsuguje wielkoci punktw od 0,5 do 10,0 z przyrostem 0,125. Okrelenie
wartoci spoza zakresu nie bdzie interpretowane jako bd. Zamiast tego zostanie uyta
najmniejsza lub najwiksza obsugiwana warto, najbardziej zbliona do wartoci
podanej.

Zmienne stanu OpenGL


OpenGL posiada zmienne przechowujce wiele wewntrznych
stanw i ustawie. Ta kolekcja ustawie jest nazywana Maszyn
stanu OpenGL. Istnieje moliwo odczytywania i ustawiania
wartoci zmiennych stanu. Do wczania i wyczania opcji
su funkcje glEnable i glDisable, wartoci zmiennych mona
ustawia funkcj gISet, za odczytywa funkcj gIGet.
Peniejszy opis Maszyny stanu OpenGL znajdziesz w rozdziale
14.

Przyjrzyjmy si przykadowi korzystajcemu z tej nowej funkcji. Kod przedstawiony na


listingu 6.3 tworzy t sam spiral, co w pierwszym przykadzie, jednak tym razem ronie
rozmiar kadego kolejnego punktu, od najmniejszego do najwikszego dozwolonego
rozmiaru. Ten kod pochodzi z programu POINTSZ na pytce CD-ROM, z foldera tego
rozdziau. Wynik dziaania programu widzimy na rysunku 6.4.

Listing 6.3. Kod programu POINTSZ tworzcy spiral coraz wikszych punktw_______________

// Definiuje sta o wartoci zblionej do PI


#define GL_PI 3.1415f

// Wywoywane w celu narysowania sceny


void RenderScene(void>

GLfloat x , y , z,angle; // Zmienne dla wsprzdnych i ktw GLfloat


sizes[ 2 ] ; // Przechowuje obsugiwany zakres wielkoci
// punktw GLfloat step; // Przechowuje
obsugiwany przyrost wielkoci
// punktw GLfloat
curSize; // Stor current size
154 Cz II * Uywanie OpenGL

// Pobranie zakresu obsugiwanych wielkoci i przyrostu wielkoci


glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY,Sstep);

// Ustawienie pocztkowego rozmiaru punktw


curSize = sizes [ 0 ] ;

// Ustawienie pocztkowej zmiennej Z z =


-50.Of;

// Przejcie caego okrgu trzy razy


forfangle = O . O f ; angle <= (2.Of*3.1415f)*3.Of; angle += O . l f )
{
// Oblicza wartoci z i y na okrgu
x = 50.0f*sin(angle);
y = 50.Of*cos(angle);

// Okrelenie rozmiaru punktu przed wybraniem prymitywu


glPointSize(curSize);

// Rysowanie punktu
glBegin(GL_POINTS);
glVertex3f( x , y, z ) ;
glEnd();

// Zwikszenie wsprzdnej Z i wielkoci punktu z +=


0 . 5 f ; curSize += step;
Rysunek 6.4.
Wynik dziaania
programu POINTSZ

Ten przykad demonstruje kilka wanych rzeczy. Pocztkujcy powinni zwrci uwag, e
funkcja glPointSize musi by wywoywana na zewntrz pary glBegin/glEnd. Nie
wszystkie funkcje OpenGL mog by wywoywane wewntrz tej pary. Poniewa
glPointSize wpywa na wszystkie rysowane po jej wywoaniu punkty, samo rysowanie
Rozdzia 6. Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________155

punktw odbywa si dopiero wewntrz pary glBegin/glEnd. Kompletn list funkcji,


ktre mona wywoywa wewntrz tej pary, znajdziesz w sekcji podrcznika.

Najwaniejsz rzecz, jak z pewnoci dostrzege w dziaaniu programu, jest to, e


punkty o najwikszych rozmiarach s po prostu kwadratami. Jest to domylne dziaanie,
jednak niepodane w wielu aplikacjach. Poza tym zapewne zastanawiasz si, jak mona
zwikszy wielko punktu o wartoci mniejsze od 1. Jeli warto 1.0 reprezentuje jeden
piksel, jak narysowa mniej ni jeden piksel lub, powiedzmy, 2,5 piksela?

Wynika to z tego, e rozmiar podany w funkcji glPointSize nie jest dokadnym rozmiarem
punktu w pikselach, ale raczej przyblion rednic okrgu opisujcego wszystkie piksele
uyte do narysowania punktu. Moesz namwi OpenGL, aby rysowao okrge punkty, tj.
wypenione okrgi, wywoujc funkcj
glEnable(GL_POINT_SMOOTH);

Inne funkcje okrelaj sposb wygadzania punktw i linii, jednak naley to ju do sze-
rokiego tematu zwizanego z antyaliasingiem (rozdzia 16). Antyaliasing to technika
uywana do wygadzania zbkowanych krawdzi i zaokrglania wierzchokw. Wspo-
minamy o tym jedynie, aby mg sam poeksperymentowa i aby nabra apetytu na
dalsze rozdziay!

Rysowanie linii w trzech wymiarach


Uywany dotd przez nas prymityw, GL_POINTS, by bardzo prosty; dla kadego wska-
zanego wierzchoka rysowany by punkt. Nastpnym logicznym krokiem jest okrelenie
dwch wierzchokw i narysowanie pomidzy nimi odcinka. Wanie do tego suy nastpny
prymityw, GL_LINES. Poniszy krtki fragment kodu rysuje pojedynczy odcinek pomidzy
punktami (O, O, 0) a (50, 50, 50):
glBegin(GL_LINES);
glVertex3f( 0 . 0 , 0 . 0 , 0 . 0 ) ;
glVertex3f(50.0, 50.0,
5 0 . 0 ) ; glEnd();

Zwr uwag e do okrelenia pojedynczego odcinka wymagane s dwa wierzchoki. Dla


kadych dwch wierzchokw jest rysowany jeden odcinek. Jeli podamy nieparzyst ilo
wierzchokw, ostatni wierzchoek zostanie po prostu zignorowany. Listing 6.4, z
przykadowego programu LINES na pytce CD-ROM, rysuje bardziej zoony ksztat,
skadajcy si z odcinkw tworzcych promienie okrgu. Wynik dziaania tego programu
jest pokazany na rysunku 6.5.

Listing 6.4. Fragment kodu z programu LINES rysujcy seri odcinkw tworzcych promienie okrgu

// Wywoywane tylko raz dla wszystkich punktw


glBegin(GL_LINES);

z = O.Of;
f o r f a n g l e = O . O f ; angle <= GL PI*3.0f; angle += 0 . 5 f )
156____________________________________Cz II Uywanie OpenGL

// Grna poowa okrgu


x = 50.0f*sin(angle) ;
y = 50.0f*cos (angle) ;
glVertex3f ( x , y, z ) ; // pocztek odcinka

// Dolna poowa okrgu


x = 50.0f*sin(angle+3.1415f) ;
y = 50.0f*cos(angle+3.1415f) ;
glVertx3f ( x , y, z ) ; // koniec odcinka
// Koniec rysowania
glEndO ;

Rysunek 6.5.
Wynik dziaania
programu LINES

amane i amane zamknite


Nastpne dwa prymitywy OpenGL, take oparte na odcinkach, umoliwiaj podanie listy
wierzchokw, ktre zostan poczone odcinkami linii. Gdy zastosujesz prymityw
GL_LINE_STRIP, zostanie utworzona amana skadajca si z segmentw czcych
kolejne wierzchoki. Poniszy kod rysuje dwa segmenty amanej, biegncej przez trzy
wierzchoki w paszczynie xy. Wygld amanej zosta przedstawiony na rysunku 6.6.
glBegin(GL_LINES);
glVertex3f( 0 . 0 , 0 . 0 , 0 . 0 ) ; // V0
glVertex3f( 5 0 . 0 , 5 0 . 0 , 5 0 . 0 ) ; // VI
glVertex3f( 5 0 . 0 , 100.0, 0 . 0 ) ; // V2
glEnd();

Ostatni prymityw oparty na odcinkach to GL_LINE_LOOP. Ten prymityw jest podobny do


prymitywu GL_LINE_STRIP, z tym e po narysowaniu ostatniego segmentu amanej jest
rysowany dodatkowy segment, zamykajcy ca aman. Uywajc tego prymitywu
moemy atwo rysowa zamknite ksztaty. Rysunek 6.7 przedstawia aman zamknit
narysowan na podstawie tych samych wierzchokw co na rysunku 6.6.
Rozdziaf 6. Rysowanie w trzech wymiarach: linie, punkty i 157
wielokty

Rysunek 6.6.
Przykad prymitywu
GL_LINE_STR1P V2(50,100,
rozpitego na trzech
wierzchokach 0) V,
V(0,0,0)
Rysunek 6.7.
amana zamknita
rozpita na tych
samych
wierzchokach, co
amana z rysunku 6.6

-* x

Przyblianie krzywych odcinkami


Program POINTS, przedstawiony wczeniej na rysunku 6.3, pokazywa, jak rysowa punkty
wzdu zadanej krzywej. Moe kusi ci ch zbliania punktw do siebie (przez ustawienie
mniejszego przyrostu kta) w celu utworzenia gadkiej, jednolitej linii krzywej, zamiast serii
punktw jedynie j przybliajcych. To cakowicie poprawna operacja, jednak moe
zajmowa bardzo duo czasu w przypadku wikszych i bardziej skomplikowanych
krzywych, skadajcych si z tysicy punktw.
Lepszym sposobem przyblienia krzywej jest uycie prymitywu GL_LINE_STRIP, czcego
kolejne punkty. Gdy punkty zbliaj si do siebie, krzywa staje si gadsza, i to bez
koniecznoci okrelania jej wszystkich punktw. Listing 6.5 przedstawia kod z listingu 6.2,
w ktrym prymityw GL_LINES zastpiono prymitywem GL_LINE_ STRIPS. Wynik dziaania
tego nowego programu, LSTRIPS, zosta pokazany na rysunku 6.8. Jak wida, przyblienie
krzywej jest cakiem dobre. Przekonasz si, e ta technika jest stosowana powszechnie w
programach OpenGL.

Listing 6.S. Kod programu LSTRIPS, przybliajcy krzyw za pomoc amanej_________ __ __

// Wywoywane tylko raz dla wszystkich punktw


glBegin(GL LIN STRIP);

z = -50.O f ;
for(angle = O . O f ; angle <= (2. O f * 3 . 1415f)*3.Of; angle += O . l f )
158 Cz II Uywanie OpenGL

x = 50. Of *sin (angle) ;


y = 50 .Of*cos (angle) ;

// Okrelenie punktu i przesunicie si nieco w gr osi Z


glVertex3f ( x , y, z ) ; z += 0.5f;
// Koniec rysowania
glEnd ( ) ;

Rysunek 6.8.
Program LSTR1PS, 2
krzyw przyblion
za pomoc amanej

Ustalanie gruboci linii


Podobnie jak mona ustawi rne wielkoci punktw, mona rwnie ustawi rne
gruboci linii. Suy do tego funkcja glLineWidth:
void glLineWidth(GLfloat w i d t h ) ;

Funkcja glLineWidth otrzymuje pojedynczy parametr, okrelajcy przyblion grubo


rysowanych linii, w pikselach. Podobnie jak w przypadku wielkoci punktw, nie wszystkie
gruboci linii s obsugiwane, wic zawsze powiniene sprawdzi, jakie gruboci s
dostpne. Uyj poniszego kodu w celu odczytania zakresu gruboci linii oraz naj-
mniejszej wartoci przyrostu ich gruboci.
GLfloat s i z e s [ 2 ] ; // Zakres szerokoci linii
GLfloat step; // Przyrost szerokoci linii

// Pobranie dostpnych rozmiarw linii i najmniejszej wartoci //


przyrostu
glGetFloatv(GL_LINE_WIDTH_RANGE,sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY,Sstep);

Tablica sizes bdzie zawiera dwa elementy okrelajce najmniejsz i najwiksz do-
zwolon warto parametru funkcji glLine Width. Dodatkowo, zmienna step bdzie za-
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________159

wieraa najmniejsz dozwolon warto przyrostu gruboci linii. Specyfikacja OpenGL


wymaga, aby bya obsugiwana przynajmniej jedna grubo linii, 1,0. Implementacja
OpenGL Microsoftu obsuguje gruboci linii od 0,5 do 10,0 z przyrostem 0,125.
Okrelenie wartoci spoza zakresu nie bdzie interpretowane jako bd. Zamiast tego
zostanie uyta najmniejsza lub najwiksza obsugiwana warto, najbardziej zbliona do
wartoci podanej.

Listing 6.6 przedstawia kod wykorzystujcy funkcj glLineWidth. Fragment kodu pochodzi
z programu LINESW i rysuje dziesi odcinkw o rnych grubociach. Zaczyna od dou
okna, od punktu o wsprzdnej -90 w osi y i przechodzi w gr w krokach po 20
jednostek. Kady nastpny odcinek jest grubszy od poprzedniego o jeden piksel. Wynik
dziaania programu ilustruje rysunek 6.9.

Rysunek 6.9.
Wynik dziaania funkcji glLine Width z
programu LINESW

Listing 6.6. Rysowanie odcinkw o


rnych grubociach

II Wywoywane w celu
narysowania sceny
void
RenderScene( v o i d )
{
GLfloat y; // Zmienna dla zmieniajcej si wsprzdnej Y
GLfloat
fSizes[2];
// Zakres
szerokoci linii
GLfloat
fCurrSize; // Przechowuje biec szeroko

// Pobranie dostpnych rozmiarw linii // i


zapamitanie najmniejszej wartoci przyrostu
glGetFloatv(GL_LINE_WIDTH_RANGE,fSizes); fCurrSize =
fSizes[0];
// Przejcie w osi Y po 20 punktw forty =
-90.Of; y < 9 0 . Of; y += 20.Of) (
// Ustawienie szerokoci linii
glLineWidthffCurrSize);
160____________________________________Cz II Uywanie OpenGL

// Narysowanie linii
glBegin(GL_LINES);
glVertex2f(-80.O f , y);
glVertex2f(80.Of, y ) ;
glEnd();
// Zwikszenie szerokoci linii
fCurrSize += l . O f ; }

Zwr uwag, e tym razem do okrelenia wsprzdnych wierzchokw zamiast funkcji


glVertex3f() uylimy funkcji glVertex2f(). Jak wspomniano, jest to tylko wygoda, gdy
rysujemy w paszczynie xy, z wartoci ustawion na 0. Aby si przekona, e linie
wci s rysowane w trzech wymiarach, wciskajc klawisze strzaek sprbuj obrci scenk
dookoa. Zobaczysz, e odcinki s narysowane na tej samej paszczynie.

Linie przerywane
Oprcz zmieniania szerokoci linii moemy take rysowa linie kropkowane lub prze-
rywane. Aby rysowa takie linie, musisz najpierw wczy przerywanie, wywoujc
funkcj
glEnable(GL_LINE_ST1PPLE);

a nastpnie przy pomocy funkcji glLineStipple okreli dese uywany przy rysowaniu
linii:
void glLineStipple(GLint factor, GLushort pattern);

UWAGA:
Kada opcja wczana funkcj glEnable() moe by wyczona
funkcj glDisable().

Rysunek 6.10. Wzr = OXOOFF = 255


Wzr przerywania
zastosowany do k A [ ^
utworzenia segmentu
linii Binornie=
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

Wzr linii = l t l i l l l t l l l l l l l l l

linia =
Rozdzia 6. Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________161

Parametr pattern to 16-bitowa warto okrelajca wzr uywany podczas rysowania linii
przerywanych. Kady bit reprezentuje sekcj odcinka, ktra moe by narysowana lub nie.
Domylnie, kady bit odpowiada pojedynczemu pikselowi, lecz parametr factor suy jako
mnonik zwikszajcy szeroko wzoru. Na przykad ustawienie parametru factor na 5
powoduje, e kady bit we wzorze reprezentuje pi kolejnych pikseli linii, ktre albo
wszystkie s wczone, albo wyczone. Co wicej, bit O (najmniej znaczcy) jest uywany
jako pierwszy. Przykadowy wzr linii ilustruje rysunek 6.10.

Dlaczego bity s odczytywane od tyu?


Zastanawiasz si moe, laczego bity we wzorcu linii s
odczytywanie od najmniej znaczcego. Wewntrznie, OpenGL
duo szybciej przesuwa bity w lew stron, za kadym razem,
gdy chce pobra kolejny bit maski. W przypadku
wysokowydajnych aplikacji, konieczno wewntrznego
odwracania wzorca (atwiejszego do opanowania przez czo-
wieka) zajmowaaby zbyt duo cennego czasu procesora.

Listing 6.7 przedstawia przykad uycia wzorca linii, skadajcego si z serii naprze-
miennych zer i jedynek (0101010101010101). Ten program rysuje dziesi odcinkw, od
dou do gry okna. Kada linia korzysta z tego samego wzorca, 0x5555, jednak w
kadej nastpnej linii warto mnonika wzorca zwiksza si o 1. Efekt poszerzajcych si
wzorw wyranie wida na rysunku 6.11.

Rysunek
6.11.
Wynik dziaania
programu
LSTIPPLE

Listing 6.7. Kod z programu LSTIPPLE demonstrujcy efekt zastosowania rnych mnonikw wzorca linii

// Wywoywane w celu narysowania sceny


void RenderScene(void)
GLfloat y; // Zmienna wsprzdnej Y
GLint factor = 1; // Wspczynnik przerw
GLushort pattern = 0x5555; // Dese przerw
162 ___ _____ _____ ________Cz II Uywanie OpenGL

// Wczenie przerywania
glEnable(GL_LINE_STIPPLE);

// Przechodzenie w osi Y po 20 jednostek


forty = - 9 0 . O f ; y < 9 0 . O f ; y += 2 0 . O f )
{
// Wyzerowanie czynnika wypenienia i desenia
glLineStipple(factor,pattern);

// Rysowanie linii
glBegin(GL_LINES);
glVertex2f(-80.Of, y ) ;
glVertex2f(80.Of, y) ;
glEnd();

factor++;

Rysowanie trjktw w przestrzeni 3D


Wiesz ju, jak rysowa punkty i odcinki, a nawet jak przy uyciu prymitywu GL_LI-
NE_LOOP rysowa zamknite ksztaty. Za pomoc tych trzech prymityww moesz
tworzy dowolne ksztaty w trjwymiarowej przestrzeni. Moesz na przykad narysowa
sze kwadratw, ukadajc je tak, aby tworzyy szecian.

Z pewnoci zauwaye jednak, e ksztaty tworzone z uyciem tych prymityww nie s


wypenione adnym kolorem - przecie rysowane s tylko linie. Aby narysowa
jednolit powierzchni, potrzebujemy czego wicej ni punkty i odcinki; potrzebujemy
wieloktw. Wielokt to zamknity ksztat, ktry moe (ale nie musi) by wypeniony
aktualnie wybranym kolorem; wielokt stanowi podstaw tworzenia wszystkich jednolitych
obiektw w OpenGL.

Trjkt: twj pierwszy wielokt


Najprostszym istniejcym wieloktem jest trjkt, ktry, jak wiadomo, posiada trzy kra-
wdzie. Do rysowania trjktw suy prymityw GL_TRJANGLES; trjkty s tworzone
w oparciu o trzy wierzchoki. Poniszy kod rysuje dwa trjkty, oparte na trzech
wierzchokach kady, przedstawione na rysunku 6.12.
glBegin(GLJTRIANGLES);
glvertex2f( O . O f , O . O f ) ; // V0
glVertex2f( 2 5 . O f , 25. O f ) ; // VI
glVertex2f( 5 0 . O f , O . O f ) ; // V2
sowanie w trzech wymiarach: linie, punkty i wielokty 163

glVertex2f(-50.0f, O . O f ) ; // V3
glVertex2f(-75.O f , 50.O f ) ; //V4
. glVertex2f(-25.Of, O . O f ) ; // V5
glEnd () ;

12.
tfese
tmitywu ILE

! Zwr uwag, e trjkty


zostan wypenione
biecym kolorem
rysowania. Jeli w pewnym
momencie nie okrelisz
koloru rysowania, nie
bdziesz wiedzia, jaki
kolor zostanie uyty (nie ma domylnego koloru rysowania).

Wybr najszybciej rysowanych prymityww


Programista OpenGL najczciej wybiera wanie rysowanie
trjktw. Okazuje si, e przy odrobinie wysiku kady
wielokt da si zoy z jednego lub wikszej iloci
odpowiednio uoonych trjktw. Wikszo sprztowych
akceleratorw 3D zostaa zoptymalizowania do rysowania
trjktw, a wiele programw testujcych szybko grafiki
trjwymiarowej podaje wynik wanie jako ilo trjktw
rysowanych w cigu sekundy.

trunek
Wana waciwo kadego wieloktnego prymitywu zostaa zilustrowana na rysunku
6.12. Zwr uwag na kierunek strzaek przy liniach czcych wierzchoki trjkta.
Przy rysowaniu pierwszego trjkta, linie s rysowane od wierzchoka V0 do wie-
rzchoka VI, nastpnie do wierzchoka V2, a na koniec z powrotem do wierzchoka V0. Ta
cieka zostaa wyznaczona przez kolejno podawania wierzchokw i w tym przypadku, z
twojego punktu widzenia, jest zgodna z ruchem wskazwek zegara. Rwnie drugi trjkt
zosta utworzony w tym samym kierunku.

Poczenie pooenia wierzchokw z kolejnoci ich definiowania jest nazywane kie-


runkiem. W przypadku trjktw z rysunku 6.12 mwimy, e maj kierunek zgodny z
ruchem wskazwek zegara (ang. clockwise winding, CW), poniewa ich wierzchoki s
uoone wanie w takiej kolejnoci. Gdybymy w trjkcie z lewej strony zamienili
miejscami wierzchoki V4 i V5, otrzymalibymy trjkt o kierunku przeciwnym do ruchu
wskazwek zegara (ang. counterclockwise winding, CCW), tak jak pokazano na
rysunku 6.13.
164 Cz II Uywanie OpenGL

Rysunek 6.13.
Dwa trjkty o
rnych
kierunkach

Trjkqt o kierunku przeciwnym do ruchu Trjkt o kierunku zgodnym z ruchem


wskazwek zegara (Przednia strona) wskazwek zegara (Tylna strona)

OpenGL domylnie zakada, e wielokty o kierunku przeciwnym do ruchu wskazwek


zegara s skierowane przodem do patrzcego. Oznacza to, e trjkt po lewej stronie
rysunku 6.13 pokazuje nam swoj przedni stron, za w przypadku trjkta z prawej
strony widzimy jego tyln stron.

Jakie to ma znaczenie? Jak si wkrtce przekonasz, czsto zdarza si, e przedniej i tylnej
stronie trjkta chcemy nada rne charakterystyki. Mona na przykad cakowicie ukry
ty wielokta lub te nada mu inny kolor i waciwoci odbijania wiata (rozdzia 9).
Bardzo wane jest wic zachowanie spjnych kierunkw wieloktw w scenie, poprzez
uycie wieloktw skierowanych przodem do tworzenia zewntrznych powierzchni
jednolitych obiektw. W nastpnych sekcjach, powiconych jednolitym obiektom,
zademonstrujemy to zagadnienie uywajc bardziej zoonych modeli.

Jeli chcesz zmieni domylne dziaanie OpenGL, moesz wywoa funkcj


glFrontFace(GL_CW);

Parametr GL_CW instruuje OpenGL, aby za odwrcone przodem byy uwaane trjkty o
kierunku zgodnym z ruchem wskazwek zegara. Aby powrci do kierunku przeciwnego do
ruchu wskazwek zegara dla trjktw widzianych z przodu, uyj tej funkcji z parametrem
GL_CCW.

Paski trjktw
W przypadku wielu ksztatw i powierzchni zdarzy ci si rysowa kilka poczonych
trjktw. Uywajc prymitywu GL_TRIANGLE_STRIP, moesz zaoszczdzi mnstwo czasu
przy rysowaniu paskw trjktw. Rysunek 6.14 przedstawia kolejno tworzenia paska
trjktw skadajcego si z trzech trjktw rozpitych na piciu wierzchokach V0 i V4.
Jak wida, wierzchoki nie s przetwarzane w tej samej kolejnoci, w jakiej s podawane.
Powodem takiego dziaania jest konieczno zachowania kierunku (przeciwnego do ruchu
wskazwek zegara) kadego trjkta.
Rozdzia 6. + Rysowanie w trzech wymiarach: linie, punkty i wielokty 165

Rysunek 6.14.
Przebieg tworzenia
paska trjktw
GL TRIANGLE
STRIP

(Na marginesie, przy omawianiu dalszych wieloktnych prymityww nie bdziemy ju


przedstawia kodu demonstrujcego okrelanie wierzchokw po instrukcji gIBegin. Z
pewnoci wiesz ju, o co w tym chodzi. Pniej, gdy zajmiemy si rzeczywistym
przykadowym programem, powrcimy do przykadw).

Za korzystaniem z paska trjktw zamiast okrelania kadego trjkta z osobna prze-


mawiaj dwa argumenty. Po pierwsze, po podaniu trzech pierwszych wierzchokw, dla
kadego nastpnego trjkta musimy poda tylko jeden wierzchoek. Gdy do narysowania
jest wiele trjktw, oszczdzamy dziki temu wiele czasu i pamici. Druga korzy wynika
z tego, e, jak wspomniano wczeniej, przy komponowaniu obiektw lub powierzchni
dobrze jest korzysta wanie z trjktw, a nie z innych prymityww.

Inna korzy, pynca z reprezentowania duych paskich


powierzchni z kilku mniejszych trjktw, wystpuje w
momencie gdy scena zostaje owietlona rdem wiata.
Dziki uyciu kilku trjktw OpenGL moe lepiej symulowa
efekty owietlenia. Wicej na temat tej techniki powiemy sobie
w rozdziale 9.

Wachlarze trjktw
Rysunek 6.15.
Etapy tworzenia
trjktw w prymitywie
GL TRIANGLE FAN

Oprcz tworzenia paskw trjktw, moesz tworzy take wachlarze trjktw. Prymityw
GL_TRIANGLE_FAN suy do tworzenia grupy trjktw o jednym wsplnym punkcie.
Rysunek 6.15 przedstawia wachlarz trzech trjktw utworzony przez podanie czterech
dodatkowych wierzchokw. Pierwszy wierzchoek, V0, wyznacza wsplny punkt
wachlarza. Gdy pierwsze trzy wierzchoki zostan uyte do narysowania pierwszego
trjkta, kady nastpny trjkt jest budowany w oparciu o wierzchoek wsplny (V0),
nastpny wierzchoek oraz wierzchoek bezporednio go poprzedzajcy (Vn-l).
166____________________________________Cz II Uywanie OpenGL

Zwr uwag, e trjkty s tworzone w kierunku zgodnym z ruchem wskazwek zegara, a


nie w przeciwnym.

Budowanie jednolitych obiektw


Tworzenie jednolitego obiektu z trjktw (lub innych wieloktw) wymaga czego
wicej ni tylko skadania wierzchokw w trjwymiarowej przestrzeni. Przyjrzyjmy si
przykadowemu programowi TRIANGLE, w ktrym wykorzystano dwa wachlarze trjktw
w celu utworzenia stoka w widocznym obszarze przestrzeni. Pierwszy wachlarz tworzy
ksztat stoka, w ktrym pierwszy wierzchoek pokrywa si z wierzchokiem stoka, za
pozostae wierzchoki tworz okrg przesunity w d osi z. Drugi wachlarz formuje koo i
ley dokadnie w paszczynie xy, tworzc podstaw stoka.

Wynik dziaania programu TRIANGLE zosta pokazany na rysunku 6.16. W tym momencie
spogldamy dokadnie w d osi z i widzimy jedynie koo utworzone przez wachlarz
trjktw. Poszczeglne trjkty zrnicowano nadajc im na przemian kolory czerwony i
zielony.

Rysunek 6.16.
Pocztkowy wygld
programu
TRIANGLE

Kod funkcji SetupRC i RenderScene


zosta przedstawiony na listingu 6.8. (Nowe
zmienne i znaczniki zostan wyjanione za
chwil). Ten program demonstruje kilka
aspektw komponowania trjwymiarowych
obiektw. Zwr uwag na elementy menu
Efekty; bdziemy ich uywa do
wczania i wyczania pewnych
elementw rysunku 3D, dziki czemu
bdziemy mogli lepiej pozna pewne
zagadnienia zwizane z tworzeniem trjwymiarowych obiektw.

Listing 6.8. Fragmenty kodu z przykadowego programu TRIANGLE_____________________

// Ta f u n k c j a odpowiada za inicjowanie kontekstu renderowania void


SetupRC()
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________167

// Czarne to
glClearColor ( O . O f , O.Of, O.Of, l.Of );

// Kolor rysowania zielony


glColorSf ( O . O f , l.Of,
O.Of);
// Ustawienie trybu cieniowania na paski
glShadeModel (GL_FLAT) ;
// Wielokty o kolejnoci krawdzi zgodnej z ruchem wskazwek //
zegara s widoczne od frontu. Odwracamy t o , // gdy korzystamy z
wachlarza trjktw glFrontFace (GL_CW) ;

// Wywoywane w celu narysowania sceny


void RenderScene (void)
{
GLfloat x,y,angle; // Zmienne dla wsprzdnych i ktw
int iPivot = 1; // Uywane do uzyskania przemiennych kolorw
// Wyczyszczenie okna i bufora gbokoci
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;

// Wczenie usuwania niewidocznych trjktw, //


jeli znacznik jest ustawiony if ( b C u l l )
glEnable (GL_CULL_FACE) ;
else
glDisable (GL_CULL_FACE) ;

// Wczenie bufora gbokoci, jeli znacznik jest ustawiony if


(bDepth)
glEnable (GL_DEPTH_TEST) ;
else
glDisable (GL_DEPTH_TEST) ;
// Rysowanie tylko siatki wielokta, //
jeli znacznik jest ustawiony if
(bOutline)
glPolygonMode (GL_BACK, GL_LINE) ;
else
glPolygonMode (GL_BACK, GL_FILL) ;

// Zachowanie stanu macierzy i wykonanie obrotu


glPushMatrix();
glRotatef(xRot, l . O f , O . O f , O . O f ) ;
glRotatef(yRot, O . O f , l.Of, O . O f ) ;

// Pocztek wachlarza trjktw


glBegin(GL_TRIANGLE_FAN);
// Czubek stoka stanowi wsplny wierzchoek wachlarza; jest //
przesunity w celu otrzymania stoka, a nie koa glVertex3f { O . O f ,
O.Of, 75.O f ) ;
168____________________________________Cz II Uywanie OpenGL

// Przejcie przez okrg i wyznaczenie parzystych trjktw


wachlarza for(angle = O . O f ; angle < (2.Of*GL_PI); angle +=
(GL_PI/8.Of))
// Obliczenie pozycji x i y nastpnego wierzchoka x
= 50.0f*sin(angle); y = 50.Of*cos(angle);
// Zmiana koloru z czerwonego na zielony
if((iPivot %2) == 0)
glColorSf( O . O f , l . O f , O . O f ) ;
else
glColorSf( l . O f , O . O f , O . O f ) ;
// Zmiana koloru dla nastpnego trjkta
iPivot++;

// Okrelenie nastpnego wierzchoka wachlarza trjktw


glVertex2f( x , y ) ;

// Koniec rysowania stoka


glEnd() ;

// Rozpoczcie nowego wachlarza w celu zakrycia podstawy


glBegin(GL_TRIANGLE_FAN);

// rodek wachlarza w rodku ukadu


glVertex2f( O . O f , O . O f ) ;
for(angle = O . O f ; angle < (2.Of*GL_PI); angle += (GL_PI/8.Of))
// Obliczenie pozycji x i y nastpnego wierzchoka x =
50.0f*sin(angle); y = 50.Of*cos(angle);
// Zmiana koloru z czerwonego na zielony
if((iPivot %2) == 0)
glColorSf( O . O f , l.Of, O . O f ) ;
else
glColor3f( l . O f , O.Of, O . O f ) ;
// Zmiana koloru dla nastpnego trjkta
iPivot++;
// Okrelenie nastpnego wierzchoka wachlarza trjktw
glVertex2f( x , y) ;

// Koniec rysowania wachlarza podstawy


glEnd() ;

// Odtworzenie transformacji
glPopMatrix();
// Zrzucenie polece graficznych
glFlusht); }
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty ______ 169

Ustawianie kolorw wieloktw


Jak dotd, kolor rysowania ustawialimy tylko raz i rysowalimy jedynie pojedynczy
ksztat. Teraz, gdy mamy do czynienia z wiksz iloci wieloktw, rzeczy staj si
bardziej interesujce. Chcemy uy rnych kolorw, aby atwiej rozrnia poszczeglne
trjkty. Kolory s okrelane dla wierzchokw, a nie dla wieloktw. O tym, czy wielokt
bdzie posiada jednolity kolor (kolor okrelony dla ostatniego wierzchoka tworzcego
wielokt), czy te kolor zmieniajcy si pynnie od wierzchoka do wierzchoka, decyduje
model cieniowania wielokta. Linia
glShadeModel(GL_FLAT);

instruuje OpenGL, aby wypeniao wielokty jednolitym kolorem, zgodnym z kolorem


aktualnym w momencie podawania ostatniego wierzchoka wielokta. Wanie dziki
temu moemy atwo zmienia kolor trjkta z zielonego na czerwony, przed podaniem
nastpnego wierzchoka w wachlarzu. Z drugiej strony, linia
glShadeMode(GL_SMOOTH);

nakazywaaby zastosowanie pynnego przejcia pomidzy kolorami wierzchokw, poprzez


interpolacj kolorw porednich. Na temat kolorw i cieniowania porozmawiamy w
rozdziale 8.

Korzystanie z bufora gbokoci


Wciskajc jeden z klawiszy kursora obr stoek dookoa; nie wybieraj jeszcze adnej
pozycji z menu Efekty. Zauwaysz co dziwnego: stoek wydaje si odchyla w ty i w
przd po 180, za jego podstawa zawsze bdzie skierowana w twoj stron. Janiej
przedstawia to rysunek 6.17.

Rysunek 6.17. _ f _+180


Obracajcy si
stoek wydaje si
jedynie odchyla
w przd i w ty

Dzieje si tak, poniewa podstawa stoka jest rysowana ju po


narysowaniu jego cian. Oznacza to, e bez wzgldu na orientacj
stoka, jego podstawa jest rysowana na nim, co daje wraenie
odchylania si. Ten efekt nie ogranicza si jedynie do
rnych stron i czci obiektu. Jeli jest rysowanych kilka obiektw i jeden z nich jest
rysowany bliej ni drugi (z punktu widzenia obserwatora), drugi rysowany obiekt
zawsze przesania obiekt narysowany jako pierwszy.

Moesz usun ten problem dziki technice zwanej buforem gbokoci, a OpenGL posiada
specjalne funkcje, ktre zajm si tym za ciebie. Idea jest prosta: gdy jest rysowa-
170____________________________________Cz II Uywanie OpenGL

ny piksel przypisywana mu warto warto (zwana wartoci z) okrelajca odlego


punktu dla tego piksela od obserwatora. Pniej, gdy w tym samym miejscu ekranu ma
zosta narysowany kolejny piksel, warto z nowego piksela jest porwnywana z war-
toci z piksela ju narysowanego. Jeli warto z nowego piksela jest wiksza, oznacza to,
e jego punkt jest bliej obserwatora, wic stary piksel jest przesaniany przez nowy. Jeli
warto z nowego piksela jest mniejsza, to odpowiadajcy mu punkt musi znajdowa si
dalej od obserwatora i nie przysania starego piksela. Ten mechanizm jest
implementowany za pomoc wewntrznego bufora gbokoci, ktry szczegowo omwimy
w rozdziale 15.

Aby wczy testowanie gbokoci, po prostu wywoaj


glEnable(GL_DEPTH_TEST);

Na listingu 6.8 wczamy testowanie gbokoci w momencie gdy zmienna bDepth ma


warto True wyczamy, gdy ma warto False.
// Wczenie bufora gbokoci, jeli znacznik jest ustawiony
if(bDepth)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);

Zmienna bDepth jest ustawiana w momencie wybrania w menu Efekty polecenia Bufor
gbokoci. Naley pamita, e bufor gbokoci musi by wyzerowany za kadym razem
gdy przystpujemy do narysowania sceny. Bufor gbokoci jest podobny do bufora
koloru, z tym e zamiast koloru przechowuje informacje o odlegociach pikseli od
obserwatora. Dziki temu mona wyznaczy, czy dany piksel znajduje si bliej lub dalej ni
inny piksel.
// Wyczyszczenie okna i bufora gbokoci
glClar(GL_COLOR_BUFFER_BIT | GL_DEPTH__BUFFER_BIT) ;

Rysunek 6.18 przedstawia menu Efekty z wczonym buforem gbokoci. Oprcz tego
przedstawia stoek z podstaw poprawnie ukryt za ciankami. Jak wida, bufor gbokoci
jest praktycznie nieodzowny jeli chodzi o rysowanie jednolitych trjwymiarowych
obiektw.

Rysunek 6.18.
W tym pooeniu podstawajest poprawnie
zasonita przez cian, stoka
Rozdzia 6. Rysowanie w trzech wymiarach: linie, punkty i wielokty 171

Ukrywanie niewidocznych powierzchni


Widzimy, e jako rysunku ogromnie si poprawia, gdy nie s rysowane powierzchnie
zasonite przez inne powierzchnie. Jednak mimo to wydajno programu nie jest zbyt
wysoka, gdy warto z kadego rysowanego piksela musi by porwnana z wartoci z
poprzednio narysowanego piksela. Czasem jednak z gry wiadomo, e dana powierzchnia
nigdy nie zostanie narysowana, wic po co j a w ogle okrela? Na przykad po to, aby
nie rysowa tylnych cian powierzchni.

W naszym przykadzie stoek jest bry zamknit i nigdy nie widzimy jego wntrza.
OpenGL w rzeczywistoci (wewntrznie) rysuje tylne ciany z tyu stoka, a nastpnie
przednie strony wieloktw, skierowane w nasz stron. Nastpnie, przez porwnanie
wartoci w buforze gbokoci, eliminuje ciany stoka znajdujce si dalej. Rysunki
6.19a i 6.19b przedstawiaj stoek w pewnym pooeniu z wczonym (a) i wyczonym
(b) buforem gbokoci. Zwr uwag e czerwone i zielone trjkty zamieniaj si
miejscami w momencie wczenia i wyczenia bufora gbokoci. Bez bufora gbokoci,
w dalszym cigu widzimy strony trjktw znajdujcych si dalej.

Rysunek
6.19a.
Z wczonym
buforem gbokoci

Rysunek
6.19b.
Bez wczonego
172____________________________________Cz II Uywanie OpenGL

Wczeniej w tym rozdziale wyjanialimy, jak OpenGL korzysta z kierunku wielokta w


celu wyznaczenia jego przedniej i tylnej strony oraz e wane jest, aby wielokty
tworzce powierzchni obiektw posiaday ten sam, spjny kierunek. Wanie ta spjno
zapewnia, e OpenGL renderuje tylko przd, tylko ty lub obie strony wieloktw. Poprzez
wyeliminowanie wieloktw skierowanych tyem, moemy znacznie zredukowa czas
renderowania sceny. Mimo korzystania z bufora gbokoci, OpenGL i tak wewntrznie
braby pod uwag takie wielokty, chyba e jawnie nakaemy mu, aby tego nie robi.

Eliminacja wieloktw skierowanych tyem jest nazywana usuwaniem niewidocznych


powierzchni. Usuwanie niewidocznych powierzchni jest wczane lub wyczane przy
pomocy poniszego fragmentu kodu z listingu 6.8:
// Wielokty o kolejnoci krawdzi zgodnej z ruchem wskazwek
// zegara
// s widoczne od frontu, odwracamy to gdy
// korzystamy z wachlarza trjktw
glFrontFace(GL_CW);

// Wczenie usuwania niewidocznych trjktw //


jeli znacznik jest ustawiony if(bCull)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);

Zwr uwag, e najpierw zmieniamy definicj wieloktw skierowanych przodem na


wielokty o kierunku zgodnym z ruchem wskazwek zegara (poniewa tak wanie s
uoone trjkty w wachlarzach).

Rysunek 6.20.
Podstawa stoka zostaa ukryta, gdy
przednia strona jej trjktw jest
skierowana do rodka bryy

Rysunek 6.20 demonstruje


efekt wycinania podstawy
stoka w momencie
wczenia usuwania
niewidocznych powierzchni.
Dzieje si tak, poniewa nie
przestrzegamy zasady
wymagajcej, aby wszystkie
wielokty na powierzchni
obiektu miay ten sam kie-
runek. Wachlarz trjktw tworzcy podstaw stoka skada si z trjktw o kierunku
zgodnym z ruchem wskazwek zegara, podobnie jak wachlarz tworzcy ciany stoka,
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty _____________ 173

jednak przednia strona wachlarza podstawy jest skierowana do wntrza stoka. Wyjania
to rysunek 6.21.

Rysunek 6.21. j. .
' ,, , . . Przednia strono
Sposb zoenia
stoka z dwch wachlarzy trjktw
Przednia strona
trjktw

Moglibymy rozwiza ten problem zmieniajc kierunek


przedniej strony trjktw funkcj
glFrontFace(GL_CCW);

wywoywan tu przed rysowaniem drugiego wachlarza trjktw. Jednak w tym przy-


kadzie chcemy, aby zobaczy usuwanie tylnych powierzchni w dziaaniu, a take
chcielibymy przygotowa ci do nastpnej demonstracji wyginania wieloktw.

Tryby wieloktw
Wielokty nie musz by wypenione biecym kolorem. Domylnie, wielokty s rysowane
jednolitym kolorem, moesz jednak zmieni to zachowanie nakazujc, by wielokty byy
rysowane jedynie jako sylwetki lub nawet jako punkty (s wtedy rysowane jedynie
wierzchoki). Funkcja glPolygonMode() umoliwia okrelenie, aby wielokty byy
renderowane jako wypenione, jako kontur lub jako punkty. Oprcz tego, tryb ren-
derowania moe by przypisany obu stronom wielokta lub tylko stronie wybranej. Po-
niszy kod z listingu 6.8 przedstawia ustawianie trybu wielokta na wypeniony lub
siatkowy, w zalenoci od stanu zmiennej logicznej bOutline:
// Rysowanie tylko siatki wielokta, jeli znacznik jest ustawiony
if(bOutline)
glPolygonMode(GL_BACK,6L_LINE); else
glPolygonMode(GL_BACK,GL_FILL);

Rysunek 6.22 pokazuje, e wszystkie wielokty skierowane tyem s rysowane jako siatka.
(Aby stworzy ten obrazek, musielimy wyczy usuwanie tylnych powierzchni, gdy w
przeciwnym razie zostayby usunite i nie byoby wida siatki). Zwr uwag, e teraz
podstawa stanowi siatk i nie jest wypeniona, dziki czemu moesz zajrze do wntrza
stoka, w ktrym wewntrzne ciany take s rysowane jako siatkowe trjkty.
174____________________________ Cz II Uywanie
ppenGL

Rysunek 6.22.
Uycie funkcji gIPolygonMode() w celu
narysowania jednej strony trjktw jako
siatki

Inne prymitywy
Trjkty s najczciej
wybieranymi prymitywami,
gdy wikszo kart
graficznych
zoptymalizowanych dla
OpenGL najszybciej rysuje
wanie trjkty; jednak nie s jedynymi dostpnymi obiektami. Niektre karty potrafi
rysowa sprztowo take inne ksztaty, za w programie czsto atwiej jest uy oglnych
prymityww graficznych. Do pozostaych prymityww OpenGL nale czworokty
oraz paski czworoktw, a take wielokty o dowolnej liczbie krawdzi. Jeli wiesz, e
twj program bdzie dziaa w komputerze z kart, ktra obsuguje takie wielokty
sprztowo, moesz pokusi si o zastosowanie ich w celu osignicia lepszej wydajnoci.
Czworokty
Nastpnym ksztatem po trjkcie jest czworokt. Do rysowania czworoktw suy pry-
mityw GL_QUADS. Na rysunku 6.23 widzimy, e czworokt jest rozpity na czterech
wierzchokach. Zwr uwag, e ten czworokt ma kierunek zgodny z ruchem wskazwek
zegara.

Rysunek 6.23.
Przykad prymitywu
GL_QUAD
Rozdzia 6. Rysowanie w trzech wymiarach: linie, punkty i wielokty 175

Paski czworoktw
Tak jak w przypadku paskw trjktw, moesz utworzy take paski czworoktw;
suy do tego prymityw GL_QUAD_STRIP. Rysunek 6.24 przedstawia przebieg po-
wstawania paska czworoktw skadajcego si z dwch czworoktw rozpitych na
szeciu wierzchokach. Poszczeglne czworokty, podobnie jak czworokt prymitywu
GL_QUADS, maj kierunek zgodny z ruchem wskazwek zegara.

Rysunek 6.24. V, 2 V,
Przebieg
powstawania paska
czworoktw
GL_QUAD_STRIP

V, V

Oglne wielokty
Ostatnim prymitywem OpenGL jest GL_POLYGON, ktry moe zosta uyty do nary-
sowania wielokta o dowolnej liczbie krawdzi. Rysunek 6.25 przedstawia wielokt
skadajcy si z piciu wierzchokw. Wielokty tworzone za pomoc GL_POLYGON maj
kierunek zgodny z ruchem wskazwek zegara.
Rysunek
6.25.
Proces tworzenia
wielokta
GL POLYGON

A co z prostoktami?
Wszystkie dziesi prymityww OpenGL jest uywanych
pomidzy wywoaniami gIBegin/glEnd do rysowania oglnych
ksztatw. Jeden z ksztatw jest tak powszechny, e zamiast
prymitywu posiada wasn funkcj; tym ksztatem jest
prostokt. By to pierwszy ksztat, ktry narysowalimy w
rozdziale 3. Funkcja glRect() zapewnia atwy i wygodny
sposb rysowania prostoktw, bez koniecznoci odwoywania
si do prymitywu GL_QUAD.

Wypenianie wieloktw
Istniej dwie metody wypeniania jednolitych wieloktw. Bardziej uniwersaln metod jest
mapowanie tekstur, w ktrym bitmapa jest nakadana na powierzchni wielokta
(omawiamy to w rozdziale 11). Innym sposobem jest okrelenie desenia, tak jak to czy-
176 Cz II * Uywanie OpenGL

nilimy w przypadku linii. Wzr desenia dla wielokta nie jest niczym innym jak mo-
nochromatyczn bitmap o rozmiarach 32x32, uywan do wypenienia wielokta.

Aby wczy wypenianie wielokta, wywoaj funkcj


glEnable(GL_POLYGON_STIPPLE);

a nastpnie
glPolygonStipple(pBitmap);

gdzie pBitmap to wskanik do obszaru danych zawierajcych wzr desenia. Od tego


momentu wszystkie wielokty bd wypeniane wzorem okrelonym przez zawarto
pamici wskazywanej przez pBitmap (typu GLubyte *). Ten dese jest podobny do uy-
wanego przy przerywanych liniach, z tym e bufor ma rozmiar wystarczajcy do po-
mieszczenia wzorca 32x32 bity. Oprcz tego bity s odczytywane od najbardziej do
najmniej znaczcego, czyli przeciwnie ni w przypadku linii. Dese ogniska, jakiego
uyjemy do wypeniania wieloktw, zosta przedstawiony na rysunku 6.26.

Rysunek 6.26. 4 2 l 8 4 Z l B 4 2 l 8 4 2 l8 4 2 l 9 4 2 l 8 4 2 l 8 4 2 l
Budowanie wzoru
desenia wypeniania
wieloktw

1 2864 32 16 8 4 2 1 1 2 8 6 4 3 2 16 8 4 2 1 1 2 8 M 3216 8 4 2 1 1 2 8 6 4 3 2 1 6 8 4 2 l

Y
= 0X1F 0X1F OXCO
0X80

Przechowywanie pikseli
Jak dowiesz si w rozdziale 11, moesz modyfikowa sposb
interpretacji pikseli wzorca wypenienia; suy do tego funkcja
glPixelStofe(). Na razie pozostamy jednak przy zwykym
wypenianiu wieloktw.
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 177

Aby skonstruowa mask reprezentujc ten wzr, przechowamy bitmap wierszami, od


dou do gry. Na szczcie, inaczej ni w przypadku linii, dane s interpretowane tak,
jak je zapisujemy, i najbardziej znaczcy bajt jest odczytywany jako pierwszy. Kady
bajt moe wic by zapisany od strony lewej do prawej i przechowany w tablicy wartoci
GLubyte na tyle duej, aby pomiecia 32 wiersze po cztery bajty kady.

Kod uyty do przechowania wzorca przedstawia listing 6.9. Kady wiersz tablicy repre-
zentuje wiersz punktw z rysunku 6.26. Pierwszy wiersz w tablicy stanowi ostatni wiersz
rysunku, i tak dalej, a do ostatniego wiersza w tablicy, ktry odpowiada pierwszemu
wierszowi na rysunku.

Sugestia: wr tu pniej
Jeli wci nie rozumiesz, jak ta bitmapa ogniska jest przechowywana i
interpretowana, sugerujemy, aby wrci tu pniej, gdy ju opanujesz
materia z rozdziau 11, Grafika rastrowa".

Listing 6.9. Definicja maski przedstawiajcej ognisko z rysunku 6.26


0x00, 0x00, 0x00, 0x00,
// Bitmapa ogniska 0x00, 0x00, 0x00, 0x00,
GLubyte f i r e [ ] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, OxcO,
0x00, 0x00, 0x01, OxfO,
0x00, 0x00, 0x07, OxfO,
OxOf, 0x00, Oxlf, OxeO,
Oxlf 0x80, Oxlf, OxcO,
OxOf, OxcO, Ox3f, 0x80,
0x07, OxeO, Ox7e, 0x00,
0x03, OxfO, Oxff, 0x80,
0x03, Oxf5, Oxff, OxeO,
0x07, Oxfd, Oxff, Oxf8,
Oxlf, Oxfc, Oxff, Oxe8,
Oxff, Oxe3, Oxbf, 0x70,
Oxde, 0x80, Oxb7, 0x00,
0x71, 0x10, Ox4a, 0x80,
0x03, 0x10, Ox4e, 0x40,
0x02, 0x88, Ox8c, 0x20,
0x05, 0x05, 0x04, 0x40,
0x02, 0x82, 0x14, 0x40,
0x02, 0x40, 0x10, 0x80,
0x02, 0x64, Oxla, 0x80,
0x00, 0x92, 0x29, 0x00,
0x00, OxbO, 0x48, 0x00,
0x00, Oxc8, 0x90, 0x00,
0x00, 0x85, 0x10, 0x00,
0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00 }
178____________________________________Cz II Uywanie OpenGL

Abymy mogli skorzysta z tego wzorca, musimy najpierw wczy wypenianie wielo-
ktw, a nastpnie wskaza ten wzr jako wzr wypeniania. Wanie to wykonuje
przykadowy program PSTIPPLE, a nastpnie rysuje omiokt (ksztat znaku Stop),
uywajc wzorca wypenienia. Interesujcy nas kod znajduje si na listingu 6.10, za
wynik dziaania programu zosta przedstawiony na rysunku 6.27.

Rysunek 6.27.
Wynik dziaania
programu
PSTIPPLE

Listing 6.10. Fragmenty programu


PSTIPPLE rysujcego \vielokat i
wypeniajcego go wzorcem

II Ta funkcja
odpowiada za
inicjowanie kontekstu
renderowania
void SetupRCO
{
// Czarne to
glClearColor( O . O f
, O . O f , O . O f , l.Of );

// Kolor rysowania czerwony


glColorSf( l . O f , O.Of,
O.Of);
// Wczenie wypeniania wielokta
glEnable{GL_POLYGON_STIPPLE);

// Wskazanie desenia wypeniania


glPolygonStipple(fire);

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glPushMatrix();
glRotatef(xRot, l . O f , O . O f , O . O f ) ;
glRotatef(yRot, O . O f , l . O f , O . O f ) ;
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________179

// Utworzenie k s z t a t u znaku STOP


// Dla uproszczenia zostanie uyty standardowy wielokat
glBegin(GL_POLYGON);
glVertex2f( - 2 0 . O f , 50.O f ) ;
glVertex2f( 2 0 . O f , 50.O f ) ;
glVertex2f( 5 0 . O f , 20.O f ) ;
glVertex2f( 5 0 . O f , -20.O f ) ;
glVertex2f(20.Of, -50.O f ) ;
glVertex2f(-20.O f , -50.O f ) ;
glVertex2f(-50.O f , -20.O f ) ;
glVertex2f(-50.O f , 20.O f ) ;
glEnd();

// Zrzucenie polece graficznych


glFlushf) ;

Rysunek 6.28 przedstawia omiokt nieco obrcony. Jak wida, wielokat jest w dalszym
cigu wypeniony, jednak dese nie obraca si wraz z nim. Dzieje si tak, poniewa
wzorzec wypenienia jest uywany wycznie do wypeniania wieloktw na ekranie.
Jeli chcesz naoy na wielokat bitmap imitujc jego powierzchni, bdziesz musia
zastosowa mapowanie tekstur (rozdzia 12).

Rysunek 6.28.
Wygld wielokta po obrceniu go wok
osi pionowej. Jak wida, wzr wypenienia
nie obraca si wraz z wieloktem

Reguy konstruowania
wieloktw
Gdy przy tworzeniu zoonej
powierzchni korzystasz z
wielu wieloktw, musisz
pamita o dwch wanych
zasadach.

Po pierwsze, wszystkie
wielokty musz by paskie. Tzn. wszystkie wierzchoki wielokta musz lee na tej samej
paszczynie, jak przedstawiono na rysunku 6.29. Wielokat nie moe by wykrcony" ani
wygity" w przestrzeni.
180 Cz II Uywanie OpenGL

Rysunek 6.29.
Paski i niepaski
wielokt

Wielokt piaski Wielokt niepaski

Jest to wic jeszcze jeden powd, aby korzysta z trjktw. adnego trjkta nie da si
wykrci" tak, aby ktry z wierzchokw nie spoczywa na innej paszczynie ni
pozostae, poniewa zgodnie z zasadami geometrii, wanie trzy punkty wyznaczaj pa-
szczyzn. (Jeli wic uda ci si narysowa niewaciwy trjkt, oczywicie poza usta-
wieniem go w zym kierunku, by moe czeka ci nagroda Nobla!)

Po drugie, krawdzie konstruowanego wielokta, nie mog si przecina, za sam wie-


lokt musi by wieloktem wypukym. Wypuky" oznacza e, nie moe posiada adnych
wci. Bardziej oficjalna definicja wielokta wypukego wie si z rysowaniem
przechodzcej przez niego linii. Jeli jakakolwiek linia prosta przecina krawdzie wielokta
wicej ni dwa razy, taki wielokt nie jest wypuky. Przykady poprawnych i nie-
poprawnych wieloktw pokazuje rysunek 6.30.

Rysunek 6.30.
Dozwolone i
niedozwolone
wielokty

Wielokty dozwolone Wielokty niedozwolone

Skd takie ograniczenia co do wieloktw?


Moe zastanawiasz si, dlaczego OpenGL nakada takie
ograniczenia dotyczce konstruowania wieloktw. Operacje
na wieloktach mog by bardzo skomplikowane, za
ograniczenia OpenGL wynikaj z zastosowania bardzo
szybkich algorytmw renderowania wieloktw.
Prawdopodobnie te ograniczenia nie bd dla ciebie zbyt
kopotliwe, gdy za pomoc dostpnych prymityww moesz
tworzy dowolne ksztaty (w ostatecznoci skadajc je z
prymityww GLJJNES czy nawet GL.POINTS).
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 181

Podzia wielokta
Cho OpenGL potrafi rysowa jedynie wielokty wypuke, istnieje sposb tworzenia
wieloktw niewypukych czc dwa lub wicej wieloktw wypukych. Na przykad,
wemy czteroramienn gwiazd przedstawion na rysunku 6.31. Ten ksztat z ca
pewnoci nie jest wypuky i w zwizku z tym narusza reguy OpenGL dotyczce kon-
struowania wieloktw. Jednak gwiazda po prawej stronie jest skonstruowana z szeciu
trjktw, ktre s zupenie dozwolone.
Rysunek 6.31.
Niewypuka
czteroramienn
gwiazda zoona z
szeciu trjktw

Gdy wielokty zostan wypenione, nie bdzie wida adnych krawdzi i caa figura bdzie
stanowi pojedynczy ksztat na ekranie. Jeli jednak uyjesz funkcji glPolygonMode w celu
przeczenia si na rysowanie sylwetki, bdzie wida szkielety trjktw skadajcych si na
gwiazd, co w pewnych przypadkach moe by bardzo mylce.

OpenGL posiada w tym celu specjalny znacznik, zwany znacznikiem krawdzi. Usta-
wiajc lub zerujc ten znacznik podczas podawania listy wierzchokw, informujesz
OpenGL, ktre linie maj zosta potraktowane jako zewntrzne krawdzie figury (linie
tworzce sylwetk figury), a ktre jako linie wewntrzne (ktre nie powinny by widoczne).
Suy do tego funkcja glEdgeFlag(), wywoywana z pojedynczym parametrem, bdcym
wartoci logiczn, wczajc lub wyczajc znacznik krawdzi. Gdy znacznik zostanie
ustawiony na warto True, wszystkie nastpne wierzchoki bd definioway krawdzie
nalece do sylwetki figury. Na listingu 6.11 widzimy zastosowanie tego w praktyce, w
programie STAR z pytki CD-ROM.

Listing 6.11. Fragment programu STAR, wykorzystujcego funkcj glEdgeFlag_______________

// Rysowanie trjktw
glBegin(GL_TRIANGLES) ;

glEdgeFlag(bEdgeFlag);
glVertex2f(-20.Of, O . O f ) ;
glEdgeFlag(TRUE); glVertex2f
(20.Of, O . O f ) ;
glVertex2f( O . O f , 40.O f ) ;
glVertex2f(-20.Of,O.Of);
glVertex2f( - 6 0 .Of,-20.Of);
glEdgeFlag(bEdgeFlag);
glVertex2f(-20.Of,-40.Of);
glEdgeFlag(TRUE);
182 Cz II * Uywanie OpenGL

glVertex2f(-20.Of,-40.Of);
glVertex2f( O . O f , -80.O f ) ;
glEdgeFlag(bEdgeFlag);
glVertex2f( 2 0 . O f , -40.O f ) ;
glEdgeFlag(TRUE);

glVertex2f( 2 0 . O f , -40.O f ) ;
glVertex2f( 6 0 . Of, -20.O f ) ;
glEdgeFlag(bEdgeFlag);
glVertex2f(20.Of, O . O f ) ;
glEdgeFlag(TROE);

// rodkowy kwadrat jako dwa trjkty


glEdgeFlag(bEdgeFlag); glVertex2f(-
20.Of, O . O f ) ; glVertex2f(-20.Of,-
40.Of); glVertex2f( 2 0 . Of, O . O f ) ;

glVertex2f(-20.Of,-40.Of);
glVertex2f( 2 0 . Of, -40.O f ) ;
glVertex2f( 2 0 . Of, O . O f ) ;
glEdgeFlag(TRUE);

// koniec rysowania
glEnd();

Zmienna boolowska bEdgeFlag jest wczana i wyczana poprzez polecenia w menu


Krawdzie. Jeli ten znacznik ma warto True, wszystkie krawdzie s traktowane jako
widoczne i pojawiaj si, gdy figura jest wywietlana w trybie GL_LINES. Na rysunkach
6.32a i 6.32b widzimy wynik dziaania programu STAR w trybie siatkowym, z
wywietlaniem i bez wywietlania wewntrznych krawdzi.
Rysunek 6.32a.
Program STAR z
wczonymi
wewntrznymi
krawdziami
Rozdzia 6. Rysowanie w trzech wymiarach: linie, punkty i wielokaty 183

Rysunek 6.32b.
Program STAR
z
wyczonymi
wewntrznymi

Podsumowanie
W tym rozdziale zdobylimy mnstwo informacji. Potrafisz ju tworzy wasn trjwy-
miarow przestrze do renderowania, wiesz take, jak narysowa kady z prymityww, od
punktw i odcinkw a po zoone wielokaty. Dowiedziae si rwnie, jak z dwu-
wymiarowych prymityww mona tworzy powierzchni trjwymiarowych obiektw.

Zachcamy do eksperymentw z tym, czego nauczye si w tym rozdziale. Uyj swojej


wyobrani i przed przejciem do dalszych rozdziaw utwrz jakie trjwymiarowe
obiekty. Bdziesz mia wtedy wasne przykady, z ktrymi bdziesz mg eksperymentowa, a
jednoczenie, dziki pewnej praktyce, atwiej opanujesz dalszy materia ksiki.

Czas na symulacj czogu/robota


Poczynajc od tego rozdziau zaczynamy tworzenie symulatora
czogu/robota, ktry bdzie stanowi uzupeniajcy przykad na
pytce CD-ROM. Celem tej symulacji jest otrzymanie czogu i
robota, ktre mog porusza si po pewnej przestrzeni,
widzianej wanie z perspektywy czogu lub robota. Symulator
nie bdzie omawiany w tekcie ksiki, ale symulacja bdzie
stopniowo rozbudowywana za pomoc technik opisywanych w
kolejnych rozdziaach. Moesz zacz ju teraz i pozna
obiekty wystpujce w wirtualnym wiecie czogu i robota.
Przyjrzyj si, jak te obiekty zostay skomponowane wycznie
z prymityww opisywanych w tym rozdziale.
184 Cz II Uywanie

Tat
Podrcznik o
Pry
m
gIBegin_____
Przeznaczenie Poprzedza podawanie listy wierzchokw definiujcych jeden lub wicej
prymityww.
Plik nagwkowy <gl.h>
Skadni void glBegin(GLenum mod);
a Opis Ta funkcja, w poczeniu z funkcj glEnd, jest przeznaczona do tworzenia prymityww
OpenGL. Wewntrz pary wywoa glBegin/glEnd mona poda wiele wierzchokw,
definiujcych seri prymityww tego samego rodzaju. Oprcz definiowania
wierzchokw, wewntrz pary glBegin/glEnd mona zmienia rne opcje i
ustawienia, wpywajce na sposb tworzenia i rysowania prymityww.
Pomidzy wywoaniami gIBegin i glEnd mona wywoywa jedynie
nastpujce funkcje: glVertex, glColor, gllndex, glNormal, glEvaICoord,
glCallLists, glTextCoord, glEdgeFlag oraz glMaterial.
Parametr
y mod GLenum: Ten parametr okrela rodzaj konstruowanych prymityww.
Moe by jedn z wartoci z tabeli 6. l.
Zwracana warto Brak.
Przykad Przykady uycia tej funkcji znajdziesz w kadym programie
Patrz opisywanym w tym rozdziale. Poniszy kod przedstawia
tworzenie pojedynczego punktu, pooonego w rodku ukadu
take wsprzdnych:
gIBegin(GL_POINTS);
glVertex3f{ 0 . 0 , 0 . 0 , 0 . 0 ) ; // punkt w rodku ukadu
glEnd();
glEnd, glVertex

Tabela 6.1.
Prymitywy OpenGL obsugiwane przez funkcj glBegin()

Staa Rodzaj prymitywu

GL_POINTS Kady wskazany wierzchoek okrela pojedynczy punkt.


GL_LINES Podane wierzchoki definiuj koce odcinkw. Kade dwa
wierzchoki definiuj osobny odcinek. Jeli zostanie podana
nieparzysta ilo wierzchokw, ostatni wierzchoek jest
ignorowany.
GL LIN
Podane wierzchoki definiuj aman. Po podaniu
pierwszego wierzchoka, kady nastpny definiuje
kolejny segment amanej.
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokaty 185

Tabela 6.1.
Prymitywy OpenGL obsugiwane przez funkcj glBeginf) - cig dalszy
Staa Rodzaj prymitywu

GL LIN LOOP Dziaa podobnie jak GL_LINE_STRIP, z tym e po okreleniu ostatniego


wierzchoka rysowany jest dodatkowy segment, zamykajcy aman. Tego
prymitywu zwykle uywa si do tworzenia ksztatw naruszajcych
ograniczenia narzucane przez GL_POLYGON.
GL TRIANGLES Podane wierzchoki okrelaj wierzchoki trjktw. Kade trzy
wierzchoki definiuj pojedynczy, osobny trjkt. Jeli ilo
wierzchokw nie jest podzielna przez trzy, nadmiarowe wierzchoki
s ignorowane.
GL TR1ANGLE STRIP Podane wierzchoki okrelaj pasek trjktw. Po podaniu
pierwszych trzech wierzchokw, kady nastpny wierzchoek, wraz
z dwoma poprzednimi, tworzy kolejny trjkt paska. Kada trjka
wierzchokw (poza trzema pierwszymi) jest automatycznie
aranowana, tak aby zapewni jednakowy kierunek wszystkich
trjktw paska.
GL TR1ANGLE FAN Podane wierzchoki okrelaj wachlarz trjktw. Pierwszy
wierzchoek wyznacza punkt wsplny wachlarza, za kady
wierzchoek, poczwszy od czwartego, definiuje kolejny trjkt
wachlarza. W ten sposb mona zdefiniowa dowoln liczb
trjktw.
GL_QUADS Kady zestaw czterech wierzchokw definiuje czworokt. Jeli
ilo wierzchokw nie jest podzielna przez cztery, nadmiarowe
wierzchoki s ignorowane.
GL_QUAD_STRIP Podane wierzchoki s uywane do tworzenia paska
czworoktw. Po okreleniu pierwszego czworokta, kada
nastpna para wierzchokw wyznacza kolejny czworokt,
oparty na tych wierzchokach i dwch poprzednich. W
odrnieniu od GL_QUADS, kada para wierzchokw jest
uywana w odwrotnej kolejnoci, w celu zapewnienia
jednakowego kierunku wszystkich czworoktw w pasku.
GL POLYGON Podane wierzchoki s uywane do tworzenia wielokta wypukego.
Krawdzie wielokta nie mog si przecina. Ostatni wierzchoek
jest automatycznie czony krawdzi z pierwszym wierzchokiem,
w celu zamknicia wielokta.

glCulIFace
Przeznaczenie Plik Okrela niewidoczn stron wieloktw.
nagwkowy
Skadnia void glCullFace(GLenum mod);
186 Cz II Uywanie
OpenGL

Opis Ta funkcja wycza owietlenie, cieniowanie, obliczenia koloru i inne


operacje dla przedniej lub tylnej strony wieloktw. Eliminuje
niepotrzebne obliczenia, gdy tylna strona wielokta nigdy nie jest
widoczna, bez wzgldu na jego orientacj. Samo usuwanie niewidocznych
cian jest wczane i wyczane za pomoc funkcji glEnable i glDisable z
parametrem GL_CULL_FACE. Do okrelania przedniej strony
wieloktw suy funkcja glFrontFace(); kierunek wielokta jest
wyznaczany na podstawie okrelenia kolejnoci jego wierzchokw
(zgodnie z ruchem wskazwek zegara lub przeciwnie do niego).
Parametr
y mod GLenum: Okrela, ktra strona wielokta ma by niewidoczna (usunita).
Dozwolone wartoci to GL_FRONT (przednia) oraz GL_BACK (tylna).
Zwracana warto Brak.
Przykad Poniszy przykad (z programu TRIANGLE w tym rozdziale) przedstawia
wycznie rysowanie wieloktw zwrconych tyem, pod warunkiem, e
zmienna bCull ma warto True:
// Wielokty o kolejnoci krawdzi zgodnej z ruchem //
wskazwek zegara s widoczne od frontu. Odwracamy // to
gdy korzystamy z wachlarza trjktw glFrontFace(GL_CW);

// Wczenie usuwania niewidocznych trjktw,


// jeli znacznik jest ustawiony if(bCull)
glEnable(GL_CDLL_FACE);
else
glDisable(GL_CULL_FACE);

glFrontFace, glLightModel
Patrz take

glEdgeFlag
Przeznaczenie Okrela krawdzie wielokta jako wewntrzne (niewidoczne) lub
zewntrzne (widoczne).
Plik
nagwkowy void glEdgeFlag(GLboolean flag);
void glEdgeFlagv(const GLboolean *flag);
Skadnia
Gdy dwa lub wicej wieloktw jest czonych w wikszy region,
zewntrzne (widoczne) krawdzie definiuj sylwetk nowej figury. Ta
funkcja suy do okrelenia krawdzi wewntrznych, ktre zwykle nie
powinny by widoczne. Funkcja odnosi si jedynie do trybw rysowania GL
LIN i GL POINT.
r Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty_____________187

Parametry
flag GLboolean: Ustawia stan znacznika krawdzi. Warto Tnie oznacza
krawdzie zewntrzne, za warto False - krawdzie wewntrzne.
*flag const GLboolean *: Wskanik do wartoci okrelajcej stan znacznika
krawdzi.
Zwracana warto Brak.
Przykad Poniszy przykad (z programu STAR w tym rozdziale) przedstawia
ustawienie znacznika krawdzi na False w odniesieniu do krawdzi
wystpujcych wewntrz figury. Figura (czteroramienna gwiazda) jest
rysowana jako wypeniona, jako sylwetka lub jako punkty w
wierzchokach.
// Narysowanie jedynie zewntrznych konturw
// wielokta, jeli jest ustawiony taki znacznik
if(iMode == MODE_LINE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

if{iMode == MODE_POINT)
glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);

if(iMode == MODE_SOLID)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

// Rysowanie trjktw
glBegin(GLJTRIANGLES);
glEdgeFlag(bEdgeFlag);
glVertex2f(-20.Of, O . O f ) ;
glEdgeFlag(TRUE);
glVertex2f(20.Of, O . O f ) ;
glVertex2f( O . O f , 40.O f ) ;

glVertex2f(-20.Of,O.Of);
glVertex2f( - 6 0 . Of,-20.0f);
glEdgeFlag(bEdgeFlag);
glVertex2f( - 2 0 . 0 f , -40 . 0 f);
glEdgeFlag(TRUE);
glVertex2f(-20.Of,-40.Of);
glVertex2f( O . O f , -80.O f ) ;
glEdgeFlag(bEdgeFlag);
glVertex2f( 2 0 . Of, -40.O f ) ,
glEdgeFlag(TRUE);
glVertex2f(20.Of, -40.O f ) ,
glVertex2f( 6 0 . Of, -20.O f ) ;
glEdgeFlag(bEdgeFlag);
glVertex2f(20.Of, O . O f ) ;
glEdgeFlag(TRUE);
188 Cz II Uywanie OpenGL

// rodkowy kwadrat jako dwa trjkty


glEdgeFlag(bEdgeFlag); glVertex2f(-
20.Of, O . O f ) ; glVertex2f(-20.Of,-
40.Of); glVertex2f (20. Of, 0.0"f);
glVertex2f(-20.Of,-40.Of);
glVertex2f(20.Of, -40.O f ) ;
glVertex2f(20.Of, O . O f ) ;
glEdgeFlag(TRUE);
// koniec rysowania
glEndO ;

Patrz take glBegin, glPolygonMode

glEnd
Przeznaczenie Plik Koczy list wierzchokw definiujcych prymitywy.
nagwkowy
Skadnia Opis void glEnd();
Ta funkcja jest uywana w poczeniu z funkcj glBegin w celu okrelenia
wierzchokw prymityww OpenGL. Wewntrz pary wywoa glBegin/glEnd
mona poda wiele wierzchokw, definiujcych seri prymityww tego
samego rodzaju. Oprcz definiowania wierzchokw, wewntrz pary
glBegin/glEnd mona zmienia rne opcje i ustawienia, wpywajce na
sposb tworzenia i rysowania prymityww. Pomidzy wywoaniami glBegin i
glEnd mona wywoywa jedynie nastpujce funkcje: glVertex, glColor,
gllndex, glNormal, glEvalCoord, glCallLists, glTextCoord, glEdgeFlag oraz
glMaterial.
Zwracana warto Brak.
Przykad Przykady uycia tej funkcji znajdziesz w kadym programie opisywanym w
tym rozdziale. Poniszy kod przedstawia tworzenie pojedynczego punktu,
pooonego w rodku ukadu wsprzdnych:
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, 0 . 0 ) ; // punkt w rodku ukadu
glEndO ;

Patrz take glBegin, glVertex

gl Front Face
Przeznaczenie Okrela, ktra strona wielokta ma by traktowana jako przednia.
Plik nagwkowy <gl-h>
Skadnia void glFrontFace(GLenum mod);
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 189

Opis Gdy scena zawiera obiekty zamknite (nie wida ich wntrza), obliczenia
koloru i owietlenia dla wewntrznych stron obiektu nie s potrzebne.
Funkcja glCullFace wycza te obliczenia dla przedniej lub tylnej strony
wieloktw, za funkcja glFrontFace okrela, ktra strona jest przednia, a
ktra tylna. Kierunek wielokta okrela si na podstawie kolejnoci
podawania jego wierzchokw (z punktu widzenia obserwatora) -w kierunku
zgodnym lub przeciwnym do ruchu wskazwek zegara. Ta funkcja umoliwia
okrelenie, ktra strona wielokta jest przednia: strona zgodna z kierunkiem
ruchu wskazwek zegara, czy te strona przeciwna do ruchu wskazwek.
Parametry
mod GLenum: Okrela orientacj przedniej strony wieloktw: zgodn z
ruchem wskazwek (GL_CW) lub przeciwn do ruchu wskazwek
zegara (GL_CCW).
Zwracana warto Brak.
Przykad Poniszy przykad (z programu TRIANGLE w tym rozdziale) przedstawia
sposb wyczenia rysowania trjktw skierowanych tyem do
obserwatora. Przedtem konieczne jest wskazanie, ktra strona wieloktw
ma by traktowana jako przednia.
// Wielokty o kolejnoci krawdzi zgodnej // z ruchem
wskazwek zegara s widoczne od frontu. // Odwracamy
to, gdy korzystamy // z wachlarza trjktw
glFrontFace(GL_CW);

// Wczenie usuwania niewidocznych trjktw,


// jeli znacznik jest ustawiony if(bCull)
glEnable(GL_CULL_FACE);
else
glDisable(GL_COLL_FACE);

glCullFace, glLightModel
Patrz take

glGetPolygonStipple
Przeznaczenie Zwraca biecy wzr wypeniania wieloktw.
Plik nagwkowy
Skadnia Opis void glGetPolygonStipple(GLubyte *mask);
Ta funkcja zwraca mask 32x32 bity, reprezentujc wzr wypenienia
wieloktw. Maska jest kopiowana do bufora w pamici, wskazywanego
przez wskanik *mask. Sposb upakowania pikseli jest okrelany przez
ostatnie wywoanie funkcji glPixelStore.
190 Cz II Uywanie OpenGL

Parametry
mod GLubyte: Wskanik do bufora, w ktrym ma zosta umieszczona maska
bitw.
Zwracana warto Brak.
Przykad
Poniszy fragment kodu ilustruje pobieranie biecego wzoru
wypeniania:
Glubyte m a s k [ 3 2 * 4 ] ; // 4 bajty = 32 bity x 32 wiersze

glGetPolyginStipple(mask);

Patrz take glPolygonStipple, glLineStipple, glPixelStore

gllineStipple
Przeznaczenie Okrela wzr wypeniania linii przerywanych rysowanych z uyciem
prymityww GLJLINES, GL_LINE_STIPPLE oraz GL_LINE_LOOP.
Plik nagwkowy
Skadnia void glLineStipple(GLint factor, GLushort pattern);
Opis Ta funkcja okrela styl wypenienia linii przerywanych. Wzr przerywania
linii okrela parametr pattern, za wielko segmentw okrela parametr
factor. Domylnie, kady bit wzorca pattern odpowiada jednemu pikselowi
rysowanej linii. Aby uy linii przerywanych, musisz najpierw wywoa
funkcj
glEnable (GL_LINE_STIPPLE) ;

Domylnie, przerywanie linii jest wyczone. Jeli rysujesz kilka segmentw


linii, wzr przerywania jest zerowany dla kadego segmentu, tj. dla kadego
nastpnego segmentu wzorzec przerywania jest interpretowany od
pocztku.
Parametry
factor GLint: Mnonik okrelajcy, ile pikseli linii odpowiada pojedynczemu
bitowi wzorca przerywania. Domyln wartoci jest l, za wartoci
maksymaln moe by 255.
pattern GLushort: Okrela 16-bitowy wzorzec przerywania. Jako pierwszy
interpretowany jest bit najmniej znaczcy. Domylny wzorzec zawiera
same jedynki (rysowana jest ciga linia).
Zwracana warto Brak.
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 191

Przykad Poniszy fragment kodu (z programu LSTIPPLE w tym rozdziale) ilustruje


uycie wzorca 0x5555 (0101010101010101), dajcego lini kropkowan.
Dla kadej nastpnej rysowanej linii jest zwikszana warto mnonika
wzorca, co powoduje, e fragmenty linii i odstpy staj si coraz dusze.
// Wywoywane w celu narysowania sceny void
RenderScene(void)

GLfloat y; // Zmienna wsprzdnej Y


GLint factor = 1; // Wspczynnik przerw
GLushort pattern = 0x5555; // Dese przerw

// Wczenie przerywania
glEnable(GL_LINE_STIPPLE);

// Przechodzenie w osi Y po 20 jednostek


for(y = - 9 0 . O f ; y < 9 0 . O f ; y += 2 0 . O f )
{
// Wyzerowanie czynnika wypenienia i desenia
glLineStipple(factor,pattern);

// Rysowanie linii
glBegin(GL_LINES);
glVertex2f(-80.Of, y ) ;
glVertex2f( 8 0 . Of, y ) ;
glEnd();

factor++;
Patrz take glPolygonStipple

gllineWidth
Przeznaczenie Okrela szeroko linii rysowanych przy uyciu prymityww GL_LINES,
GL_LINE_STIPPLE oraz GLLINELOOP.
Plik
nagwkowy void glLineWidth(GLfloat width);
Skadnia Ta funkcja ustala szeroko (w pikselach) rysowanych linii. Biec
szeroko linii mona pobra za pomoc poniszego kodu:
GLfloat fSize;

glGetFloatv(GL_LINE_WIDTH, fSize) ;
192 Cz II Uywanie OpenGL

Bieca szeroko linii zostanie wpisana do zmiennej fSize. Za pomoc


poniszego kodu moesz wyznaczy minimaln i maksymaln dostpn
szeroko linii:
GLfloat fSizes[2];

glGetFloatv(GL_LINE_WIDTH_RANGE, fSizes) ;

W tym przypadku, minimalna grubo linii zostanie wpisana do fSizes[0], za


szeroko maksymalna - do fSizes[l].
Na koniec, najmniejszy dopuszczalny przyrost szerokoci linii moe
zosta odczytany przez poniszy fragment kodu:
GLfloat fStepSize;

glGetFloatv(GL_LINE_WIDTH_GRANULARITY, SfStepSize);

Specyfikacja OpenGL wymaga, aby w kadej implementacji bya


dostpna co najmniej jedna szeroko linii, wynoszca l piksel. W
oglnej implementacji Microsoftu dostpny zakres obejmuje szerokoci
od 0,5 do 10,0 pikseli, z krokiem 0,125 piksela.
GLfloat: Okrela szeroko rysowanych linii. Domyln wartoci
Parametry jest 1.0.
wldth Brak.
Poniszy fragment kodu (z programu LINESW w tym rozdziale)
Zwracana warto demonstruje rysowanie linii o rnych grubociach.
Przykad void RenderScene(void)

GLfloat y; // Zmienna dla wsprzdnej Y


GLfloat fSizes[ 2 ] ; // Zakres szerokoci linii
GLfloat fCurrSize; // Przechowuje biec szeroko

// Pobranie dostpnych rozmiarw linii // i


zapamitanie najmniejszej wartoci przyrostu
glGetFloatv(GL_LINE_WIDTH_RANGE, fSizes) ; fCurrSize =
fSizes[ 0 ] ;

// Przejcie w osi Y po 20 punktw for(y


= - 9 0 . O f ; y < 9 0 . O f ; y += 20.O f ) {
// Ustawienie szerokoci linii
glLineWidth(fCurrSize) ;

// Narysowanie linii
glBegin(GL_LINES);
glVertex2f(-80.Of, y);
glVertex2f(80.Of, y ) ;
glEnd();
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 193

// Poszerzenie linii
fCurrSize += l . O f ;

Patrz take glPointSize

gIPointSize
Przeznaczenie Okrela rozmiar punktw rysowanych przy uyciu prymitywu
GL_POINTS.
Plik
nagwkowy void glPointSize(GLfloat size);
Skadnia Ta funkcja ustala rozmiar (w pikselach) punktw rysowanych przy uyciu
prymitywu GL_POINTS.
Biecy rozmiar punktw mona pobra za pomoc poniszego kodu:
GLfloat fSize;

glGetFloatv(GL_POINT_SIZE, SfSize) ;

Biecy rozmiar punktw zostanie wpisany do zmiennej fSize. Za pomoc


poniszego kodu moesz wyznaczy minimalny i maksymalny dostpny
rozmiar punktw:
GLfloat fSizes[2] ;

glGetFloatv(GL_POINT_SIZE_RANGE, fSizes) ;

W tym przypadku minimalny rozmiar punktw zostanie wpisany do


fSizes[0], za rozmiar maksymalny - do fSizesfl].
Na koniec, najmniejszy dopuszczalny przyrost rozmiaru punktw moe
zosta odczytany przez poniszy fragment kodu:
GLfloat fStepSize; glGetFloatv(GL_POINT_SIZE_GRANULARITY,

SfStepSize) ;

Specyfikacja OpenGL wymaga, aby w kadej implementacji by dostpny co


najmniej jeden rozmiar punktw, wynoszcy l piksel. W oglnej
implementacji Microsoftu, dostpny zakres obejmuje rozmiary od 0,5 do 10,0
pikseli, z krokiem 0,125 piksela.

Parametry
size GLfloat: Okrela przyblion rednic rysowanych punktw. Domyln
wartoci jest 1,0.
194 Cz II Uywanie
OpenGL

Zwracana warto Brak.


Przykad Poniszy fragment kodu (z programu POINTSZ w tym rozdziale)
demonstruje rysowanie punktw o rnych rozmiarach.
GLfloat x,y,z,angle; // Zmienne dla wsprzdnych
/ / i ktw GLfloat s i z e s [ 2 ] ;
// Przechowuje obsugiwany
// zakres wielkoci punktw
GLfloat step; // Przechowuje obsugiwany
// przyrost wielkoci punktw
GLfloat curSize; // Przechowuje biecy rozmiar

// Pobranie zakresu obsugiwanych wielkoci // i


przyrostu wielkoci
glGetFloatv(GL_POINT_SIZE_RANGE,sizes) ;
glGetFloatv(GL_POINT_SIZE_GRANULARITY, Sstep) ;

// Ustawienie pocztkowego rozmiaru punktw


curSize = sizes[0];
// Ustawienie pocztkowej zmiennej Z z
= -50. Of;
// Przejcie caego okrgu trzy razy
for(angle = O . O f ; angle <= (2.0f*3 . 1415f ) *3.0f ; angle += O.lf)
(
// Oblicza wartoci z i y na okrgu
x = 50. Of*sin (angle) ;
y = 50. Of*cos (angle) ;

// Okrelenie rozmiaru punktu przed


// wybraniem prymitywu glPointSize
(curSize) ;

// Rysowanie punktu
glBegin(GL_POINTS) ;
glVertex3f ( x , y, z ) ;
glEnd ( ) ;
// Zwikszenie wsprzdnej Z i wielkoci punktu z
+= 0.5f; curSize += step;

Patrz take glLineWidth

glPolygonMode
Przeznaczenie Okrela tryb rysowania wieloktw.
Plik nagwkowy <gl.h>
Skadnia void glPolygonMode(GLenum face, GLenum mod);
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty

r Opis Ta funkcja umoliwia zmian sposobu rysowania wieloktw. Domylnie,


wielokty s kolorowane lub cieniowane przy uyciu biecego koloru i

waciwoci materiau. Mona jednak nakaza rysowanie jedynie sylwetki


195

lub punktw odpowiadajcych wierzchokom wielokta. Co wicej, mona


okreli tryb rysowania osobno dla przedniej, tylnej lub obu stron
wielokta.
Parametry
face GLenum: Okrela stron wieloktw, do ktrej bdzie si odnosi dane
wywoanie funkcji: GL_FRONT (przednia strona), GL_BACK (tylna strona)
lub GL_FRONT_AND_BACK (obie strony).
mod GLenum: Okrela nowy tryb rysowania. Domylnym trybem jest GL_FILL,
dajcy wypenione wielokty. GL_LINE powoduje rysowanie jedynie
sylwetek wieloktw (zewntrznych krawdzi), za GL_POINT powoduje
rysowanie jedynie punktw w wierzchokach wielokta. O tym, czy krawdzie
i wierzchoki wielokta zostan narysowane, decyduje warto znacznika
krawdzi, ustawianego funkcj glEdgeFlag.
Zwracana warto Brak.
Przykad Poniszy fragment kodu (z programu TRIANGLE w tym rozdziale)
demonstruje rysowanie tylnych stron wieloktw w postaci siatki
krawdzi, w zalenoci od wartoci zmiennej bOutline.
// Rysowanie tylko siatki wielokta, //
jeli znacznik jest ustawiony
if(bOutline)
glPolygonMode(GL_BACK,GL_LINE); else
glPolygonMode(GL_BACK,GL_FILL);
glEdgeFlag, glLineStipple, glLineWidth, glPointSize, glPolygonStipple
Patrz take

glPolygonStipple
Przeznaczenie Okrela wzr wypeniania wieloktw.
Plik nagwkowy
Skadnia Opis void glPolygonStipple(const GLubyte *mask);
Do wypeniania wieloktw mona uy wzorca bitowego o wymiarach 32x32
bity. Przedtem naley wywoa funkcj
glEnable(GL_POLYGON_STIPPLE). Jedynki we wzorcu s rysowane
biecym kolorem wypeniania, zera nie s rysowane.
Parametry
*mask const GLubyte: Wskazuje na bufor o rozmiarze 32x32 bity, zawierajcy wzr
wypeniania wielokta. O sposobie upakowania bitw wzorca decyduje funkcja
glPixelSize. Podczas interpretacji wzorca jako pierwszy odczytywany jest
najbardziej znaczcy bajt.
196 Cz II Uywanie OpenGL

Zwracana warto Brak.


Przykad Poniszy fragment kodu (z programu PSTIPPLE w tym rozdziale) ilustruje
uycie wzorca wypeniania wielokta. Wypeniany wielokt ma ksztat
omiokta (znaku Stop).
// Wczenie wypeniania wielokta
glEnable(GL_POLYGON_STIPPLE);

// Wskazanie desenia wypeniania


glPolygonStipple(fire);

// Wywoywane w celu narysowania sceny


void RenderScene(void)

// Utworzenie ksztatu znaku STOP


// Dla uproszczenia zostanie uyty standardowy wielokt
glBegin(GL_POLYGON);
glVertex2f(-20.Of, 50.O f ) ;
glVertex2f( 2 0 . Of, 50.O f ) ;
glVertex2f( 5 0 . O f , 20.O f ) ;
glVertex2f( 5 0 . Of, -20.O f ) ;
glvertex2f( 2 0 . Of, -50.O f ) ;
glVertex2f(-20.Of, -50.O f ) ;
glVertex2f(-50.O f , -20.O f ) ;
glVertex2f(-50.Of, 20.O f ) ;
glEnd();

Patrz take glLineStipple, glGetPolygonStipple, glPixelStore

glVertex
Przeznaczenie Plik Okrela wsprzdne wierzchoka w trjwymiarowej przestrzeni.
nagwkowy
Skadnia void glVertex2d(GLdouble x, GLdouble y);
void glVertex2f(GLfloat x, GLfloat y);
void glVertex2i(GLint x, GLint y);
void glVertex2s(GLshort x, GLshort y);
void glVertex3d(GLdouble x, GLdouble y, GLdouble z);
void glVertex3f(GLfloat x, GLfloat y, GLfloat z);
void glVertex3i(GLint x, GLint y, GLint z);
void glVertex3s(GLshort x, GLshort y, GLshort z);
Rozdzia 6. * Rysowanie w trzech wymiarach: linie, punkty i wielokty 197

void glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);


void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void glVertex4i(GLint x, GLint y, GLint z, GLint w);
void gIVertex4s(GLshort x, GLshort y, GLshort z, GLshort w);
void glVertex2dv(const GLdouble *v);
void glVertex2fv(const GLfloat *v);
void gVertex2iv(const GLint *v);
void glVertex2sv(const GLshort *v);
void glVertex3dv(const GLdouble *v);
void glVertex3fv(const GLfloat *v);
void glVertex3iv(const GLint *v);
void glVertex3sv(const GLshort *v);
void glVertex4dv(const GLdouble *v);
void glVertex4fv(const GLfloat *v);
void glVertex4iv(const GLint *v);
void glVertex4sv(const GLshort *v);
Opis Ta funkcja suy do okrelenia wsprzdnych wierzchokw dla punktw,
linii i wieloktw, wskazanych w wywoaniu funkcji glBegin. Ta funkcja nie
moe by wywoywana poza par funkcji glBegin/glEnd.
Parametry
x,y,z Wsprzdne x, y oraz z wierzchoka. Gdy z nie jest podawane, domyln
wartoci tej wsprzdnej jest 0,0.
Wsprzdna w wierzchoka. Ta wsprzdna jest uywana do skalowania i
w nakadania tekstury; jej domyln wartoci jest 1,0. Przy skalowaniu trzy
pozostae wsprzdne s dzielone przez t wsprzdn.
Tablica wartoci, zawierajca 2, 3 lub 4 wartoci konieczne do
zdefiniowania wierzchoka.
Zwracana warto Brak.
Przykad Ta funkcja wystpuje we wszystkich przykadach w tej ksice (i
praktycznie we wszystkich programach OpenGL). Poniszy kod
przedstawia rysowanie pojedynczego punktu pooonego w rodku
ukadu wsprzdnych.
glBegin(GL_POINTS);
glVertex3f( 0 . 0 , 0.0, 0 . 0 ) ;
glEnd();

Patrz take glBegin, glEnd


Rozdzia 7.
Manipulowanie
przestrzeni 3D:
transformacje
wsprzdnych
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


4 Ustawi swoj pozycj w scenie * gluLookAt/glTranslate/glRotate
* Ustawi obiekty w scenie * glTranslate/glRotate
* Skalowa obiekty * glScale
* Wczy rzutowanie perspektywiczne * gluPerspective
* Wykonywa obliczenia na macierzach 4 glLoadMatrix/glMultMatrix

W rozdziale szstym nauczye si rysowa linie, punkty i inne ksztaty. Aby zamieni
kolekcj prymityww w spjn scen, musisz je odpowiednio uoy wzgldem siebie i
wzgldem obserwatora. W tym rozdziale zaczniemy przemieszcza ksztaty i obiekty w
ukadzie wsprzdnych. (W rzeczywistoci nie przesuwamy obiektw, ale raczej prze-
suwamy ukad wsprzdnych, tak aby uzyska podany widok). Moliwo umie-
szczania i orientowania obiektw w scenie jest podstawow spraw dla kadego progra-
misty trjwymiarowej grafiki. Jak si przekonasz, wygodnie jest opisa ksztat obiektu
umieszczonego w rodku ukadu wsprzdnych, a dopiero potem obrci obiekt i przesun
go we waciwe pooenie.
200____________________________________Cz II Uywanie OpenGL

Czy to jest ten rozdzia z matematyk?


Tak, to wanie ten rozdzia. Moesz si jednak odpry - postaramy si, aby nie by a
tak straszny.

Kluczem do transformacji obiektw i ukadu wsprzdnych s dwie macierze modelo-


wania, przechowywane przez OpenGL. Aby zapozna ci z tymi macierzami, ten rozdzia
stanowi pewien kompromis pomidzy dwoma kracowymi podejciami do grafiki
komputerowej. Z jednej strony, moglibymy ci ostrzec: przed przeczytaniem tego
rozdziau przejrzyj podrcznik algebry liniowej". Z drugiej strony moglibymy sprbowa
ci oszuka, twierdzc, e nauczysz si tworzy trjwymiarow grafik bez wszystkich tych
skomplikowanych wzorw matematycznych". Nie popieramy jednak adnej z tych dwch
szk.

Rzeczywicie, moesz tworzy wspania trjwymiarow grafik bez bliszej znajomoci


zaawansowanej matematyki, podobnie jak moesz kadego dnia prowadzi samochd nie
wiedzc nic o mechanice i zasadzie dziaania silnika. Jest jednak lepiej jeli wiesz
przynajmniej, e od czasu do czasu trzeba wymieni olej, napeni bak paliwem czy
wymieni opony, gdy stan si yse. Czynic to, stajesz si odpowiedzialnym (i
bezpiecznym!) posiadaczem pojazdu. Jeli chcesz by profesjonalnym programist
OpenGL, powiniene co wiedzie o wykorzystywanej matematyce. Musisz opanowa
przynajmniej podstawy, tak aby wiedzie, co moesz zrobi i jakie narzdzia bd do tego
najodpowiedniejsze.

Zatem, mimo e nie potrafisz przemnoy w myli dwch macierzy, powiniene jednak
wiedzie, czym s macierze i jakie maj zastosowanie w trjwymiarowej magii OpenGL.
Zanim jednak odkurzysz ten stary podrcznik algebry liniowej (czy jest kto, kto go nie
ma?), pozbd si obaw - OpenGL wszystkie obliczenia bierze na siebie. Potraktuj to jak
uycie kalkulatora do podzielenia duej liczby, ktrej nie potrafiby podzieli na
papierze. Mimo e nie musisz robi tego samodzielnie, w dalszym cigu musisz wiedzie,
co i po co dzielisz. Widzisz - moesz mie ciastko i jednoczenie je je!

Przeksztacenia
Przeksztacenia umoliwiaj rzutowanie trjwymiarowych wsprzdnych na dwuwy-
miarowy ekran. Przeksztacenia umoliwiaj take obracanie obiektw, przesuwanie, a
nawet ich rozciganie, kurczenie czy zawijanie. Zamiast bezporednio modyfikowa
obiekt, przeksztacenie modyfikuje ukad wsprzdnych. Gdy przeksztacenie obr
ukad wsprzdnych, wszystkie rysowane obiekty bd obrcone. Po okreleniu wierz-
chokw, a przed narysowaniem obiektw na ekranie, korzystamy z trzech rodzajw
przeksztace: punktu obserwacji, modelu i rzutowania. W tej sekcji opiszemy waci
woci kadego z tych przeksztace, zebranych w tabeli 7.1.
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych 201

Tabela 7.1.
Rodzaje przeksztace -w OpenGL
Przeksztacenie Zastosowanie

Punktu obserwacji Okrela pooenie obserwatora lub kamery


Modelu Przesuwa obiekty w scenie Opisuje dwoisto
Widoku modelu przeksztace widoku i modelu Obcina i
Rzutowanie dostosowuje rozmiary bryy widzenia Skaluje
Widoku okna kocowy obraz do wymiarw okna

Wsprzdne obserwatora
Wan koncepcj w tym rozdziale swsprzdne obserwatora. Wsprzdne obserwatora
okrelaj ukad wsprzdnych obserwatora, bez wzgldu na wszelkie przeksztacenia,
ktre mog zosta zastosowane - potraktuj je jako bezwzgldne" wsprzdne
ekranowe. Tak wic wsprzdne obserwatora nie s rzeczywistymi wsprzdnymi, lecz
reprezentuj raczej pewien ustalony ukad wsprzdnych, uywany jako ukad odniesienia.
Wszystkie przeksztacenia omawiane w tym rozdziale s opisywane wanie pod ktem ich
efektw wzgldem ukadu wsprzdnych obserwatora.

Rysunek 7.1 przedstawia ukad wsprzdnych obserwatora widziany z dwch rnych


miejsc. Z lewej strony (a) ukad wsprzdnych obserwatora jest przedstawiony tak, jak
widzi go uytkownik (tzn. prostopadle do ekranu monitora). Po prawej stronie (b) ukad
wsprzdnych obserwatora zosta nieco obrcony, aby lepiej byo wida pooenie osi z.
Z punktu widzenia uytkownika, dodatnie wartoci osi x i y biegn, odpowiednio, w
prawo i w gr. Dodatnie wartoci osi z biegn w kierunku patrzcego.
Rysunek 7.1.
Dwa widoki ukadu
wsprzdnych
obserwatora

l +z
Obserwator/V^

y y

Gdy rysujesz trjwymiarowe obiekty w OpenGL, uywasz ukadu wsprzdnych karte-


zjaskich. Gdyby nie zostay uyte adne przeksztacenia, ten ukad byby identyczny z
ukadem wsprzdnych obserwatora. Wszystkie przeksztacenia zmieniaj biecy
ukad wsprzdnych wzgldem ukadu wsprzdnych obserwatora. Wanie w ten
sposb s obracane i przesuwane obiekty sceny - przez przesunicie i obrcenie ukadu
202____________________________________Cz II Uywanie

wsprzdnych wzgldem ukadu wsprzdnych obserwatora. Rysunek 7.2 przedstaw


dwuwymiarowy przykad ukadu wsprzdnych obrconego o 45 stopni wzgldt
ukadu wsprzdnych obserwatora. Kwadrat narysowany w tym odwrconym ukadj
wsprzdnych take wydaje si obrcony.

Rysunek 7.2.
Ukad wsprzdnych y Przeksztacony
wsprzdnych obserwatora
s^ ** yi ukad
obrcony wzgldem
ukladu
v
wsprzdnych y' Vl^- Przeksztacony kwadrat delu
obserwatora ' '~

W tym rozdziale przestudiujemy


metody suce do modyfikacji
biecego ukad wsprzdnych
przed narysowaniem obiektw. Moesz nawet zachowa stan bieceg ukadu, wykona
pewne przeksztacenia i narysowa cz obiektw, a nastpnie od tworzy stan ukadu i
zacz przeksztaca go w inny sposb. Poprzez odpowiedni do br przeksztace moesz
dowolnie umieszcza i obraca obiekty w scenie.

Przeksztacenia punktu obserwacji


Przeksztacenie punktu obserwacji jest pierwszym przeksztaceniem sceny. Jest uywa ne
do wyznaczenia pooenia oka i kierunku patrzenia obserwatora (kamery). Domyt nie,
punktem obserwacji jest pocztek ukadu wsprzdnych, za kierunek patrzeniif
pokrywa si z osi z, w stron malejcych wartoci (do" monitora). Ten punkt obser
wacji jest przesuwany wzgldem ukadu wsprzdnych obserwatora, w celu umie
szczeni oka" w odpowiednim punkcie i skierowania go w odpowiednim kierunku Gdy
punkt obserwacji pokrywa si z pocztkiem ukadu wsprzdnych, wszystkie obiekty o
dodatnich wartociach wsprzdnej z znajduj si za plecami" obserwatora,
Przeksztacenie punktu obserwacji umoliwia ustawienie punktu obserwacji w dowol nym
pooeniu i obrcenie go w dowolnym kierunku. Okrelenie przeksztacenia punktu
obserwacji odpowiada ustawieniu i skierowaniu kamery na scen.
i
Podczas definiowania sceny, przeksztacenie punktu obserwacji musi by okrelone jako!
pierwsze, przed wszystkimi innymi przeksztaceniami, gdy to przeksztacenie przesuwa
biecy ukad wsprzdnych wzgldem ukadu wsprzdnych obserwatora. Wszystkie
nastpne przeksztacenia dotycz tego nowo zmodyfikowanego ukadu. Pniej - gdy
sprbujemy sami stosowa przeksztacenia - dokadniej zobaczysz, jak to dziaa.

Przeksztacenia modelu
Przeksztacenia modelu s uywane do manipulowania modelem i jego poszczeglnymi
obiektami. W tym przeksztaceniu obiekty s przesuwane, modelowane i skalowane.
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 203

Rysunek 7.3 ilustruje trzy przeksztacenia modelu, zastosowane na obiektach. Rysunek 7.3a
pokazuje przesunicie (translacj), w ktrym obiekt jest przesuwany o zadany wektor.
Rysunek 7.3b przedstawia obrt (rotacj), w ktrej obiekt jest obracany wok zadanej osi.
Na koniec, rysunek 7.3c pokazuje efekt skalowania, w ktrym rozmiary obiektu s
zwikszane lub zmniejszane o zadan warto. Skalowanie moe by nierwnomierne
(obiekt moe by skalowany o rne wartoci w rnych kierunkach) i moe by uyte do
ciskania" lub rozcigania obiektw.

Rysunek 7.3.
Przeksztacenia
modelu
y---y

Przesunicia
(a)

Kocowy wygld sceny lub obiektu zaley gwnie od kolejnoci zastosowanych prze-
ksztace modelu. Jest to szczeglnie istotne w przypadku przesuni poczonych z
obrotem. Rysunek 7.4a przedstawia przeksztacenie kwadratu, w ktrym kwadrat jest
najpierw obracany wok osi z, a nastpnie przesuwany wzdu nowo przeksztaconej osi
x. Na rysunku 7.4b ten sam kwadrat jest najpierw przesuwany wzdu osi x, a
nastpnie obracany wok osi z. Rnica w kocowym pooeniu kwadratu wynika z tego,
e kade przeksztacenie odbywa si wzgldem poprzednio zastosowanych przeksztace.
Na rysunku 7.4a kwadrat jest najpierw obracany wzgldem rodka ukadu. Na rysunku
7.4b, po przesuniciu kwadratu, wykonywany jest obrt wzgldem nowo przesunitego
rodka ukadu.
204 Cz II Uywanie OpenGL

Rysunek 7.4.
Przeksztacenia
modelu:
obrt/przesunicie
oraz
przesunicie/obrt

Dwoisto widoku modelu


Przeksztacenia punktu obserwacji i przeksztacenia modelu s w rzeczywistoci tym
samym, jeli chodzi o ich wpfyw na kocowy wygld sceny. Rozrnienie pomidzy nimi jest
stosowane wycznie dla wygody programisty. W rzeczywistoci nie ma adnej rnicy
pomidzy przesuniciem obiektu a przesuniciem w drug stron ukadu odniesienia-jak
pokazano na rysunku 7.5, kocowy efekt jest taki sam. (Najwyraniej wida to, gdy
siedzimy w stojcym pocigu, za na ssiednim peronie rusza pocig; czsto wydaje si
wtedy, e to nasz pocig odjeda w przeciwnym kierunku). Termin widok modelu" jest
uywany w celu wskazania, e moesz potraktowa przeksztacenie jako przeksztacenie
modelu lub jako przeksztacenie punktu obserwacji, cho w rzeczywistoci s one tym
samym, czyli przeksztaceniem widoku modelu.

Rysunek 7.5.
Dwa sposoby
patrzenia na
przeksztacenie
punktu obserwacji

Przesunicie obserwatora Przesunicie ukadu wsprzdnych


(a) (b)
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych 205

Tak wic przeksztacenie punktu obserwacji jest wanie przeksztaceniem modelu za-
stosowanym w odniesieniu pozornego obiektu (kamery lub oka) przed narysowaniem
obiektw. Jak ju wkrtce zobaczysz, kady nastpny obiekt sceny podlega kolejnym
przeksztaceniom. Pocztkowe przeksztacenie zapewnia ukad odniesienia, na ktrym
opieraj si wszystkie nastpne przeksztacenia.

Przeksztacenia rzutowania
Przeksztacenia rzutowania s stosowane w kocowej scenie, z ju zastosowanymi
wszystkimi przeksztaceniami widoku modelu. Rzutowanie okrela bry widzenia i de-
finiuje paszczyzny obcinania. Co wicej, przeksztacenie rzutowania okrela, jak uko-
czona scena (po zakoczeniu modelowania) jest rzutowana na kocowy obraz na ekranie. W
tym rozdziale poznasz dwa rodzaje rzutowania: rwnolege {perspektywiczne.

W rzutowaniu rwnolegym wszystkie obiekty s rysowane na ekranie z zachowaniem


ich oryginalnych rozmiarw. Takie rzutowanie jest typowe dla systemw CAD i doku-
mentacji technicznej, w ktrych wane jest zachowanie rzeczywistych proporcji obiektw.

Rzutowanie perspektywiczne przedstawia obiekty w taki sposb, w jaki widzimy je w


rzeczywistym wiecie. Cech rzutowania perspektywicznego jest pozorne zmniejszanie si
bardziej oddalonych obiektw; obiekty pooone dalej wydaj si mniejsze od takich
samych obiektw pooonych bliej. W takim rzutowaniu linie rwnolege nie zawsze
s rysowane jako rwnolege. Na przykad szyny toru kolejowego biegn rwnolegle,
lecz w rzutowaniu perspektywicznym zbiegaj si w pewnym odlegym punkcie. Taki
punkt nosi nazw punktu zbiegu.

Zalet rzutowania perspektywicznego jest to, e nie musisz sam decydowa, ktre obiekty
maj by mniejsze i jak mae powinny by odlege obiekty. Wszystko, co musisz
zrobi, to zdefiniowa scen za pomoc przeksztace widoku modelu, a nastpnie za-
stosowa przeksztacenie perspektywiczne. OpenGL zajmie si ca magi.

Rysunek 7.6 przedstawia rzutowanie perspektywiczne i rwnolege na przykadzie


dwch rnych scen.
Rysunek 7.6.
Przykady
rzutowania
rwnolegego
i perspektywicznego

Perspektywiczna Rwnolege Perspektywiczne

Oglnie, rzutowanie rwnolege powinno by stosowane podczas modelowania pro-


stych obiektw, dla ktrych nie ma znaczenia odlego od obserwatora. Rzutowanie
perspektywiczne zwykle wyglda naturalnie wtedy, gdy stosunek rozmiaru obiektu do
206____________________________________Cz II Uywanie OpenGL

jego odlegoci od obserwatora jest do may (ogldamy due obiekty z duej odle-
goci). Tak wic samochd stojcy na wystawie moe by przedstawiony w rzucie
rwnolegym, ale jeli staniesz dokadnie przed mask i spojrzysz w kierunku samo-
chodu, perspektywa zaczyna nabiera duego znaczenia. Rzutowanie perspektywiczne
jest uywane przy renderowaniu scen skadajcych si z wielu rozrzuconych obiektw, na
przykad widokw architektonicznych czy widokw z lotu ptaka, lub w przypadku
duych obiektw, ktre w zalenoci od punktu obserwacji mog si wydawa znie-
ksztacone. W wikszoci przypadkw rzutowanie perspektywiczne jest najodpo-
wiedniejsze.

Przeksztacenia okna
Gdy wszystko zostanie wymodelowane i przeksztacone, mamy dwuwymiarowy rzut
sceny, ktry powinien zosta umieszczony w jakim oknie na ekranie. To odwzorowanie
obrazu na fizyczne wsprzdne okna jest ostatnim z przeksztace i nosi nazw
przeksztacenia okna. Okna (widoki) zostay omwione pokrtce w rozdziale trzecim, w
ktrym rozcigalimy lub ciskalimy obraz tak, aby kwadratowy rysunek zmieci si w
prostoktnym oknie.

Ach, te macierze...
Uzbrojeni w podstawowy sownik definicji i przeksztace, jestemy gotowi do prze-
prowadzenia prostych operacji na macierzach. Zobaczmy, jak OpenGL przeprowadza te
transformacje oraz jakie funkcje su do osignicia zamierzonego efektu.
Matematyka kryjca si za operacjami na macierzach jest znacznie uproszczona dziki
stosowaniu tzw. zapisu macierzowego. Kade z omawianych przeksztace mona osign
przez przemnoenie macierzy zawierajcych wsprzdne wierzchokw przez macierz
opisujc dane przeksztacenie. Tak wic wszystkie przeksztacenia dostpne w
OpenGL sprowadzaj si do mnoenia przez siebie dwch lub wicej macierzy.

Co to jest macierz?
Macierz nie jest niczym innym jak zestawem liczb uoonych w wierszach i kolumnach -
czyli z punktu widzenia programisty jest po prostu dwuwymiarow tablic. Macierz nie
musi by kwadratowa, jednak we wszystkich wierszach musi by ta sama ilo ele-
mentw; take wszystkie kolumny musz mie jednakow wysoko, tj. zawiera je-
dnakow ilo elementw. Przykady macierzy pokazuje rysunek 7.7. (Te macierze nie
reprezentuj niczego szczeglnego, a jedynie demonstruj wasn struktur). Zwr
uwag, e macierz moe skada si z pojedynczej kolumny elementw.
Rozdzia 7. + Manipulowanie przestrzeni 3D: transformacje wsprzdnych______ ___207
1 4 7 0 42
Rysunek 7.7.
2 5 8 1.5 0.877
Przykady macierzy
_3 6 9_ _2 14

Naszym celem nie jest zagbianie si w szczegy matematyki i manipulowania macie-


rzami. Jeli chcesz dowiedzie si czego wicej o manipulowaniu macierzami i samo-
dzielnym kodowaniu pewnych specjalnych przeksztace, dobrym punktem wyjcia
moe by literatura podana w dodatku B.

Kolejka przeksztace
W celu zastosowania przeksztace opisywanych w tym rozdziale, bdziemy modyfikowa
gwnie dwie macierze: macierz widoku modelu oraz macierz rzutowania. Nie martw
si, OpenGL zapewnia specjalne funkcje przeznaczone do modyfikowania tych macierzy
jako caoci. Poszczeglne elementy tych macierzy bdziesz modyfikowa tylko wtedy, gdy
zechcesz osign jakie specjalne efekty.
Droga od wsprzdnych wierzchoka do wsprzdnych punktu na ekranie jest duga i
mudna. Proces przeksztace wsprzdnych zosta przedstawiony na rysunku 7.8.
Najpierw wsprzdne wierzchoka s zamieniane na macierz 1x4, w ktrej pierwsze
trzy elementy odpowiadaj wsprzdnym x, y i z. Czwarty element to wspczynnik
skalowania, ktry moesz sam okreli, stosujc funkcje wierzchokw wymagajce
podania czterech argumentw. To jest wanie wsprzdna w, domylnie przyjmujca
warto 1,0. Zwykle rzadko bdziesz modyfikowa t warto bezporednio, zamiast
tego stosujc jedn z funkcji skalowania macierzy widoku modelu.
Rysunek 7.8. O X ne Macierz x Macierz
Kolejka r y. ne widoku y. rzutowania -*
Dzielenie dla x/w
przeksztace
wierzchoka
W z
Sf w
ko modelu
Prze w cone
u perspektywy y /w -
rsp _ pun
wi ygin z/w
e ol lr ol Jcszt kt
a Znormalizowane wsprzdne urzdzenia
otrze
tedn
qi obcinania

e
rzch
Przeksztacenie
okna
(take macierz)

Wsprzdne okna

Nastpnie wierzchoek jest mnoony przez macierz widoku modelu, okrelajc wsp-
rzdne ukadu obserwatora. Wsprzdne ukadu obserwatora s mnoone przez macierz
rzutowania, a nastpnie obcinane przez wsprzdne obcinania. Powoduje to wyelimi-
nowanie wszystkich danych poza bry widzenia. Obcite wsprzdne s nastpnie
208 Cz II Uywanie <

dzielone przez wsprzdn w, w celu otrzymania znormalizowanych wsprzdnych!


urzdzenia (punkt jest rzutowany perspektywicznie). Warto w moe by zmodyfik wana
przez przeksztacenie rzutowania lub przeksztacenie widoku modelu, w zaleno-j ci od
zastosowanych przeksztace. Oczywicie, OpenGL i wysokopoziomowe funkcje operacji
na macierzach ukrywaj wszystkie szczegy zwizane z obliczeniami.
Na koniec, trjka wsprzdnych jest odwzorowywana na dwuwymiarow paszcz okna;
suy do tego przeksztacenie okna. To przeksztacenie take jest reprezentov przez
macierz, ale nie okrelasz jej ani nie modyfikujesz bezporednio. OpenGL twr j sam w
oparciu o wartoci przekazane funkcji glYiewport.

Macierz widoku modelu


Macierz widoku modelu to macierz 4 x 4 , reprezentujca przeksztacony ukad wsp
rzdnych, uywany do rozmieszczania i orientowania obiektw. Wierzchoki twr;
prymitywy s uywane jako jednokolumnowa macierz, przemnaana przez macierz i doku
modelu w celu obliczenia nowych wsprzdnych, przeksztaconych wzgl ukadu
obserwatora.
Na rysunku 7.9 macierz zawierajca wsprzdne pojedynczego wierzchoka jest mn ona
przez macierz widoku modelu w celu otrzymania nowych wsprzdnych w ukj dzie
obserwatora. Dane wierzchoka zawieraj w rzeczywistoci cztery elementy, w l rych
dodatkowy element, warto w, reprezentuje wspczynnik skalowania. Ta wa jest
domylnie ustawiana na 1,0 i rzadko bdziesz zmienia j samodzielnie.

Rysunek 7.9.
Rwnanie macierzowe
opisujce przeksztacenie
widoku modelu dotyczce
pojedynczego wierzchoka

Przesunicie
Spjrzmy na przykad modyfikujcy macierz widoku modelu. Powiedzmy, e chcea
narysowa kostk za pomoc funkcji auxWireCube() z biblioteki AUX. Wywoamy]
prostu
auxWireCube(10.Of);

i mamy kostk umieszczon w rodku ukadu wsprzdnych, z krawdziami o dugcj


dziesiciu jednostek. Aby przed narysowaniem kostki przesun j w gr osi y oj
jednostek, musimy przemnoy macierz widoku modelu przez macierz opisujc] sunicie
w gr osi y o 10 jednostek, a dopiero potem narysowa kostk. W szkiek wej formie, kod
wygldaby mniej wicej tak:
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 209

// Konstruowanie macierzy przesunicia o 10 jednostek w gr osi Y //

Przemnoenie j e j przez macierz widoku modelu

// Narysowanie kostki
auxWireCube( l O . O f );

W rzeczywistoci tak macierz konstruuje si bardzo prosto, jednak wymaga to sporo


linii kodu. Na szczcie mamy do dyspozycji specjaln funkcj wyszego poziomu:
void glTranslatef(GLfloat x, GLfloat y, GLfloat z ) ;

Parametry tej funkcji okrelaj przesunicie w osi x, y oraz z. W ten sposb tworzona jest
odpowiednia macierz i wykonywane jest mnoenie. Teraz podany wyej pseudokod moe
wyglda nastpujco, za efekt jego dziaania jest przedstawiony na rysunku 7.10.
// Przesunicie w gr osi Y o 10 jednostek
glTranslatef( O . O f , 10.Of, O . O g ) ;

// Narysowanie kostki
auxWireCube( l O . O f );

Rysunek 7.10.
Kostka przesunita
o 10 jednostek w
gr osi y

Obrt
Aby obrci obiekt wok jednej z trzech osi, musielibymy utworzy macierz obrotu i
przemnoy j przez macierz widoku modelu. Jednak take w tym przypadku mamy do
dyspozycji specjaln funkcj:
glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) ;

Ta funkcja obraca obiekt o kt angle wok linii wyznaczonej przez wektor [x, y, z].
Kierunek obrotu jest okrelany w stopniach w kierunku przeciwnym do ruchu wska-
zwek zegara. W najprostszym przypadku obrt nastpuje wok jednej z osi, tak e
musi zosta podana tylko jedna warto.

Moesz take wykonywa obrt wok dowolnej osi, przekazujc wartoci x, y i z


okrelajce wektor wyznaczajcy o obrotu. Aby zobaczy o obrotu, moesz po prostu
narysowa lini biegnc od rodka ukadu do punktu o wsprzdnych (x, y, z).
Poniszy kod obraca kostk o 45 stopni wok zadanej osi, okrelonej wektorem [1,1, 1];
ilustruje to rysunek 7.11.
210 Cz II Uywanie
OpenGL

// Wykonanie przeksztacenia
glRotatef(45.Of, l.Of, l.Of, l . O f ) ;

// Narysowanie kostki
auxWireCube(10.0f);

Rysunek
7.11.
Kostka obrcona
wok zadanej osi

Skalowanie

Skalowanie powoduje zwikszenie lub zmniejszenie obiektu we wszystkich trzech


osiach o zadane wspczynniki. Funkcja
glScalef(GLfloat x, GLfloat y, GLfloat z ) ;
mnoy wsprzdne x, y i z obiektu przez podane
wspczynniki.
Skalowanie nie musi by jednorodne. Moesz uy go take do cinicia" lub rozci-
gnicia obiektu. Poniszy kod tworzy prostopadocian o wikszej szerokoci dwa razy ni
wysokoci, a wysokoci takiej samej jak kostki w poprzednich przykadach. Wynik
widzimy na rysunku 7.12.
// Wykonanie skalowania glScalef
( 2 . Of, l.Of, 2 . 0 f ) ;
// Narysowanie kostki
auxWireCube( l O . O f );
Rysunek
7.12.
Niejednorodne
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________211

Macierz tosamociowa
Z pewnoci zastanawiasz si, czemu suya wstpna dyskusja o macierzach. Czy nie
moglibymy po prostu uywa funkcji przesuwajc obiekty we waciwe miejsca? Czy
rzeczywicie powinno obchodzi nas to, e modyfikowana jest macierz widoku modelu?
Odpowied brzmi: i tak, i nie, ale tylko w przypadku rysowania w scenie pojedynczego
obiektu. Powodem jest to, e efekty uycia tych funkcji si kumuluj. Za kadym
razem, gdy wywoujesz jedn z tych funkcji, tworzona jest odpowiednia macierz, ktra jest
mnoona przez macierz widoku modelu. Otrzymana w wyniku macierz staje si now
macierz widoku modelu, modyfikowan przez nastpne przeksztacenie, itd.
Przypumy, e chcemy narysowa dwie kule: jedn o 10 jednostek w kierunku osi y i
jedn o 10 jednostek w kierunku osi x, tak jak pokazano na rysunku 7.13. Mgby pokusi
si o napisanie kodu wygldajcego mniej wicej tak:
// Przejcie o 10 jednostek w kierunku osi y
glTranslatef(O.Of, 10.Of, O . O f ) ;
// Narysowanie pierwszej kuli
auxSolidSphere(1.0f);

// Przejcie o 10 jednostek w kierunku osi x


glTranslatef(10.Of, O.Of, O . O f ) ;
// Narysowanie drugiej kuli
auxSolidSphere(1.0f);

Rysunek 7.13.
Dwie kule narysowane na osiach y ix

We jednak pod uwag, e kade wywoanie


funkcji glTranslate jest kumulowane w
macierzy widoku modelu, wic drugie
wywoanie przesunie kul o dziesi jednostek w
dodatnim kierunku x wzgldem
poprzedniego przesunicia w kierunku osi y.
W ten sposb powstanie scena pokazana na
rysunku 7.14.
212 Cz II Uywanie OpenGL

Rysunek 7.14.
Wynik dwch
kolejnych przesuni

10

Mgby zastosowa dodatkowe wywoanie funkcji glTranslate w celu wycofania si o


10 jednostek w d osi y, ale w przypadku rozbudowanych scen kod staby si bardzo
skomplikowany i trudny do debuggowania. Prostsz metod jest ustawienie macierzy
widoku modelu w znany stan - w tym przypadku, ustalenie pooenia na pocztku
ukadu wsprzdnych obserwatora.

Osiga si to poprzez zaadowanie do macierzy widoku modelu macierzy tosamociowej.


Macierz tosamociowa okrela e nie jest wykonywane adne przeksztacenie, w
efekcie powodujc e wszystkie podawane wsprzdne s podawane w ukadzie
wsprzdnych obserwatora. Macierz tosamociowa zawiera same zera, z wyjtkiem
elementw wystpujcych na przektnej macierzy, ktre maj warto 1. Gdy macierz
tosamociowa jest mnoona przez jakkolwiek macierz wierzchoka, w wyniku otrzymujemy
niezmienion macierz tego wierzchoka. To rwnanie przedstawia rysunek 7.15.

Rysunek 7.15. 8.0 1.0 0 0 0 8.


Po przemnoeniu
macierzy wierzchoka 4.5 0 1.0 0 0 0
przez macierz 4.
tosamociow
-2.0 0 0 1. 0
otrzymujemy 1.0 0 0 0
0 1.0 5-
niezmienion macierz
wierzchoka

Jak ju ustalilimy, szczegy wykonywania operacji na macierzach wykraczaj poza


ramy tej ksiki. Wystarczy, e zapamitasz, i zaadowanie macierzy tosamociowej
oznacza, e na wierzchokach nie zostanie wykonane adne przeksztacenie. Po prostu w
ten sposb przywracasz pocztkowy stan macierzy widoku modelu.

Ponisze dwie linie kodu aduj macierz tosamociow do macierzy widoku modelu:
glMatrixMode(GL_MODELVIEW);
glLoadldentity(};

Pierwsza linia okrela, e bdziemy si odwoywa do macierzy widoku modelu. Gdy


ustawisz biec macierz robocz (macierz, do ktrej odnosz si funkcje operujce na
macierzach), pozostaje ona biec, a sam wskaesz inn macierz. Druga linia aduje
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________213

macierz tosamociow do biecej macierzy (w tym przypadku do macierzy widoku


modelu).
Poniszy kod tworzy scen przedstawion na rysunku 7.13:
// Uczynienie macierzy widoku modelu macierz biec i wyzerowanie
// j e j
glMatrixMode(GL_MODEVIEW);
glLoadldentity() ;

// Przejcie o 10 jednostek w gr osi y


glTranslatef( O . O f , 10.Of, O . O f ) ;

// Narysowanie pierwszej kuli


auxSolidSphere(l.Of} ;

// Ponowne wyzerowanie macierzy widoku modelu


glLoadldentity();
// Przejcie o 10 jednostek w kierunku osi x
glTranslatef(10.Of, O . O f , O . O f } ;
// Narysowanie drugiej kuli
auxSolidSphere( l . O f );

Stosy macierzy
Nie zawsze zerowanie macierzy widoku modelu, przed umieszczeniem w scenie kolejnego
obiektu, jest podane. Czsto wygodnie jest zachowa biecy stan macierzy, a
nastpnie odtworzy go po umieszczeniu innych obiektw. Jest to szczeglnie uyteczne,
gdy na pocztku przygotujesz macierz widoku modelu jako macierz widoku sceny (czyli
punkt obserwacji nie znajduje si ju na pocztku ukadu wsprzdnych).
Aby to umoliwi, OpenGL tworzy stos macierzy dla macierzy widoku modelu oraz
macierzy rzutowania. Stos macierzy dziaa tak, jak kady stos programowy. Moesz
umieci biec macierz na stosie w celu zachowania jej stanu, a potem odpowiednio
przeksztaci grup nastpnych obiektw. Gdy zechcesz odtworzy stan macierzy, po
prostu zdejmiesz j ze stosu. Ilustruje to rysunek 7.16.
Rysunek 7.16.
Dziaanie stosu
macierzy

Stos macierzy
214 Cz II Uywanie OpenGL

Stos macierzy tekstur


Stos macierzy tekstur jest jeszcze jednym stosem dostpnym
dla programisty. Jest uywany przy przeksztaceniach
wsprzdnych tekstur. Mapowanie i wsprzdne tekstur
zostan omwione w rozdziale 12.

Stos moe osign maksymaln wysoko, ktr mona odczyta za pomoc wywoa
glGet(GL_MAX_MODELVIEW_STACK_DEPTH);

lub
glGet(GL_MAX_PROJECTION_STACK_DEPTH) ;

Jeli zostanie przekroczona maksymalna wysoko stosu, wystpi bd GL_STACK_


OYERFLOW; jeli sprbujesz zdj macierz z pustego stosu, wystpi bd GL_
STACK_UNDERFLOW. Wysoko stosu jest zalena od implementacji. W przypadku
programowej implementacji Microsoftu, maksymalna wysoko stosu wynosi 32 dla
stosu macierzy widoku modelu, a 2 dla stosu macierzy rzutowania.

Atomowy przykad
Sprbujmy zastosowa nabyt wiedz w praktyce. W nastpnym przykadzie zbudujemy
prosty, animowany model atomu. W rodku atomu umiecimy pojedyncz kul,
reprezentujc jdro, dookoa ktrego bd porusza si trzy elektrony. Uyjemy rzuto-
wania rwnolegego, tak jak we wszystkich poprzednich przykadach w ksice. (Inne
interesujce rzutowania zostan omwione w nastpnej sekcji, Rzutowania").

Rysunek 7.17.
Dziaanie programu ATOM

Nasz program ATOM,


korzystajc z timera,
przesuwa elektrony cztery
razy w cigu sekundy (czyli
o wiele wolniej, ni poruszaj
si prawdziwe elektrony!).
Za kadym razem, gdy
wywoywana jest funkcja
RenderScene, zwikszany
jest kt obrotu elektronu
dookoa jdra. Ponadto
kady elektron kry w innej
paszczynie. Funkcja RenderScene z tego
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________215

przykadu jest przedstawiona na listingu 7.1, za wynik dziaania programu widzimy na


rysunku 7.17.

Listing 7.1. Funkcja rysunkowa z programu


ATOM______________________________
// Wywoywane w celu narysowania sceny
void RenderScene(void)
{
// Kt obrotu dookoa jdra
static float fElectl = O.Of;
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Wyzerowanie macierzy widoku modelu


glMatrixMode(GL_MODELVIEW);
glLoadldentity();
// Przeksztacenie caej sceny do ukadu obserwatora //
To jest pocztkowe przeksztacenie widoku
glTranslatef( O . O f , O . O f , -100.O f ) ;
// Czerwone jdro
glRGB(255, O, 0);
auxSolidSphere(10.0f);
// te elektrony
glRGB(255,255,0);

// Orbita pierwszego elektronu


// Zachowanie przeksztacenia widoku
glPushMatrix ();
// Obrt o kt
glRotatef(fElectl, O . O f , l.Of, O . O f ) ;

// Przesunicie elektronu z pocztku ukadu na orbit


glTranslatef( 9 0 . Of, O.Of, O . O f ) ;
// Rysowanie elektronu
auxSolidSphere( 6. Of) ;

// Odtworzenie przeksztacenia widoku


glPopMatrix ();

// Orbita drugiego elektronu


glPushMatrix () ;
glRotatef(45.Of, O.Of, O.Of, l . O f ) ;
glRotatef(fElectl, O.Of, l.Of, O . O f ) ;
glTranslatef(-70.Of, O.Of, O . O f ) ;
auxSolidSphere( 6 . 0 f );
glPopMatrix () ;
// Orbita trzeciego elektronu
glPushMatrix();
glRotatef(360.Of-45.0f,O . O f , O . O f , l . O f ) ;
glRotatef(fElectl, O . O f , l . O f , O . O f ) ;
glTranslatef( O . O f , O . O f , 60.O f ) ;
auxSolidSphere(6.Of);
glPopMatrix();
216 Cz II * Uywanie OpenGL

// Zwikszenie ka_ta obrotu


fElectl += 10.O f ; if(fElectl >
360.O f ) fElectl = O . O f ;

// Zrzucenie polece graficznych


glFlush() ;

Przeanalizujmy kod umieszczajcy jeden z elektronw, omawiajc po kilka linii naraz.


Pierwsza linia zachowuje biecy stan macierzy widoku modelu, odkadajc na stos biece
przeksztacenie:
// Orbita pierwszego elektronu
// Zachowanie przeksztacenia widoku
glPushMatrix () ;

Nastpnie ukad wsprzdnych jest obracany dookoa osi y o kt fElectl:


II Obrt o kt
glRotatef(fElectl, O . O f , l . O f , O . O f ) ;

Nastpnie umieszczamy elektron na orbicie, przesuwajc obrcony ukad wsprzdnych:


// Przesunicie elektronu z pocztku ukadu na orbit
glTranslatef( 9 0 . Of, O . O f , O . O f ) ;

Potem nastpuje rysowanie elektronu (w postaci kuli), po czym jest odtwarzany stan
macierzy widoku modelu, przez zdjcie jej ze stosu macierzy:
// Rysowanie elektronu
auxSolidSphere( 6 . 0 f );

// Odtworzenie przeksztacenia widoku


glPopMatrix();

Te operacje powtarzaj si dla pozostaych elektronw.

Rzutowania
Do tej pory w przykadach uywalimy macierzy widoku modelu do umieszczania punktu
obserwacji oraz do rozmieszczania obiektw w scenie. Macierz rzutowania okrela za
rozmiar i ksztat naszej bryy widzenia.

Jak dotd, cay czas tworzylimy zwyk, prostopadocienn bry widzenia, za pomoc
funkcji glOrtho okrelajc pooenie bliszej, dalszej, lewej, prawej, grnej oraz dolnej
paszczyzny obcinania. Gdy do macierzy rzutowania zostanie zaadowana macierz
tosamociowa, brya widzenia zajmuje przestrze od rodka ukadu do punktu o
wsprzdnych rwnych l dla wszystkich trzech osi - macierz rzutowania nie
realizuje zatem adnego skalowania ani perspektywy. Jak si wkrtce przekonamy, nie jest
to jedyna moliwo, jak mamy do dyspozycji.
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 217

Rzutowanie rwnolege
W rzutowaniu rwnolegym, ktrego uywalimy do tej pory najczciej, brya
widzenia ma ksztat prostopadocienny, a zatem szeroko logiczna obiektu mierzona
wzdu przeciwlegych paszczyzn (tylnej i przedniej, grnej i dolnej, lewej i prawej)
jest identyczna. Daje to w efekcie rzut rwnolegy, odpowiedni dla zobrazowania
obiektw, dla ktrych chcemy unikn znieksztacenia perspektyw. Rzutowanie takie jest
przydatne w programach CAD i rysunkach architektonicznych (w izometriach), w
ktrych chcemy zachowa waciwe rozmiary i proporcje obiektw.

Rysunek 7.18 przedstawia wynik dziaania przykadowego programu ORTHO z pytki


CD-ROM. W celu utworzenia tego wydronego pudeka uylimy rzutowania rwno-
legego, tak jak we wszystkich poprzednich przykadach.
Rysunek 7.18.
Wydrone pudeko
przedstawione w
rzucie rwnolegym

Rysunek 7.19 przedstawia ten obiekt lekko obrcony, aby mg si zorientowa jak
wyglda z boku.

Rysunek 7.19.
Dopiero po
obrceniu obiektu
moemy zorientowa
si co do jego
dugoci

Na rysunku 7.20 patrzymy dokadnie w kierunku pudeka. Poniewa w tym widoku pu-
deko nie zwa si wraz ze wzrostem odlegoci, nie jest to obraz zbliony do rzeczy-
wistego. Aby uzyska perspektyw, zastosujemy rzutowanie perspektywiczne.
218 Cz II * Uywanie OpenGL

Rysunek 7.20.
Wydrone pudeko
widziane prosto od
frontu

Rzutowanie perspektywiczne
W rzutowaniu perspektywicznym otrzymujemy efekt zmniejszania si obiektw wraz ze
wzrostem ich odlegoci od obserwatora. Szeroko tylnej paszczyzny bryy widzenia jest
rna od szerokoci paszczyzny przedniej. Tak wic obiekt pooony przy przedniej czci
bryy widzenia jest rysowany jako wikszy ni takie same obiekty pooone w dalszych
czciach bryy widzenia.

Obrazem w naszym nastpnym przykadzie bdzie geometryczny ksztat zwany ostro-


supem widzenia. Ostrosup widzenia stanowi cz piramidy, widzianej od strony
wierzchoka. Ostrosup widzenia jest pokazany na rysunku 7.21; widzimy tam take po-
oenie oka obserwatora.
Rysunek 7.21. Perspektywiczna brya widzenia
Rzutowanie
perspektywiczne
okrelone przez
ostrosup widzenia

Do definiowania ostrosupa widzenia suy funkcja glFrustum. Jej parametrami s


wsprzdne oraz odlego pomidzy przedni a tyln paszczyzn obcinania. Jednak
funkcja glFrustum nie jest zbyt intuicyjna, jeli chodzi o uzyskanie podanego efektu.
atwiej jest uy funkcji gluPerspective, umoliwiajcej bardziej intuicyjne okrelenie
perspektywy:
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear,
^GLdouble zFar) ;

Parametrami tej funkcji s kt pola widzenia w kierunku pionowym (fovy\ stosunek


wysokoci do szerokoci bryy (aspect) oraz odlegoci do bliszej i dalszej paszczyzny
obcinania (zNear i zFar), przedstawione na rysunku 7.22. Stosunek wysokoci do szero-
r
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych 219

koci jest obliczany przez podzielenie wysokoci (h) przez szeroko (w) przedniej pa-
szczyzny obcinania.

Rysunek 7.22.
Ostrosup widzenia
definiowany funkcj
gluPerspective

Listing 7.2 przedstawia zmodyfikowany program rzutowania rwnolegego z poprze-


dniego przykadu, w ktrym tym razem zastosowano rzutowanie perspektywiczne.
Dziki temu uzyskujemy bardziej realistyczny obraz wydronego pudeka, pokazany na
rysunkach 7.23, 7.24 oraz 7.25. Jedyn znaczc zmian w kodzie przedstawionym na
listingu 7.2 jest dodanie wywoania funkcji gluPerspective.

Rysunek 7.23.
Wydrone pudeko
vi rzucie
perspektywicznym

Rysunek 7.24.
Pudeko "widziane
z boku; wyranie
wida efekt
zbiegania si.
krawdzi
220___________________ Cz II Uywanie
OpenGL

Rysunek 7.25.
Spogldanie w gb pudeka przy
zastosowanym rzutowaniu
perspektywicznym

Listing 7.2. Przygotowanie rzutowania


perspektywicznego w przykadowym
programie PERSPECT

// Zmiana bryy
widzenia i widoku.
// Wywoywane w
momencie zmiany
wymiaru okna
void
ChangeSize(GLsizei
w, GLsizei h)
{
GLfloat fAspect;

// Zabezpieczenie przed dzieleniem przez O i f ( h


== 0) h = 1;

// Ustawienie widoku na rozmiar okna


glViewport( O , O, w, h ) ;

fAspect = (GLfloat)w/(GLfloat)h;

// Wyzerowanie ukadu wsprzdnych


glMatrixMode(GL_PROJECTION);
glLoadldentity();

// Przygotowanie rzutowania perspektywicznego


gluPerspective( 6 0 . Of, fAspect, 1 . 0 , 4 0 0 . 0 ) ;

glMatrixMode(GL_MODELVIEW);
glLoadldentity();

Przykad daleko-blisko
Aby uzupeni przykady manipulowania przeksztaceniami widoku modelu i rzutowania,
przygotowalimy program stanowicy model dziaania ukadu sonecznego. W celu
uzyskania lepszego efektu wczylimy owietlenie i cieniowanie, dziki czemu lepiej
wida efekt dziaania programu. O cieniowaniu i owietleniu bdziemy mwi w dwch
nastpnych rozdziaach.
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 221

W naszym modelu Ziemia porusza si dookoa Soca, za Ksiyc obiega Ziemi, rdo
wiata zostao umieszczone za plecami obserwatora, tak aby owietlao Soce.
Nastpnie jest przesuwane na rodek Soca, tak aby owietlao Ziemi i Ksiyc od
strony Soca, dziki czemu otrzymujemy fazy ksiyca. To doskonay przykad, jak
atwo mona uzyska realistyczne efekty w OpenGL.
Listing 7.3 przedstawia kod przygotowujcy rzutowanie oraz kod renderujcy, utrzymujcy
system w ruchu. Timer, zdefiniowany w innym miejscu programu, cztery razy na
sekund uniewania obszar okna, wymuszajc odwieenie jego zawartoci. Spogldajc na
rysunki 7.26 i 7.27, zwr uwag e Ziemia, gdy znajduje si bliej nas, jest wiksza ni
wtedy, gdy znajduje si po drugiej stronie Soca.

Rysunek 7.26.
Ukad soneczny z
Ziemi pooon
dalej

Rysunek 7.27.
Ukad soneczny z
Ziemi po dalszej
stronie

Listing 7.3. Fragmenty kodu przykadowego programu SOLAR

// Zmiana bryy widzenia i widoku. Wywoywane w momencie zmiany


// wymiaru okna
void ChangeSize(GLsizei w, GLsizei h)
222____________________________________Cz I Uywanie OpenGL

{
GLfloat fAspect;
// Zabezpieczenie przed dzieleniem przez O
i f ( h == 0) h 1;
// Ustawienie widoku na rozmiar okna
glViewport( O , O, w, h ) ;
// Obliczenie stosunku dugoci bokw okna
fAspect = (GLfloat)w/(GLfloat)h;
// Wyzerowanie ukadu wsprzdnych
glMatrixMode(GL_PROJECTION);
glLoadldentity();
// Kt widzenia 45 stopni, blisza i dalsza paszczyzna 1 . 0 i 425
gluPerspective( 4 5 . Of, fAspect, 1 . 0 , 4 2 5 . 0 ) ;
// Zerowanie macierzy widoku modelu
glMatrixMode(GL_MODELVIEW);
glLoadldentity();

// Wywoywane w celu narysowania sceny


void RenderScene(void)
// Kty obrotu Ksiyca i Ziemi
static float fMoonRot = O . O f ;
static float fEarthRot = O . O f ;
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glMatrixMode(GL_MODELVIEW); glPushMatrix();

// Umieszczenie rda wiata przed przeksztaceniem widoku


glLightfv(GL_LIGHTO,GL_POSITION,lightPos) ;

// Przeksztacenie caej sceny do ukadu obserwatora


glTranslatef( O . O f , O.Of, -300.O f ) ;
// Ustawienie koloru materiau na czerwony //
Soce
glRGB(255, 255, 0);
auxSolidSphere(15.0f);
// Przesuwamy rdo wiata po narysowaniu soca!
glLightfv(GL_LIGHTO,GL_POSITION,lightPos) ;
// Obrt ukadu wsprzdnych
glRotatef(fEarthRot, O.Of, l.Of, O . O f ) ;
// Rysowanie Ziemi
glRGB(0,0,255);
glTranslatef(105.Of,O.Of,O . Of) ;
auxSolidSphere(15.0f);
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________223

// Obrt wzgldem ukadu wsprzdnych Ziemi i narysowanie //


Ksiyca glRGB(200,200,200);
glRotatef(fMoonRot, O.Of, l . O f , O . O f ) ;
glTranslatef(30.Of, O . O f , O . O f ) ;
fMoonRot+= 15.O f ; if(fMoonRot > 360.Of)
fMoonRot = O . O f ;
auxSolidSphere(6.0f);

// Wyzerowanie stanu macierzy


glPopMatrix(); // Macierz widoku modelu

// Zwikszenie kta obrotu wok Soca o 5 stopni


fEarthRot += 5 . 0 f ; i f ( fEarthRot > 360.Of) fEarthRot =
O.Of;
// Zrzucenie polece graficznych
glFlushO ;

Zaawansowane operacje na macierzach


Przy tworzeniu przeksztace nie musisz korzysta z funkcji wysokiego poziomu. Zale-
camy jednak korzystanie z nich, gdy zwykle maj one konkretne przeznaczenie i s
pod tym wzgldem wysoce zoptymalizowane, podczas gdy funkcje niskiego poziomu
maj zastosowanie bardziej oglne. Dwie z funkcji wysokiego poziomu umoliwiaj za-
adowanie wasnej macierzy i umieszczenie jej na stosie macierzy widoku modelu lub
rzutowania.

adowanie macierzy
Do macierzy rzutowania, widoku modelu lub tekstury moesz zaadowa dowoln ma-
cierz. W tym celu musisz najpierw zadeklarowa tablic szesnastu wartoci, tworzc
macierz o wymiarach 4 x 4 . Uczy dan macierz biec, a nastpnie wywoaj funkcj
glLoadMatrix.
Macierz jest przechowywana w kolejnoci kolumn, co oznacza, e ka2da kolumna jest
kolejno przegldana od gry do dou. Numery kolejnych elementw przedstawia ry-
sunek 7.28. Poniszy kod pokazuje przebieg wypeniania tablicy macierz tosamo-
ciow, a nastpnie adowanie t tablic macierzy widoku modelu. Przedstawiony kod
stanowi odpowiednik funkcji wyszego poziomu, glLoadldentity.
224 Cz II Uywanie OpenGL

Rysunek 7.28. 04 03
Kolejno 5 9
Q
numerowania
2
elementw macierzy ' ^O "14
03 07 On " 1 5

// Odpowiednik, ale bardziej elastyczny


glFloat m [ ] = { l . O f , O . O f , O . O f , O . O f ,
O.Of, l.Of, O.Of, O.Of,
O.Of, O.Of, l.Of, O.Of,
O . O f , O . O f , O . O f , l.Of };

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf( m ) ;

Tworzenie wasnych przeksztace


Moesz zaadowa tablic dowolnymi wasnymi wartociami, a nastpnie przemnoy j
przez jedn z trzech macierzy. Poniszy kod przedstawia macierz przeksztacenia,
przesuwajc wsprzdne o 10 jednostek wzdu osi x. Ta macierz jest nastpnie mnoona
przez macierz widoku modelu. Ten sam efekt moesz otrzyma wywoujc funkcj
glTranslatef.
// Definicja macierzy przesunicia glFloat
m [ ) = { l.Of, O.Of, O.Of, 10.Of,
O . O f , l.Of, O . O f , O . O f ,
O.Of, O.Of, l.Of, O.Of,
O.Of, O.Of, O.Of, l.Of };

// Przemnoenie macierzy przesunicia przez biec macierz widoku //


modelu. Otrzymana macierz stanie si now macierz widoku modelu.
glMatrixMode(GL_MODELVIEW); glMultMatrixf( m ) ;

Inne przeksztacenia
Z powielania dziaania funkcji glLoadldentity czy glTranslatef nie pyn adne szcze-
glne korzyci. Rzeczywistym powodem korzystania z moliwoci wypenienia macierzy
dowolnymi wartociami jest tworzenie zoonych przeksztace macierzowych. Jedno
z takich przeksztace jest uywane do rysowania cieni, zajmiemy si tym w rozdziale 9.
Inne przeksztacenia umoliwiaj zawinicie obiektu dookoa innego obiektu lub
uzyskanie pewnych efektw soczewek. Informacje o tych zaawansowanych zastosowaniach
znajdziesz w dodatku B.

Podsumowanie
W tym rozdziale poznae koncepcje majce podstawowe znaczenie dla tworzenia trj-
wymiarowych scen w OpenGL. Nawet jeli nie potrafisz przemnoy macierzy w myli,
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 225

wiesz ju przynajmniej, czym jest macierz i jakie ma zastosowanie przy przekszta-


ceniach. Wiesz ju take jak manipulowa macierzami rzutowania i widoku modelu, co
umoliwia rozmieszczenie i przedstawienie obiektw w scenie.

Na koniec, poznae take funkcje umoliwiajce samodzielne tworzenie macierzy prze-


ksztace, jeli zajdzie taka potrzeba. Te funkcje umoliwiaj zaadowanie macierzy
dowolnymi wartociami lub te zaadowanie macierzy, a nastpnie przemnoenie jej
przez inn macierz.

Program symulacji czogu/robota w tym rozdziale umoliwia ju poruszanie si w trjwy-


miarowym wiecie i ogldanie rozmieszczonych w nim obiektw. Jeli przeanalizujesz
kod tego programu, lepiej poznasz sposb wykorzystania rzutowania perspektywicznego
oraz uycia funkcji narzdziowej gluLookAt, uatwiajcej okrelenie przeksztacenia
punktu obserwacji. W tym momencie trjwymiarowy wiat skada si jedynie ze szkie-
letowych bry, ale ta sytuacja ju wkrtce si zmieni.

Podrcznik
glFrustum
Przeznaczenie Mnoy biec macierz przez macierz rzutowania perspektywicznego.
Plik
nagwkowy void glFrustum(GLdouble left, GLdouble right, GLdouble bottom,
GLdouble top, GLdouble near, GLdouble far);
Skadnia
Ta funkcja tworzy macierz rzutowania perspektywicznego, tworzc rzut
perspektywiczny. Zakada si w nim, e oko jest pooone w punkcie (O, O,
0), za far okrela odlego do dalszej paszczyzny obcinania, a near -
bliszej. Ta funkcja moe zakci precyzj dziaania bufora gbokoci,
jeli stosunek odlegoci dalszej do bliszej (far/near) jest duy.
Parametry
left, right GLdouble: Wsprzdne lewej i prawej paszczyzny obcinania.
bottom, top GLdouble: Wsprzdne grnej i dolnej paszczyzny obcinania.
near,far GLdouble: Odlego do bliszej i dalszej paszczyzny obcinania. Obie
wartoci musz by dodatnie.
Zwracana Brak
warto Poniszy kod przygotowuje macierz rzutowania perspektywicznego,
definiujc bry widzenia od O do 100 jednostek w osi z. W osiach x i y
brya rozciga si na 100 jednostek w kadym kierunku:
226 Cz II Uywanie

glMatrixMode(GL_PROJECTION); glLoadldentity(); PrzyU


glFrustum(-100.0f,100.0f,-100.0f,100.0f,O.Of,100.0f);
glOrtho, glMatrixMode, glMultMatrix, glYiewport
Patrz take

glLoadldentity
Przeznaczenie Plik Zeruje biec macierz do macierzy tosamociowej.
nagwkowy
Skadnia Opis void glLoad!dentity(void);
Pa
Funkcja zastpuje zawarto biecej macierzy przeksztacenia
zawartoci macierzy tosamociowej, czyli innymi sowy, zeruje ukad
Zwracana warto wsprzdnych do ukadu wsprzdnych obserwatora.
Przykad Brak J
P
Poniszy kod ilustruje zerowanie macierzy widoku modelu:
glMatrixMode(GL_MODELVIEW);
Patrz take glLoadldentity();
glLoadMatrix, glMatrixMode, glMultMatrix, glPushMatrix

glLoadMatrix
Przeznaczenie aduje wskazan macierz do biecej macierzy.
Plik nagwkowy <gl.h>
Skadnia void glLoadMatrixd(const GLdouble *m);
void glLoadMatrixf(const GLfloat *m);
Opis Zastpuje zawarto biecej macierzy przeksztacenia zawartoci
wskazanej tablicy. Czasem jednak bardziej efektywne moe by uycie
specjalnych funkcji przeznaczonych do przygotowywania przeksztace,
takich jak glLoadldentity, glRotate, glTranslate czy glScale.
Parametry
K
OT GLdouble lub GLfloat: Ta tablica reprezentuje macierz o rozmiarach
4x4, ktra zostanie zaadowana do biecej macierzy przeksztacenia.
Macierz jest zapisana w formie tablicy szesnastu wartoci,
interpretowanych kolumnami, od lewej do prawej strony.
Zwracana warto Brak
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________227

Przykad Ponisze dwa segmenty kodu s sobie rwnowane. Oba fragmenty


aduj macierz tosamociow do macierzy widoku modelu.
// Sposb bardziej efektywny
glMatrixMode(GL_MODELVIEW);
glLoadldentity();

// To samo, ale oferujce wiksz elastyczno


glFloat m [ ] = { l.Of, O.Of, O.Of, O.Of,
O.Of, l.Of, O . O f , O.Of,
O.Of, O . O f , l.Of, O . O f ,
O.Of, O.Of, O.Of, l.Of
}; glMatrixMode(GL_MODELVIEW);
glLoadMatrixf( m ) ;
Patrz take glLoadldentity, glMatrixMode, glMultMatrix, glPushMatrix

glMatrixMode_______________________
Przeznaczenie Okrela biec macierz (rzutowania, widoku modelu lub tekstury).
Plik nagwkowy <gl.h>
Skadnia void glMatrixMode(GLenum mod);
Opis Ta funkcja jest uywana do wybierania stosu macierzy, ktry bdzie
wykorzystywany w nastpnych operacjach macierzowych.
Parametry
mod GLenum: Identyfikuje stos macierzy, ktry bdzie uywany w nastpnych
operacjach macierzowych. Dozwolone s wartoci zebrane w tabeli 7.2.
Zwracana warto Brak
Przykad Ponisze dwie standardowe linie kodu wybieraj do dziaania macierz
widoku modelu, a nastpnie aduj do niej macierz tosamociow.
glMatrixMode(GL_MODELVIEW);
glLoadldentityO;
Patrz take glLoadMatrix, glPushMatrix

Tabela 7.2.
Dostpne wartoci parametru funkcji glMatrixModeQ

Tryb (parametr mod) Stos macierzy

GL_MODELVIEW Operacje macierzowe bd si odnosiy do stosu macierzy widoku


modelu
(uywanego do rozmieszczania elementw w scenie).
GL_PROJECTION Operacje macierzowe bd si odnosiy do stosu macierzy
rzutowania
(uywanego do definiowania bryy obcinania).
GL_TEXTURE Operacje macierzowe bd si odnosiy do stosu macierzy
mapowania
tekstury (uywanego do manipulowania wsprzdnymi tekstur).
228 Cz II Uywanie OpenGL

g!MultMatrix
Przeznaczenie Mnoy biec macierz przez wskazan macierz.
Plik nagwkowy <gl.h>
Skadnia void glMultMatrixd(const GLdouble *m);
void glMultMatrixf(const GLfloat *m);
Opis Ta funkcja mnoybiec macierz przeksztacenia przez wskazan
macierz. Otrzymana macierz jest umieszczana, jako macierz bieca, na
szczycie stosu macierzy.
Parametry
*m GLdouble lub GLfloat. Ta tablica reprezentuje macierz o rozmiarach
4 x 4 , ktra zostanie przemnoona przez biec macierz. Macierz jest
zapisana w formie tablicy szesnastu wartoci, interpretowanych
kolumnami, od lewej do prawej strony.
Zwracana warto Brak
Przykad Poniszy kod tworzy macierz przesunicia i mnoyjprzez biec
macierz widoku modelu. Nowo utworzona macierz zastpuje macierz
biec. Przedstawione tu mnoenie macierzy moe zosta zastpione
przez wywoanie funkcji glTranslatef(10.0f, O.Of, O.Of);.
// Definicja macierzy przesunicia
glFloat m [ ] = { l.Of, O.Of, O.Of, 10.Of,
O.Of, l.Of, O.Of, O.Of,
O.Of, O . O f , l.Of, O . O f ,
O.Of, O.Of, O.Of, l.Of };

// Przemnoenie macierzy przesunicia przez


// biec macierz widoku modelu.
// Otrzymana macierz stanie si now macierz
// widoku modelu.
glMatrixMode(GL_MODELVIEW);
glMultMatrixf( m ) ;

Patrz take glMatrixMode, glLoadldentity, glLoadMatrix, glPushMatrix

glPopMatrix
Przeznaczenie Plik Zdejmuje biec macierz ze stosu macierzy.
nagwkowy Skadnia
void glPopMatrix(void);
Opis
Ta funkcja suy do pobierania ze stosu ostatniej umieszczonej na nim
macierzy. Najczciej wykorzystuje si j do przywrcenia poprzedniego
stanu biecej macierzy przeksztacenia, odoonej wczeniej na stos za
pomoc funkcji glPushMatrix.
Zwracana warto Brak
Rozdzia 7. Manipulowanie przestrzeni 3D: transformacje wsprzdnych__________229

Przykad Poniszy kod pochodzi z programu ATOM w tym rozdziale. Ten


fragment, przez wywoanie funkcji glPushMatrix, zachowuje na stosie
biecy stan macierzy widoku modelu (ustawionej na rodek atomu). Potem
nastpuje obrt i przesunicie ukadu wsprzdnych w celu umieszczenia
elektronu, reprezentowanego przez ma kulk. Przed narysowaniem
kolejnego elektronu przywracany jest poprzedni stan macierzy, przez
wywoanie funkcji glPopMatrix.
// Orbita pierwszego elektronu
// Zachowanie przeksztacenia widoku
glPushMatrix();
// Obrt o kt
glRotatef(fElectl, O . O f , l . O f , O . O f ) ;

// Przesunicie elektronu z pocztku ukadu na orbit


glTranslatef( 9 0 . Of, O . O f , O . O f ) ;
// Rysowanie elektronu
auxSolidSphere( 6 . 0 f );
// Odtworzenie przeksztacenia widoku
glPopMatrix();
Patrz take glPushMatrix

glPushMatrix_______________________
Przeznaczenie Umieszcza na stosie macierzy biec macierz przeksztacenia.
Plik nagwkowy <gl.h>
Skadnia void glPushMatrix(void);
Opis Ta funkcja jest uywana do umieszczenia biecej macierzy na szczycie
stosu macierzy. Najczciej celem tej operacji jest ch zachowania
biecego stanu macierzy, tak aby mc go pniej odtworzy
wywoaniem funkcji glPopMatrix.
Zwracana warto Brak
Przykad Zobacz glPopMatrix
Patrz take glPopMatrix

gIRotate
Przeznaczenie Mnoy biec macierz przez macierz obrotu.
Plik nagwkowy <gl.h>
Skadnia void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
230 Cz II Uywanie OpenGL

Opis Ta funkcja mnoy biec macierz przez macierz obrotu. Kt obrotu


okrelany jest w kierunku przeciwnym do ruchu wskazwek zegara, za sam
obrt jest wykonywany wok osi okrelanej przez wektor o pocztku w
centrum ukadu wsprzdnych i kocu w punkcie (x, y, z). Nowa obrcona
macierz staje si biec macierz przeksztacenia.
Parametry
angle GLdouble lub GLfloat: Kt obrotu w stopniach. Kat mierzony jest w
kierunku przeciwnym do ruchu wskazwek zegara.
x,y,z GLdouble lub GLfloat: Wsprzdne wektora okrelajcego kierunek osi
obrotu.

Zwracana warto Brak


Przykad Poniszy kod, pochodzcy z programu SOLAR w tym rozdziale, umieszcza
Ziemi na orbicie okoosonecznej. Bieca macierz widoku modelu jest
skierowana na rodek Ziemi, po czym zostaje obrcona o kt dla Ksiyca,
a nastpnie przesunita poza Ziemi.
// Ksiyc
glRGB(200,200,200);
glRotatef(fMoonRot,O.Of, l.Of, O . O f ) ;
glTranslatef(30.Of, O.Of, O . O f ) ;
fMoonRot+= l5.Of; if(fMoonRot > 360.Of)
fMoonRot = O . O f ;

auxSolidSphere(6.0f) ;

glScale, glTranslate
Patrz take

gIScale
Przeznaczenie Mnoy biec macierz przez macierz skalowania.
Plik <gl.h>
nagwkowy void glScaled(GLdouble x, GLdouble y, GLdouble z);
Skadnia void glScalef(GLfloat x, GLfloat y, GLfloat z);
Ta funkcja mnoybiec macierz przez macierz skalowania. Nowa
macierz staje si biec macierz przeksztacenia.
Opis

Parametry GLdouble lub GLfloat: Wspczynniki skalowania dla osi x, y i z.

x,y, z Brak

Zwracana Poniszy kod modyfikujc macierz widoku modelu tworzy spaszczone


obiekty. Wierzchoki we wszystkich nastpnych prymitywach zostan
spaszczone o poow w kierunku pionowym.
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 231

glMatrixMode(GL_MODELVIEW);
glLoadldentity();
glScaled.Of, 0.5f, l.Of);
Patrz take glRotate, glTranslate

gITranslate
Przeznaczenie Plik Mnoy biec macierz przez macierz przesunicia.
nagwkowy <gl.h>
Skadnia void gITranslated(GLdouble x, GLdouble y, GLdouble z);
void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
Opis Ta funkcja mnoybiec macierz przez macierz przesunicia. Nowa
macierz staje si biec macierz przeksztacenia.
Parametry
x,y,z GLdouble lub GLfloat: Wsprzdne x, y i z wektora przesunicia.
Zwracana warto Brak
Przykad Poniszy kod pochodzi z programu SOLAR w tym rozdziale. Umieszcza
Patrz take niebiesk kul (Ziemi) w odlegoci 105 jednostek w kierunku osi x od
pocztku ukadu wsprzdnych.
// Ziemia
glColor3f( O . O f , O . O f , l . O f ) ;
glTranslate(105.Of, O . O f , O . O f ) ;
auxSolidSphere( 1 5 . Of);
glRotate, glScale

glulookAt
Przeznaczenie Definiuje przeksztacenie punktu obserwacji.
Plik nagwkowy <glu.h>
Skadnia void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx,
GLdouble upy, GLdouble upz);
Opis Ta funkcja definiuje przeksztacenie punktu obserwacji na podstawie
pozycji oka, pooenia rodka sceny oraz wektora, ktry z punktu widzenia
obserwatora jest skierowany pionowo do gry.
Parametry eyex,
eyey, eyez GLdouble: Wsprzdne x, y i z punktu pooenia oka.
232 Cz II Uywanie OpenGL

centerx, centery, GLdouble: Wsprzdne x, y i z punktu, na ktry chcemy patrze.


centerz
upx, upy, upz GLdouble: Wsprzdne x, y i z wektora okrelajcego gr" z punktu
widzenia obserwatora..
Zwracana warto
Brak
Przykad
Poniszy kod pochodzi z przykadowego programu TANK. Przedstawia
sposb zmiany przeksztacenia punktu obserwacji za kadym razem, gdy
czog lub robot zmienia pooenie.
// Wyzerowanie macierzy widoku modelu
glMatrixMode(GL_MODELVIEW); glLoadldentity()
;

// Ustawienie przeksztacenia punktu obserwacji //


na podstawie pooenia i pozycji gluLookAt(locX,
locY, locZ, dirX, dirY, dirZ, O.Of, l.Of,
O.Of);

locXdo locZ okrelaj pooenie czogu lub robota (punkt widzenia


obserwatora), za dirXdo dirZ okrelaj punkt, w kierunku ktrego
skierowany jest czog lub robot. Ostatnie trzy wartoci okrelaj
wsprzdne wektora skierowanego ku grze, ktry w tym programie
zawsze pokrywa si z kierunkiem osi y.
Patrz take glFrustum, gluPerspective

gluOrtho2D
Przeznaczenie Definiuje dwuwymiarowe rzutowanie rwnolege.
Plik nagwkowy <glu.h>
Skadnia void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom,
GLdouble top);
Opis Ta funkcja definiuje macierz dwuwymiarowego rzutowania rwnolegego.
Taka macierz rzutowania stanowi odpowiednik wywoania funkcji glOrtho /
parametrami near \far ustawionymi, odpowiednio, na O i 1.
Parametry
left, right GLdouble: Okrelaj lew i praw paszczyzn obcinania.
bottom, top GLdouble: Okrelaj doln i grn paszczyzn obcinania.
Zwracana warto Brak
Rozdzia 7. * Manipulowanie przestrzeni 3D: transformacje wsprzdnych 233

Przykad Poniszy kod ustala dwuwymiarow bry widzenia umoliwiajc


Patrz take rysowanie w paszczynie xy w zakresie od -100 do 100 jednostek w
osiach x i y. Dodatnie wartoci osi y biegn w gr, za dodatnie
wartoci osi x - w prawo.
gluOrtho2D(-100.0, 100.0, -100.0, 100.0);

glOrtho, gluPerspectiye

gluPerspectiye
Przeznaczenie
Definiuje macierz rzutowania perspektywicznego. <glu.h>
Plik nagwkowy
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear,
Skadnia GLdouble zFar);
Ta funkcja tworzy macierz opisujc ostrosup widzenia we wsprzdnych
Opis sceny. Stosunek wysokoci do szerokoci (aspect) powinien odpowiada
stosunkowi dugoci krawdzi okna widoku (okrelonego funkcj glYiewport).
Dzielenie w rzutowaniu perspektywicznym odbywa si na podstawie
wartoci kta obserwacji w pionie (fovy) oraz odlegoci do bliszej
(zNear) i dalszej (zFar) paszczyzny obcinania.
Parametry
fovy aspect GLdouble: Szeroko kta widzenia w pionie, wyraona w stopniach.
GLdouble: Stosunek szerokoci do wysokoci ostrosupa widzenia.
zNear, zFar Uywany do wyznaczania kta widzenia w poziomie.
GLdouble: Odlegoci obserwatora od bliszej i dalszej paszczyzny
obcinania. Te wartoci s zawsze dodatnie.
Zwracana warto Brak
Przykad Poniszy kod pochodzi z przykadowego programu SOLAR. Tworzy
rzutowanie perspektywiczne, ktre powoduje, e planety pooone z
drugiej strony Soca s rysowane jako mniejsze ni planety pooone
bliej patrzcego.
// Zmiana bryy widzenia i widoku.
// Wywoywane w momencie zmiany wymiaru okna
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat fAspect;
// Zabezpieczenie przed dzieleniem przez O
i f ( h == 0) h = 1;

// Ustawienie widoku na wymiary okna


glYiewport( O , O, w, h ) ;
234____________________________________Cz II Uywanie OpenGL

// Obliczenie stosunku dugoci bokw okna


fAspect = (GLfloat)w/(GLfloat)h;
// Wyzerowanie ukadu wsprzdnych
glMatrixMode(GL_PROJECTION);
glLoadldentity();
// Kt widzenia 45 stopni,
// blisza i dalsza paszczyzna 1 . 0 i 425
gluPerspective(45.0f, fAspect, 1 . 0 , 4 2 5 . 0 ) ;
// Zerowanie macierzy widoku modelu
glMatrixMode(GL_MODELVIEW);
glLoadldentity(); }
Patrz take glFrustum, gluOrtho2D
Rozdzia 8.
Kolory i cieniowanie
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Okreli kolor przy uyciu barw skadowych RGB * glColor
4 Ustawi model cieniowania * glShadeModel
* Stworzy palet 3-3-2 * CreatePalette
* Zastosowa palet * RealizePalette, SelectPalette,
UpdateColors

No, nareszcie powiemy co o kolorze! To chyba najwaniejszy aspekt kadej biblioteki


graficznej - waniejszy nawet ni moliwo tworzenia animacji. Przy tworzeniu apli-
kacji graficznych musisz mie na wzgldzie star zasad: w tym przypadku wygld
JEST wszystkim! Nie wierz, gdy kto twierdzi co innego. Tak, oczywicie, wyposaenie,
wydajno, cena i pewno dziaania take si licz, ale powiedzmy sobie szczerze - w
wikszoci przypadkw to wanie wygld decyduje o powodzeniu lub porace produktu.
Jeli chcesz powanie zaj si tworzeniem aplikacji graficznych, nie moesz progra-
mowa wycznie dla garstki intelektualistw mylcych tak jak ty. Zwr si do mas!
Zastanw si: czarno-biae telewizory byy tasze w produkcji ni telewizory kolorowe.
Podobnie czarno-biae kamery wideo, take byy tasze i atwiejsze w uyciu. Ale ro-
zejrzyj si dookoa i sam wycignij wnioski. Oczywicie, czarno-biay sprzt odgrywa
pewn rol, ale jednak powszechny jest kolor. (A swoj drog, szkoda, e pokolorowali te
filmy z Shirley Tempie...).
236 Cz II Uywanie OpenGL

Czym jest kolor?


Powiedzmy najpierw par sw o samym kolorze. Jak powstaje kolor i jak go postrzegamy?
Zrozumienie teorii koloru oraz tego, jak oko ludzkie postrzega kolorowe sceny, pomoe
nam w zrozumieniu sposobw programowego okrelania kolorw. (Jeli wiesz, jak
powstaj kolory i jak sieje postrzega, moesz spokojnie pomin t sekcj).

wiato jako fala


Kolor jest po prost dugoci fali wietlnej widzialnej dla ludzkiego oka. Jeli w szkole
uczye si fizyki, z pewnoci pamitasz, e wiato moe by traktowane zarwno
jako fala, jak i czsteczka. Moe by przedstawiane jako fala poruszajca si w prze-
strzeni, podobnie jak fale na wodzie, lub jako strumie czsteczek, na przykad jak krople
deszczu padajce na ziemi. Jeli wydaje ci si to niezrozumiae, wiesz ju, dlaczego
wikszo ludzi nie studiuje mechaniki kwantowej!

wiato odbijajce si od prawie kadej powierzchni w rzeczywistoci jest mieszanin


wielu rnych rodzajw wiata. Te rodzaje wiata s okrelane przez ich dugoci fal.
Dugo fali wiata jest mierzona jako odlego pomidzy szczytami kolejnych fal
wiata, jak ilustruje to rysunek 8.1.
Rysunek 8.1.
Sposb mierzenia
dlugoci fali
wietlnej

Dugoci fal wiata widzialnego nale do zakresu od 390 nanometrw (nanometr to l


O"9 m, jedna miliardowa metra) dla fioletu, do 720 nanometrw dla czerwieni; ten
zakres zwykle okrela si jako spektrum. Z pewnoci obiy ci si o uszy wyraenia
ultrafiolet i podczerwie; oznaczaj one wiato niewidzialne goym okiem, o dugo-
ciach fal lecych poza granicami spektrum. Spektrum, zawierajce wszystkie barwy
podstawowe, wyglda jak tcza, pokazana schematycznie na rysunku 8.2.

Rysunek 8.2.
Spektrum wiata
widzialnego

UiBsiy .;;; -Niebieski Zielony ty Pomaraczowy ' ^Cziii|lH

390 nm 720 nm
Rozdzia 8. * Kolory i cieniowanie_________________________________237

wiato jako czsteczka


- W porzdku, panie Mdralo - moesz stwierdzi - Jeli kolor jest dugoci fali
wiata i widzialne wiato mieci si w tym tczowym" zakresie, to gdzie jest brz
mojego czekoladowego batonu, czer moich butw czy choby biel tej kartki?

Odpowied na to pytanie zaczniemy od stwierdzenia, e ani czer, ani biel nie s kolorami.
W rzeczywistoci czer to brak koloru, za biel to rwnomierne wymieszane
wszystkie kolory naraz. Czyli biae przedmioty w rwnym stopniu odbijaj wszystkie
dugoci fal, za czarne obiekty pochaniaj wszystkie dugoci fal.

Brz czekoladowego batonu i wiele innych widzialnych kolorw s rzeczywicie kolo-


rami. Z punktu widzenia fizyka s one kolorami zoonymi. Skadaj si z rnych iloci
czystych" barw wystpujcych w spektrum. Aby zrozumie, jak to dziaa, pomyl o
wietle jak o czsteczkach. Kady obiekt owietlony rdem wiata jest bombardowany
miliardami miliardw" fotonw, czyli malekich czsteczek wiata. Nawizujc do
naszej fizycznej" pogawdki, kady z tych fotonw jest take fal, posiadajc
dugo, czyli kolor w spektrum.

Wszystkie obiekty fizyczne skadaj si z atomw. Odbijanie si fotonw od obiektu


zaley od rodzaju atomw, iloci atomw kadego rodzaju czy od uoenia atomw w
obiekcie. Niektre fotony zostan odbite, a niektre pochonite (pochonite fotony
zwykle zmieniaj si w ciepo), za kady rodzaj materiau lub poczenia materiaw
(na przykad w batonie czekoladowym) odbija rne dugoci fal wiata ni inne materiay.
Ilustruje to rysunek 8.3.

Rysunek 8.3.
Obiekt pochania /i^ rdo wiatu
niektre fotony, Twoje
oko
za odbija inne
^ f* .!<%

C
Xl
-^F v \\V'
\\V\
Strumie wiata (fotonw)

Cz fotonw zostaje pochonita


cz za odbia
Fotony odbite

Baton czekoladowy

Twj osobisty wykrywacz fotonw


wiato odbite od batonu czekoladowego, gdy trafia do twojego oka, jest interpretowane
jako kolor. Do oka trafiaj miliardy fotonw, skupiajc si na jego tylnej powierzchni,
siatkwce, dziaajcej jak bona aparatu fotograficznego. Miliony komrek wiatoczuych
siatkwki s podraniane uderzajcymi fotonami i wysyaj impulsy nerwowe,
238____________________________________Cz II Uywanie OpenGL

przez nerw wzrokowy przekazywane do mzgu, ktry interpretuje je jako wiato i kolor.
Im wicej fotonw trafia w komrk wiatoczu, tym bardziej zostaje ona podraniona.
Ten poziom podranienia jest interpretowany przez mzg jako natenie wiata, co jest
naturalne - im mocniejsze wiato, tym wicej fotonw trafia w komrki siatkwki.
Oko posiada trzy rodzaje komrek wiatoczuych. Wszystkie reaguj na fotony, jednak
kady rodzaj reaguje na inny zakres dugoci fal. Jeden rodzaj jest pobudzany przez
wiato zblione do czerwonego, drugi przez wiato zblione do zielonego, za trzeci
przez wiato zblione do niebieskiego. Tak wic wiato zawierajce gwnie czerwie
bdzie bardziej pobudza komrki reagujce na czerwie ni inne rodzaje komrek, za
mzg zinterpretuje sygnay jako wiato zawierajce w wikszoci czerwie. Mzg auto-
matycznie dokonuje oblicze - mieszanina rnych rodzajw wiata o rnych inten-
sywnociach zostanie zinterpretowana jako okrelony kolor. Tak wic jednakowe
natenie fal o wszystkich dugociach daje wiato biae, za brak jakiegokolwiek wiata jest
interpretowany jako czer.
Jak wida, kady kolor" postrzegany przez oko jest w rzeczywistoci zoony z fal
wietlnych o rnych dugociach i nateniach, pochodzcych z widzialnego spektrum.
Sprzt" w twoim oku wykrywa strumie fotonw jako wzgldne iloci wiata czerwo-
nego, zielonego i niebieskiego. Rysunek 8.4 przedstawia widzenie koloru brzowego,
skadajcego si z 60 procent fotonw czerwieni, 40 procent fotonw zieleni i 10 procent
fotonw wiata niebieskiego.

Rysunek 8.4. Soczewki okna "Brzowe" wiato


Jak brzowy kolor" Siatkwka / /
trafia do oka ^^,J J R R G
..:-, ^-fg* ^-

G R G

8~<Y~V-r
6 fotonw czerwieni, 4 Fotony zieleni i l foton niebieski

Komputer jako generator fotonw


atwo si domyli, e gdy chcemy wygenerowa kolor za pomoc komputera, robimy to
przez osobne okrelenie intensywnoci czerwonej, zielonej i niebieskiej skadowej
wiata. Tak si skada, e monitory komputerowe s skonstruowane tak, aby mc gene-
rowa trzy rodzaje (dugoci fal) wiata (wiesz ju, ktre), z ktrych kade moe rni si
intensywnoci. Z tyu monitora znajduje si dziao elektronowe, wystrzeliwujce
strumie elektronw w kierunku tylnej powierzchni ekranu kineskopu. Ta powierzchnia
zawiera trzy rodzaje fosforu, ktre w momencie uderzenia przez rozpdzony elektron
emituj czerwone, zielone i niebieskie wiato. W zalenoci od intensywnoci strumienia
elektronw zmienia si intensywno emitowanego wiata. Te trzy rodzaje fosforu s
uoone precyzyjnie blisko siebie, razem tworzc fizyczn kropk na ekranie, co
przedstawiono na rysunku 8.5.
Rozdzia 8. * Kolory i cieniowanie________________________________239

Rysunek 8.5. D*> elektronowe


Kolory powstajce
Ekran komputen
na monitorze
komputera
Po
sz
cz
eg
ln
e
ele
m
en
ty'
ek
ranu
Plamki czerwonego,zielonego i
niebieskiego fosforu

By moe pamitasz, e w rozdziale 3 mwilimy, i OpenGL definiuje kolor za pomoc


funkcji glColor, wanie poprzez okrelenie intensywnoci barwy czerwonej, zielonej i
niebieskiej. Tutaj omwimy bardziej szczegowo dwa tryby kolorw obsugiwanych
przez OpenGL.
* Tryb koloru RGBA by trybem, ktrego uywalimy we wszystkich dotychcza-
sowych przykadach. Przy rysowaniu w tym trybie mona precyzyjnie okreli
kolor przez podanie intensywnoci jego trzech skadowych (czerwonej, zielonej i
niebieskiej - po angielsku Red, Green oraz Blue).
4- W trybie z indeksem koloru kolor okrela si przez podanie indeksu do tablicy
dostpnych kolorw, zwanej palet. W ramach tej palety moesz precyzyjnie
okreli kady z kolorw, podajc intensywnoci jego trzech barw skadowych.

Sprzt grafiki kolorowej


Swojego czasu szczytowym osigniciem w dziedzinie sprztu do grafiki komputerowej
bya karta graficzna Hercules. Ta karta umoliwiaa wywietlanie rastrowego obrazu o
rozdzielczoci 720 na 348 punktw, lecz tylko w dwch kolorach. Kady piksel
(punkt obrazu) mg znajdowa si tylko w jednym z dwch stanw: wczonym lub
wyczonym. W tamtych czasach kada bitmapowa grafika komputerowa w komputerze
osobistym bya czym i nawet na monitorze monochromatycznym mona byo dao si
tworzy wspaniae obrazy. Nawet mnie, nie chwalc si, udao si stworzy na studiach
trjwymiarow grafik na karcie Hercules.

Przed kart Hercules istniaa karta CGA, Color Graphics Adapter. Wprowadzona wraz z
pierwszymi komputerami IBM PC, karta obsugiwaa rozdzielczo 320 x 200 punktw i
na ekranie mona byo wywietli do szesnastu kolorw jednoczenie. Bya dostpna
take wysza rozdzielczo (640 x 200), z dwoma dostpnymi kolorami, ale to rozwizanie
nie byo tak efektywne jak w przypadku karty Hercules (kolorowy monitor = duo ywej
gotwki). W porwnaniu z dzisiejszymi standardami, karta CGA miaa bardzo
niewielkie moliwoci, nie do porwnania z moliwociami graficznymi domo-
240____________________________________Cz II Uywanie OpenGL

wych komputerkw Commodore 64 czy Atari, dostpnych wtedy ju za 200 dolarw.


Przy braku rozdzielczoci odpowiednich dla aplikacji biurowych i nawet najprostszych
pakietw do modelowania, CGA znajdowaa zastosowanie gwnie prostych gier i apli-
kacji, ktre zadowalay si kolorowanym tekstem. Oglnie rzecz biorc, trudno byo
znale ekonomiczne uzasadnienie zakupu tej droszej karty.

Nastpny wikszy przeom w grafice PC nastpi w momencie, gdy IBM opracowa kart
EGA (Enhanced Graphics Adapter). Ta karta moga wywietli wicej ni 25 wierszy
tekstu w nowym trybie tekstowym, a take grafik rastrow o rozdzielczoci 640 x 350
pikseli, i to w szesnastu kolorach! Pewne techniczne poprawki eliminoway problem
migotania, wystpujcy w przypadku kart CGA, dziki czemu umoliwiay tworzenie
pynnych animacji. Od tego czasu nowe gry zrcznociowe, prawdziwe aplikacje graficzne,
a nawet grafika 3D w komputerach PC stay si nie tylko dostpne, ale take uzasadnione.
Stanowio to ogromny postp w porwnaniu z kart CGA, jednak grafika w
komputerach osobistych wci jeszcze bya w powijakach.

Ostatnim gwnym standardem kart graficznych opracowanych przez IBM bya karta
VGA (co w rzeczywistoci oznacza Yector Graphics Array, a nie, jak si powszechnie
uwaa, Video Graphics Adapter). Ta karta bya znacznie szybsza ni karta EGA, moga
wywietla 16 kolorw w wyszej rozdzielczoci 640 x 480 256 kolorw w niszej
rozdzielczoci (320 x 200). Te 256 kolorw byo wybieranych z palety ponad 16 milionw
dostpnych kolorw. W tym momencie otwary si podwoje dla wszelkiego rodzaju grafiki
komputerowej PC. Na ekranach pojawia si prawie fotorealistyczna grafika. Ray tracery,
trjwymiarowe gry, a nawet oprogramowanie do obrbki zdj masowo zaczy
pojawia si na rynku programw do komputerw osobistych.

IBM posiada take jeszcze inn, wysokowydajn kart graficzn- 8514 - do swoich stacji
roboczych". Ta karta moga wywietli 256 kolorw przy rozdzielczoci 1024 x 768.
IBM uzna, e ta karta bdzie wykorzystywana jedynie przez aplikacje CAD i naukowe!
Jednake jedno z pewnoci mona powiedzie o rynku konsumenta: zawsze chce
wicej. Ta krtkowzroczno kosztowaa firm IBM utrat pozycji niedocignionego lidera
na rynku kart graficznych do komputerw osobistych. Inni producenci zaczli tworzy
karty Super-VGA", mogce wywietla coraz wysze rozdzielczoci, w coraz
wikszych ilociach kolorw. Najpierw 800 x 600, potem 1024 x 768 i wicej, najpierw w
256 kolorach, potem w 32 tysicach, a nastpnie w ponad 65 tysicach kolorw. Obecne 24-
bitowe karty graficzne potrafi wywietli 16 milionw kolorw w rozdzielczo-ciach
1024 x 768 i wyszych. Tasze karty graficzne PC obsuguj peny kolor w
rozdzielczociach VGA lub w rozdzielczoci 800 x 600 kart Super-VGA. Wikszo
sprzedawanych obecnie komputerw osobistych moe wywietli przynajmniej 65 tysicy
kolorw w rozdzielczoci 1024 x 768.

Caa ta moc sprawia, e pojawiaj si coraz ciekawsze moliwoci fotorealistyczna


trjwymiarowa grafika to tylko jedna z nich. Gdy Microsoft zaimplementowa OpenGL do
systemu Windows, powstaa moliwo tworzenia najwyszej jakoci aplikacji
graficznych do komputerw osobistych. Obecne komputery Pentium czy Pentium Pro
wci znacznie ustpuj pod wzgldem wydajnoci nowoczesnym stacjom roboczym
SGI. Jednak gdy komputer PC zostanie wyposaony w kart akceleratora 3 D, uzyskasz
wydajno, ktra jeszcze kilka lat temu bya dostpna jedynie w przypadku stacji roboczej
za 100 tysicy dolarw! W najbliszej przyszoci typowy komputer domowy b-
Rozdzia 8. Kolory i cieniowanie_________________________________241

dzie mia moliwo przedstawienia wymylnych symulacji, gier i innych aplikacji


zwizanych z intensywnym tworzeniem grafiki.

Tryby graficzne
w komputerach osobistych
Microsoft Windows zrewolucjonizoway wiat grafiki PC w dwch aspektach. Po
pierwsze, stary si powszechnie uywanym graficznym rodowiskiem operacyjnym,
szybko zaadaptowanym przez rynek aplikacji biurowych i domowych. Po drugie, grafika
PC staa si duo atwiej dostpna dla programistw. W Windows sprzt zosta
uoglniony" przez sterowniki kart graficznych. Zamiast pisa instrukcje przeznaczone
bezporednio dla sprztu graficznego, dzisiejszy programista moe korzysta z jednego,
spjnego API, za samym porozumiewaniem si ze sprztem zajmie si system Win-
dows. Microsoft dostarcza zestawu podstawowych sterownikw (stworzonych z udziaem
producentw) do wikszoci popularnych kart graficznych. Producenci sprztu wraz ze
swoimi kartami dostarczaj specjalizowane sterowniki dla Windows, czsto take
mona pobra nowe wersje sterownikw przez Internet lub BBS.

Swego czasu Windows byy rozprowadzane ze sterownikami do monochromatycznej


karty Hercules, do kart CGA oraz EGA. Niczego wicej. Obecnie standardowa karta
VGA stanowi absolutne wymagane minimum. Nowe, sprzedawane obecnie komputery PC
s w stanie wywietli przynajmniej szesnacie kolorw w rozdzielczoci 640 x 480
punktw, lecz zwykle oferuj o wiele, wiele wiksze moliwoci.

Rozdzielczoci ekranu
Rozdzielczoci ekranu w przypadku obecnych komputerw PC zmieniaj si od 640 x
480 pikseli do 1280 x 1024 i wikszych. Jednak sama rozdzielczo obrazu nie jest
najwaniejszym czynnikiem podczas tworzenia aplikacji graficznych. Do wikszoci
zada graficznych w zupenoci wystarcza nisza rozdzielczo, 640 x 480 pikseli.
Waniejszy jest rozmiar okna, brany pod uwag przy ustalaniu bryy obcinania i widoku
(patrz rozdzia 3). Skalujc rozmiar rysunku do rozmiaru okna, moesz atwo obsuy
rne rozdzielczoci i rozmiary okien, z jakimi masz do czynienia. Dobrze napisana
aplikacja graficzna wywietli podobny obraz bez wzgldu na rozdzielczo ekranu.
Uytkownik powinien automatycznie dostrzec wicej szczegw w momencie przejcia
do wyszej rozdzielczoci.

Gboko koloru
O ile wraz ze wzrostem rozdzielczoci ekranu wzrasta ostro i ilo widocznych szczegw
obrazu, o tyle wraz ze wzrostem dostpnej iloci kolorw zwiksza si przejrzysto
rysunku. Obraz wywietlony w komputerze potraficym wywietli miliony kolorw
wyglda zdecydowanie lepiej ni wywietlony w szesnastu kolorach. Z punktu widzenia
242____________________________________Cz II Uywanie OpenGL

programisty, powiniene bra pod uwag tylko trzy gbokoci kolorw: 4 bity, 8 bitw i 24
bity.

Kolor 4-bitowy
W najgorszym razie twj program moe zosta uruchomiony w trybie graficznym umo-
liwiajcym wywietlenie jedynie 16 kolorw - nazywanym 4-bitowym, gdy kolor kadego
piksela jest opisany przez 4 bity. Te cztery bity reprezentuj warto od O do 15,
stanowic indeks do zestawu szesnastu predefmiowanych kolorw. Majc do dyspozycji
jedynie 16 kolorw, nie moesz uczyni zbyt wiele w celu poprawienia przejrzystoci i
ostroci rysowanego obrazu. Oglnie akceptuje si, e wikszo powanych aplikacji
graficznych moe ignorowa tryb o 16 kolorach.

Kolor 8-bitowy
Kolor 8-bitowy umoliwia wywietlenie na ekranie do 256 kolorw. Stanowi to znaczny
krok naprzd, za w poczeniu z ditheringiem (roztrzsaniem, ktre omwimy w dalszej
czci rozdziau) umoliwia otrzymanie w wielu przypadkach satysfakcjonujcych
wynikw. Kady piksel jest opisany przez 8 bitw, przechowujcych wartoci od O do 255,
stanowice indeks do tablicy kolorw, zwanej palet. Kolory w palecie mog by
wybierane z ponad 16 milionw dostpnych kolorw. Jeli potrzebujesz 256 odcieni koloru
czerwonego, sprzt jest w stanie ci je zapewni.
Kady kolor w palecie jest okrelany przez podanie omiobitowych wartoci, z osobna
dla kadej barwy skadowej koloru, tak wic intensywno kadej barwy skadowej moe
waha si w przedziale od O do 255. W efekcie kolorowi w palecie mona przypisa
dowolny z 16 milionw dostpnych kolorw. Przez uwane dobranie kolorw palety
mona zapewni prawie fotorealistyczny obraz na ekranie komputera PC.

Kolor 24-bitowy
Obecnie obrazy najwyszej jakoci tworzone s w trybie 24-bitowym. W tym trybie
kady piksel jest opisany przez pene 24 bity, po osiem bitw dla intensywnoci kadej
barwy skadowej (8 + 8 + 8 = 24). Dziki temu kademu pikselowi na ekranie mona
przypisa jeden z ponad 16 milionw dostpnych kolorw. Najwiksz wad tego trybu jest
ilo pamici zajmowanej przez obraz (ponad 2 MB dla ekranu 1024 x 768). Oprcz tego,
przenoszenie obszarw obrazu lub po prostu odwieanie ekranu podczas animacji trwa
znacznie duej. Na szczcie, obecne akcelerowane karty graficzne s zoptymalizowane
dla operacji tego typu.

Inne gbokoci koloru


W celu oszczdzenia pamici lub poprawy wydajnoci wiele kart graficznych obsuguje
take inne tryby koloru.
Rozdzia 8. Kolory i cieniowanie________________________________243

W celu poprawy wydajnoci, pewne karty obsuguj 32-bitowe tryby koloru, czasem
okrelane jako True Color. W rzeczywistoci, w trybie 32-bitowym na ekranie nie mona
wywietli wicej kolorw ni w trybie 24-bitowym, lecz jedynie poprawia si wydajno
programw, gdy dane kadego piksela zostaj uoone na granicy 32 bitw. Niestety,
powoduje to utrat omiu bitw (jednego bajtu) dla kadego piksela. W obecnych, 32-
bitowych procesorach Intela, dostp do adresw pamici uoonych na granicy 32 bitw
odbywa si znacznie szybciej ni w innych przypadkach.
W celu bardziej efektywnego wykorzystania pamici czsto stosuje si dwa inne popularne
tryby. Pierwszy z nich to tryb 15-bitowy, w ktrym na kad barw skadow
przypada po pi bitw. Kady piksel moe wic zosta wywietlony w jednym z
32768 kolorw. W trybie 16-bitowym, jednej ze skadowych przypada dodatkowy bit;
zwykle jest to skadowa zielona. Dziki temu na ekranie mona wywietli 65 536 do-
stpnych kolorw. Ten ostatni tryb, w przypadku reprodukcji obrazw fotograficznych, jest
praktycznie tak samo efektywny jak tryb 24-bitowy. W przypadku wikszoci obrazw
fotograficznych trudno jest dostrzec rnic pomidzy 16- a 24-bitowym trybem, cho
jeli w obrazie wystpuj wiksze gadko cieniowane paszczyzny, w trybie 16-bitowym
mona zauway na nich pewne paski.
Z punktu widzenia programisty, kolor w trybach 15- i 16-bitowych jest okrelany tak
samo, jak w trybach 24-bitowych - przez podanie intensywnoci trzech barw skado-
wych. Sprzt lub sterownik urzdzenia pobieraj t 24-bitow warto i przed ustawie-
niem koloru piksela konwertuj j do 15 lub 16 bitw.

Wybr koloru
Wiesz ju, e OpenGL okrela konkretny kolor przez oddzielne podanie intensywnoci
skadowych czerwonej, zielonej i niebieskiej. Wiesz take e sprzt obsugiwany przez
Windows moe wywietli prawie wszystkie kombinacje lub tylko bardzo niewiele
kombinacji koloru. Jak wic okrela si podany kolor jako wartoci intensywnoci
skadowych czerwonej, zielonej i niebieskiej? I jak Windows wypenia dania doty-
czce kolorw, ktre nie s dostpne?

Kostka kolorw
Poniewa kolor jest okrelany przez trzy dodatnie wartoci poszczeglnych skado-
wych, moemy zamodelowa dostpne kolory jako bry, ktr nazywa si przestrzeni
koloru RGB. Rysunek 8.6 pokazuje, e ta przestrze wyglda jak pocztek ukadu
wsprzdnych z osiami dla kolorw czerwonego, zielonego i niebieskiego. Wsprzdne
czerwona, zielona i niebieska odpowiadaj osiom x, y oraz z. W pocztku ukadu (0,0,0)
wzgldne intensywnoci wszystkich trzech skadowych wynosz zero, wic w efekcie
otrzymujemy czer. Maksymalna gboko koloru w komputerach PC to 24 bity, z 8
bitami na kad barw skadow, moemy wic zaoy, e warto 255 na kadej z osi
reprezentuje pene nasycenie danego koloru. Otrzymujemy wic kostk o dugoci boku
wynoszcej 255. Wierzchoek pooony dokadnie naprzeciw czerni, w ktrej ko-
244 Cz II Uywanie OpenGL

centracje wynosiy (O, O, 0), odpowiada bieli, ze wzgldnymi koncentracjami skadowych


(255, 255, 255). Pene nasycenie (255) wzdu kadej z osi odpowiada czystemu
kolorowi czerwonemu, zielonemu lub niebieskiemu.

Rysunek 8.6. Zielony


Przestrze kolorw
RGB
Czer
(0,0,0) Czerwony

Niebieski

Ta kostka kolorw" (rysunek 8.7) zawiera wszystkie dostpne kolory, na swojej po-
wierzchni lub we wntrzu. Na przykad, wszystkie dostpne odcienie szaroci pomidzy
czerni i biel wystpuj na przektnej czcej wierzchoki (O, O, 0) i (255, 255, 255).

Rysunek 8.7.
Przestrze kolorw
RGB (255,255,0)

Cyjan
(0,255,255)

Czerwony

Fiolet
(0,0,255 (255,0,255)
Niebieski )

Rysunek 8.8.
Wynikiem dziaania
programu CCUBE
jest kostka kolorw
Rozdzia 8. * Kolory i cieniowanie_________________________________245

Rysunek 8.8 przedstawia gadko cieniowan kostk koloru, narysowan przez przykadowy
program CCUBE z tego rozdziau. Powierzchnia kostki zawiera przejcia kolorw od
czerni w jednym rogu do bieli w przeciwnym. Czerwie, ziele i bkit wystpuj w
swoich rogach, 255 jednostek od czerni. Dodatkowo, kolory ty, cyjan i fiolet zajmuj
rogi odpowiadajce kombinacjom trzech barw podstawowych. Ten program dziaa
poprawnie nawet w trybie 16-kolorowym, za jak to si dzieje, dowiesz si w dalszej
czci rozdziau. W tym programie mona take obraca kostk w celu obejrzenia
wszystkich cian; su do tego klawisze kursora.

Ustalanie koloru rysowania


Przyjrzyjmy si funkcji glColor(). Jej prototyp jest nastpujcy:
void glColor<x><t>( r e d , green, blue, a l p h a ) ;

W nazwie funkcji <x> reprezentuje ilo argumentw; moe to by 3 dla trzech argu-
mentw - red, green oraz blue lub 4, jeeli wystpuje dodatkowy argument alpha.
(Skadnik alpha okrela przejrzysto koloru i zostanie omwiony szczegowo w roz-
dziale 15). Na razie bdziemy uywa wersji funkcji z trzema argumentami.
<t> w nazwie funkcji okrela typ uywanych argumentw. Moe to by b, d, f, i, s, ub, ui,
us dla, odpowiednio, typw byte, double, float, integer, short, unsigned byte, unsig-ned
integer oraz unsigned short. Inne wersje funkcji zawieraj w nazwie jeszcze liter v; te
wersje jako parametru wymagaj tablicy zawierajcej argumenty (v oznacza vectored w
tablicy). W sekcji podrcznika znajdziesz dokadniejszy opis parametrw funkcji
glColor().
Wikszo programw OpenGL, ktre napotkasz, korzysta z funkcji glColorSf i okrela
intensywno kadej skadowej jako 0,0 dla braku skadowej i 1,0 dla j ej penej intensy-
wnoci. Jeli jednak przyzwyczaie si do programowania w Windows, moe by ci a-
twiej korzysta z wersji glColorSub tej funkcji. Ta wersja wymaga podania trzech bajtw
bez znaku, zawierajcych wartoci od O do 255, okrelajcych intensywnoci skadowej
czerwonej, zielonej i niebieskiej. Uycie tej wersji funkcji przypomina uycie makra RGB
z Windows:
glColor3ub(0, 255, 128) = R G B ( 0 , 255, 1 2 8 ) ;

W rzeczywistoci, dziki temu moe by ci atwiej dostosowa kolory OpenGL z istnie-


jcymi kolorami RGB uywanymi w programie do rysowania elementw, ktre nie s
rysowane w OpenGL.
Pamitaj, e makro RGB okrela w Windows kolor, lecz nie powoduje zmiany biecego
koloru rysowania, tak jak robi to funkcja glColor. W zwizku z tym makra RGB moesz
uywa w poczeniu z tworzeniem pdzli lub pir GDI.
246 Cz II Uywanie OpenGL

Cieniowanie
W naszej pierwszej definicji funkcji glColor stwierdzilimy, e ta funkcja ustala biecy
kolor rysowania, za wszystkie obiekty tworzone po tym poleceniu bd rysowane bie-
cym kolorem. Przy omawianiu prymityww OpenGL (rozdzia 6) rozszerzylimy t
definicj nastpujco: funkcja glColor ustawia biecy kolor rysowania, ktry jest uy-
wany do wszystkich wierzchokw rysowanych po wywoaniu tej funkcji. Jak dotd, we
wszystkich przykadach rysowalimy bryy szkieletowe lub bryy jednolite, w ktrych
kada ze cian miaa okrelony, jednolity kolor. Gdybymy jednak okrelili inny kolor dla
kadego wierzchoka prymitywu (punktu, linii lub wielokta), jaki kolor miaoby
wntrze?

Sprbujmy odpowiedzie na to pytanie rozpoczynajc od punktw. Punkt posiada tylko


jeden wierzchoek, wic kady okrelony kolor bdzie kolorem tego punktu.

W przypadku odcinka mamy dwa wierzchoki, wic kady z nich moe mie inny kolor.
Kolor rysowanej linii zaley od modelu cieniowania. Cieniowanie jest zdefiniowane po
prostu jako pynne przejcie od jednego koloru do innego. Kade dwa punkty w prze-
strzeni kolorw RGB (rysunek 8.7) mog zosta poczone lini prost.

Pynne (ang. smooth) cieniowanie powoduje zmian koloru odcinka w miar przecho-
dzenia przez bry kolorw z jednego punktu do drugiego. Na rysunku 8.9 przedstawiono
kostk kolorw z zaznaczonymi wierzchokami dla czerni i bieli. Poniej przedstawiono
odcinek z dwoma wierzchokami, czarnym i biaym. Kolory uyte do narysowania od-
cinka odpowiadaj kolorom lecym wzdu odcinka czcego wierzchoki kostki ko-
lorw, od czerni do bieli. Otrzymujemy w wyniku odcinek zmieniajcy kolor od
czarnego, poprzez coraz janiejsze odcienie szaroci, a do osignicia na kocu bieli.

Rysunek 8.9.
Sposb cieniowania
odcinka od czerni do
bieli
Rozdzia 8. * Kolory i cieniowanie________________________________247

Matematyka, na ktrej oparte jest cieniowanie wymaga wyznaczenia rwnania linii -


czcej dwa punkty w trjwymiarowej przestrzeni kolorw RGB. Nastpnie po prostu
przechodzimy w ptli od jednego koca odcinka do drugiego, pobierajc jego wsprzdne
w przestrzeni kolorw i przypisujc je kolejnym pikselom odcinka rysowanego na
ekranie. Odpowiednie algorytmy i sposoby skalowania odcinka w przestrzeni RGB do
odcinka na ekranie s zawarte w wielu dobrych ksikach o grafice komputerowej, ale na
szczcie OpenGL wszystkie obliczenia wykonuje za nas!

W przypadku wieloktw zagadnienie cieniowania staje si troch bardziej zoone. Na


przykad trjkt take moe by reprezentowany jako paszczyzna w przestrzeni kolorw.
Rysunek 8.10 przedstawia trjkt, w ktrym kady wierzchoek jest w jednym z
penych czystych kolorw, czerwieni, zieleni i bkitu. Kod wywietlajcy ten trjkt
znajduje si na listingu 8.1, pochodzcym z przykadowego programu TRIANGLE na
pytce CD-ROM.

Rysunek 8.10.
Trjkt w przestrzeni kolorw RGB

Listing 8.1. Rysowanie pynnie


cieniowanego trjkta z wierzchokami \v
kolorach czerwonym, zielonym
________i
niebieskim_____________________
________________________

// Wczenie
pynnego
cieniowania
glShadeModel(GL
_SMOOTH);
// Rysowanie trjkta
glBegin(GLJTRIANGLES);
// Czerwony grny wierzchoek
glColor3ub((GLubyte)255,(GLubyte)O,(GLubyte)0);
glVertex3f( O . O f ,200.Of,O . O f );
// Zielony wierzchoek w prawym dolnym rogu
glColor3ub((GLubyte)O, (GLubyte)255, (GLubyte)0) ;r
glVertex3f(200.Of,-70.Of,O.Of);

// Niebieski wierzchoek w lewym dolnym rogu


glColor3ub((GLubyte)O, (GLubyte)O, (GLubyte)255);
glVertex3f(-200.Of, -70.Of, O . O f ) ; glEnd();
248 Cz II Uywanie OpenGL

Ustawianie trybu cieniowania


Pierwsza linia z listingu 8.1 suy do poinstruowania OpenGL, e powinno zosta uyte
pynne cieniowanie - czyli modelu, ktry omawiamy. To jest take domylny model
cieniowania, ale dobrym pomysem jest mimo to wywoywanie tej funkcji, w celu zape-
wnienia zamierzonego dziaania programu.

(Innym modelem cieniowania, ktry mona wczy za pomoc funkcji glShadeModel, jest
model GL_FLAT, czyli paskie cieniowanie. Paskie cieniowanie oznacza, e wewntrz
prymityww nie s wykonywane adne obliczenia zwizane z cieniowaniem. Oglnie,
przy paskim cieniowaniu kolor wntrza prymitywu jest kolorem okrelonym przy
definiowaniu jego ostatniego wierzchoka. Jedynym wyjtkiem jest prymityw GL_
POLYGON, w ktrym kolorem caego wielokta jest kolor pierwszego wierzchoka).

Nastpnie kod z listingu 8.1 ustala kolor grnego wierzchoka na czystoczerwony, kolor
prawego dolnego wierzchoka na zielony, za kolor ostatniego, lewego dolnego wierz-
choka na niebieski. Poniewa jest wczone pynne cieniowanie, wntrze trjkta jest
rysowane w taki sposb, aby powstay pynne przejcia pomidzy kolorami.

Wynik dziaania programu TR1ANGLE widzimy na rysunku 8.11. Obraz stanowi repre-
zentacj paszczyzny przedstawionej graficznie na rysunku 8.10.
Rysunek
8.11.
Wynik dziaania
programu
TR1ANGLE

Wielokty, bardziej skomplikowane ni trjkty, take mog posiada wierzchoki w


rnych kolorach. W takich przypadkach wewntrzne obliczenia staj si jeszcze bardziej
skomplikowane. Na szczcie, w OpenGL nie musisz si tym martwi. Bez wzgldu na to,
jak skomplikowany bdzie wielokt, OpenGL z powodzeniem wymaluje jego wntrze
pomidzy wierzchokami.

Zwykle nie bdziesz sam stosowa tego typu cieniowania. Jest ono uywane gwnie w
celu stworzenia efektw owietlenia; take w tym przypadku OpenGL przychodzi z
pomoc. Owietleniem zajmiemy si w rozdziale 9.
Rozdzia 8. * Kolory i cieniowanie 249

Palety Windows
Przykadowe programy TRIANGLE i CCUBE dziaaj poprawnie bez wzgldu na ilo
dostpnych kolorw. Jeli moesz zmieni gboko koloru w swoim systemie, sprbuj
uruchomi te programy przy rnych gbokociach koloru, poczynajc od 16 kolorw, a
koczc na 16 milionach kolorw, jeli karta to umoliwia. Zauwaysz, e kolory
uyte do pynnego przejcia zale od gbokoci koloru. Rysunki 8.12a i 8.12b przed-
stawiaj wynik dziaania przykadowego programu TRIANGLE odpowiednio przy 16 i
przy 16 milionach kolorw. Mimo e rysunki nie s wydrukowane w kolorze, widzimy, e
cieniowanie drugiego trjkta jest znacznie pynniejsze.

Rysunek 8.12a.
Wynik dziaania
programu
TRIANGLE przy 16
kolorach

Rysunek 8.12b.
Przy 16 milionach
kolorw cieniowanie
trjkta jest znacznie
pynniejsze

Dopasowywanie kolorw
Co si dzieje, gdy chcesz narysowa piksel w konkretnym kolorze, okrelonym omawia-
nymi przed chwil wartociami RGB? Wewntrznie Windows definiuje kolor uywajc
makra RGB, czyli omiu bitw dla kadej z barw skadowych: czerwonej, zielonej i nie-
bieskiej; w OpenGL moesz odtworzy to dziaanie uywajc funkcji glColorSub.

Jeli karta graficzna pracuje akurat w trybie 24-bitowym, to kady piksel jest rysowany
dokadnie w kolorze okrelonym przez t 24-bitow warto (trzy intensywnoci po 8
bitw). W trybach 15- i 16-bitowych, Windows przekazuje 24-bitow warto do ste-
rownika urzdzenia, ktry przed wywietleniem piksela zamienia j na warto 15- lub 16-
bitow. W 24-bitowym trybie kostka RGB mierzy 255 jednostek (czyli 8 bitw)
250____________________________________Cz II Uywanie OpenGL

w kadym kierunku. W trybach 15- lub 16-bitowym kostka kolorw mierzy 32 jednostki
(5 bitw) lub 64 jednostki (6 bitw) w danym kierunku. Sterownik urzdzenia dopasowuje
24-bitow warto koloru do najbliszej wartoci koloru w 15- lub 16-bitowej kostce
kolorw.
Rysunek 8.13 przedstawia sposb odwzorowania 8-bitowej skadowej czerwieni na 5-bi-
tow warto czerwieni.

Rysunek 8.13.
Odwzorowanie
redniointensywnej
czerwieni z 8-bitowej
wartoci na warto 5-
bitow

Na samym
kocu skali,
w trybie 4-
bitowym
mona
wywietli
tylko 16
kolorw. Te kolory s ustalone i nie mona ich modyfikowa. Wewntrznie Windows w
dalszym cigu reprezentuje kolory jako 24-bitowych wartoci RGB. Gdy okrelasz kolor
rysowania, za pomoc makra RGB lub funkcji glColor3ub, Windows uywa najbardziej
zblionego z 16 dostpnych kolorw. Jeli kolor jest przybliony do wypenienia, zostaje
przybliony przez tzw. dithering kilku dostpnych kolorw.

Dithering
Gdy mamy do dyspozycji jedynie szesnacie kolorw, tworzona grafika raczej nie bdzie
miaa najwyszej jakoci. Jedyn rzecz, jaka moe pomc, jest tzw. dithering
(roztrzsanie), stosowany w tym trybie przez GDI przy wypenianiu wieloktw lub
powierzchni. Roztrzsanie oznacza umieszczanie blisko siebie punktw w rnych ko-
lorach, w celu wywoania iluzji innego koloru zoonego. Na przykad, jeli obok siebie
uoysz w szachownic punkty niebieskie i te, cay dese bdzie sprawia wraenie
zielonego. Bez mieszania kolorw, ziele wydawaaby si ziarnista. Zmieniajc wza-
jemne proporcje tych i niebieskich punktw moesz zmienia intensywno zieleni
caego deseniu.
Windows uywa roztrzsania w celu otrzymania kolorw niedostpnych w biecej palecie.
W trybie 16-kolorowym, w przypadku bardziej zoonych scen, jako obrazu jest zwykle
bardzo kiepska. Rysunek 8.12 jasno ilustrowa roztrzsanie w Windows; prbowalimy na
nim odtworzy trjkt RGB w systemie posiadajcym jedynie 16 kolorw. Oglnie,
Windows nie wykonuje roztrzsania w OpenGL.
OpenGL moe uywa wasnego roztrzsania, ktre wcza si poleceniem
glEnable(GL_DITHER) ;
Rozdzia 8. Kolory i cieniowanie________________________________251

Moe to czasem poprawi obraz w 8- i 15-bitowych trybach. Roztrzsanie w dziaaniu


moesz sprawdzi uruchamiajc przykadowy program DITHER na pytce CD-ROM.
Ten program rysuje kostk ze ciankami w rnych kolorach, umoliwiajc wczenie
lub wyczenie roztrzsania poprzez polecenie menu. Gdy uruchomisz program w trybie 8-
bitowym lub lepszym, roztrzsanie daje niewielki efekt, jednak w trybie 16-bitowym
kostka rysowana przy uyciu renderowania wyglda zdecydowanie inaczej.

Korzyci ze stosowania palety w trybie 8-bitowym


W trybach 8-bitowych na ekranie mona wywietli 256 kolorw, co wiadczy o znacznej
poprawie jakoci grafiki komputerowej. Gdy Windows dziaa w trybie umoliwiajcym
wywietlenie 256 kolorw, sensowne byoby, aby te kolory byy rwnomiernie
rozmieszczone w przestrzeni kolorw RGB. Wtedy wszystkie aplikacje miayby do dys-
pozycji wzgldnie szeroki zakres kolorw, za podczas wybierania koloru zostaby wy-
brany najbliszy dostpny kolor. Niestety, w rzeczywistym wiecie takie podejcie nie
jest zbyt praktyczne.
Poniewa 256 kolorw palety moe by wybranych z ponad 16 milionw dostpnych
kolorw, aplikacja moe znacznie poprawi jako swojej grafiki poprzez uwane do-
branie tych kolorw - i wiele aplikacji wanie to robi. Na przykad, do stworzenia
obrazu morza konieczne bd dodatkowe odcienie bkitu. Aplikacje CAD i modelowania
modyfikuj palet tak, aby otrzyma pynne cieniowania powierzchni o okrelonym,
jednolitym kolorze. Na przykad, do precyzyjnego przedstawienia przecicia dwch rur
scena moe wymaga zastosowania ponad dwustu odcieni szaroci. Tak wic aplikacje w
komputerach PC zwykle zmieniaj palet kolorw zgodnie ze swoimi potrzebami, dziki
czemu wiele obrazw i scen osiga prawie fotorealistyczny wygld. W przypadku 256-
kolorowych bitmap, format .BMP w Windows posiada nawet wasn palet kolorw,
skadajc si z 256 pozycji zawierajcych 24-bitowe wartoci koloru dla wszystkich
elementw palety kolorw przechowywanego obrazka.
Aplikacja moe utworzy palet za pomoc funkcji CreatePalette(),w wyniku czego
otrzymuje uchwyt palety typu HPALETTE. Ta funkcja wymaga przekazania logicznej
struktury palety (LOGPALETTE) zawierajcej 256 pozycji, z ktrych kada okrela
trzy 8-bitowe wartoci dla barw skadowych, czerwonej, zielonej i niebieskiej. Jednak
zanim przejdziemy do tworzenia palety, zobaczmy, jak wielozadaniowe aplikacje mog
korzysta ze wsplnej, pojedynczej palety sprztowej w 8-bitowym trybie koloru.

Udostpnianie palety
Wielozadaniowo w Windows umoliwia wystpowanie na ekranie kilku aplikacjom
naraz. Sprzt jednak obsuguje jednoczenie tylko 256 kolorw na ekranie, wic wszystkie
aplikacje musz korzysta z tej samej palety systemowej. Jeli jedna z aplikacji zmieni
palet systemow, obrazy w innych oknach mog zmieni kolory, dajc w efekcie
psychodeliczne tcze. Aby rozdzieli palet pomidzy rne aplikacje, Windows rozsya
zestaw komunikatw. Aplikacje s informowane o tym, e ktra z aplikacji
252____________________________________Cz II Uywanie OpenGL

zmodyfikowaa systemow palet oraz o tym, e ich okno znalazo si w ognisku wej-
ciowym i w zwizku z tym mog same zmodyfikowa palet systemow.

Gdy aplikacja znajdzie si w ognisku wejciowym, Windows wysya do gwnego okna


aplikacji komunikat WM_QUERYNEWPALETTE. Ten komunikat po prostu pyta apli-
kacj, czy chce ona zrealizowa now palet. Realizacja palety oznacza, e aplikacja
kopiuje pozycje swojej prywatnej palety do palety systemowej. W tym celu aplikacja
musi najpierw wybra palet w kontekcie urzdzenia aktualizowanego okna, a nastpnie
wywoa funkcj RealizePalette(). Listing 8.2 przedstawia kod procedury obsugi tego
komunikatu; bdziemy z niego korzysta we wszystkich nastpnych przykadach w
ksice.

Listing 8.2. Typowy kod rozdzielania palety w aplikacjach Windows______________________

// Uchwyt palety tworzonej dla 8-bitowych kart graficznych


HPALETTE hPalette = NULL;

// Utworzenie palety o uchwycie hPalette

// Windows informuje aplikacj o modyfikacji systemowej palety //


Ten komunikat gwnie odpytuje aplikacj o now palet, case
WM_QUERYNEWPALETTE:
// Jeli paleta zostaa utworzona,
if( h P a l e t t e ) { int nRet;

// Wybranie palety w biecym kontekcie urzdzenia


SelectPalette(hDC, hPalette, FALSE);

// Odwzorowanie p o z y c j i biecej palety na palet //


systemow. Zwracan wartoci j e s t ilo //
zmodyfikowanych p o z y c j i palety. nRet =
RealizePalette(hDC);

// Przemalowanie, wymuszajce nowe odwzorowanie palety // w


biecym oknie InvalidateRect(hWnd,NULL,FALSE);

return nRet; }
break;

// To okno moe ustala palet, nawet jeli akurat nie j e s t


// aktywne
case WM_PALETTECHANGED:
// Nie rb niczego, jeli paleta nie istnieje lub jeli //
to okno jest oknem, ktre zmienio palet i f ( (hPalette !=
NULL) && ((HWND)wParam != hWnd))
Rozdzia 8. * Kolory i cieniowanie __ __ __ __ 253

i
// Wybranie palety w kontekcie urzdzenia
SelectPalette(hDC,hPalette,FALSE);

// Odwzorowanie pozycji w palet systemow


RealizePalette(h DC ) ;

// Przemapowanie biecych kolorw do nowo //


zrealizowanej palety UpdateColors( h D C ) ; return
0;

break;

Kolejnym komunikatem wysyanym przez Windows w celu zrealizowania palety jest


WM_PALETTECHANGED. Ten komunikat jest wysyany do okna, ktre moe zreali-
zowa swoj palet, mimo to, e nie znajduje si w ognisku wejciowym. Podczas
obsugi tego komunikatu musisz sprawdza warto parametru wParam. Jeli wParam
zawiera uchwyt biecego okna otrzymujcego komunikat, oznacza to, e zosta ju
przetworzony komunikat WM_QUERYNEWPALETTE, wic paleta nie musi by reali-
zowana ponownie.
Zwr take uwag, e na listingu 8.2 jest sprawdzana warto zmiennej hPalette (czy nie
zawiera wartoci NULL) przed przystpieniem do realizacji palety. Jeli aplikacja nie
dziaa w trybie 8-bitowym, nie trzeba realizowa adnej palety. Takie uoenie kodu
zapewnia, e aplikacja poradzi sobie zarwno w przypadku trybw korzystajcych z palety,
jak i trybw nie uywajcych palet.

Tworzenie palety
Niestety, zagadnienia zwizane z palet s zem koniecznym, gdy w dalszym cigu
aplikacje mog zosta uruchomione w systemach dziaajcych w trybie 8-bitowym. C
masz wic zrobi, gdy twj program zostanie uruchomiony w systemie umoliwiajcym
wywietlenie jedynie 256 kolorw?
W przypadku reprodukcji obrazw, zalecamy wybranie palety kolorw cile odzwier-
ciedlajcej oryginalne kolory obrazu. Jednak w przypadku oglnych aplikacji OpenGL,
przydatniejsze bdzie wybranie palety kolorw zapewniajcej najbardziej oglne roz-
mieszczenie kolorw w przestrzeni RGB. Sztuczka polega na takim wybraniu kolorw,
aby byy one rwnomiernie rozmieszczone w kostce kolorw. Wtedy, gdy zostanie
wskazany kolor nie wystpujcy akurat w palecie, Windows wybierze kolor najbardziej
zbliony. Jak ju wspomniano, takie rozwizanie nie jest idealne, ale w przypadku scen
renderowanych za pomoc OpenGL stanowi wszystko, co moemy zrobi. Dopki w scenie
nie wystpuje mapowanie tekstur zawierajcych szeroki zakres kolorw, otrzymane
wyniki mog by cakiem zadowalajce.
254 Cz II Uywanie OpenGL

Czy potrzebujesz palety?


Aby sprawdzi, czy twoja aplikacja potrzebuje palety, po ustaleniu formatu pikseli moesz
wywoa funkcj DescribePixelFormat(). Sprawd warto pola dwFlags otrzymanej
struktury PDCELFORMATDESCRIPTOR. Jeli ustawiony jest bit PFD_NEED_PALETTE,
powiniene utworzy palet, ktra bdzie uywana przez aplikacj. Kod tego testu jest
zawarty w listingu 8.3.

Listing 8.3. Sprawdzenie, czy aplikacja wymaga palety_____________________________

PIKELFORMATDESCRIPTOR pfd; // Deskryptor formatu pikseli int


nPixelFormat; // Indeks formatu pikseli

// Pobranie indeksu formatu pikseli oraz deskryptora formatu pikseli


nPixelFormat = GetPixelFormat( h D C ) ;
DescribePixelFormat(hDC, nPixelFormat, sizeof(PIKELFORMATDESCRIPTOR),
spfd);

// Czy ten format pikseli wymaga palety? Jeli nie, po prostu nie //
twrz j e j i zwr warto NULL if(!(pfd.dwFlags & PFD_NEED_PALETTE))
return NULL;

// Kod tworzenia palety

Struktura palety
Aby utworzy palet, musisz najpierw zaalokowa pami dla struktury LOGPALET-
TE. Ta struktura jest wypeniana informacjami opisujcymi palet, a nastpnie prze-
kazywana funkcji Win32, CreatePalette(). Struktura LOGPALETTE jest zdefiniowana
nastpujco:
typedef struct tagLOGPALETTE { // Igpl
WORD palYersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[1]; }
LOGPALETTE;

Pierwsze dwie skadowe to nagwek palety, okrelajcy jej wersj (zawsze ustawiany na
0x300) oraz ilo pozycji palety (256 dla trybw 8-bitowych). Kada pozycja jest
zdefiniowana jako struktura PALETTEENTRY, zawierajca skadowe RGB dla pozycji
koloru.
Poniszy kod alokuje pami dla palety logicznej:
LOGPALETTE *pPal; // Wskanik do obszaru pamici dla palety logicznej

// Zaalokowanie pamici na struktur logicznej palety


Rozdzia 8. Kolory i cieniowanie_________________________________255

// i wszystkie j e j pozycje
pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
nColors*sizeof(PALETTEENTRY));

nColors okrela ilo kolorw w palecie, ktra do naszych celw zawsze wynosi 256.
Kada pozycja palety jest struktur PALETTEENTRY, zdefiniowan nastpujco:
typedef struct tagPALETTEENTRY { // pe
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags; }
PALETTEENTRY;

Skadowe peRed, peGreen oraz peBlue okrelaj 8-bitowe wartoci reprezentujce


wzgldne intensywnoci poszczeglnych barw skadowych koloru. W ten sposb, kada z
256 pozycji palety zawiera 24-bitow definicj koloru. Skadowa peFlag opisuje za-
awansowane wykorzystanie pozycji palety. Do zastosowa OpenGL mona j ustawi po
prostu na NULL.
Oprcz palety 3-3-2, Windows obsuguje take inne palety, na przykad przeznaczone do
wywietlenia dwustu odcieni szaroci.

Paleta 3-3-2
A teraz par sztuczek. Nasze 256 pozycji palety musi by nie tylko rwnomiernie roz-
prowadzone w obrbie kostki kolorw, ale musi take by uoone w odpowiedniej ko-
lejnoci. Wanie ta kolejno umoliwi OpenGL wybranie z palety najbliszej wartoci
koloru. Jak pamitamy, w 8-bitowych trybach mamy po trzy bity dla czerwieni i zieleni
oraz dwa bity dla bkitu. Tak palet zwykle okrela si mianem palety 3-3-2. Tak
wic nasza kostka kolorw RGB bdzie mierzya 8x8x4 jednostki, odpowiednio w osiach
czerwonej, zielonej i niebieskiej.
Aby wyszuka w tej palecie dany kolor, warto 8-8-8 (24-bitowa warto koloru)
musi zosta przeskalowana do wartoci 3-3-2. Ta omiobitowa warto staje si inde-
ksem do naszej palety. Intensywnoci czerwieni od O do 7 w palecie 3-3-2 musz odpo-
wiada intensywnociom od O do 255 w palecie 8-8-8. Sposb poczenia skadowych R,
G i B w indeks palety ilustruje rysunek 8.14.
Rysunek 8.14. Intensywno Intensywno Intensywno
Upakowanie bitw bkitu zieleni czerwieni
palety 3-3-2 '***A>

7|t|5|4|3|l|l|Q|
.

Gdy budujemy palet, w ptli przechodzimy przez wartoci od O do 255. Nastpnie de-
komponujemy indeks do wartoci czerwieni, zieleni i bkitu, reprezentowanych przez te
wartoci (w ramach palety 3-3-2). Kada skadowa jest mnoona przez 255, po czym
dzielona przez maksymaln reprezentowaln warto, co daje efekt skokowego przej-
256 Cz II * Uywanie OpenGL

cia od wartoci O do 7 dla czerwieni i zieleni oraz od O do 3 dla bkitu. W celu zade-
monstrowania przebiegu oblicze, tabela 8.1 przedstawia wartoci niektrych pozycji
palety.

Tabela 8.1.
Kilka przykadw wartoci pozycji palety 3-3-2

Pozycja palety Binarnie (B G R) Skadowa Skadowa zielona Skadowa


niebieska czerwona
0 00 000 000 0 0 0
1 00000001 0 0 1*255/7
2 00 000 010 0 0 2*255/7
3 00000011 0 0 3*255/7
9 00001 001 0 1*255/7 1*255/7
10 00001 010 0 1*255/7 2*255/7
137 10001 001 2*255/3 1*255/7 1*255/7
138 10001 010 2*255/7 1*255/7 2*255/3
255 11 111 111 3*255/3 7*255/7 7*255/7

Budowanie palety

Niestety, w tym momencie OpenGL w Windows obsuguje w trybie RGBA jedynie palet
3-3-2. Jest to okrelone w strukturze PIXELFORMATDESCRIPTOR zwracanej przez
funkcj DescribePixelFormat(). Pola cRedBits, cGreenBits oraz cBlueBits tej struktury
podaj 3, 3 oraz 2 jako liczb bitw reprezentujcych poszczeglne skadowe. Co wicej,
pola CRedShift, cGreenShift oraz cBlueShift okrelaj, o ile bitw naley przesun
kad warto w lewo (w tym przypadku o O, 3 i 6 bitw dla czerwieni, zieleni i bkitu).
Te ustawienia wartoci tworz indeks pozycji palety (rysunek 8.14).

Kod z listingu 8.4 tworzy w miar potrzeby palet i zwraca jej uchwyt. Ta funkcja wy-
korzystuje pola iloci i przesunicia bitw dla kadej skadowej ze struktury PIXEL-
FORMATDESCRIPTOR, tworzc palet 3-3-2.

Listing 8.4. Funkcja tworzca palet 3-3-2

II Jeli trzeba, tworzy palet 3-3-2 dla wskazanego kontekstu


// urzdzenia
HPALETTE GetOpenGLPalette(HDC hDC)
HPALETTE hRetPal = NULL; // Uchwyt tworzonej palety //
PIXELFORMATDESCRIPTOR pfd; Deskryptor formatu pikseli //
LOGPALETTE *pPal; Wskanik do obszaru pamici
//dla palety logicznej //
int nPixelFormat; Indeks formatu pikseli
Rozdzia 8. * Kolory i cieniowanie_________________________________257

int nColors; // Ilo pozycji palety


int i; // Licznik
BYTE RedRange,GreenRange,BlueRange;
// Zakres dla kadej pozycji koloru ( 7 , 7 i 3)

// Pobranie indeksu formatu pikseli oraz deskryptora formatu


// pikseli
nPixelFormat = GetPixelFormat(hDC);
DescribePixelFormat(hDC, nPixelFormat,
sizeof(PIXELFORMATDESCRIPTOR) , Spfd);
// Czy ten format pikseli wymaga palety? Jeli nie, po prostu nie //
twrz jej i zwr warto NULL if(!(pfd.dwFlags S PFD_NEED_PALETTE))
return NULL;
// Ilo pozycji w palecie. 8 bitw oznacza 256 pozycji
nColors = l pfd.cColorBits;
// Zaalokowanie pamici na struktur logicznej palety
// i wszystkie jej pozycje
pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
nColors*sizeof(PALETTEENTRY));

// Wypenienie nagwka palety pPal->palVersion =


0x300; // Windows 3 . 0 pPal->palNumEntries =
nColors; // rozmiar tabeli
// Budowanie maski wszystkich jedynek. Tworzy liczb
// reprezentowan przez x dolnych bitw ustawionych, gdzie
// x = pfd.cRedBits, pfd.cGreenBits oraz pfd.cBlueBits.
RedRange = (l pfd.cRedBits) - 1 ;
GreenRange (l pfd.cGreenBits) - 1;
BlueRange = (l pfd.cBlueBits) -1;
// Przejcie przez wszystkie pozycje palety
for(i = 0 ; i < nColors; i++)

// Wypenienie 8-bitowych odpowiednikw kadego komponentu pPal-


>palPalEntry [ i ] .peRed = (i pfd.cRedShift) & RedRange; pPal-
>palPalEntry[ i ] .peRed = (unsigned char)(
(double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
pPal->palPalEntry[ i ] .peGreen = (i pfd.cGreenShift) &
^GreenRange;
pPal->palPalEntry[ i ] .peGreen = (unsigned char)(
(double)pPal->palPalEntry[ i ] .peGreen * 255.0 /
^GreenRange) ;
pPal->palPalEntry[i].peBlue = (i pfd.cBlueShift) &
^BlueRange;
pPal->palPalEntry[ i ] .peBlue = (unsigned char)(
(double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);
pPal->palPalEntry[ i ] .peFlags = (unsigned char) NULL; }
258____________________________________Cz II Uywanie OpenGL

// Otworzenie palety
hRetPal = CreatePalette(pPal);

// Wybranie i zrealizowanie palety dla biecego kontekstu //


urzdzenia
SelectPalette(hDC,hRetPal,FALSE) ;
RealizePalette(hDC);
// Zwolnienie pamici uytej przez struktur palety logicznej
free(pPal);
// Zwrcenie uchwytu nowej palety
return hRetPal;

Tworzenie i usuwanie palety


Paleta powinna zosta utworzona i zrealizowana przed utworzeniem i uczynieniem biecym
kontekstu renderowania. Funkcja z listingu 8.4 wymaga jedynie kontekstu urzdzenia, ju po
ustaleniu formatu pikseli. Funkcja zwraca uchwyt palety, jeli rzeczywicie jest taka
potrzeba. Listing 8.5 przedstawia kolejno operacji wykonywanych podczas tworzenia i
niszczenia okna. Jest on podobny do przedstawionego wczeniej kodu zwizanego z
tworzeniem i niszczeniem kontekstu renderowania, lecz w tym przypadku bierzemy pod
uwag take ewentualn obecno palety.

Listing 8.5. Tworzenie i niszczenie palety_____________________________________

// Utworzenie okna, przygotowania dla OpenGL case


WM_CREATE:
// Przechowanie kontekstu urzdzenia
hDC = GetDC(hwnd);
// Wybranie formatu pikseli
SetDCPixelFormat(hDC);
// Jeli trzeba, utworzenie palety
hPalette = GetOpenGLPalette(hDC);

// Utworzenie kontekstu renderowania i uczynienie go


// biecym
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
SetupRC();
break;

// Okno jest niszczone, wic robimy porzdki case


WM_DESTROY:
// Odoenie biecego kontekstu renderowania i usunicie
// go
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);

// Osunicie palety, jeli zostaa utworzona


if(hPalette != NULL)
DeleteObject(hPalette);
Rozdzia 8. Kolory i cieniowania________________________________259

// Poinformowanie aplikacji o zakoczeniu dziaania


PostQuitMessage( 0 ) ;
break;

Pewne ograniczenia
Nie wszystkie pozycje 256 - kolorowej palety zostan odwzorowane do palety systemowej.
Windows rezerwuje 20 pozycji dla statycznych kolorw systemowych, obejmujcych 16
standardowych kolorw EGA/YGA. Zabezpiecza to przed zmian kolorw
komponentw okien (paskw tytuowych, przyciskw etc.) przez aplikacj zmieniajc
palet systemow. Gdy aplikacja realizuje swoj palet, tych 20 kolorw pozostanie
niezmienionych. Na szczcie, niektre z tych kolorw wystpuj lub cile odzwierciedlaj
kolory z palety 3-3-2. Te, ktre nie odzwierciedlaj danych kolorw, s na tyle
podobne, e, nie raczej zauwaysz rnicy.

Tryb indeksu koloru


OpenGL obsuguje take alternatywny tryb indeksu koloru. W tym trybie kolor do operacji
rysunkowych jest okrelany przez wskazanie indeksu do tablicy kolorw, a nie trjki
wartoci dla poszczeglnych skadowych.
Nie mona korzysta jednoczenie z trybu indeksu i z trybu RGBA. Oznacza to, e jeli
uywasz trybu indeksu na urzdzeniu True Color (lub zblionym do True Color, na
przykad w trybie 16-bitowym), nie bdziesz mia dostpu do wszystkich moliwych
kolorw. W niektrych implementacjach paleta indeksu koloru moe zawiera do 4096
pozycji. Jednak implementacja Microsoftu obsuguj e jedynie 256 pozycji.
Moesz uy trybu indeksu koloru w odwzorowaniach konturu, w ktrych niektre funkcje
powierzchni zwracaj indeks do palety. Ten tryb jest nieco szybszy ni RGBA i nie
wystpuj w nim ograniczenia palety 3-3-2. Na przykad, jeli potrzebujesz dwustu odcieni
szaroci, moesz je uzyska. Jednak w trybie indeksu kolorw nie s dostpne pewne efekty
owietlenia omawiane w nastpnym rozdziale.

Kiedy uywa trybu indeksu koloru?


Tak naprawd rzadko zachodzi konieczno korzystania z trybu indeksu koloru. Zwykle
stosuje si go w celu lepszego zapanowania nad palet. Moesz w nim tworzy take
animacje palety, ale tylko w przypadku urzdze korzystajcych z palety (8-bitowych
kart graficznych). Animacja palety wystpuje wtedy, gdy zmieniasz kolory pozycji palety,
co powoduje zmiany koloru tych pikseli ekranu, ktrym przypisano dan pozycj palety.
W ten sposb mona uzyska pynne zmiany kolorw dla pewnych efektw specjalnych.
260____________________________________Cz II Uywanie OpenGL

Kolejny powd do uywania trybu indeksu koloru maj aplikacje, ktre wykorzystuj
kolor do wskazania trzeciego wymiaru - na przykad stopnia wgbienia pewnych ob-
szarw obiektu. Moesz take uy tego trybu przy tworzeniu obrazw, w ktrych nie jest
wymagana zorganizowana paleta. Na koniec, w przypadku trybw 8-bitowych, tryb
indeksu koloru moe by troch szybszy, gdy podczas zmiany palety czsto konieczne
jest manipulowanie tylko jednym kanaem (a nie trzema czerwonym, zielonym i nie-
bieskim).

Oprcz ogranicze co do wyboru kolorw, w trybie indeksu kolorw nie mona korzysta
z pewnych innych efektw specjalnych OpenGL wcznie z wieloma efektami
owietlenia i cieniowania, antyaliazingu czy alpha blendingu. Oglnie lepiej wic ko-
rzysta z trybu RGBA.

Jak ju wspomniano, najwiksz korzyci pync ze stosowania trybu indeksu koloru jest
wiksza kontrola nad palet w 8-bitowych trybach koloru. Paleta 3-3-2 ogranicza
moliwoci wyboru kolorw, wic gdy w trybie 8-bitowym potrzebujesz dwustu odcieni
czerwieni w celu naprawd gadkiego pocieniowania obiektu, nie masz szczcia.
Jednak w trybie indeksu koloru, pozycjom palety mona przypisa dowolne wartoci
kolorw, od najciemniejszych do najjaniejszych. Moesz przy tym podzieli palet na
dowoln ilo pasm. Przykadowy program INDEX wywietla wanie taki trjkt,
pynnie pocieniowany od czerni do czerwieni (rysunek 8.15). Takie cieniowanie w trybie
8-bitowym, przy uyciu palety 3-3-2, nie byoby moliwe.

Rysunek 8.15.
Wynik dziaania programu IN D EX,
przedstawiajcy dwiecie odcieni czerwieni

Uycie trybu indeksu koloru


Aby wczy tryb indeksu koloru, jedyne, co
musisz zrobi, to przypisa wartoci pola
iPixelType struktury
PKELFORMATDESCRIPTOR sta
PFD_TYPE_COLORJNDEX. Przedtem musisz
jednak utworzy palet. W przypadku trybu indeksu koloru, paleta jest specyficzna dla
aplikacji. Do przykadowego programu INDEX potrzebujemy palety skadajcej si
jedynie z odcieni koloru czerwonego, tak aby mc uzyska pynne cieniowanie take w
trybie 8-bitowym. Kod uyty do utworzenia tej palety zosta przedstawiony na listingu 8.6.
Rozdzia 8. Kolory i cieniowanie_________________________________261

Listing 8.6. Kod tworzcy palet skadajc si wycznie z odcieni koloru


czerwonego___________
// Tworzy palet z przejciem koloru od czarnego do jasnoczerwonego
HPALETTE GetRedPalette(HDC hDC)

HPALETTE hRetPal = NULL; // Uchwyt tworzonej palety


LOGPALETTE *pPal; // Wskanik do pamici dla palety
// logicznej
int i; // Licznik

// Zaalokowanie pamici na struktur logicznej palety


// i wszystkie jej pozycje
pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
256*sizeof(PALETTEENTRY));

// Wypenienie nagwka palety


pPal->palVersion = 0x300; // Windows 3 . 0 pPal-
>palNumEntries = 256; // rozmiar tabeli

// Przejcie przez wszystkie pozycje palety i utworzenie kolejnych //


odcieni koloru czerwonego, for(i = 0 ; i < 256; i++)
// Intensywno czerwieni od O do 255 pPal-
>palPalEntry[ i ] .peRed = i; pPal-
>palPalEntry[ i ] .peGreen = 0; pPal-
>palPalEntry[ i ] .peBlue = 0; pPal-
>palPalEntry[ i ] .peFlags = (unsigned char) NULL;

// Utworzenie palety
hRetPal = CreatePalette (pPal);

// Wybranie i zrealizowanie palety dla biecego kontekstu


// urzdzenia
SelectPalette( h D C , hRetPal,FALSE);
RealizePalette(hDC);
// Zwolnienie pamici uytej przez struktur palety logicznej
free(pPal);

// Zwrcenie uchwytu nowej palety return


hRetPal; }

Zwr uwag, e ten kod zawsze zwraca uchwyt palety, gdy w ogle nie sprawdzamy, czy
wybrany format pikseli wymaga palety. Dzieje si tak, poniewa trybu indeksu koloru
moemy uy take w trybach o wikszych ilociach kolorw. Wszystkie pozostae czci
kodu zwizane z realizacj palety pozostaj niezmienione.

Rysowanie trjkta
Przejdmy do fragmentu kodu nadajcego najwyszemu wierzchokowi trjkta kolor o
indeksie O, czyli najciemniejszy kolor palety (czer). Kolor dwch dolnych wierzchokw
trjkta jest ustawiony na indeks palety 255, najjaniejszy odcie czerwieni. Przy
262____________________________________Cz II Uywanie OpenGL

wczonym pynnym cieniowaniu, ten kod (listing 8.7) daje obraz trjkta przedstawionego
na rysunku 8.15.

Listing 8.7. Kod rysujcy cieniowany trjkt w programie INDEX_______________________

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wczenie pynnego cieniowania
glShadeModel(GL_SMOOTH);

// Ustawienie koloru czyszczenia na pierwsz pozycj palety //


(czer) glClear!ndex(O.Of);
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT);
// Rysowanie trjkta
glBegin(GLJTRIANGLES);
// Najciemniejszy czerwony wierzchoek (czarny)
gllndexi(0);
glVertex3f( O . O f ,200.Of,O . O f );
// Najjaniejsze czerwone dolne wierzchoki
gllndexi(255);
glVertex3f(200.Of,-70.Of,O.Of);
glVertex3f(-200.Of, -70.Of, O . O f ) ;
glEnd();

// Zrzucenie polece graficznych


glFlushO;

Podsumowanie
W tym rozdziale zajlimy si jednym z najwaniejszych elementw kadego pakietu
graficznego: kolorem. Wiesz ju, jak okrela kolor przez podanie barw skadowych
RGB, a take jak te skadowe maj si do siebie w przestrzeni (kostce) kolorw RGB.
Poznae zastosowanie funkcji glColor do kolorowania wierzchokw, wiesz wic, jak
wpywa to na efekty cieniowania. Wyjanilimy wybr kolorw OpenGL w trybach ko-
lorw 4-, 8-, 16- i 24-bitowych. Zademonstrowalimy budowanie palety 3-3-2, uywanej
przez OpenGL w trybach 8-bitowych. Na koniec, rzucilimy okiem na tryb indeksu koloru
oraz sposb jego wykorzystania w celu uzyskania wikszej kontroli nad palet w 8-
bitowych trybach kolorw.
Poprawne uycie kolorw i cieniowania jest nieodzownym elementem dobrej trjwy-
miarowej grafiki. W nastpnym rozdziale wyjanimy, jak OpenGL stosuje cieniowanie w
celu uzyskania efektw owietlenia. Dowiesz si, jak okrela kolory materiaw i
warunki owietlenia, a take jak umoliwi OpenGL wybr kolorw przy rysowaniu.
Rozdzia 8. + Kolory i cieniowanie 263

Podrcznik
glClearlndex
Przeznaczenie Ustawia numer koloru ta dla buforw indeksu koloru.
Plik nagwkowy
Skadnia Opis void glClearIndex(GLfloat color);
Ta funkcja okrela numer (indeks) koloru, ktry w trybie indeksu koloru
zostanie uyty do wymazania (wyczyszczenia) buforw koloru. Efektem
ubocznym jest wymazanie zawartoci okna i ustawienie koloru ta na kolor
(indeks) okrelony parametrem color.
Parametry
color GLfloat: Warto uywana przy czyszczeniu buforw koloru funkcj
glClear. Domyln wartoci jest 0.
Zwracana warto Brak
Przykad Patrz Przykadowy program INDEX w tym rozdziale.
take glClear, glGet

glColor
Przeznaczenie Ustawia biecy kolor w trybie koloru RGBA.
Plik nagwkowy <gl.h>
Skadnia void glCo!or3b(GLbyte red, GLbyte green, GLbyte blue);
void glColor3d(GLdouble red, GLdouble green, GLdouble blue);
void glColor3f(GLfloat red, GLfloat green, GLfloat blue);
void g!Co!or3i(GLint red, GLint green, GLint blue);
void glColor3s(GLshort red, GLshort green, GLshort blue);
void glColor3ub(GLubyte red, GLubyte green, GLubyte blue);
void glColor3ui(GLuint red, GLuint green, GLuint blue);
void glColor3us(GLushort red, GLushort green, GLushort blue);
void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
void gICoor4d(GLdouble red, GLdouble green, GLdouble blue,
GLdouble alpha);
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void glColor4i(GLint red, GLint green, GLint blue, GLint alpha);
void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort
alpha);
264 Cz II Uywanie OpenGL

void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte


alpha);
void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha);
void g!Color4us(GLushort red, GLushort green, GLushort blue,
GLushort alpha);
void glColor3bv(const GLbyte *v); void
glColor3dv(const GLdouble *v); void
glColor3fv(const GLfloat *v); void
glColor3iv(const GLint *v); void
glColor3sv(const GLshort *v); void
glColor3ubv(const GLubyte *v); void
glColor3uiv(const GLuint *v); void
glColor3usv(const GLushort *v); void
glColor4bv(const GLbyte *v); void
glCo!or4dv(const GLdouble *v); void
glColor4fv(const GLfloat *v); void
gIColor4iv(const GLint *v); void
glColor4sv(const GLshort *v); void
glColor4ubv(const GLubyte *v); void
glColor4uiv(const GLuint *v); void
glColor4usv(const GLushort *v);
Opis Ta funkcja okrela biecy kolor przez okrelenie wartoci trzech barw
skadowych koloru. Niektre funkcje akceptuj take skadow alfa. Kady
komponent reprezentuje warto intensywnoci barwy skadowej od zera
(0,0) do penej intensywnoci (1,0). Funkcje z przyrostkiem v wymagaj
podania wskanika do tablicy zawierajcej poszczeglne komponenty.
Kady element tej tablicy musi by tego samego typu. Gdy nie jest
podawany komponent alfa, jego warto domylnie ustawia si na 1,0. Gdy
uywane s funkcje, ktre nie korzy staj z argumentw
zmiennoprzecinkowych, zakres od zera do najwyszej wartoci
reprezentowanej przez dany typ jest odwzorowywany w
zmiennoprzecinkowy zakres od 0,0 do l ,0.
Parametry
red Okrela intensywno czerwonej barwy skadowej.
green Okrela intensywno zielonej barwy skadowej.
blue Okrela intensywno niebieskiej barwy skadowej.
alpha Okrela intensywno skadowej alfa. Uywany tylko w wersjach funkcji
wymagajcych podania czterech argumentw.
Wskanik do tablicy zawierajcej czerwon, zielon i niebiesk warto
skadowej, a by moe take warto alfa.
Rozdzia 8. Kolory i cieniowanie 265

Zwracana warto Brak


Przykad Poniszy kod pochodzi z przykadu CCUBE w tym rozdziale. Nadaje
Patrz jednemu z wierzchokw kostki kolorw kolor biay.
take // Przednia ciana
glBegin(GL_POLYGON>;
// Biay
glColor3ub((GLubyte)255, (GLubyte)255, (GLubyte)255);
glVertex3f( 5 0 . Of, 50.O f , 50.O f ) ;

gllndex

glColorMask
Przeznaczenie Wcza lub wycza modyfikacje skadowych koloru w buforach koloru.
Plik
nagwkowy void glColorMask(GLboolean bRed, GLboolean bGreen, GLboolean
bBlue, GLboolean bAlpha);
Skadnia
Ta funkcja umoliwia okrelenie, ktre skadowe koloru w buforze koloru
bd mogy by modyfikowane (domylnie wszystkie mog by
modyfikowane). Na przykad, ustawienie parametru bAlpha na GL_FALSE
blokuje wszystkie zmiany w skadowej alfa bufora koloru okna.
Parametry
bRed GLboolean: Okrela, czy skadowa czerwona moe by modyfikowana.
bGreen GLboolean: Okrela, czy skadowa zielona moe by modyfikowana.
bBlue GLboolean: Okrela, czy skadowa niebieska moe by modyfikowana.
bAlpha GLboolean: Okrela, czy skadowa alfa moe by modyfikowana. Brak
Zwracana Przykadowy program MASK na pytce CD-ROM, w folderze tego
rozdziau.
warto
, glColor, gllndex, gl!ndexMask, glDepthMask, glStencilMask

Przykad
gllndex
Przeznaczenie Ustala biecy indeks koloru dla rysowanych wierzchokw.
Plik <gl.h>
nagwkowy void gl!ndexd(GLdouble c);
void glIndexf(GLfloat c); void
gl!ndexi(GLint c);
266 Cz II Uywanie OpenGL

void glIndexs(GLshort c); void


gllndexdv(const GLdouble *c); void
gllndexfv(const GLfloat *c); void
gilndexiv(const GLint *c); void
gllndexsv(const GLshort *c);
Opis Ta funkcja zmienia biecy indeks koloru na indeks okrelony przez c.
Parametry Wewntrznie indeks koloru jest przechowywany jako liczba
zmiennopozycyjna.
Zwracana warto
Przykad
Nowy indeks koloru, ktry zostanie uyty w nastpnych poleceniach.
Wskanik do nowego indeksu koloru, ktry zostanie uyty w nastpnych
poleceniach.
Brak
Przykadowy program INDEX w tym rozdziale rysuje gadko cieniowany
trjkt. Grny wierzchoek trjkta otrzymuje kolor o indeksie O,
ustawionym na czer, za dolne wierzchoki otrzymuj kolor o indeksie 255,
ustawiony na jaskraw czerwie.
// Rysowanie trjkta
glBegin(GL_TRIANGLES);
// Najciemniejszy czerwony wierzchoek (czarny)
gllndexi( 0 ) ;
glVertex3f( O . O f ,200.0f,O .O f);

// Najjaniejsze czerwone dolne wierzchoki


gllndexi(255);
glVertex3f(200.0f,-70.0f,O . O f );
glVertex3f(-200.Of, -70.Of, O . O f ) ;
glEnd();

Patrz take glColor

gllndexMask
Przeznaczenie Maskuje bity bufora indeksw kolorw, ktre w trybie indeksu kolorw
mog by modyfikowane.
Plik nagwkowy
Skadnia void gl!ndexMask(GLuint mask);
Opis Ta funkcja umoliwia zamaskowanie poszczeglnych bitw w buforze
indeksw kolorw. Gdy bit maski jest ustawiony, odpowiedni bit indeksu
moe by modyfikowany. Gdy bit maski jest wyzerowany, odpowiedni bit
indeksu nie moe by modyfikowany, czyli jest zabezpieczony przed
zmian w wyniku operacji rysunkowych. Ta funkcja ma zastosowanie
jedynie w trybie indeksu koloru.
Rozdzia 8. + Kolory i cieniowanie 267

Parametry
mask GLuint: Okrela binarn mask bitow, wczajc lub wyczajc zapis
poszczeglnych bitw w buforze indeksw koloru.
Zwracana warto Brak
Przykad
Przykadowy program MASK na pytce CD-ROM, w folderze tego
rozdziau.
gllndex, glDepthMask, glStencilMask
Patrz take

gILogicOp
Przeznaczenie Ustala logiczn operacj na pikselach w trybie indeksu koloru.
Plik nagwkowy
Skadnia Opis void glLogicOp(GLenum opcode);
Logiczna operacja na pikselach okrela sposb czenia wartoci pikseli.
Gdy zamiast piksela jest wpisywana nowa warto indeksu koloru
(rysowany jest nowy punkt), jest on czony logicznie z biecym indeksem
koloru ju istniejcego piksela. Aby wczy operacje logiczne na kolorze
pikseli, wywoaj funkcj glEnable(GL_LOGIC_OP). Aby je wyczy,
wywoaj glDisable(GL_LOGIC_OP). Gdy s wczone logiczne operacje na
indeksach kolorw pikseli, nowe wartoci pikseli s czone logicznie z
wartociami indeksu pikseli ju istniejcych; sam za operacj logiczn
okrela parametr opcode. Gdy operacje logiczne nie s wczone, efekt
rysowania pikseli jest taki, jakby wybrana bya operacja GL_COPY, czyli
zwyke rysowanie. Logiczne operacje na indeksach pikseli nie s
obsugiwane w trybie koloru RGBA.
Parametry
opcode GLenum: Okrela rodzaj operacji logicznej wykonywanej na wartociach
Zwracana warto indeksw koloru pikseli. Dozwolone s wartoci z tabeli 8.2. Ta tabela
zawiera list operacji logicznych oraz wzorw okrelajcych ich dziaanie,
Przykad gdzie s reprezentuje warto indeksu koloru piksela rdowego
(istniejcego), za d reprezentuj e warto indeksu koloru piksela docelowego
(rysowanego).
Patrz take Brak
Przykadowy program FLASHER na pytce CD-ROM. W tym przykadzie
zastosowano operacj logiczn GL_XOR w celu stworzenia pynnej
animacji bez podwjnego buforowania.
glGet, gllsEnabled, glEnable, glDisable
268 Cz II Uywanie OpenGL

Tabela 8.2.
Operacje logiczne na pikselach

Opcode Wynik
GL_CLEAR 0
GL_SET 1
GL_COPY s
GL_COPY_INVERTED !s
GL_NOOP d
GLJNYERT !d
GL_AND s&d
GLJMAND !(s & d)
GL_OR s|d
GL_NOR !(s | d)
GL_XOR sAd
GL_EQUIW !(s A d)
GL_AND_REVERSE s&!d
GL_AND_INVERTED !s&d
GL_OR_REVERSE s|!d
GL_OR_INVERTED !s|d

gIShadeModel
Przeznaczenie Ustala domylny tryb cieniowania paski lub gadki.
Plik nagwkowy
Skadnia Opis void glShadeModel(GLenum mod);
Prymitywy OpenGL s zawsze cieniowane, jednak model cieniowania moe
by paski (GL_FLAT) lub gadki (GL_SMOOTH). W najprostszym
scenariuszu, przed narysowaniem prymitywu jest ustawiany pojedynczy
kolor funkcj glColor(). Taki prymityw ma jednolity, niezmienny kolor, bez
wzgldu na cieniowanie. Jeli dla kadego wierzchoka zostanie okrelony
inny kolor, to w zalenoci od trybu cieniowania zmienia si wygld obiektu.
Przy wczonym gadkim cieniowaniu, kolor wntrza wieloktw jest
interpolowany na podstawie koloru poszczeglnych wierzchokw, czyli
kolor zmienia si pynnie od jednego wierzchoka do innego. Zmiany
kolorw przebiegaj zgodnie ze zmian koloru punktw odcinka czcego
dwa kolory w przestrzeni kolorw. Jeli przy tym jest wczone owietlenie,
OpenGL dokonuje take innych oblicze, majcych na celu wyznaczenie
poprawnego koloru
SL
Rozdzia 8. * Kolory i cieniowanie_________________________________269

piksela (patrz rozdzia 9). Przy paskim cieniowaniu, cay prymityw jest
rysowany w kolorze zdeterminowanym przez kolor przypisany ostatniemu
wierzchokowi prymitywu. Jednym wyjtkiem jest prymityw
GL_POLYGON; w tym przypadku o kolorze wielokta decyduje kolor
okrelony dla pierwszego wierzchoka.
Parametry
mod GLenum: Okrela tryb cieniowania, GL_FLAT (paski) lub
GL_SMOOTH (gadki). Domylnym trybem jest GL_SMOOTH.
Zwracana warto Brak
Przykad Przykadowe programy TRIANGLE i CCUBE na pytce CD-ROM,
w folderach tego rozdziau.
Patrz take glColor, glLight, glLightModel
Rozdzia 9.
Owietlenie i
rda wiata
W tym rozdziale:
Dowiesz si, jak... Uywane funkcje
4 Okreli model owietlenia 4 glLightMaterial
4 Okreli parametry owietlenia 4 glLight
4 Okreli waciwoci refleksyjne materiau * glColorMaterial, glMaterial
4 Uywa normalnych do powierzchni 4 glNormal

W tym rozdziale omawiamy owietlenie: w naszym mniemaniu najciekawsz rzecz w


OpenGL. Bibliotek OpenGL poznawae od pocztku - od sposobu tworzenia pro-
gramw, przez skadanie obiektw z prymityww, a nastpnie manipulowanie nimi w
przestrzeni 3D. W rozdziale smym dowiedziae si, jak nadawa obiektom kolory oraz
jak uzyska rne sposoby cieniowania. Wszystko to w kolejnoci i w porzdku, ale
powiedzmy sobie szczerze - kady w miar zdolny student, zaopatrzywszy si w dobr
ksik o grafice komputerowej, moe osign to samo, wykorzystujc choby GDI
Windows. Parafrazujc znane stwierdzenie, Gdzie jest miso?".
Mona powiedzie, e zaczyna si wanie tutaj. W wikszoci pozostaej czci ksiki
nauka traci na znaczeniu, za zaczyna rzdzi magia. Jak stwierdzi Arthur C. Clark, kada
odpowiednio zaawansowana technologia jest nieodrnialna od magii. Oczywicie, w
owietleniu nie ma prawdziwej magii, jednak z pewnoci czsto mona odnie takie
wraenie. (Jeli chcesz zagbi si w matematyk, zajrzyj do dodatku B).
Inn nazw tego rozdziau mogoby by Dodawanie realizmu scenie". Widzisz, w rze-
czywistym wiecie nie liczy si tylko kolor obiektu, jaki zaczlimy okrela w roz-
dziale 8. Oprcz posiadania koloru, obiekt moe wydawa si lnicy lub matowy, a
moe nawet jarzy si wasnym wiatem. Okrelony kolor obiektu zmienia si w jasnym
lub ciemnym owietleniu; rnic sprawia nawet kolor wiata owietlajcego
272____________________________________Cz II Uywanie OpenGL

obiekt. Owietlony obiekt, ogldany pod rnymi ktami, moe mie zupenie inaczej
pocieniowane ciany. Wikszo z pozostaych zagadnie w czciach II i III zwizanych
jest z technikami umoliwiajcymi nadanie scenie coraz wicej realizmu. Od wic
kalkulator (jeli chcesz), za kapelusz maga i we gboki oddech... Zaczynamy pokaz
magiczny!

wiato w rzeczywistym wiecie


Rzeczywiste obiekty nie maj wycznie jednolitego lub pocieniowanego koloru, opartego
jedynie na wartociach barw skadowych RGB. Rysunek 9.1 przedstawia wynik
dziaania programu JET z pytki CD-ROM. To prosty samolot, stworzony rcznie z trj-
ktw, przy wykorzystaniu jedynie metod opisanych dotd w ksice. Jak zwykle, JET i
inne programy w tym rozdziale umoliwiaj obracanie modeli za pomoc klawiszy
kursora w celu lepszego przedstawienia efektw.

Rysunek 9.1.
Prosty samolot zbudowany przez dobraniem
odmiennego koloru dla kadego z trjktw

Kolory dobrano po to, aby


podkreli trjwymiarow
struktur samolotu. Oprcz
tego, e jest zoony z
trjktw, nasz samolot w
niczym nie przypomina
rzeczywistego obiektu.
Przypumy, e stworzye
model tego samolotu i
pomalowae kad
powierzchni pokazanym
w oknie kolorem. Ten
rzeczywisty model wci bdzie lnicy lub matowy, w zalenoci od uytej farby, za
kolor kadej z powierzchni bdzie zmienia si w zalenoci od kta padania wiata i kta,
pod ktrym na ni patrzysz.
OpenGL, jeli chodzi o owietlenie, doskonale sobie radzi z odzwierciedlaniem rzeczy-
wistego wiata. Dopki obiekt nie emituje wasnego rda wiata, w OpenGL jest ilu-
minowany przez trzy rne rodzaje wiata: otaczajce (ang. ambient), rozproszone (ang.
diffuse) oraz odbysku1 (ang. specular).

1
W rzeczywistym wiecie mamy oczywicie tylko jeden rodzaj wiata. Podzia na
rodzaje wiata w OpenGL wynika ze sposobu komputerowego modelowania
owietlenia. (Przy. tum.)
Rozdzia 9. * Owietlenie i rda wiata 273

wiato otaczajce
wiato otaczajce to wiato, ktre nie pochodzi z adnego okrelonego kierunku. Ma
swoje rdo, jednak promienie wiata odbijaj si po caym pomieszczeniu lub scenie i
generalnie s pozbawione kierunku. Obiekty iluminowane wiatem otaczajcym s
rwnomiernie owietlone na wszystkich powierzchniach we wszystkich kierunkach.
Wszystkie poprzednie przykady w tej ksice moesz uzna za owietlone biaym
wiatem otaczajcym, gdy obiekty byy zawsze widoczne i rwnomiernie pokoloro-
wane (lub cieniowane), bez wzgldu na ich obrt i kt patrzenia. Obiekt owietlony
przez wiato otaczajce przedstawia rysunek 9.2.
Rysunek 9.2.
Obiekt owietlony
wycznie wiatem
otaczajcym

wiato rozproszone
wiato rozproszone pochodzi z konkretnego kierunku, lecz jest odbijane od powierzchni
rwnomiernie. Nawet jeli wiato jest odbijane rwnomiernie, powierzchnia jest ja-
niejsza, gdy wiato pada na ni bezporednio, ni wtedy, gdy pada na ni pod wikszym
ktem. Dobrym przykadem rda wiata rozproszonego jest owietlenie jarzeniowe lub
wiato soneczne padajce w boczne okno w poudnie. Na rysunku 9.3 obiekt jest
owietlony rdem wiata rozproszonego.

Rysunek 9.3.

rdo wiata rozproszonego


Obiekt owietlony
wycznie wiatem \\\\ V-7wiato |est rozproszone rwnomierne
rozproszonym ^^

wiato odbyskw
Podobnie jak wiato rozproszone, wiato odbyskw posiada kierunek, ale jest odbijane
ostro i w jedn stron. Bardziej pobyskujce obiekty moemy pozna po jasnych,
lnicych plamach wiata na ich powierzchniach (na ekranie s rysowane z uyciem
274____________________________________Cz II Uywania OpenGL

koloru odbyskw - ang. specular color). Obiekt owietlony wycznie wiatem odby-
skw zosta przedstawiony na rysunku 9.4.

Rysunek 9.4. rdo wiata odbyskw


Obiekt owietlony /^^X~ ^wia*> iest wN ostro
wycznie wiatem ^j^jE^^ i w jednym kierunku
odbtyskw

Zmy to razem
adne rdo wiata nie jest zoone wycznie z jednego z tych trzech rodzajw wiata.
Skada si raczej z rnych intensywnoci kadego z rodzajw. Na przykad, czerwone
wiato lasera w laboratorium skada si prawie wycznie z czystego czerwonego wiata
odbysku. Jednak czsteczki dymu lub kurzu wirujce w pomieszczeniu rozpraszaj
promie, przez co wida go, jak biegnie przez pokj. To rozproszenie reprezentuje
skadow wiata rozproszonego. Gdyby promie by jasny, a w pokoju nie byoby adnego
innego rda wiata, zauwayby, e przedmioty w pomieszczeniu przybray czerwony
odcie. Byaby to wanie niewielka skadowa wiata otoczenia.
W zwizku z tym mwimy, e rdo wiata w scenie skada si z trzech skadowych o-
wietlenia: otoczenia, rozpraszania i odbyskw. Podobnie jak inne kolory, kady komponent
wiata jest definiowany przez warto RGBA, okrelajc wzgldne intensywnoci
czerwieni, zieleni i bkitu tworzcych ten komponent. (A do rozdziau 15 bdziemy
ignorowa skadow alfa). Na przykad, nasze czerwone wiato lasera mogoby zosta opisane
za pomoc wartoci z tabeli 9.1.

Tabela 9.1.
Kolor i dystrybucja wiata dla rda czerwonego wiata laserowego

Czerwony Zielony Niebieski Alfa


Odbyskw 0,99 0,0 0,0 1,0
Rozproszone 0,10 0,0 0,0 1,0
Otaczajce 0,05 0,0 0,0 1,0

Zauwa, e czerwony promie lasera nie zawiera wiata zielonego ani niebieskiego.
Zwr take uwag, e wiato odbyskw, rozproszone i otoczenia, moe przybiera
wartoci z zakresu od 0,0 do 1,0. Moesz zinterpretowa t tabel jako okrelajc, e
czerwone wiato lasera w pewnych scenach bdzie miao bardzo du skadow odby-
skw, ma skadow wiata rozproszonego i bardzo ma skadow wiata otaczajcego.
Gdziekolwiek skierujesz promie takiego wiata, zobaczysz najprawdopodobniej
czerwony punkt. Oprcz tego, z powodu warunkw panujcych w pomieszczeniu (dym,
Rozdzia 9. Owietlenie i rda wiata___________________________275

kurz etc.), skadowa wiata rozproszonego umoliwi spostrzeenie drogi promienia w


powietrzu. Na koniec, skadowa wiata otaczajcego - take wynikajcego z obecnoci
czsteczek dymu i kurzu - skieruje troszk wiata na wszystkie obiekty w po-
mieszczeniu. Skadowe otaczajce i rozpraszania czsto s czone, gdy w naturze
take bardzo czsto wystpuj razem.

Materiay w rzeczywistym wiecie


wiato jest jednak tylko jednym z elementw rwnania. W rzeczywistym wiecie obiekty
posiadaj take wasny kolor. W rozdziale 8 stwierdzilimy, e kolor obiektu mona
zdefiniowa jako dugoci fal odbijanego od niego wiata. Niebieska pika odbija wi-
kszo niebieskich fotonw i pochania inne. Zakadamy przy tym, e wiato padajce na
pik zawiera takie niebieskie fotony, wic mog one zosta dostrzeone przez ob-
serwatora. Oglnie, wikszo scen w rzeczywistym wiecie jest owietlonych wiatem
biaym, bdcym rwnomiern mieszanin wszystkich kolorw. (W wietle biaym wi-
kszo obiektw ukazuje swe waciwe, naturalne" kolory.) Jednak nie zawsze tak jest;
gdy niebiesk pik umiecisz w ciemnym pokoju i owietlisz j jedynie tym wia-
tem, obserwatorowi bdzie wydawaa si czarna, poniewa cae wiato zostanie po-
chonite, za nie bdzie niebieskiego wiata, ktre mogoby zosta odbite.

Waciwoci materiau
Gdy uywamy owietlenia, nie opisujemy wieloktw jako posiadajcych konkretny
kolor, ale raczej jako zrobione z materiaw o okrelonych waciwociach refleksyjnych.
Zamiast mwi, e wielokt jest czerwony, mwimy, e jest zrobiony z materiau
odbijajcego gwnie wiato czerwone. Wci twierdzimy, e powierzchnia jest czer-
wona, ale tym razem musimy okreli take waciwoci refleksyjne materiau w odnie-
sieniu do rde wiata otaczajcego, rozpraszajcego i odbyskw. Materia moe by
lnicy i doskonale odbija wiato odblaskw, pochaniajc przy tym wikszo wiata
otaczajcego i rozpraszajcego. Odwrotnie, paski pokolorowany obiekt moe absorbowa
cae wiato odbyskw i w adnych warunkach nie wydawa si lnicym. Kolejn
waciwoci, ktr moemy okreli, jest waciwo emisji obiektw emitujcych
wasne wiato, takich jak wietliki czy zegarki wiecce w ciemnoci.

Owietlanie materiaw
Dobranie wiata i waciwoci materiaw tak, aby uzyska podany efekt, wymaga nieco
praktyki. Nie ma tu kostek kolorw ani prostych regu dajcych szybkie i proste odpowiedzi.
Wanie tu analiza ustpuje miejsca sztuce, a nauka magii. Na pytce CD-ROM, w folderze
tego rozdziau, znajduje si program o nazwie MATLIGHT (od Materials and Lighting
Studio). Ten program umoliwia zmian na bieco waciwoci materiau i wiata w
scenie skadajcej si z kilku prostych obiektw. Programu MATLIGHT moesz uy
w celu pobawienia si rnymi kombinacjami waciwoci. Oprcz tego,
276____________________________________Cz II Uywanie OpenGL

poniewa zosta doczony kod rdowy, moesz zastpi obiekty programu wasnymi
obiektami i dopracowa ich waciwoci przed umieszczeniem ich w swoich scenach.

Podczas rysowania obiektu OpenGL decyduje, jakiego koloru uy dla kadego piksela
sceny. Obiekt ma wasne refleksyjne" kolory, a rdo wiata wasne. Jak OpenGL
wyznacza, ktrych kolorw naley uy? Zrozumienie tego nie jest trudne, pod wa-
runkiem, e potrafisz mnoy uamki. (Widzisz, a nauczyciel mwi, e kiedy ci si to
przyda!)

Kademu wierzchokowi prymitywu jest przypisywana warto koloru RGB obliczona


poprzez przemnoenie efektu skadowej otaczajcej, rozpraszajcej i odbyskw rda
wiata przez waciwoci koloru otaczajcego, rozpraszajcego i odbyskw materiau. W
wyniku zastosowania gadkiego przejcia pomidzy wierzchokami osiga si iluzj
iluminacji obiektu!

Obliczanie efektw wiata otaczajcego


Po pierwsze, powiniene odrzuci notacj koloru i myle o nim wycznie w kategoriach
intensywnoci skadowej czerwonej, zielonej i niebieskiej. W przypadku rda wiata
otaczajcego o pintensywnych skadowych czerwonej, zielonej i niebieskiej,
otrzymaby warto RGB dla tego rda wynoszc (0,5, 0,5, 0,5). Jeli takie wiato
otaczajce owietla obiekt z waciwociami koloru otaczajcego okrelonymi w war-
tociach RGB jako (.50, 1.0, .50), to wynikowym kolorem" dla wiata otaczajcego
byoby
(0.50 * .50, 0.5 * 10.0, 0.50 * .50) = (0.25, 0.5, 0.25)

co odpowiada przemnoeniu przez siebie poszczeglnych barw skadowych wiata ota-


czajcego i koloru otaczajcego materiau, tak jak na rysunku 9.5.

Rysunek 9.5.
Obliczanie koloru U Q
dla skadowej \lntensywnosc 5 \ Intensywno 5 \ Intensywno 5
otaczajcej koloru
obiektu
5 x 5 = 25 5x1=5 5x5 = 25
O
t
a
czajcy "kolor" materiau (.5,1,.5)

Tak wic komponenty koloru materiau okrelaj po prostu procent odbijanego wiata
danego rodzaju. W naszym przykadzie intensywno skadowej czerwonej wiata ota-
czajcego wynosia 1/2, za waciwo materiau .5 dotyczca skadowej czerwonej
wiata otaczajcego okrelia, e tylko poowa poowy intensywnoci zostaa odbita.
Poowa poowy to 1/4, czyli 0,25.
Rozdzia 9. * Owietlenie i rda wiata_____________________________277

Efekty wiata rozpraszajcego i odbyskw


W przypadku wiata otaczajcego byo to do proste. wiato rozpraszajce take
posiada intensywnoci RGB, w podobny sposb wspgrajce z waciwociami mate-
riau. Jednak wiato rozpraszajce ma kierunek, wic intensywno na powierzchni
obiektu zmienia si w zalenoci od kta midzy t powierzchni a kierunkiem rda
wiata. To samo odnosi si do intensywnoci powierzchni owietlanych wiatem od-
byskw. Oglny efekt jako warto RGB jest obliczany tak samo jak w przypadku wiata
otaczajcego, gdzie intensywno rda wiata (po zmodyfikowaniu wedug kta
padania) jest mnoona przez wspczynnik odbicia wiata dla materiau. Na koniec, wszystkie
trzy wartoci RGB s sumowane w celu otrzymania kocowego koloru obiektu. Jeli
ktrakolwiek z intensywnoci barw skadowych przekracza warto l ,0, jest obcinana do
tej wartoci (nie mona zastosowa wikszej intensywnoci ni pena!).

Oglnie, skadowe otaczajca i rozpraszajca rde wiata i materiaw s takie same i


maj najwikszy wpyw na okrelanie koloru obiektu. wiata odbyskw i waciwoci
materiaw dla odbyskw najczciej s jasnoszare lub biae. Skadowa odbyskw
przede wszystkim zaley od kta padania wiata, za odbyski na powierzchni obiektu
zwykle s biae.

Umieszczenie wiata w scenie


By moe wydaje ci si to zbyt du iloci teorii naraz. Zwolnijmy wic nieco i za-
cznijmy poznawa przykady kodu OpenGL, potrzebne do wczenia owietlenia; dziki
temu utrwalimy take to, czego si dotd dowiedziae. Zademonstrujemy take pewne
dodatkowe waciwoci i wymagania dotyczce owietlenia w OpenGL. Kilka nast-
pnych przykadw zostao zbudowanych na podstawie programu JET. Pocztkowa wersja nie
zawieraa adnego kodu zwizanego z owietleniem i po prostu rysowaa trjkty przy
wczonym buforze gbokoci. Jednak gdy skoczymy, na metalicznej powierzchni
obracanego samolotu bd przesuwa si jasne odblaski soca.

Wczanie owietlenia
Aby poinformowa OpenGL, e ma zacz oblicza owietlenie, wywoaj funkcj
glEnable() z parametrem GL_LIGHTING:
glEnable(GL_LIGHTING);

Ta pojedyncza instrukcja nakazuje OpenGL, aby przy obliczaniu koloru kadego wierz-
choka w scenie bra pod uwag waciwoci materiau i parametry owietlenia. Jednak bez
okrelenia waciwoci materiau lub rda wiata twj obiekt pozostanie ciemny i
nieowietlony, tak jak pokazano na rysunku 9.6. Spjrz do kodu kadego z przykadw
opartych na programie JET, a przekonasz si, e w kadym z nich, tu po przygotowaniu
kontekstu renderowania, jest wywoywana funkcja SetupRC(). Wanie tam odbywa si
inicjowanie wszelkich parametrw owietlenia.
278__________________ ___ Cz II Uywanie OpenGL

Rysunek 9.6.
Program 2 wczonym owietleniem, jednak
bez zdefiniowania parametrw owietlenia i
waciwoci materiaw

Przygotowanie modelu
owietlenia
Po wczeniu obliczania owietlenia,
pierwsze, co musisz zrobi, to przygotowa
model owietlenia. Trzy parametry
okrelajce model owietlenia s
ustawiane za pomoc funkcji glLightModel().
Pierwszym parametrem owietlenia,
uywanym w naszym nastpnym przykadzie, jest GL_LIGHT_MODEL_AMBIENT.
Umoliwia okrelenie globalnego wiata otaczajcego, owietlajcego wszystkie obiekty
ze wszystkich stron. Poniszy kod okrela uycie jasnego, biaego wiata:
// Jasne biae wiata = pena intensywno wszystkich skadowych RGB
GLfloat ambientLightU = f l . O f , l . O f , l . O f , 1.0 } ;
// Wczenie wiata
glEnable(GL_LIGHTING);
// Ustawienie modelu owietlenia tak aby korzysta ze wiata
otoczenia
// okrelonego w ambientLight[]
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);

Pokazana tu odmiana funkcji glModelLight, glModelLightfy, jako pierwszy parametr


otrzymuje ustawiany lub modyfikowany parametr modelu owietlenia, a jako drugi - tablic
wartoci RGBA skadajcych si na wiato. Domylne wartoci RGBA globalnego wiata
otaczajcego to (0,2, 0,2, 0,2, 1,0), czyli do ciemne. Inne parametry modelu
owietlenia umoliwiaj wskazanie, czy s owietlane przednie, tylne czy obie strony
wieloktw, a take kty dla obliczania owietlenia rozproszonego i odbyskw. Wicej
informacji na temat tych parametrw znajdziesz w sekcji podrcznika.
Rozdzia 9. Owietlenie i rda wiata_____________________________279

Przygotowanie waciwoci materiau


Gdy mamy ju rdo wiata otaczajcego, musimy tak ustawi waciwoci materiaw,
aby wielokty odbijay wiato i ebymy widzieli samolot. Spjrz na poniszy fragment
kodu:
GLfloat g r a y [ ] = { 0 . 7 5 f , 0.75f, 0 . 7 5 f , l . O f };

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);

glBegin(GL_TRIANGLES);
glVertex3f(-15.Of, O . O f , 30.O f ) ;
glVertex3f( O . O f , 15.Of, 30.O f ) ;
glVertex3f( O . O f , O . O f , -56.O f ) ;
glEnd();

Pierwszy parametr funkcji glMaterialfy okrela, czy bd ustawiane waciwoci przedniej


(GL_FRONT), tylnej (GL_BACK) czy obu stron materiau (GL_FRONT_AND_ BACK).
Drugi parametr informuje o ustawianej waciwoci; w tym przypadku wspczynniki
odbicia wiata rozpraszajcego i otaczajcego s ustawiane na tak sam warto.
Ostatnim parametrem jest tablica zawierajca wartoci RGBA okrelajce dan waciwo.
Wszystkim prymitywom stworzonym po wywoaniu funkcji glMaterial bd nadawane
ostatnio ustawione waciwoci, a do momentu innego wywoania funkcji glMaterial.
W wikszoci sytuacji skadowe rozpraszajca i otaczajca s takie same, a dopki nie
chcesz odbyskw (iskier, lnicych miejsc), nie musisz definiowa ich waciwoci. Je-
dnak nawet mimo to do mudne byoby przygotowywanie tablicy dla kadego koloru w
naszym modelu i wywoywanie funkcji glMaterial() przed kadym wieloktem czy grup
wieloktw.
To prowadzi nas do drugiej i zalecanej metody ustalania waciwoci materiaw, zwanej
ledzeniem kolorw. W przypadku ledzenia kolorw informujesz OpenGL, aby ustawiao
waciwoci materiau w momencie wywoywania funkcji glColor. Aby wczy ledzenie
kolorw, wywoaj funkcj glEnab!e() z parametrem GL_COLOR_MA-TERIAL:
glEnable(GL_COLOR_MATERIAL);

Nastpnie funkcj glColorMaterial okrel waciwoci materiau, ktre bd ustawiane


zgodnie z wartociami przekazanymi funkcji glColor
Na przykad, aby ustawi waciwoci otaczajc i rozpraszajc dla przednich stron
wieloktw tak, aby ledziy wywoania glColor, wywoaj
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

W tym momencie wczeniejszy kod ilustrujcy ustawianie waciwoci materiau ulegby


zmianie na obecny. To wyglda jak wicej kodu, jednak w rzeczywistoci, przy wzrocie
liczby wieloktw, oszczdza koniecznoci pisania wielu linii kodu i wykonuje si troch
szybciej.
280____________________________________Cz II Uywanie OpenGL

// Wcz ledzenie kolorw


glEnable(GL_COLOR_MATERIAL) ;

// Kolory rozpraszania i otaczania dla przednich stron wieloktw //


ledz kolor ustawiany w glColor glColorMaterial(GL_FRONT,
GL_AMBIENT_AND_DIFFUSE);

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFOSE, gray);

glColor3f(0.75f, 0.75f, 0 . 7 5 f ) ;

glBegin(GL_TRIANGLES) ;
glvertex3f(-15.Of, O . O f , 30.O f ) ;
glVertex3f( O . O f , 15.Of, 30.O f ) ;
glVertex3f( O . O f , O . O f , -56.O f ) ;
glEnd();

Listing 9.1 zawiera kod, ktry dodalimy w funkcji SetupRC do naszego przykadu
JET, ustawiajcy jasne wiato otaczajce oraz dobierajcy waciwoci materiau tak,
aby mg odbija wiato i by widoczny. Oprcz tego zmienilimy kolory samolotu, tak
e teraz kada sekcja, a nie kady wielokt, s rysowane w osobnych kolorach. Zwr
uwag, e kocowy wynik (rysunek 9.7) nie rni si zbytnio od obrazka, dla ktrego
jeszcze nie wczylimy owietlenia. Jeli jednak zredukujemy wiato otaczajce o
poow, otrzymamy obraz pokazany na rysunku 9.8. Osigamy to przez ustawienie
nastpujcych wartoci RGBA wiata otaczajcego:
GLfloat mbientLightn = { 0. 5f, 0.5f, 0.5f, l . O f };

Rysunek 9.7.
Wynik dziaania ukoczonego programu
AMBIENT

Listing 9.1. Zmiana warunkw owietlenia


otaczajcego

// Ta funkcja
odpowiada za
inicjowanie kontekstu
renderowania // Oprcz
tego tworzy i
i n i c j u j e wiata void
SetupRC() {
// Wartoci
owietlenia
// Jasne biae
wiato
GLfloat ambientLightl] = { l . O f , l.Of, l.Of, l.Of };
Rozdzia 9. * Owietlenie i rda wiata 281

glEnable(GL_DEPTH_TEST), // Usuwanie niewidocznych powierzchni


glFrontFace(GL_CCW); // Wielokty o kierunku przeciwnym do
// ruchu wskazwek s widziane z
// przodu
glEnable(GL_CULL_FACE); // Nie pokazuj wntrza obiektw

// Owietlanie
glEnable(GL_LIGHTING); // Wczenie owietlenia

// Ustawienie modelu owietlenia tak aby korzysta ze wiata //


otoczenia
// okrelonego w ambientLight[]
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);

glEnable(GL_COLOR_MATERIAL);// Wczenie ledzenia koloru dla


^materiaw

// Kolory rozpraszania i otaczania dla przednich stron wieloktw //


ledz kolor ustawiany w glColor
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

// Jasnoniebieskie to
glClearColor( O . O f , O . O f , 05.f,l.Of);
Rysunek 9.8.
Wynik dziaania
programu AMBIENT
ze rdem wiata
przygaszonym o
poow

Wiemy wic ju, jak mona zredukowa wiato otaczajce w scenie, w celu stworzenia
ciemniejszego obrazu. Jest to uyteczne w symulacjach, w ktrych stopniowo zapada
mrok lub w ktrych blokowane jest rdo wiata kierunkowego, na przykad gdy
obiekt znajdzie si w cieniu innego, wikszego obiektu.

Uywanie rda wiata


Manipulowanie wiatem otaczajcym ma swoje zastosowania, jednak w wikszoci
aplikacji prbujcych odtworzy rzeczywisty wiat trzeba okreli jedno lub wicej
282____________________________________Cz II Uywanie OpenGL

konkretnych rde wiata. Oprcz intensywnoci i kolorw, te rda posiadaj take po-
oenie i kierunek. Pooenie rde wiata moe radykalnie wpyn na wygld sceny.
OpenGL obsuguje do omiu niezalenych rde wiata umieszczonych w dowolnym
miejscu sceny lub poza bry widzenia. Moesz umieci rdo wiata w nieskoczonej
odlegoci, sprawiajc, e jego promienie bd rwnolege, lub ustawi je blisko,
sprawiajc, e jego promienie bd rozbiegay si dookoa. Moesz take okreli wiato
punktowe, z zadanym stokiem wiata, jak rwnie manipulowa innymi charakte-
rystykami wiata.

Gdzie jest gra?


Gdy okrelasz rdo wiata, informujesz OpenGL, gdzie ono jest i w jakim kierunku
wieci. Czsto rda wiata bd wieci we wszystkich kierunkach lub ich promienie
bd ograniczone. W przypadku kadego rysowanego obiektu promienie wiata bie-
gnce od rda (kadego poza czystym wiatem otaczajcym) bd uderza pod pe-
wnym ktem w powierzchni wieloktw obiektw. Oczywicie, w przypadku wiata
kierunkowego, niekoniecznie powierzchnie wszystkich wieloktw bd owietlone. W
celu zrealizowania efektu cieniowania pomidzy wieloktami, OpenGL musi by w
stanie obliczy wspomniany kt padania.
Na rysunku 9.9 wielokt (kwadrat) zosta owietlony promieniem wiata z pewnego
rda. W momencie zetknicia si z powierzchni, promie tworzy z ni kt A. Nastpnie
wiato odbija si pod ktem B w kierunku obserwatora (gdy w przeciwnym razie by go
nie zobaczy). Te kty, w powizaniu z omawianymi dotd waciwociami owietlenia i
materiau, su do obliczenia wynikowego koloru punktu w danym miejscu. Tak si
skada (ze wzgldw projektowych), e miejscami uywanymi przez OpenGL s
wierzchoki wieloktw. Obliczajc wynikowy kolor w kadym z wierzchokw, a
nastpnie przeprowadzajc gadkie cieniowanie (opisywane w rozdziale 8), OpenGL
tworzy iluzj owietlenia. Magia!

Rysunek 9.9. H rdo wiata


wiato odbija si od ^\
0bsMwator
obiektw pod ^-' vs^
okrelonym ktem ^\ ""

Z punktu widzenia programisty, ukazuje to pewn niedogodno koncepcji. Kady wielokt


jest tworzony jako zestaw wierzchokw, ktre s tylko punktami w przestrzeni. Na kady
wierzchoek pada pod pewnym ktem strumie wiata. Jak wic ty lub OpenGL moecie
obliczy kt pomidzy punktem a lini (lini promienia wiata)? Oczywicie,
geometrycznie nie da si wyznaczy kta pomidzy pojedynczym punktem a lini w
przestrzeni 3D, gdy istnieje nieskoczona liczba rozwiza. Z tego wzgldu naley
Rozdzia 9. * Owietlenie i rda wiata_____________________________283

przypisa kademu wierzchokowi dodatkowe informacje, okrelajce kierunek od


wierzchoka w gr, czyli na zewntrz od powierzchni prymitywu.

Normalne do powierzchni
Linia poprowadzona od wierzchoka w gr zaczyna si na jakiej wyimaginowanej
paszczynie (lub wielokcie) i biegnie do niej pod ktem prostym. Ta linia jest nazywana
wektorem normalnym. Sowo wektor moe raczej kojarzy ci si z rzucanymi od
niechcenia terminami zaogi Star Trek, ale w tym wypadku oznacza po prostu lini pro-
stopad do danej powierzchni. Wektor jest lini wskazujc w pewnym kierunku, za
sowo normalny to kolejne okrelenie, jakie jajogowi wymylili dla sowa prostopady
(oznaczajcego przecinanie si pod ktem 90). Tak jakby sowo prostopady nie byo
okropne samo w sobie!
Tak wic, wektor normalny to linia wskazujca, prostopada do powierzchni wielokta.
Rysunek 9.10 przedstawia przykady wektorw normalnych w dwch i trzech wymiarach.

Rysunek 9.10. ^ Wektor normalny


. . . . '' Wektor normalny
; trjwymiarowy '
wektor normalny

90

Dwuwymiarowy wektor normalny Trjwymiarowy wektor normalny

By moe zapytasz, dlaczego musimy okreli wektor


normalny dla kadego wierzchoka? Dlaczego nie moglibymy po prostu utworzy
pojedynczej normalnej dla caego wielokta i uy jej w odniesieniu do kadego
wierzchoka? Moglibymy - i w pierwszych przykadach wanie to bdziemy robi.
Istniej jednak sytuacje, kiedy nie chcemy, aby wszystkie normalne w wierzchokach byy
dokadnie prostopade do powierzchni wielokta. Z pewnoci zauwaye, e wiele
powierzchni nie jest paskich! Moesz przyblia je paskimi, wieloktnymi obszarami,
ale skoczy si to otrzymaniem poszarpanej lub wielociennej powierzchni. Nieco
pniej omwimy technik tworzenia iluzji gadkich krzywych za pomoc odcinkw
poprzez wykrcanie" normalnych do powierzchni (jeszcze wicej magii!). Ale na
wszystko przyjdzie czas.

Okrelanie normalnej
Aby zobaczy, jak okrelamy normaln dla wierzchoka, spjrz na rysunek 9.11 - pa-
szczyzn unoszc si ponad paszczyzn \z w przestrzeni 3 D. Zwr uwag na lini
biegnc przez wierzchoek (l, l, 0), prostopad do paszczyzny. Gdybymy wybrali
dowolny punkt na tej linii, powiedzmy, e (1> 10, 0), odcinek od pierwszego punktu (l,
l, 0) do drugiego punktu (l, 10, 0) byby naszym wektorem normalnym. Drugi wybrany
punkt w tym wypadku wskazuje, e kierunek naszego wierzchoka wskazuje
284 Cz II Uywanie OpenGL

w gr osi y. Uywa si tego take do wskazania przedniej i tylnej strony wieloktw,


zakadajc, e wektor biegnie w gr od przedniej strony wielokta.

Rysunek Wektor norn


9.11.
Wektor normalny
/
(1,10,0)
biegncy przd
prostopadle do
paszczyzny \|
A:
ty)

Jak widzisz, drugi punkt, okrelajcy koniec wektora normalnego, znajduje si o pewn
liczb jednostek w osiach x, y oraz z od wierzchoka. Zamiast okrela dwa punkty dla
kadego wektora normalnego, moemy odj wierzchoek od drugiego punktu wektora
normalnego, aby otrzyma pojedyncz trjk wsprzdnych opisujc odlegoci x, y i z
od wierzchoka. Dla naszego przykadu bdzie to
( l , 10, 0) -
( l , l, 0) (1-1, 10-1, 0) = (O, 9, 0)

Mona na to spojrze jeszcze inaczej; jeliby wierzchoek zosta


przeniesiony do pocztku ukadu, punkt okrelony przez odjcie dwch oryginalnych
punktw w dalszym cigu wskazywaby kierunek na zewntrz, pod ktem 90 do
paszczyzny. Taki nowo przetransformowany wektor normalny przedstawia rysunek 9.12.
Rysunek 9.12.
Nowo
przetransformowany .'' (1,10,0)
wektor normalny

Przesunity wektoi

Ten wektor jest kierunkow wartoci informujc OpenGL, w ktrym kierunku zwrcony
jest wierzchoek (lub wielokt). W nastpnym segmencie kodu widzimy, jak wektory
normalne s okrelane dla jednego z trjktw w przykadowym programie JET:
glBegin(GLJTRIANGLES);
glNormalSf( O . O f , -l.Of, O . O f ) ;
glVertex3f( O . O f , O . O f ,
60.O f ) ;
Rozdzia 9. * Owietlenie i rda wiata_____________________________285

glVertex3f(-15.Of, O . O f , 30.O f ) ;
glVertex3f( 1 5 .Of,O.Of,30.Of); glEnd();

Funkcja glNormalSf pobiera trjk wsprzdnych okrelajc wektor normalny wska-


zujcy w kierunku prostopadym do tego trjkta. W tym przykadzie normalne wszy-
stkich trzech wierzchokw maj ten sam kierunek, w stron ujemnej czci osi y. To
bardzo prosty przykad, gdy trjkt ley pasko na paszczynie xz i w rzeczywistoci
stanowi doln cz samolotu.

Perspektywa podawania normalnej dla kadego wierzchoka lub wielokta w naszych


scenach mogaby wydawa si przeraajca, zwaszcza e bardzo niewiele powierzchni
ley dokadnie na jednej z gwnych paszczyzn. Nie bj si, wkrtce zaprezentujemy
nadajc si do ponownego wykorzystania funkcj, ktr moesz wywoywa w celu
obliczenia normalnych dla swoich wierzchokw.

Kierunek wieloktw
Zwr szczegln uwag na kolejno wierzchokw w
trjkcie samolotu. Jeli ogldasz ten trjkt z kierunku, w
ktrym wskazuje wektor normalny, wierzchoki s uoone
dookoa trjkta w kierunku przeciwnym do ruchu wskazwek
zegara. Wanie to nazywa si kierunkiem wielokta.
Domylnie, przednia strona wielokta jest zdefiniowana jako
strona, od ktrej wierzchoki wydaj si uoone w kierunku
przeciwnym do ruchu wskazwek zegara.

Normalne jednostkowe
Aby OpenGL mg realizowa ca swoj magi, wszystkie normalne do powierzchni
musz zosta zamienione na normalne jednostkowe. Normalna jednostkowa to po prostu
wektor normalny o dugoci 1. Normalna na rysunku 9.12 ma dugo 9. Dugo
wektora oblicza si przez zsumowanie jego skadowych podniesionych do kwadratu, a
nastpnie wycignicie z sumy pierwiastka kwadratowego. Po podzieleniu kadej
skadowej przez dugo otrzymujemy wektor wskazujcy dokadnie w tym samym kie-
runku, ale o dugoci jednej jednostki. W naszym przypadku otrzymamy wektor (O, l, 0).
Nazywa si to normalizacj. Tak wic w celu obliczenia owietlenia, wszystkie wektory
normalne trzeba znormalizowa. I jak tu nie mwi w argonie!

Moesz poinformowa OpenGL, aby automatycznie zamienia wektory normalne na


normalne jednostkowe; w tym celu moesz wczy normalizacj parametrem GL NOR-
MALIZE:
glEnable(GL_NORMALIZE);

To jednak narzuca pewne ograniczenia co do wydajnoci. Lepiej jest samemu wczeniej


obliczy normalne, zamiast zmusza OpenGL, aby to robi.

Majc dowolny wektor normalny w postaci trjki wsprzdnych, za pomoc kodu z


listingu 9.2 moesz atwo znale odpowiadajcy mu jednostkowy wektor normalny.
286 Cz II Uywanie
OpenGL

Listing 9.2. Funkcja redukujca wektory normalne do jednostkowych wektorw


normalnych________
// Redukuje wektor normalny okrelony jako zestaw trzech wsprzdnych //
do normalnego wektora o dugoci l (normalizuje podany wektor). void
ReduceToUnit(float vector[3]) {
float length;

// Obliczenie dugoci wektora


length = (float)sqrt((vector[ 0 ] *vector[ 0 ] ) +
(vector[l]*vector[l]) +
(yector[ 2 ] *vector[ 2 ] ));
// Zabezpieczenie przed wektorami, ktrych dugo moe by
// zbyt bliska zeru if(length ==
O . O f ) length = l . O f ;

// Normalizacja wektora polega na podzieleniu kadej ze //


wsprzdnych przez dugo wektora vector[0] /= length;
vector[l] /= length; vector[2] /= length;

Znajdowanie normalnej
Rysunek 9.13 przedstawia kolejny wielokt, ktry ju nie ley po prostu na jednej z g-
wnych paszczyzn. Wektor normalny prostopady do tej powierzchni nie jest ju tak
prosty do odgadnicia, potrzebujemy wic jakiego prostego sposobu obliczania nor-
malnych dla dowolnego wielokta w przestrzeni 3D.
Rysunek 9.13.
Niebanalne
wyznaczanie
normalnej
Normalna

Moesz atwo obliczy wektor normalny dla kadego wielokta skadajcego si z przy-
najmniej trzech wierzchokw lecych w tej samej paszczynie (paskiego wielokta).
Rysunek 9.14 przedstawia trzy punkty: Pl, P2 i P3, uyte do zdefiniowania dwch we-
ktorw: wektora VI z Pl do P2 oraz wektora V2 z P l do P3. Matematycznie rzecz
biorc, dwa wektory w przestrzeni 3 D definiuj paszczyzn (ley w niej nasz wielokt).
Jeli obliczysz iloczyn wektorowy tych dwch wektorw (w zapisie matematycznym VI
x V2), otrzymany w wyniku wektor bdzie prostopady do paszczyzny (czyli bdzie
Rozdzia 9. * Owietlenie i rda wiata____________________________287

normaln). Rysunek 9.15 pokazuje wektor V3 wyprowadzony jako wynik iloczynu we-
ktorowego wektorw VI i V2.

Rysunek 9.14.
Dwa wektory zdefiniowane przez trzy punkty na
paszczynie
Rysunek 9.15.
Wektor normalny jako iloczyn wektorowy dwch
wektorw

Nie martw si, jeli jeszcze nie wiesz, jak obliczy iloczyn
wektorowy dwch wektorw; wszystko, czego
potrzebujesz, to fiinkcja z listingu 9.3. Aby jej uy,
przeka jej tablic zawierajc trzy dowolne wierzchoki
swojego wielokta (podane z zachowaniem kolejnoci
przeciwnej do ruchu wskazwek zegara), a take tablic,
ktra po powrocie z funkcji bdzie zawiera obliczony
wektor normalny. Aby mg zobaczy, jak dziaa ta
funkcja, zostay zapewnione stae wartoci dla
wsprzdnych x, y i z.

Listing 9.3. Funkcja obliczajca wektor normalny dla trzech dowolnych wierzchokw wielokta______

// Punkty p l , p2 i p3 s podane w kolejnoci przeciwnej


// do ruchu wskazwek zegara
void calcNormal(float v [ 3 ] [ 3 ] , float o u t [ 3 ] )
{
float vl[3],v2[3];
static const int x = 0;
static const int y = 1;
static const int z = 2;
// Obliczenie dwch wektorw na podstawie trzech punktw
v l [ x ] = v [ 0 ] [ x ] - v [ l ] [ x ] ; vi[ y ] = v [ 0 ] [ y ] - v [ l ] [ y ] ;
vl[z] = v[0] [z] - v[l] [ z ] ;
v2[x] = v[l] [x] - v[2] [x] ;
v2[y] = v [ l ] [ y ] - v[2][ y ] ;
v2[z] = v[l][z] - v[2][ z ] ;

// Obliczenie iloczynu wektorowego dwch wektorw w celu


// otrzymania wektora normalnego, ktry zostanie przechowany w
// o u t [ ]
ou t[x ] = v l [ y ] * v 2 [ z ] - v l [ z ] * v 2 [ y ] ;
out[y] = vl[z]*v2[x] - vl[x]*v2 [z];
o u t f z ] = vl[x]*v2[y] - vl[y]*v2[x] ;
288____________________________________Cz II Uywanie OpenGL

// Normalizowanie wektora (przeskalowanie dugoci do jednoci)


ReduceToUnit( o u t ) ;

Przygotowanie rda wiata


Gdy znasz ju wymagania co do przygotowania wieloktw tak, aby wspdziaay ze
rdem wiata, nadszed czas na wczenie samych wiate! Listing 9.4 przedstawia
funkcj SetupRC() z przykadowego programu LITJET. Cz procesu przygotowaw-
czego do tego programu tworzy rdo wiata i umieszcza je z gry po lewej stronie,
nieco poza obserwatorem. rdo wiata GL_LIGHTO posiada skadowe otaczajc i
rozpraszajc, ustawione zgodnie z zawartoci tablic ambientLight[] oraz diffuseLight[]. W
rezultacie otrzymujemy umiarkowane biae wiato.
GLfloat ambientLightU = ( 0.3f, 0.3f, 0.3f, l.Of };
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, l.Of
};

// Przygotowanie i wczenie wiata O


glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight);

Do pozycjonowania wiata suy poniszy kod:


GLfloat lightPosM = { -50.f, 50.O f , 100.O f , l . O f } ;

glLightfv(GL_LIGHTO,GL_POSITION,lightPos);

W tym kodzie lightPosf] zawiera pooenie wiata. Ostatni wartoci w tej tablicy jest
1,0, czyli podane wsprzdne oznaczaj koordynaty rda wiata. Gdyby ostatni
wartoci w tablicy byo 0,0, oznaczaoby to e wiato znajduje si w nieskoczonej
odlegoci, w kierunku wektora zawartego w tej tablicy. Zajmiemy si tym nieco
pniej.

Na koniec, rdo wiata GLJJGHTO jest wczane:


glEnable(GL_LIGHTO); Listing 9.4. Przygotowywanie owietlenia i kontekstu renderowania

w programie LITJET__________

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i i n i c j u j e wiata void SetupRCO (
// Wartoci i wsprzdne rda wiata
GLfloat ambientLightn = { 0.3f, 0.3f, 0.3f, l . O f );
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, l . O f };
GLfloat lightPosU = {-50 . f, 50 . Of, 100.Of, l . O f } ;

glEnable(GL_DEPTH_TEST); // Usuwanie niewidocznych powierzchni


glFrontFace(GL_CCW); // Wielokty o kierunku przeciwnym do
// ruchu wskazwek s widziane z
// przodu
Rozdzia 9. Owietlenie i rda wiata_____________________________289

glEnable(GL_CULL_FACE); // Nie pokazuj wntrza obiektw

// Wczenie owietlenia
glEnable(GL_LIGHTING);

// Przygotowanie i wczenie wiata O


glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
glEnable(GL_LIGHTO);

// Wczenie ledzenia koloru materiau


glEnable(GL_COLOR_MATERIAL);

// Ustawienie waciwoci materiau


glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Jasne niebieskie to
glClearColor(O.Of, O . O f , l . O f ,
l.Of );

Przygotowanie waciwoci materiau


Zwr uwag, e w listingu 9.4 wczane jest ledzenie koloru, za ledzonymi skado-
wymi s skadowe otaczajca i rozpraszajca przednich czci wieloktw. Wanie to
zdefiniowalimy w przykadowym programie AMBIENT:
// Wczenie ledzenia koloru materiau
glEnable(GL_COLOR_MATERIAL);

// Ustawienie waciwoci materiau


glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

Rysowanie wieloktw
Kod renderowania z pierwszych dwch przykadw JET teraz ulega znacznej zmianie, tak
aby uwzgldni nowy model owietlenia. Listing 9.5 pochodzi z funkcji RenderSce-ne()
programu LITJET.

Listing 9.5. Przykad kodu ustalajcego kolor i obliczajcego normalne dla -wierzchokw wieloktw___

float n o r ma l [ 3 J; // Miejsce na obliczona normaln do powierzchni

// Ustalenie koloru materiau


glRGB(0, 255, 0 ) ;
glBegin(GLJTRIANGLES);
glNormal3f( O . O f , -l.Of, O . O f ) ;
glVertex3f( O . O f , O . O f , 60.O f ) ;
glVertex3f(-15.Of, O . O f , 30.O f ) ;
glVertex3f(15.Of,O.Of,30.Of);
//glEndO;
290 Cz II Uywanie OpenGL Rc

// Wierzchoki dla tego panelu float


v [ 3 ] [ 3 ] = {{ 15.O f , O . O f , 30.O f } , {
O . O f , 15.Of, 30.O f } , { O . O f , O . O f ,
60.O f } } ;

// Obliczenie normalnej dla paszczyzny


calcNormal( v , normal);

// Narysowanie trjkta przy uyciu (dla wszystkich wierzchokw)


// normalnej do paszczyzny
//glBegin(GLJTRIANGLES);
glNormal3fv(normal);
glVertex3fv(v[0]);
glvertex3fv(v[l]);
glVertex3fv(v[2]);
7/glEndO ;

Zauwa, e obliczamy wektor normalny uywajc naszego kodu z listingu 9.3. Oprcz
tego waciwoci materiaw ledz teraz kolory ustawiane funkcj glColor (zastpion
naszym makrem glRGB). Zwr take uwag, e nie kady trjkt jest blokowany par
funkcji glBegin()/glEnd(). Moesz raz okreli, e rysujesz trjkty, za kade trzy no
we wierzchoki bd tworzyy trjkt, chyba e odwoasz to instrukcj glEnd(). W przy
padku bardzo duych iloci wieloktw, moe to znacznie poprawi wydajno, dziki
wyeliminowaniu wielu niepotrzebnych wywoa funkcji. ,

Rysunek 9.16 przedstawia dziaanie programu LITJET. Obracajc samolot za pomoc


klawiszy kursorw, moesz oglda efekt cieniowania powierzchni, owietlanych wiatem
pod coraz to innymi ktami.

Rysunek 9.16.
Dziaanie programu
LITJET

Rada dotyczca wydajnoci


Njoczywistszym sposobem poprawienia wydajnoci tego kodu byoby
wczeniejsze obliczenie wszystkich normalnych dla wierzchokw i prze-
chowanie ich w celu uycia w funkcji RenderScene. Zanim jednak to wy-
Rozdzia 9. + Owietlenie i rda wiata 291

prbujesz, w rozdziale 10 poczytaj o listach wywietlania. Listy wy-


wietlania umoliwiaj przechowanie nie tylko obliczonych wartoci dla
wektorw normalnych, ale take danych dla samych wieloktw. Pamitaj,
przykady w tym rozdziale maj na celu zademonstrowanie koncepcji,
niekoniecznie musz stanowi najefektywniejszy moliwy kod.

Efekty owietlenia
wiato otaczajce i rozpraszajce w przykadzie LITJET wystarczy jedynie do zapewnienia
iluzji owietlenia. Powierzchnia samolotu jest cieniowana zgodnie z ktem padania
wiata. Gdy samolot si obraca, te kty si zmieniaj i dostrzegasz efekt owietlenia,
dziki czemu moesz atwo odgadn, skd pada wiato.
Pominlimy jednak wiato odbyskw, a take waciwoci odbyskw materiau sa-
molotu. Cho wystpuj efekty cieniowania, sama powierzchnia samolotu jest raczej
pasko pokolorowana. Waciwoci otaczajca i rozpraszajca materiau s wystarczajce,
jeli modelujesz obiekty udajce plastelin, drewno, karton, szmaty czy inne niepo-
yskliwe materiay. Jednak w przypadku metalicznych powierzchni, takich jak powoka
samolotu, poysk jest najczciej nieodzowny.

Odbyski
wiato i waciwoci materiau dotyczce odbyskw nadaj obiektowi wymagany poysk.
Ten poysk moe rozjani pewne czci obiektu i tworzy plamy odbyskw w momencie,
gdy wiato pada pod ktem ostrym do kta patrzenia na powierzchni. Plama odbysku
wystpuje wtedy, gdy prawie cae wiato padajce na powierzchni jest odbijane w
kierunku obserwatora. Dobrym przykadem plam odbyskw mog by odby-ski soca na
wodzie.

wiato odbyskw
Dodanie skadowej odbyskw do rda wiata jest bardzo atwe. Poniszy program
pokazuje przygotowanie rda wiata z programu LITJET, zmodyfikowane tak, aby
uwzgldni skadow odbyskw.
// Wartoci i wsprzdne rda wiata GLfloat
ambientLigta [ ] = { 0.3f, 0.3f, 0.3f, l.Of }; GLfloat
diffuseLight[] = { 0 . 7 f, 0 . 7 f, 0 . 1 f, l . O f }; GLfloat
specular[] = { l.Of, l.Of, l.Of, l . O f } ; GLfloat
lightPos[] = { O . O f , 150.Of, 150.Of, l . O f };

// Wczenie owietlenia
glEnable(GL LIGHTING);
292____________________________________Cz II Uywanie OpenGL

// Przygotowanie i wczenie wiata O


glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight) ;
glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHTO,GL_SPECULAR,specular) ;
glLightfv(GL_LIGHTO,GL_POSITION,lightPos) ;
glEnable(GL_LIGHTO);

Tablica specular[] definiuje bardzo jasne, biae wiato dla skadowej odbfyskw wiata.
Naszym celem byo wymodelowanie jasnego wiata sonecznego. Linia
glLightfv(GL_LIGHTO,GL_SPECULAR, specular) ;

po prostu dodaje skadow odbyskw do rda wiata GL_LIGHTO.


Gdyby byy to jedyne zmiany w programie LITJET, nie zobaczylibymy adnej rnicy w
wygldzie samolotu. Dzieje si tak, poniewa nie zdefiniowalimy jeszcze waciwoci
odbyskw materiaw skadajcych si na nasz samolot.

Waciwoci odbyskw materiau


Dodanie waciwoci odbyskw do materiau jest tak samo proste jak dodanie skadowej
odbyskw do rda wiata. Nastpny segment kodu przedstawia kod z programu
LITJET, take zmodyfikowany w celu dodania skadowej odbyskw do waciwoci
materiau.
// Wartoci i wsprzdne rda wiata
GLfloat specref[] = { l.Of, l.Of, l.Of, l.Of };

// Wczenie ledzenia koloru materiau


glEnable(GL_COLOR_MATERIAL);

// Ustawienie waciwoci materiau


glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Od tego momentu wszystkie materiay maj pen waciwo //


odbyskw z ustawionym wysokim poyskiem glMaterialfv(GL_FRONT,
GL_SPECULAR,specref); glMateriali(GL_FRONT,GL_SHININESS,128);

Jak wczeniej, wczylimy ledzenie koloru, tak e waciwoci otaczajca i rozpra-


szajca materiau odpowiadaj biecemu kolorowi ustawionemu funkcj glColor().
(Oczywicie nie chcemy, aby waciwo odbyskw bya zgodna z kolorem ustawianym
funkcjglColor, gdy okrelilimy j oddzielnie i nie chcemy jej zmienia).
Tym razem dodalimy tablic specreff] zawierajc wartoci RGBA dla waciwoci
odbyskw materiau. Ta tablica z samymi jedynkami daje w wyniku powierzchni, od-
bijajc prawie cae padajce w kierunku obserwatora wiato. Linia
glMaterialfv(GL_FRONT, GL_SPECULAR, specref);

ustawia waciwoci materiau dotyczce wszystkich nastpnych wieloktw, ktre


dziki temu nabieraj poysku. Poniewa nie wywoujemy ju pniej funkcji glMate-
Rozdzia 9. * Owietlenie i rda wiata_____________________________293

rial z waciwoci GL_SPECULAR, t waciwo bd posiaday wszystkie mate-


riay. Uczynilimy to celowo, aby wszystkie wielokty samolotu wyglday, jakby zostay
uczynione z bardzo poyskliwego materiau.

To, co zrobilimy w tej funkcji przygotowawczej, jest bardzo wane: okrelilimy, e


waciwoci otaczajca i rozpraszajca wszystkich nastpnych wieloktw (dopki nie
zmienimy ich wywoujc funkcj glMaterial lub glColorMaterial) bd si zmienia
wraz ze zmianami biecego koloru, lecz waciwo odbyskw materiaw pozostanie
taka sama.

Stopie poyskliwoci
Jak ju wspomnielimy, jasne wiato poyskw i wysoka warto waciwoci poysku
materiau powoduj rozjanienie kolorw obiektu. W naszym przykadzie, obecne, eks-
tremalnie jasne wiato poyskw (pena intensywno) i waciwo poysku materiau
(take pena intensywno) powoduj, e samolot staje si prawie cakowicie biay lub
jasnoszary, z wyjtkiem tych powierzchni, ktre s odwrcone od rda wiata (w takim
wypadku staj si czarne i nieowietlone). Aby zmniejszy ten efekt, po okreleniu
skadowej odbyskw stosujemy nastpn lini kodu:
glMateriali(GL_FRONT,GL_SHININESS, 128) ;

Waciwo GL_SHININESS ustawia stopie poyskliwoci materiau, okrelajcy, jak


maa i skupiona bdzie plama poysku. Warto O okrela nieskupion plam poysku,
czyli w rzeczywistoci rwnomierne rozjanienie kolorw wszystkich pikseli wielokta.
Jeli ustawisz t warto, zredukujesz rozmiar plamy i zwikszysz stopie skupienia po-
ysku, powodujc powstanie lnicej plamy. Im wiksza warto, tym bardziej lnica
staje si powierzchnia. We wszystkich implementacjach OpenGL warto tego parametru
naley do przedziau od l do 128.

Listing 9.6 przedstawia nowy kod funkcji SetupRC, pochodzcy z programu SHINY-
JET. Jest to jedyny fragment kodu, jaki uleg zmianie w stosunku do poprzedniego pro-
gramu LITJET (oczywicie poza nazw programu). W tym programie samolot wydaje si
bardzo poyskliwy. Rysunek 9.17 przedstawia wynik dziaania tego programu, jednak
aby mc w peni doceni efekt, powiniene uruchomi program i przytrzyma jeden z
klawiszy kursora w celu obrcenia samolotu w promieniach soca.

Listing 9.6. Funkcja SetupRC z programu SHINYJET, powodujca powstanie odbyskw na samolocie

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i inicjuje wiata void SetupRC()

// Wartoci i wsprzdne rda wiata GLfloat


ambientLight[] = { 0.3f, 0.3f, 0.3f, l . O f }; GLfloat
diffuseLightU = ( 0.7f, 0.7f, 0 . 7 f , l . O f }; GLfloat
specular[] = { l . O f , l.Of, l. Of, l.Of}; GLfloat
lightPos[] = { O.Of, 150.Of, 150.Of, l.Of }; GLfloat
specref[] = { l.O f, l . O f , l.Of, l . O f };
294____________________________________Cz II Uywanie OpenGL

glEnable(GL_DEPTH_TEST); // Usuwanie niewidocznych powierzchni


glFrontFace(GL_CCW); // Wielokty o kierunku przeciwnym do
// ruchu wskazwek s widziane z
// przodu glEnable(GL_CULL_FACE);
// Nie pokazuj wntrza obiektw

// Wczenie owietlenia
glEnable(GL_LIGHTING);

// Przygotowanie i wczenie wiata O


glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHTO,GL_SPECULAR,specular) ;
glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
glEnable(GL_LIGHTO);

// Wczenie ledzenia koloru materiau


glEnable(GL_COLOR_MATERIAL);

// Ustawienie waciwoci materiau


glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Od tego momentu wszystkie materiay maj pen waciwo


// odbyskw z ustawionym wysokim poyskiem
glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
glMateriali(GL_FRONT,GL_SHININESS,128) ;

// Jasne niebieskie to
glClearColor(O.Of, O . O f , l . O f , l.Of
);

Rysunek 9.17.
Dziaanie programu
SHINYJET

Urednianie normalnych
Wspomnielimy wczeniej, e przez wykrcanie" normalnych mona tworzy gadkie
krzywe powierzchnie za pomoc prostych linii. Ta technika, zwana urednianiem nor-
malnych, daje interesujc iluzj optyczn. Zamy, e mamy powierzchni tak jak
pokazana na rysunku 9.18, ze zwykymi normalnymi do powierzchni.
Rozdzia 9. + Owietlenie i rda wiata 295

Rysunek 9.18.
Powierzchnia
amana, ze zwykymi
normalnymi

Cho normalne zostay narysowane pomidzy wierzchokami, w rzeczywistoci s okrelone


dla kadego z nich. Jeli wemiesz pod uwag, e kady wierzchoek styka si take z
inn paszczyzn, moesz okreli normaln tego wierzchoka jako redni normalnych
poszczeglnych paszczyzn. Wsplny wierzchoek dwch stykajcych si paszczyzn
(ilustruje to rysunek 9.19), bdzie mia inn normaln w momencie rysowania kadej z
powierzchni. Jeli wemiemy redni z tych dwch normalnych i zastosujemy j przy
definiowaniu kadej z powierzchni, to gdy OpenGL je pocieniuje, poczenie ich obu
bdzie si wydawao mniej ostre.

Rysunek 9.19.
Urednianie
normalnych sprawia,
e ostre krawdzie
wydaj si mniej ostre

Listing 9.7 przedstawia funkcj renderujc tworzc powierzchni przedstawion na


rysunku 9.18. (Ten kod pochodzi z programu WAYEY na pytce CD-ROM). Powie-
rzchnia jest tworzona przez przechodzenie od strony lewej do prawej na wsprzdnej x i
zmian kierunku w osi y. Wsprzdne z s stae, gdzie -50 odpowiada przedniej krawdzi
obiektu, za 50 - tylnej.

Listing 9.7. Funkcja RenderSceneprogramu WAVEY______________________________

// Wywoywane w celu narysowania sceny void


RenderScene(void)

float normal[3]; // Miejsce na obliczane normalne


float v [ 4 ] [3]; // Miejsce na wsprzdne prostokta
float lastY; float // Lewa strona prostokta
nextY; float // Prawa strona prostokta
temp; float x; // Tymczasowe miejsce na zamian zmiennych
// Miejsce na wsprzdn X

// Stan menu okrela, c z y jest wczony tryb szkieletowy


if(iState == WIRE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); else
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
296____________________________________Cz II Uywanie OpenGL

// Stan menu okrela, czy jest wczone gadkie cieniowanie


iffiState == SMOOTH || iState == AVERAGE)
glshadeModel(GL_SMOOTH);
else
glshadeModel(GL_FLAT);

// Wyczyszczenie okna kolorem ta


glClear(GL_COLOR_BOFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotw


glPushMatrix();
glRotatef(xRot, l.Of, O . O f , O . O f ) ;
glRotatef(yRot, O . O f , l.Of, O . O f ) ;

// Ustalenie niebieskiego koloru powierzchni


glRGB(0,0,255) ;

// Inicjowanie krokw Y
lastY = O . O f ; nextY =
10.O f ;

// Przejcie przez wsprzdne x od lewa do prawa budowanie //


prostoktw o zmiennych pochyleniach w gr i w d f o r ( x = -
6 0 . O f ; x < 6 0 . O f ; x+= 2 0 . O f )
{
// Pierwszy wierzchoek
v [ 0 ] [ 0 ] = x; // wsp. X dla lewej
v [ 0 ] [ 1 ] = lastY;
v [ 0 ] [ 2 ] = 50.O f ; // wsp. Z dla tyu

// Drugi wierzchoek
v [ l ] [ 0 ] = x; // wsp. X dla lewej
v [ l ] [ 1 ] = lastY;
v [ l ] [ 2 ] = -50.O f ; // wsp. Z dla przodu

// Trzeci wierzchoek
v[2][0] = x + 20.Of; // wsp. X dla prawej
v[2][1] = nextY;
v[2] [2] = -50.O f ; // wsp. Z dla przodu

// Czwarty wierzchoek
v [ 3 ] [ 0 ] = x + 20.Of;// wsp. X dla prawej
v [ 3 ] [ 1 ] = nextY;
v [ 3 ] [ 2 ] = 5 0 . O f ; // wsp. Z dla tyu

// Pocztek wielokta
glBegin(GL_POLYGON);
ifUState != AVERAGE)
{
// Obliczenie i ustawienie wektora normalnego,
// chyba e w menu wybrano urednianie
calcNormal( v , normal);
glNormal3fv(normal);
Rozdzia 9. * Owietlenie i rda wiata _____________________________ 297

else // Urednianie normalnych. Nieco oszukujemy, bo


// wiemy e normalne w s k a z u j w gr lub w d <
// Normalne wskazuj prosto w gr
i f ( n e x t Y == 10)
glNorma!3f (O.Of, l. O f , O . O f ) ;
else
// Normalne w s k a z u j prosto w d
glNorma!3f ( O . O f , -l.Of, O . O f ) ; }
// Podanie dwch lewych wierzchokw
glVertex3fv(v[0] ) ; glVertex3fv(v[l] )
,-

// To samo, ale normalna po drugiej stronie wskazuje // w


przeciwnym kierunku iffiState == AVERAGE) ( if(nextY ==
10)
glNormalSf ( O . O f , - l . O f , O . O f ) ; // Normalna wskazuje
// d
else
glNorma!3f ( O . O f , l . O f , O . O f ) ; // Normalna wskazuje
// gr
}
// Okrelenie dwch prawych wierzchokw
glVertex3fv(v[2] ) ; glVertex3fv(v[3] ) ; glEnd ( ) ;

// Zamiana pozycji wsprzdnych Y


temp = lastY;
lastY = nextY;
nextY = temp;
}
glPopMatrix() ;

// Zrzucenie polece rysunkowych


glFlush ( ) ;

Program WAYEY posiada opcje menu umoliwiajce rysowanie szkieletu, paskie lub
gadkie cieniowania bd wreszcie urednianie normalnych. Rysunek 9.20 przedstawia
powierzchni aman przy wczonym paskim cieniowaniu, za rysunek 9.2 1 - t sam
powierzchni z urednionymi normalnymi. Mona dostrzec, e na drugim rysunku wzdu
caej powierzchni przebiegaj gadkie fale.
298 Cz II Uywanie OpenGL

Rysunek 9.20.
Powierzchnia
amana, ze zwykymi
normalnymi do
powierzchni

Rysunek
9.21.
Ta sama
powierzchnia po
urednieniu
normalnych

wiata punktowe
Jak dotd, pozycj wiata okrelalimy nastpujco:
// Tablica zawierajca pozycj
GLfloat lightPosU = { O.Of, 150.Of, 150.Of, l.Of },

// Ustawienie pozycji wiata


glLightfv(GL_LIGHTO,GL_POSITION,lightPos);

Tablica HghtPosf] zawiera wartoci x, y i z okrelajce albo samo pooenie rda


wiata w scenie, albo kierunek, z ktrego wiato biegnie. Ostatnia warto, w tym
przypadku 1,0, wskazuje, e wiato wystpuje we wskazanym miejscu. Domylnie,
Rozdzia 9. * Owietlenie i rda wiata_____________________________299

wiato rozchodzi si rwnomiernie we wszystkich kierunkach -jednak mona to zmieni w


celu uzyskania efektu wiata punktowego.

Aby rdo wiata znalazo si w nieskoczonej odlegoci, w kierunku wskazywanym


przez wektor zawarty w tablicy lightPosf], w ostatnim elemencie tej tablicy powiniene
umieci warto 0,0. Kierunkowe rdo wiata, bo tak si takie rdo nazywa, r-
wnomiernie owietla powierzchnie obiektw, tzn. wszystkie promienie wiata biegn
rwnolegle. Z drugiej strony, w przypadku pozycyjnych rde wiata promienie
wietlne rozchodz si ze sceny. Plamy odbyskw w programie SHINYJET byyby nie do
uzyskania z kierunkowym rdem wiata. Zamiast lnicych miejsc, caa powierzchnia
stawaaby si biaa w momencie skierowania jej wprost do wiata (czyli gdyby wiato
padao na ni pod ktem 90).

Tworzenie wiata punktowego


Tworzenie wiata punktowego nie rni si od tworzenia rda wiata kierunkowego.
Kod z listingu 9.8 przedstawia funkcj SetupRC() z przykadowego programu SPOT.
Ten program tworzy w rodku okna niebiesk kul. Tworzone jest wiato punktowe,
ktre mona obraca dookoa kuli za pomoc klawiszy kursora. W miar jak wiato
punktowe porusza si dookoa kuli, na jej powierzchni pojawia si plama odbysku.

Listing 9.8. Przygotowanie owietlenia \v programie SPOT___________________________

// Wartoci i wsprzdne wiate GLfloat lightPos[] = {


O . O f , O . O f , 75.Of, l . O f }; GLfloat specular[] = {
l . O f , l . O f , l . O f , l.Of}; GLfloat specref[] = { l . O f ,
l. O f , l . O f , l.Of}; GLfloat ambientLight[] = { 0.5f, 0.5f,
0.5f, l. O f }; GLfloat spotDirN = { O . O f , O . O f , -l.Of };

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i i n i c j u j e wiata void SetupRC()

glEnable(GL_DEPTH_TEST); // Usuwanie niewidocznych powierzchni


glFrontFace(GL_CCW); // Wielokty o kierunku przeciwnym do
// ruchu wskazwek s widziane
// z przodu
glEnable(GL_CULL_FACE); // Nie pokazuj wntrza obiektw

// Wczenie owietlenia
glEnable(GLJLIGHTING);

// Przygotowanie i wczenie wiata O


// Zastosowanie lekkiego wiata otaczajcego, aby obiekty byy
// widoczne
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);

// wiato skada si ze skadowych rozpraszajcej i odbyskw


glLightfv(GL_LIGHTO,GL_DIFFUSE,ambientLight);
glLightfv(GL_LIGHTO,GL_SPECULAR,specular);
glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
300 ____________________________________ Cz II Uywanie OpenGL

// Wczenie efektu wiata punktowego //


Kt wyczenia wynosi 60 stopni glLightf
(GL_LIGHTO, GL_SPOT_CUTOFF, 60. Of) ;

// Jasny wieccy punkt


glLightf (GL_LIGHTO, GL_SPOT_EXPONENT, 100 . Of ) ;

// Wczenie tego wiata


glEnable (GL_LIGHTO) ;

// Wczenie ledzenia koloru


glEnable (GL_COLOR_MATERIAL) ;

// Kolor otaczajcy i rozpraszajcy materiau ledz funkcj


// glColor
glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE) ;

// Od tego momentu wszystkie materiay maj pen waciwo //


odbyskw z ustawionym wysokim poyskiem glMaterialfv(GL_FRONT,
GL_SPECULAR, specref ) ; glMateriali(GL_FRONT, GL_SHININESS, 128) ;

// Czarne to
g!ClearColor(O.Of, O.Of, O.Of, l.Of ) ;

Za zmian wiata pozycyjnego w punktowe odpowiadaj ponisze linie:


// Wczenie efektu wiata punktowego // Kt
rozwarcia wynosi 60 stopni glLightf (GL_LIGHTO,
GL_SPOT_CUTOFF, 60 . Of ) ;

// Jasny wieccy punkt


glLightf (GL_LlGHTO,GL_SPOT_EXPONENT,100.0f);

Warto GL_SPOT_CUTOFF okrela kt rozwarcia stoka wiata, emitowanego ze


rda wiata punktowego. W przypadku normalnego wiata pozycyjnego, ten kt wynosi
180, przez co wiato nie jest ograniczone adnym stokiem. wiata punktowe emituj
stoek wiata, a obiekty poza tym stokiem nie s owietlane. Rysunek 9.22 pokazuje,
jak kt rozwarcia ma si do szerokoci stoka.

Rysunek 9.22.
Kt rozwarcia stoka wiata
punktowego
wiato punktowe
Rozdzia 9. Owietlenie i rda wiata____________________________301

Rysowanie wiata punktowego


Gdy umiecisz w scenie wiato punktowe, musi ono skd biec. To, e umiecisz w jakim
miejscu rdo wiata punktowego, nie oznacza jeszcze, e zobaczysz tam jasny punkt.
W przypadku naszego programu SPOT, w miejscu pooenia rda wiata
umiecilimy czerwony stoek, wskazujcy, skd pochodzi wiato. Wewntrz pod-
stawy stoka umiecilimy t kul, imitujc bak arwki. Kompletny kod sucy do
rysowania sceny zosta przedstawiony na listingu 9.9.

Zwr szczegln uwag na instrukcj


glPushAttrib(GL_LIGHTING_BIT);

Zaraz po niej wyczamy owietlenie i rysujemy jasn t kul. Nastpnie wywoujemy


instrukcj
glPopAttribO ;

Pierwsza instrukcja zachowuje stan wszystkich zmiennych stanu owietlenia. Moemy


potem wyczy wiato na czas rysowania tej arwki, a nastpnie z powrotem wczy
system owietlenia. Dokadny opis parametrw funkcji glPushAttrib i glPopAttrib
znajdziesz w sekcji podrcznika w rozdziale 14. Przykadowy obraz z programu SPOT
przedstawia rysunek 9.23.

Rysunek 9.23.
Przykad dziaania programu SPOT,
demonstrujcego wiato punktowe

Listing 9.9. Funkcja renderujca programu


SPOT, pokazujca sposb obracania
wiata punktowego

// Wywoywane w celu
narysowania sceny
void RenderScene(void)
{
// Wyczyszczenie
okna biecym
kolorem ta
glClear(GL_COLOR_BUFFER_BIT l
GL_DEPTH_BUFFER_BIT);

// Ustawienie koloru materiau i narysowanie kuli w rodku


glRGB(0, O, 2 5 5 ) ; auxSolidSphere( 3 0 . O f ) ;
302____________________________________Cz II Uywanie OpenGL

// Teraz umieszczamy wiato


// Zachowanie przeksztace wsprzdnych
glPushMatrix();
// Obrt ukadu wsprzdnych
glRotatef(yRot, O.Of, l.Of, O . O f ) ;
glRotatef(xRot, l.Of, O.Of, O . O f ) ;

// Okrelenie nowego pooenia i kierunku w obrconych //


wsprzdnych
glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
glLightfv(GL_LIGHTO,GL_SPOT_DIRECTION,spotDir);

// Rysowanie czerwonego stoka imitujcego rdo wiata


glRGB(255,0,0);
// Przemieszczenie pocztku w celu przesunicia stoka //
w miejsce rda wiata
glTranslatef(lightPos[ 0 ] ,lightPos[ 1 ] ,lightPos[ 2 ] );
auxSolidCone( 4 . 0 f , 6 . 0 f ) ;
// Narysowanie mniejszej, przesunitej kuli imitujcej arwk //
Zachowanie zmiennych stanu owietlenia
glPushAttrib(GL_LIGHTING_BIT);

// Wyczenie owietlenia i narysowanie jasnej tej kuli


glDisable(GL_LIGHTING); glRGB(255,255,0);
auxSolidSphere(3.0f);
// Przywrcenie zmiennych stanu owietlenia
glPopAttribO ;
// Przywrcenie stanu macierzy
glPopMatrix();
// Zrzucenie polece graficznych
glFlushO ;

Cienie
Rozdzia powicony owietleniu a prosi si o wspomnienie o cieniach. Uzupenienie
sceny o cie moe znacznie poprawi jej realizm i efekt wizualny. Na rysunkach 9.24a i
9.24b widzimy dwa widoki owietlonej kostki, z cieniem i bez cienia (ten przykadowy
program pochodzi z rozdziau 2). Kostka z rysunku 9.24b z cieniem wyglda o wiele
bardziej wiarygodnie.
Rozdzia 9. * Owietlenie i rda wiata 303

Rysunek 9.24a.
Owietlona kostka
bez cienia

Rysunek 9.24b.
Owietlona kostka
z cieniem

Czym jest cie?


Koncepcyjnie, rysowanie cienia jest cakiem proste. Cie powstaje wtedy, gdy jaki obiekt
zasania wiato padajce na inny obiekt. Obszar obiektu, na ktry pada cie w ksztacie
obiektu zasaniajcego, pozostaje ciemny. Moemy tworzy cienie programowo, spa-
szczajc oryginalny obiekt na paszczyzn powierzchni, na ktrej ten obiekt spoczywa.
Nastpnie spaszczony obiekt jest rysowany na czarno lub w jakim ciemnym kolorze, by
moe z zachowaniem pewnej przezroczystoci (spjrz na przykad cienia z rozdziau 16).
To spaszczenie ilustruje rysunek 9.25.
Rysunek 9.25.
Spaszczenie obiektu
w celu otrzymania
cienia

Proces spaszczania obiektu na inn powierzchni jest wynikiem z zastosowania jednej z


tych zaawansowanych manipulacji macierzami, opisanych w rozdziale 7. Tutaj spr-
bujemy tak uproci to zagadnienie, jak tylko si da.
304____________________________________Cz II Uywanie OpenGL

Kod zgniatajcy"
Chcemy spaszczy" macierz rzutu widoku modelu, tak aby wszystkie rysowane przy jej
uyciu obiekty stay si dwuwymiarowe. Bez wzgldu na orientacj obiektu, zostanie on
spaszczony do paszczyzny, na ktr pada cie. Drugim elementem jest odlego i
kierunek rda wiata. Kierunek wiata determinuje ksztat cienia oraz wpywa na jego
rozmiar. Jeli kiedykolwiek widziae swj cie wczesnym rankiem lub tu przed
zachodem soca, wiesz, jak dugi moe on by w zalenoci od pooenia soca.
Funkcja z listingu 9.10 pobiera trzy punkty lece na paszczynie, na ktr ma pa
cie, pozycj rda wiata oraz, na koniec, wskanik do macierzy przeksztacenia,
ktra ma zosta wypeniona. Nie zagbiajc si zbytnio w algebr liniow, ta funkcja
oblicza wspczynniki rwnania paszczyzny, na ktr ma pada cie, i cznie z poo-
eniem wiata wykorzystuje je do stworzenia macierzy przeksztacenia. Jeli przemnoysz
t macierz przez biec macierz widoku modelu, wszystkie nastpne obiekty zostan
spaszczone na t paszczyzn.

listing 9.10. Funkcja tworzca macierz przeksztacenia dla cieni_______________________

// Na podstawie rwnania paszczyzny i pooenia wiata tworzy //


macierz rzutu cienia.
// Obliczona macierz jest umieszczona w tablicy destMat[][] void
MakeShadowMatrix(GLfloat points[ 3 ] [ 3 ] , GLfloat lightPos[4],
GLfloat destMat[ 4 ] [ 4 ] ) (
GLfloat planeCoeff[ 4 ] ;
GLfloat dot;

// Znalezienie wspczynnikw rwnania paszczyzny


// Wyszukanie trzech pierwszych wspczynnikw tak samo
// jak przy znajdowaniu normalnej
calcNormal(points,planeCoeff) ;

// Znalezienie ostatniego wspczynnika przez zastpowanie wstecz


planeCoeff[ 3 ] = - (
(planeCoeff[ 0 ] *points[ 2 ] [ 0 ] ) + (planeCoeff[ 1 ] *points[ 2 ] [ 1 ] ) +
(planeCoeff[ 2 ] *points[ 2 ] [ 2 ] ));

// Iloczyn skalarny paszczyzny i pooenia wiata dot


= planeCoeff[ 0 ] * lightPos[0] +
planeCoeff[ 1 ] * lightPostl] +
planeCoeff[ 2 ] * lightPos[2] +
planeCoeff[ 3 ] * lightPos[ 3 ] ;
// A teraz rzutowanie
// Pierwsza kolumna
destMat[0][ 0 ] = dot - lightPos[0] * planeCoeff[ 0 ] ;
destMat[ 1 ] [ 0 ] = O . O f - lightPos[0] * planeCoeff[1];
destMat[2][ 0 ] = O . O f - lightPos[0] * planeCoeff[ 2 ] ;
destMat[ 3 ] [ 0 ] = O . O f - lightPos[0] * planeCoeff[ 3 ] ;
Rozdzia 9. * Owietlenie i rda wiata 305

// Druga kolumna
destMatlO][ 1 ] - O . O f - lightPos[l] * planeCoeff[ 0 ] ,
destMat[ 1 ] [ 1 ] = dot - lightPostl] v planeCoeff[ 1 ] ;
destMat[2][ 1 ] = O . O f - lightPostl] * planeCoeff[ 2 ] ,
destMat[3][ 1 ] = O . O f - lightPos[l] * planeCoeff[ 3 ] ,

// Trzecia kolumna
destMat[0][ 2 ] = O . O f - lightPos[2] * planeCoeff[ 0 ] ,
destMat[ 1 ] [ 2 ] = O . O f - lightPos[2] *
destMat[2][ 2 ] = dot - planeCoeff[ 1 ] ; lightPos[2] *
destMat[3][ 2 ] = O . O f planeCoeff[ 2 ] ;
- lightPos[2] * planeCoeff[ 3 ] ,
// Czwarta kolumna
destMatlO][ 3 ] O.Of
destMat[ 1 ] [ 3 ] O.Of - lightPos[3] * planeCoeff[ 0 ] j
destMat[2][ 3 ] O.Of - lightPos[3] * planeCoeff[ 1 ] ;
destMat[3][ 3 ] dot - - lightPos[3] * planeCoeff[ 2 ] ;
lightPos[3] * planeCoeff[ 3 ] ;

Przykad cienia
Aby zademonstrowa uycie funkcji z listingu 9.10, umiecilimy nasz samolot w po-
wietrzu, wysoko nad ziemi. Umiecimy rdo wiata ponad nim i nieco z lewej strony.
Gdy uyjesz klawiszy kursora w celu obrcenia samolotu, cie samolotu bdzie
odpowiada jego spaszczonej sylwetce na ziemi. Wynik dziaania programu SHADOW
zosta przedstawiony na rysunku 9.26.
Rysunek 9.26.
Wynik dziaania
programu SHADOW

Kod z listingu 9.11 pokazuje sposb przygotowania macierzy cienia na potrzeby tego
przykadu. Zwr uwag, e tworzymy macierz raz i przechowujemy j w zmiennej
globalnej.
306 ____________________________________ Cz II Uywanie OpenGL

. Przygotowanie macierzy rzutu cienia _______________________________

GLfloat lightPost] = { -75. Of, 150. Of, -50. Of, O . O f } ;

// Macierz przeksztacenia do tworzenia cienia


GLfloat shadowMat [ 4 ][ 4 ];

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i inicjuje wiata void SetupRC ( ) {
// Dowolne trzy punkty na "ziemi" (kierunek przeciwny do //
ruchu wskazwek)
GLfloat points[3] [31 = U -30. Of, -149. Of, -20. Of },
{ -30. Of, -149. Of, 20. Of
}, { 40. Of, -149. Of, 20.
Of } } ;
glEnable (GL_DEPTH_TEST) ; // Usuwanie niewidocznych powierzchni
glFrontFace (GL_CCW) ; // Wielokty o kierunku przeciwnym do
// ruchu wskazwek s widziane
// z przodu glEnable
(GL_CULL_FACE) ; // Nie pokazuj wntrza obiektw
// Wczenie owietlenia
glEnable (GL_LIGHTING) ;

// Kod przygotowujcy owietlenie itd.

II Jasne niebieskie to
glClearColor (O.Of, O.Of, l.Of, l.Of ) ;

// Obliczenia macierzy rzutowania w celu narysowania cienia na


// "ziemi"
MakeShadowMatrix(points, lightPos, shadowMat);

Listing 9.12 przedstawia kod renderujcy programu SHADOW. Najpierw rysujemy sa-
molot tak jak zwykle, a nastpnie odtwarzamy macierz widoku modelu i mnoymy j
przez macierz cienia. W ten sposb otrzymujemy spaszczon macierz rzutowania. Na-
stpnie ponownie rysujemy samolot (zmodyfikowalimy kod, tak aby korzysta ze zna-
cznika informujcego funkcj DrawJet e powinna rysowa samolot na czarno lub w
kolorze). Po kolejnym odtworzeniu macierzy widoku modelu rysujemy ma t kul
znajdujc si mniej wicej w miejscu zajmowanym przez rdo wiata, po czym
rysujemy poniej samolotu paszczyzn, imitujc ziemi". Ten prostokt ley na tej
samej paszczynie, na ktrej rysowany jest cie samolotu.
Rozdzia 9. * Owietlenie i rda wiata____________________________307

Listing 9.12. Rysowanie samolotu i jego


cienia________________________________
// Wywoywane w celu narysowania sceny
void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glPushMatrix O;

// Rysowanie samolotu w nowym pooeniu,


// Przed obrceniem samolotu umieszczenie wiata we waciwym
// miejscu
g!Lightfv(GL_LIGHTO,GL_POSITION,lightPos);
glRotatef(xRot, l . O f , O . O f , O . O f ) ;
glRotatef(yRot, O.Of, l.Of, O . O f ) ;
DrawJet(FALSE) ;

// Przywrcenie oryginalnego stanu macierzy


glPopMatrix();

// Przygotowania do rysowania cienia na ziemi


// Wyczenie owietlenia i zachowanie macierzy rzutowania
glPushAttrib(GL_LIGHTING_BIT) ;
glDisable(GL_LIGHTING);
glPushMatrix();

// Przemnoenie przez macierz rzutu cienia


glMultMatrixf((GLfloat *)shadowMat);

// Obrcenie samolotu w nowej, spaszczonej przestrzeni


glRotatef(xRot, l.Of, O.Of, O . O f ) ; glRotatef(yRot,
O.Of, l.Of, O . O f ) ;

// Warto TRUE oznacza rysowanie cienia


DrawJet(TRUE);

// Przywrcenie macierzy przeksztacenia


glPopMatrix();

// Rysowanie rda wiata (soca)


glPushMatrix();
glTranslatef(lightPos[ 0 ] ,lightPos[ 1 ] , lightPos[ 2 ] );
glRGB(255,255,0);
auxSolidSphere( 5 . 0 f );
glPopMatrix();

// Rysowanie " z i e m i " , cieniujemy j rcznie do ciemnej zieleni //


w celu stworzenia iluzji gbokoci glBegin(GL_QUADS);
glRGB(0,128,0) ;
glVertex3f( 40 0.O f , -150.O f , -200.O f ) ;
glVertex3f(-400.Of, -150.Of, -200.O f ) ;
glRGB(0,255,0) ;
glVertex3f(-400.Of, -150.Of, 200.O f ) ;
glVertex3f(400.Of, -150.Of, 200.O f ) ;
glEnd();
308____________________________________Cz II Uywanie OpenGL

// Przywrcenie zmiennych stanu owietlenia


glPopAttribO ;
// Zrzucenie polece graficznych
glFlushO ;

Owietlenie i tryb indeksu koloru


W rozdziale 8 poznae tryb indeksu koloru, w ktrym kolor okrelany jest jako indeks
palety, a nie jako barwy skadowe wiata. Powoduje to oczywiste konsekwencje jeli
chodzi o owietlenie. Wikszo funkcji owietlenia oczekuje, e wiata i waciwoci
materiau zostan okrelone jako wartoci RGBA.

W przypadku trybu indeksu koloru OpenGL korzysta z pewnych zaoe, jednak w tym
trybie wiata mog zawiera jedynie skadow rozpraszajc i odbyskw. Materiay
mog posiada waciwo lnienia, otaczajc, rozpraszajc i odbyskw cho w pe-
wnych przypadkach to wystarcza, ale czsto uzyskany efekt nie jest wart wysiku.

Aby mona byo zastosowa owietlenie, paleta musi zawiera trzy pasma kolorw dla
kolorw otaczajcych, rozpraszajcych i odbyskw. Aby osign satysfakcjonujce
rezultaty, te pasma zwykle obejmuj odcienie od czarnego, poprzez odcienie pojedyn-
czego koloru, a do biaego. Istnieje moliwo zdefiniowania ich tak, aby stworzy
gadko cieniowany obiekt w jednym kolorze, ale ma to mae zastosowanie w prakty-
cznych aplikacjach.

Oglnie, wikszo publikacji dotyczcych OpenGL zaleca unikanie trybu indeksu koloru
w poczeniu z efektami owietlenia. Jednak jeli musisz go uy, pytka CD-ROM zawiera
dodatkowy przykad o nazwie ILIGHT, ilustrujcy uycie trybu indeksu koloru w celu
owietlenia sceny zawierajcej kilka obiektw. Jednak wszystkie te obiekty maj ten sam
kolor!

Podsumowanie
W tym rozdziale zostae wprowadzony w pewne bardziej zaawansowane i magiczne"
dziedziny OpenGL. Dowiedziae si, jak okrela jedno lub kilka rde wiata oraz jak
definiowa ich charakterystyk w postaci skadowych otaczajcej, rozpraszajcej i
odbyskw. Wyjanilimy take, jak odpowiednie waciwoci materiau wspgraj ze
skadowymi rde wiata, a take zademonstrowalimy pewne efekty specjalne, takie jak
tworzenie plam odbyskw czy wygadzanie ostrych krawdzi.

Oprcz tego zostao omwione pooenie rda wiata, a take tworzenie i manipulo-
wanie wiatami punktowymi. Zaprezentowana w treci wysokopoziomowa funkcja do
operowania macierzami bardzo uatwi tworzenie cieni. Na koniec wyjanilimy, dlacze-
Rozdzia 9. Owietlenie i rda wiata 309

go powiniene unika trybu indeksu koloru przy tworzeniu efektw owietlenia. Pro-
gramy demonstracyjne w tym rozdziale s cakiem proste, ale wicej przykadw znaj-
dziesz na pytce CD-ROM, w folderze tego rozdziau. Programy na pytce demonstruj
wszystkie opisywane efekty, cznie ze scenami zawierajcymi wicej ni jedno rdo
wiata.

Podrcznik
glColorMaterial
Przeznaczenie Sprawia, e kolory materiau ledz biecy kolor ustawiany funkcj
glColor.
Plik nagwkowy
Skadnia void glColorMaterial(Glenum face, GLenum mod);
Opis Ta funkcja umoliwia ustawianie waciwoci materiau bez koniecznoci
bezporedniego wywoywania funkcji glMaterial. Jeli uyjesz tej funkcji,
pewne waciwoci materiau mog by automatycznie ustawianie w
momencie wywoania funkcji glColor. Domylnie ledzenie koloru jest
wyczone; aby je wczy, musisz wywoa funkcj
glEnable(GL_COLOR_MATERIAL). Aby ponownie wyczy ledzenie
koloru, wywoaj funkcj glDisable(GL_COLOR_MATERIAL).
Parametry
face GLenum: Okrela, ktra strona wielokta powinna ledzi biecy kolor.
Dozwolone parametry to GL_FRONT (przednia), GL_BACK (tylna) lub
GL_BACK_AND_FRONT (obie strony).
mod GLenum: Okrela, ktra waciwo materiau ma zalee od biecego
koloru. Dozwolone parametry to GL_EMISSION, GL_AMBIENT,
GL_DIFFUSE, GL_SPECULAR oraz GL_AMBIENT_AND_DIFFUSE.
Zwracana warto Brak
Przykad Poniszy kod z przykadowego programu AMBIENT wcza ledzenie
koloru, a nastpnie ustawia waciwo otaczajc i rozpraszajc
materiau tak, aby ledziy kolor ustawiany funkcj glColor
// Wczenie ledzenia koloru przez materiay
glEnable(GL_COLOR_MATERIAL);

// Kolory rozpraszania i otaczania dla


// przednich stron wieloktw ledz kolor
// ustawiany w glColor
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

Patrz take glColor, glMaterial, glLight, glLightModel


310 Cz II Uywanie
OpenGL

glCulIFace
Przeznaczenie Okrela, ktra strona wielokta, przednia czy tylna, ma by usuwana z
rysunku.
Plik nagwkowy
Skadnia void glCullFace(GLenum mod);
Opis Ta funkcja wycza obliczenia dotyczce owietlenia, cieniowania i koloru
przedniej lub tylnej strony wielokta. Jeli, na przykad, obiekt jest
zamknity i tylne ciany wieloktw nigdy nie bd widoczne, bez wzgldu
na przemieszczenie i obrt, wyczenie rysowania tylnych cian
wyeliminuje niepotrzebne obliczenia w scenie. Usuwanie niewidocznych
cian jest wczane i wyczane przez wywoanie funkcji glEnable i
glDisable z parametrem GL_CULL_FACE. Przednia i tylna strona
wielokta jest definiowana funkcj glFrontFace oraz poprzez kolejno
definiowania wierzchokw wielokta (przeciwnie do ruchu wskazwek
zegara lub zgodnie z nim).
Parametry
mod GLenum: Okrela, ktra strona wielokta powinna by usunita. Dozwolone
parametry to GLJFRONT (przednia) lub GLJ3ACK (tylna).
Zwracana warto Brak
Przykad Poniszy kod z przykadowego programu AMBIENT pokazuje sposb
wyczenia oblicze dotyczcy wntrza samolotu. Oprcz tego konieczne
jest wskazanie, ktra strona wieloktw jest na zewntrz, przez okrelenie
kierunku uoenia ich wierzchokw.
// Wielokty o kierunku przeciwnym do //
ruchu wskazwek s widziane z przodu
glFrontFace(GL_CCW);
// Nie pokazuj wntrza obiektw
glEnable(GL_CULL_FACE);

Patrz take glFrontFace, glLightModel

glFrontFace
Przeznaczenie Okrela, ktra strona wielokta jest traktowana jako przednia, a ktra jako
tylna.
Plik nagwkowy
Skadnia void glFrontFace(GLenum mod);
Opis Gdy scena skada si z obiektw zamknitych (nie mona zobaczy ich
wntrza), nie ma potrzeby obliczania koloru i wiata dla wewntrznych
stron obiektu. Do wyczenia tych oblicze suy funkcja glCulIFace. Z kolei
funkcja glFrontFace okrela, ktra strona wielokta ma by
Rozdzia 9. * Owietlenie i rda wiata 311

traktowana jako przednia. Jeli wierzchoki wielokta s podawane


w takiej kolejnoci, e ukadaj si w kierunku ruchu wskazwek zegara,
mwimy, e wielokt ma kierunek zgodny z ruchem wskazwek zegara.
Jeli wierzchoki ukadaj si w kierunku przeciwnym, mwimy,
e wielokt ma kierunek przeciwny do ruchu wskazwek zegara.
Ta funkcja umoliwia okrelenie, e przedni czci wielokta moe by
strona zgodna z ruchem wskazwek zegara lub strona odwrotna.
Paramet
ry GLenum: Okrela, orientacj przedniej strony wielokta. Dozwolone
parametry to GL_CW (zgodnie z ruchem wskazwek) lub GL_CCW
(przeciwnie do ruchu wskazwek).
Zwracana warto Brak
Przykad Poniszy kod z przykadowego programu AMBIENT pokazuje sposb
wyczenia oblicze dotyczcych wntrza samolotu. Oprcz tego konieczne
jest wskazanie, ktra strona wieloktw jest na zewntrz, przez okrelenie
kierunku uoenia ich wierzchokw.
// Wielokty o kierunku przeciwnym do //
ruchu wskazwek s widziane z przodu
glFrontFace(GL_CCW);

// Nie pokazuj wntrza obiektw


glEnable(GL_CULL_FRCE);

Patrz take glCullFace, glLightModel

gIGetMaterial
Przeznaczenie Zwraca biece waciwoci materiau.
Plik <gl.h>
nagwkowy void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params);
Skadnia void glGetMaterialiv(GLenum face, GLenum pname, GLint *params);
Ta funkcja jest uywana do odczytywania biecych waciwoci materiau
przednich lub tylnych cian wieloktw. Zwracane wartoci s umieszczane
pod adresem wskazywanym przez params. W wikszoci przypadkw
bdzie to tablica czterech wartoci zawierajca skadowe RGBA
odczytywanej waciwoci.
Paramet
ry face GLenum: Okrela stron wielokta, ktrej waciwoci materiau bd
odczytywane. Dozwolone parametry to GL_FRONT (strona przednia) lub
GL_BACK (strona tylna).
312 Cz II Uywanie OpenGL

pname GLenum: Okrela waciwo materiau, ktr chcemy odczyta.


face Dozwolone wartoci to GL_AMBIENT, GL_DIFFUSE,
GL_SPECULAR, GL_EMISSION, GL_SHININESS oraz
GL_COLOR_INDEXES.
GLint* lub GLfloat*: Tablica liczb zmiennopozycyjnych lub cakowitych
reprezentujca zwracane wartoci. Dla parametrw GL_AMBIENT,
GL_DIFFUSE, GL_SPECULAR i GL_EMISSION jest to
czteroelementowa tablica zawierajca skadowe RGBA danego parametru.
Dla GL_SHININESS zwracana jest pojedyncza warto okrelajca warto
poysku materiau.
GL_COLOR_INDEXES zwraca tablic trzech elementw zawierajcych
skadowe otaczajc, rozpraszajc i odbyskw w formie indeksw
kolorw. GL_COLOR_INDEXES jest uywane jedynie w owietleniu
wykorzystujcym tryb indeksu koloru.
Zwracana warto Brak
Przykad Poniszy kod ilustruje sposb odczytania i przechowania wszystkich
biecych waciwoci materiau.
// Miejsce na wszystkie waciwoci materiau GLfloat
ambientMat[ 4 ] , diffuseMat[ 4 ] , specularMat[ 4 ] ,
emissionMat[ 4 ] ;
GLfloat shine;

// Odczyt wszystkich waciwoci materiau


glGetMaterialfv(GL_FRONT, GL_AMBIENT, ambientMat);
glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseMat);
glGetMaterialfv(GL_FRONT, GL_SPECULAR, specularMat),
glGetMaterialfv(GL_FRONT, GL_EMISSION, emissionMat),
glGetMaterialfv(GL_FRONT, GL SHININESS, Sshine);
Patrz take
glMaterial

gIGetLight
Przeznaczenie Zwraca informacje o biecych parametrach wiata.
Plik nagwkowy <gl.h>
Skadnia void glGetLightfv(GLenum light, GLenum pname, GLfloat *params);
void glGetLightiv(GLenum light, GLenum pname, GLint *params);
Opis Ta funkcja jest uywana do odczytywania biecych waciwoci jednego z
omiu rde wiata. Zwracane wartoci s umieszczane pod adresem
wskazywanym przez params. W wikszoci przypadkw bdzie to tablica
czterech wartoci zawierajca skadowe RGBA odczytywanej waciwoci.
Rozdzia 9. Owietlenie i rda wiata 313

Parametry
ttght GLenum: Okrela rdo wiata, ktrego parametry chcemy odczyta. Ta
pname warto naley do zakresu od O do GL_MAX_LIGHT (8 dla Windows NT i
params Windows 95). Stae dla rde wiata to GL_LIGHTO, GL_LIGHT1 ...
GL_LIGHT7.
Zwracana
GLenum: Okrela waciwo wiata, ktr chcemy odczyta. Dozwolone
warto wartoci to GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,
Przykad GL_POSITION, GL_SPOT_DIRECTION, GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION oraz GL_QUADRATIC_ATTENUATION.
GLint* lub GLfloat*: Tablica liczb zmiennopozycyjnych lub cakowitych
reprezentujca zwracane wartoci. Wartoci zwracane s w formie tablicy
czterech, trzech lub jednego elementu. Wartoci zwracane dla kadej z
waciwoci zawiera tabela 9.2.
Brak
Poniszy kod ilustruje sposb odczytania i przechowania biecych
waciwoci rda wiata.
// Miejsce na waciwoci rda wiata
GLfloat ambientComp[4], diffuseComp[4], specularComp[ 4 ] ;

// Odczyt waciwoci wiata


glGetLightfv(GL_LIGHTO, GL_AMBIENT, ambientComp);
glGetLightfv(GL_LIGHTO, GL_DIFFOSE, diffuseComp);
glGetLightfv(GL_LIGHTO, GL_SPECOLAR, specularComp),

Patrz take glLight

Tabela 9.2.
Dostpne parametry funkcji glGetLight

Waciwo Zwracane wartoci

GL_AMBIENT Cztery skadowe RGBA.


GLJ3IFFUSE Cztery skadowe RGBA.
GL_SPECULAR Cztery skadowe RGBA.
GL POSITION Cztery elementy okrelajce pooenie rda wiata. Pierwsze trzy
GL SPOT DIRECTION elementy okrelaj pooenie wiata. Jeli czwarty element ma
warto 1,0, wiato rzeczywicie znajduje si we wskazanym
miejscu. W przeciwnym razie rdo wiata jest kierunkowe i
promienie s rwnolege.
Trzy elementy okrelajce kierunek rda wiata punktowego.
Wektor nie jest znormalizowany i jest podany we wsprzdnych
obserwatora.
314 Cz II Uywanie OpenGL

Tabela 9.2.
Dostpne parametry funkcji glGetLight - cig dalszy

Waciwo Zwracane wartoci

GL_S POT_EXPONENT Pojedyncza warto okrelajca stopie skupienia


GL_SPOT_CUTOFF wiata.
Pojedyncza warto okrelajca kt rozwarcia
GL_CONSTANT_ATTENUATION stoka wiata punktowego.
GL_LINEAR_ATTENUATION GL Pojedyncza warto okrelajca stae zanikanie
QUADRATIC ATTENUATION wiata. Pojedyncza warto okrelajca liniowe
zanikanie wiata. Pojedyncza warto okrelajca
nieliniowe zanikanie wiata.

gILight
Przeznaczenie Ustawia parametry jednego z omiu dostpnych rde wiata. <gl.h>
Plik nagwkowy void glLightf(GLenum light, GLenum pname, GLfloat param); void
Skadnia
glLighti(GLenum light, GLenum pname, GLint param); void
Opis glLightfv(GLenum light, GLenum pname, const GLfloat *params); void
glLightiv(GLenum light, GLenum pname, const GLint *params);
Ta funkcja jest uywana do ustawiania parametrw jednego z omiu rde
wiata. Pierwsze dwie odmiany funkcji wymagaj jedynie pojedynczego
parametru sucego do ustawienia jednej z nastpujcych waciwoci:
GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,
GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION oraz
GL_QUADRATIC_ATTENUATION.
Dwie pozostae odmiany wymagaj podania wskanika do tablicy kilku
waciwoci. W ten sposb okrelane s waciwoci:
GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION,
GL_SPOT_DIRECTION. Te odmiany funkcji mog by uyte take do
ustawienia parametrw skadajcych si z pojedynczej wartoci, przez
umieszczenie w tablicy *params pojedynczego elementu.
Parametry
light GLenum: Okrela rdo wiata, ktrego parametry chcemy zmodyfikowa.
pname Ta warto naley do zakresu od O do GL_MAX_LIGHT (8 dla Windows
NT i Windows 95). Stae dla rde wiata to GLJJGHTO, GL_LIGHT1 ...
GL_LIGHT7.
GLenum: Okrela waciwo wiata, ktr chcemy zmodyfikowa.
Dozwolone wartoci i znaczenie parametrw zawiera tabela 9.2.
Rozdzia 9. * Owietlenie i rda wiata 315

param GLint lub GLfloat: Okrela warto parametrw reprezentowanych przez


params pojedyncz warto. Nale do nich parametry GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION oraz
GL_QUADRATIC_ATTENUATION. Znaczenie parametrw zawiera
tabela 9.2.
GLint* lub GLfloat*: Tablica liczb zmiennopozycyjnych lub cakowitych
zawierajca wartoci ustawianych parametrw. Znaczenie parametrw
podaje tabela 9.2.
Zwracana warto Brak
Przykad Poniszy kod z programu LITJET ilustruje sposb ustawienia rda wiata
w lewym grnym rogu poza obserwatorem. rdo wiata podaje jedynie
skadowe otaczajc i rozpraszajc.
// Wartoci i wsprzdne rda wiata GLfloat
ambientLight[] = { 0.3f, 0.3f, 0.3f, l.Of }; GLfloat
diffuseLightU = { 0.7f, 0.7f, 0 . 1 1, l.Of }; GLfloat
UghtPosN = {-50.f,50.Of, 100.Of, l.Of };

// Wczenie owietlenia
glEnable(GL_LIGHTING);

// Przygotowanie i wczenie wiata O


glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight) ,
glLightfv(GL_LIGHTO,GL_DIFFUSE, diffuseLight) ,
glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
glEnable(GL_LIGHTO);

Patrz take glGetLight

gilightModel
Przeznaczenie Ustawia parametry modelu owietlenia uywanego przez OpenGL.
Plik <gl.h>
nagwkowy void glLightModelf(GLenum pname, GLfloat param); void
Skadnia gILightModeli(GLenum pname, GLint param); void
Opis gILightModelfv(GLenum pname, const GLfloat *params); void
glLightModeliv(GLenum pname, const GLint *params);
Ta funkcja jest uywana do ustawiania parametrw modelu owietlenia
uywanego przez OpenGL. Moe by ustawiony dowolny z trzech
parametrw modelu owietlenia. GL_LIGHT_MODEL_AMBIENT jest
uywany do ustawienia domylnego wiata otaczajcego dla sceny.
Domylnie to wiato ma warto RGBA (0,2, 0,2, 0,2, 1,0). Do ustawienia
tego modelu mog zosta uyte jedynie dwie ostatnie odmiany funkcji, gdy
umoliwiaj przekazanie tablicy zawierajcej wartoci RGBA. Parametr
GL_LIGHT_MODEL_TWO_SIDE jest uywany do
316 Cz II Uywanie OpenGL

okrelenia, czy bd owietlane obie strony wieloktw. Domylnie


owietlana jest tylko przednia (wyznaczana przez kierunek wierzchokw)
strona wieloktw, w wyniku zastosowania waciwoci materiau przedniej
strony, okrelonego funkcj glMaterial(). Na koniec, okrelenie parametru
GL_LIGHT_MODEL_LOCAL_VIEWER modyfikuje obliczenia kta
odbicia dla odbyskw tak, e widok znajduje si w kierunku ujemnej osi z
we wsprzdnych obserwatora (patrz rozdzia 6).
Parametry
pname GLenum: Okrela parametr modelu owietlenia. Dozwolone parametry to
param GL_LIGHT_MODEL_AMBIENT,
GL_LIGHT_MODEL_LOCAL_VIEWER oraz
GL_LIGHT_MODEL_TWO_SIDE.
Glint lub GLfloat: Dla GL_L1GHT_MODEL_LOCAL_VIEWER warto
0,0 wskazuje, e kty wiata odbyskw przybieraj kierunek widoku
zgodny z ujemnym kierunkiem osi z. Kada inna warto oznacza, e
odbyski s widziane z pocztku ukadu wsprzdnych. Dla
GLJLIGHT_MODEL_TWO_SIDE, warto 0,0 wskazuje, e w
obliczeniach owietlenia bdzie brana pod uwag tylko przednia strona
wieloktw. Kada inna warto okrela, e przy obliczeniach bd brane
pod uwag obie strony wieloktw. Ten parametr nie daje efektu w
przypadku punktw, odcinkw i bitmap.
params GLint* lub GLfloat*: W przypadku GL_LIGHT_MODEL_TWO_SIDE i
GL_LIGHT_MODEL_LOCAL_VIEWER jest to wskanik do tablicy liczb
cakowitych lub zmiennopozycyjnych, w ktrych jako warto parametru
uywany jest tylko pierwszy element. W przypadku parametru
GL_LIGHT_MODEL_AMBIENT wskazywana tablica zawiera cztery
elementy, bdce skadowymi wartoci RGBA.
Zwracana warto Brak
Przykad Poniszy kod z programu AMBIENT ilustruje sposb ustawienia
globalnego rda wiata otaczajcego na jasny, biay kolor.
// Jasne biae wiato
GLfloat ambientLight[] { l.Of, l.Of, l.Of,
l.Of

// Usuwanie niewidocznych powierzchni


glEnable(GL_DEPTH_TEST);
// Wielokty o kierunku przeciwnym do ruchu wskazwek s
// widziane z przodu
glFrontFace(GL_CCW);
// Nie pokazuj wntrza obiektw
glEnable(GL_CULL_FACE);
// Owietlanie
glEnable(GL_LIGHTING); // Wczenie owietlenia
Rozdzia 9. 4 Owietlenie i rda wiata 317

// Ustawienie modelu owietlenia tak, // aby korzysta


ze wiata otoczenia // okrelonego w ambientLight[]
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight) ,
glLight, glMateria
Patrz take

gIMaterial
Przeznaczenie Ustawia parametry materiau uywane w modelu owietlenia.
Plik nagwkowy <gl.h>
Skadnia void glMaterialf(GLenum face, GLenum pname, GLfloat param); void
Opis glMateriali(GLenum face, GLenum pname, GLint param);
void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
void glMaterialiv(GLenum face, GLenum pname, const GLint *params);
Ta funkcja jest uywana do ustawienia waciwoci materiau wieloktw.
Parametry GL_AMBIENT, GL_DIFFUSE oraz GL_SPECULAR
wpywaj na sposb odbijania odpowiednich skadowych wiata.
GL_EMISSION jest uywanew celu nadania materiaom takiego wygldu,
jakby emitoway wasne wiato. GL_SHININESS moe zmienia si w
zakresie od O do 128, gdzie wiksze wartoci powodujjaniejsze i bardziej
skupione plamy odbyskw na powierzchni materiau. Na koniec,
GL_COLOR_INDEXES jest uywany w celu okrelenia waciwoci
materiau w trybie indeksu koloru.
Parametry
face GLenum: Okrela stron
pname wielokta, do ktrej bd si
odnosi ustawiane
waciwoci materiau.
Dozwolone parametry to
GL_FRONT (strona
przednia), GL_BACK (strona
tylna) lub
GL_FRONT_AND_BACK
(przednia i tylna).
GLenum: Dla pierwszych
dwch odmian okrela
warto parametru
param reprezentowanego przez
pojedyncz warto. Obecnie
jedynym takim parametrem
params jest GL_SHININESS.
Pozostae dwie odmiany,
wymagajce przekazania
tablicy wartoci, mog suy
do ustawienia nastpujcych
waciwoci:
GL_AMBIENT,
GL_DIFFUSE,
GL_SPECULAR,
GL_EMISSION,
GL_SHININESS,
GL_AMBIENT_AND_
DIFFUSE oraz
GL_COLOR_INDEXES
.
GLint lub GLfloat:
Warto parametru
okrelanego przez
pname
(GL_SHININESS).
GLint* lub GLfloat*: Tablica
liczb cakowitych lub
zmiennopozycyjnych
zawierajca wartoci dla
ustawianego parametru.

318 Cz II Uywanie OpenGL

Zwracana warto Brak


Przykad Patrz Spjrz na przykadowy program LITJET w tym rozdziale.
take glGetMaterial, glColorMaterial, glLight, glLightModel

gINormal
Przeznaczenie Definiuje normaln do powierzchni dla nastpnego wierzchoka lub
zestawu wierzchokw.
Plik nagwkowy
Skadnia void glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz);
void glNorma!3d(GLdouble nx, GLdouble ny, GLdouble nz);
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
void glNormal3i(GLint nx, GLint ny, GLint nz);
void glNormal3s(GLshort nx, GLshort ny, GLshort nz);
void glNorma!3bv(const GLbyte *v);
void glNorma!3dv(const GLdouble *v);
void glNormal3fv(const GLfloat *v);
void glNorma!3iv(const GLint *v);
void gINormal3sv(const GLshort *v);
Opis Wektor normalny jest skierowany w gr, prostopady do powierzchni
Parametry nx
wielokta. Normalne s uywane w obliczeniach owietlenia
i cieniowania. Okrelenie wektora o dugoci l poprawia szybko
ny nz renderowania. OpenGL automatycznie konwertuje normalne na normalne
v jednostkowe w momencie wczenia parametru
glEnable(GLJNORMALIZE).

Zwracana warto
Okrela wsprzdn x wektora normalnego.
Przykad
Okrela wsprzdn y wektora normalnego.
Okrela wsprzdn z wektora normalnego.
Wskazuje tablic trzech wartoci odpowiadajcych wsprzdnym x, y i z
wektora normalnego.
Brak
Poniszy kod z programu LITJET demonstruje ustawianie wektora
normalnego przed rysowaniem wielokta.
float normal[ 3 ] ; // Wierzchoki dla tego
panelu float v [ 3 ] [ 3 ] = {{ 15.Of, O . O f ,
30.O f } , ( O.Of, 15.Of, 30.O f } ,
Rozdzia 9. Owietlenie l rda wiata____________________________319

{ O.Of, O.Of, 60.O f } } ;

// Obliczenie normalnej do paszczyzny


calcNormal(v,normal);
// Narysowanie trjkta przy uyciu //
tej samej normalnej do paszczyzny // dla
wszystkich wierzchokw
glBegin(GLJTRIANGLES);
glNormal3fv(normal);
glVertex3fv(v[0]);
glVertex3fv(v[l]);
glVertex3fv(v[2]);
glEnd();
Patrz take glTexCoord, glVertex
Rozdzia 10.
Modelowanie
i kompozycja obiektw 3D
W tym rozdziale:
Dowiesz si, jak... Uywane funkcje
* Skada trjwymiarowe obiekty z wieloktw * glBegin/glEnd/glVertex
4 Optymalizowa wywietlanie obiektw za * glNewList/glEndList/glCallList
pomoc list wywietlania

Jeste ju w peni przygotowany, aby zacz powanie korzysta z OpenGL. W odr-


nieniu od poprzednich rozdziaw, ten bdzie dotyczy gwnie zastosowania nabytej
wiedzy w praktyce. Mamy zamiar wyznaczy sobie pewne zadanie, po czym krok po
kroku doprowadzi do logicznego koca: gotowego programu. Podczas tego procesu
dowiesz si, jak dzieli obiekty w scenie na mniejsze czci, atwiejsze w tworzeniu i
zarzdzaniu. Zoymy skomplikowany obiekt z mniejszych, prostszych obiektw, ktre z
kolei bd zbudowane wycznie z prymityww OpenGL.
Oprcz tego, jakby mimochodem, dowiesz si, do czego su list wywietlania i jak ich
uywa. Jednym z najwaniejszych powodw ich stosowania jest szybko, wic jako
premi sprbujemy pokaza ci sposoby testowania szybkoci dziaania kodu.

Okrelenie zadania
Aby zademonstrowa budowanie obiektu z prostszych elementw, uyjemy interesujcego,
cho niezbyt skomplikowanego przykadu, tworzcego model metalowej ruby (takiej,
jakie su na przykad do przykrcania dyskw twardych). Cho nasza rubka moe nie
by dostpna w adnym sklepie z elastwem, ma jednak pewne zalety. Po-
322_______________________________________Cz II Uywanie OpenGL

winnimy wic uczyni j tak prost, jak to tylko moliwe, starajc si jednak niczego nie
utraci z sensu naszego zadania.

ruba bdzie miaa szecioktn gwk oraz nagwintowany trzpie, podobnie jak wiele
innych typowych stalowych rubek. Poniewa to tylko wiczenie, uprocimy gwint
owijajc" go na powierzchni trzpienia, a nie wycinajc go w nim.

Szkic modelu, jaki chcemy utworzy, przedstawia rysunek 10.1. Zbudujemy trzy gwne
elementy tej ruby - gwk, trzpie oraz gwint - indywidualnie, a nastpnie zoymy je
razem w kocowy obiekt.

Rysunek 10.1. / S^ruba,


G|6wka ktr
postaramy si
wymodelowa Trzpie
\v tym rozdziale ___
Gwint

Wybr rzutowania
Zanim zaczniemy konstruowanie, najpierw potrzebujemy rzutowania, czyli paszczyzny
odniesienia dla przedstawianych obiektw. W przypadku tego przykadu najlepsze bdzie
rzutowanie rwnolege. To typowe rzutowanie dla aplikacji typu C AD, w ktrych obiekt
jest dokadnie mierzony i modelowany. Ta ruba ma okrelon wysoko, szeroko i ilo
zwojw gwintu, a przy tym pozostaje stosunkowo maa. Uycie rzutowania
perspektywicznego miaoby sens wtedy, gdybymy modelowali co wikszego, na przykad
krajobraz, w ktrym efekt perspektywy byby bardziej widoczny.

Listing 10.1 stanowi kod tworzcy bry widzenia. Tworzy rzutowanie rwnolege oraz
ukad wsprzdnych rozcigajcy si po 100 jednostek w osiach x i y. Wzdu osi z dodano
dodatkowe 100 jednostek; umiecimy tam obserwatora.

Listing 10.1. Przygotowanie rzutowania rwnolegego dla przykadw w tym rozdziale_______ ____

// Zmiana bryy widzenia i widoku.


// Wywoywane w momencie zmiany wymiaru okna
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.O f ;

// Zabezpieczenie p r z e d dzieleniem przez O i f ( h


== 0) h = 1;

// Ustawienie widoku na rozmiary okna


glViewport(O, O, w, h);
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________323

// Wyzerowanie stosu macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glLoadldentity();

// Ustanowienie bryy obcinania


// (lewa, prawa, dolna, grna, blisza, dalsza)
if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -
nRange*2.0f,
nRange*2.0f) ;
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -
nRange*2. Of,
nRange*2.0f);

glMatrixMode(GL_MODELVIEW) ;
glLoadldentity{);

Wybr owietlenia i waciwoci materiau


Po wybraniu rzutowania, nastpnym krokiem jest wybranie modelu owietlenia do na-
szego widoku ruby. Listing 10.2 zawiera kod sucy do przygotowania kontekstu ren-
derowania, cznie z owietleniem i waciwociami materiau. Musimy si upewni, e
wiato otaczajce bdzie na tyle jasne, i bdziemy widzie wszystkie cechy obiektu;
dodamy take wiato odbyskw, aby ruba wygldaa rzeczywicie jak przedmiot z
metalu. Pojedyncze rdo wiata zostanie umieszczone w lewym grnym rogu.

Listing 10.2. Przygotowanie kontekstu renderowania oraz parametrw owietlenia_____________

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i inicjuje wiata void SetupRC()

// Wartoci i wsprzdne rda wiata GLfloat


ambientLight[] = ( 0 . 4 f , 0 . 4 f , 0 . 4 f , l . O f }; GLfloat
diffuseLightN = { 0 . 7 f , 0 . 7 f , 0 . 7 f , l . O f }; GLfloat
specular[] = { 0 . 9 f , 0 . 9 f , 0 . 9 f , l . O f } ; GLfloat
lightPos[] = ( -50.O f , 200.O f , 200.Of, l . O f ); GLfloat
specreff] = { 0 . 6 f , 0 . 6 f , 0 . 6 f , l.Of };

glEnable(GL_DEPTH_TEST); // Osuwanie niewidocznych powierzchni


glEnable(GL_CULL_FACE); // Nie pokazuj wntrza obiektw

// Wczenie owietlenia
glEnable(GL_LIGHTING);
// Przygotowanie i wczenie wiata O
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);
glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight);
g!Lightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHTO,GL_SPECULAR,specular); <
324____________________________________Cz II Uywanie OpenGL

// Umieszczenie i wczenie wiata


glLightfv(GL_LIGHTO,GL_POSITION,lightPos);
glEnable(GL_LIGHTO);

// Wczenie ledzenia koloru materiau


glEnable(GL_COLOR_MATERIAL);

// Ustawienie waciwoci materiau


glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Od tego momentu wszystkie materiay maj pen waciwo //


odbyskw z ustawionym wysokim poyskiem glMaterialfv(GL_FRONT,
GL_SPECULAR,specref); glMateriali(GL_FRONT,GL_SHININESS, 64) ;

// Czarne to
glClearColor(O.Of, O . O f , O . O f , l.Of );

Wywietlanie rezultatu
Gdy okrelilimy widok, owietlenie oraz parametry materiau, jedyne co pozostao, to
wyrenderowanie sceny. Listing 10.3 przedstawia schemat kodu uywanego do wywie-
tlania ruby i jej elementw. Wystpujce tu linie SomeFunc() to po prostu miejsca na
wywoania funkcji indywidualnie renderujcych gwk, trzpie i gwint ruby. Zacho-
wujemy stan macierzy, wykonujemy obroty (za pomoc klawiszy kursora, podobnie jak w
innych przykadach w tej ksice) oraz wywoujemy funkcj renderujc dany element
obiektu.

Listing 10.3. Renderowanie obiektu z uwzgldnieniem obrotw________________________

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy


glMatrixMode(GL_MODELVIEW);
glPushMatrix();

// obrt wok osi x i y


glRotatef(xRot, l. O f, O . O f ,
O . O f ) ; glRotatef(yRot, O . O f ,
l.Of, O . O f ) ;

// Kod rysujcy obiekt

SomeFuncO; // miejsce wywoania funkcji


glPopMatrix();
// Zrzucenie polece graficznych
glFlushO;
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________325

Konstruowanie modelu po kawaku


Kade zadanie programistyczne mona rozbi na mniejsze, atwiejsze do opanowania
czci. Te mniejsze czci atwiej jest opanowa i zakodowa, wprowadza to take pewne
moliwoci ponownego wykorzystania kodu. Trjwymiarowe modelowanie rwnie nie jest
wyjtkiem; stworzymy zoony obiekt z kilku mniejszych i mniej skomplikowanych
obiektw.

Zdecydowalimy si podzieli rub na trzy czci: gwk, trzpie i gwint. Takie po-
dejcie zdecydowanie uatwia nam graficzne zaprojektowanie elementw, ale take daje
nam trzy obiekty, ktre moemy wykorzysta w przyszoci. W bardziej skomplikowanych
aplikacjach do modelowania, atwo ponownego wykorzystania ma decydujce
znaczenie. Na przykad w aplikacji typu C AD bdziesz musia modelowa wiele rnych
rodzajw rub - o rnych dugociach, grubociach i gstoci gwintu. Zamiast funkcji
RenderHead(), renderujcej gwk w naszym przykadzie, mgby napisa funkcj
pobierajc parametry okrelajce ilo ktw, grubo i rednic gwki ruby.

Kolejn rzecz jest fakt, e kady element ruby modelujemy w ukadzie wsprz-
dnych najwygodniejszym do opisania obiektu. Najczciej obiekty s modelowane w
pocztku ukadu wsprzdnych, a dopiero pniej przemieszczane w odpowiednie
miejsce. Pniej, gdy bdziemy komponowa ostateczny obiekt, bdziemy przenosi i
obraca poszczeglne elementy, a nawet skalowa je w razie potrzeby.

Gwka
Gwka naszej ruby ma ksztat prostopadocianu o szeciu cianach oraz paskich
podstawach. Moemy skonstruowa ten obiekt z dwch szecioktw reprezentujcych
d i gr gwki oraz serii szeciu czworoktw reprezentujcych boczne cianki. Mo-
glibymy uy prymityww GL_QUAD i GL_POLYGON, aby rysowa przy jak naj-
mniejszej liczbie wierzchokw; jednak, jak ju wczeniej wspomnielimy, jeli to tylko
moliwe, powiniene uywa trjktw. W przypadku kadej karty akceleratora OpenGL (a
take pewnych programowych implementacji) zwykle krcej trwa narysowanie
dwch trjktw ni jednego czworokta.

Rysunek 10.2 pokazuje, w jaki sposb gwka naszej ruby zostanie skonstruowana z
trjktw. Uyjemy wachlarza szeciu trjktw dla grnej i dolnej powierzchni, za
kada z bocznych cianek bdzie skada si z dwch trjktw.

Rysunek 10.2.
Trjkty skadajce
si na gwk ruby

Tak wic na ca gwk ruby skadaj si 24 trjkty: po 6 na gr i d plus 12 na


cianki boczne. Funkcj renderujc gwk ruby zawiera listing 10.4. Z kolei rysunek
10.3 przedstawia wynik dziaania programu HEAD z pytki CD-ROM. Zwr uwag,
326 Cz II Uywanie OpenGL

e kod nie zawiera adnych funkcji, ktrych dotd nie omawialimy, lecz jest bardziej
zoony ni jakikolwiek wczeniejszy przykad.

Rysunek 10.3.
Dziaanie programu
HEAD

Listing 10.4. Renderowanie gwki ruby

// Tworzy gwk ruby void


RenderHead(void) {
float x,y,angle;
float height = 25.O f ; // Wyliczone pozycje
float diameter = 30.O f ; // Grubo gwki
float // rednica gwki
normal[ 3 ] ,corners[ 4 ] [ 3 ] , // Miejsce na wierzchoki
// i normalne
float step = (3.1415f/3.0f); // step = 1/6 okrgu = szeciokt

// Ustawienie koloru materiau dla gwki ruby


glColorSf( O . O f , O.Of, 0 . 7 f ) ;
// Wielokty zgodne z ruchem wskazwek s widziane z przodu,
// co ustalamy dla wachlarzy glFrontFace(GL_CW);

// Nowy wachlarz trjktw na grn powierzchni


glBegin(GL_TRIANGLE_FAN);

// Wszystkie normalne gry ruby wskazuj w gr osi z


glNormal3f( O . O f , O.Of, l . O f ) ;
// rodek wachlarza w pocztku ukadu wsprzdnych
glVertex3f( O . O f , O.Of, O . O f ) ;
// Podzia okrgu na sze sekcji i rozpoczcie podawania
// punktw tworzcych wachlarz
for(angle = O . O f ; angle < (2.0f*3.1415f); angle += step)
{
// Obliczenie pozycji x i y nastpnego wierzchoka
x = diameter*(float)sin(angle) ;
y = diameter*(float)cos(angle);
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________327

// Nastpny wierzchoek wachlarza


glVertex3f(x, y, O . O f ) ;
}
// Ostatni wierzchoek zamyka wachlarz
glVertex3f( O . O f , diameter, O . O f ) ;

// Koniec rysowania wachlarza na grna cz


glEnd();
// Przejcie do rysowania wachlarza na doln cz
// Wielokty zgodne z ruchem wskazwek s widziane z przodu,
glFrontFace(GL_CCW);

// Nowy wachlarz trjktw na doln powierzchni


glBegin(GL_TRIANGLE_FAN);
// Wszystkie normalne gry ruby wskazuj w d osi z
glNormalSf( O . O f , O . O f , - l . O f ) ;
// rodek wachlarza w pocztku ukadu wsprzdnych
glVertex3f( O . O f , O . O f , -height);

// Podzia okrgu na sze sekcji i rozpoczcie podawania


// punktw tworzcych wachlarz
for(angle = O . O f ; angle < (2.Of*3.1415f); angle += step)
(
// Obliczenie pozycji x i y nastpnego wierzchoka
x = diameter*(float)sin(angle);
y = diameter*(float)cos(angle);
// Nastpny wierzchoek wachlarza
glVertex3f( x , y, -height);
)
// Ostatni wierzchoek zamyka wachlarz
glvertex3f(O.Of, diameter, -height);
// Koniec rysowania wachlarza na grn cz
glEnd();

// Budowa bocznych cian z trjktw (po dwa). Kada ciana //


bdzie si skada z dwch trjktw tworzcych czworokt
glBegin(GLJTRIANGLES);
// Rysowanie cian
for(angle = O . O f ; angle < (2.Of*3.1415f); angle += step)
{
// Obliczenie pozycji x i y nastpnego punktu szeciokta
x = diameter*(float)sin(angle);
y = diameter*(float)cos(angle);
// Pocztek na dole gwki
corners[ 0 ] [ 0 ] = x;
corners[ 0 ] [ 1 ] = y;
corners[0][ 2 ] = -height;
328 Cz II Uywanie OpenGL

// Przejcie do gry
corners [1] [0] = x;
corners [ 1 ] [ 1 ] = y;
cornersfl] [ 2 ] = O.Of;
// Obliczenie nastpnego punktu szeciokta x =
diameter* (float) sin (angle+step) ; y = diameter*
(float) cos (angle+step) ;
// Sprawdzenie, czy to koniec
if (angle+step < 3.1415*2.0)
{
// Jeli koniec, po prostu zamknicie wachlarza
// w znanej wsprzdnej
corners [ 2 ] [ 0 ] = x;
corners [ 2 ] [ 1 ] = y;
corners[2] [ 2 ] = O . O f ;

corners [ 3 ] [ 0 ) = x;
corners [ 3 ] [ 1 ] = y;
corners [ 3 ] [ 2 ] = -height;
else
// Jeli nie koniec, punkty na grnej i dolnej //
czci gwki corners [2] [0] = O.Of; corners [ 2 ]
[ 1 ] = diameter; corners[2] [ 2 ] = O . O f ;

corners[3] [0] = O . O f ;
corners [ 3 ] [ 1 ] = diameter;
corners [ 3 ] [2] = -height;

// Wektory normalne dla caej cianki wskazuj //


ten sam kierunek calcNormal (corners, normal);
glNormal3fv(normal) ;

// Kady trjkt okrelamy osobno jako lecy //


obok nastpnego glVertex3fv(corners [ 0 ] )
glVertex3fv(corners [ 1 ] ) glVertex3fv(corners [ 2 ] )
glVertex3fv(corners [ 0 ] )
glVertex3fv(corners [ 2 ] )
glVertex3fv(corners [ 3 ] )

glEnd();

Trzpie
Trzpie ruby nie jest niczym innym jak cylindrem z dnem. Utworzymy cylinder roz-
kadajc punkty na okrgu w paszczynie xy, a nastpnie uyjemy dwch wartoci z
w tych punktach, tworzc wielokty przybliajce cianki cylindra. Jednak take tym
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________329

razem cianki bd skadane wycznie z trjktw. Ksztat cylindra przedstawia rysunek


10.4.

Rysunek 10.4.
Trjkty skadajce
si na cianki
cylindra

Uywajc wachlarza trjktw, utworzymy take dno cylindra. Zwr uwag e im


mniejszy krok dookoa okrgu, tym mniejsze bd paskie cianki na ciankach cylindra i
tym gadszy bdzie si wydawa trzpie.
Kod wykorzystany do utworzenia tego cylindra zosta przedstawiony na listingu 10.5.
Zwr uwag, e tym razem normalne wierzchokw nie s obliczane dla trjktw
przy uyciu wierzchokw trjktw. Zwykle ustawialimy normalne wierzchokw rwne
normalnej dla caego trjkta, jednak poniewa tym razem modelujemy krzyw po-
wierzchni, normalne w kadym z wierzchokw bd normalnymi dla modelowanej
krzywej.

Listing 10.5. Renderowanie trzpienia ruby___________________________________

// Tworzy trzpie ruby w postaci cylindra z zamknitym dnem


void RenderShaft(void)
{
float x,y,angle; // Uywane do obliczenia cian
// cylindra
float height = 7 5 . O f ; // Wysoko cylindra
float diameter = 20.O f ; // rednica cylindra
float normal[ 3 ] ,corners[ 4 ] [ 3 ] ; // Miejsce na wierzchoki i
// normalne
float step = ( 3 . 1 4 1 5 f / 5 0 . 0 f ) ; // Przyblia ciany cylindra 100
// paskimi segmentami

// Ustawienie koloru materiau na trzpie ruby


glColor3f( O . O f , O . O f , 0 . 7 f ) ;
// Wielokty przeciwne do ruchu wskazwek s widziane z przodu, //
(domylnie dla trjktw) glFrontFace(GL_CCW);

// Najpierw zoymy cian jako 100 czworoktw uformowanych //


z przystajcych do siebie trjktw glBegin(GL_TRIANGLES);
// Rysowanie cianek
for(angle = O . O f ; angle < (2.0f*3.1415f); angle += step)
{
// Obliczenie pozycji x i y nastpnego wierzchoka
x = diameter*(float)sin(angle) ;
y = diameter*(float)cos(angle) ;
330 Cz II * Uywanie OpenGL

// Pobranie wsprzdnej tego punktu i wycignicie //


dugoci cylindra corners[ 0 ] [ 0 ] = x; corners[ 0 ] [ 1 ] = y;
corners[0][ 2 ] = -height;
corners[ 1 ] [ 0 ] = x;
corners[ 1 ] [ 1 ] = y;
corners[l]( 2 ] = O . O f ;
// Pobranie nastpnego punktu i zrobienie tego samego x
= diameter*(float)sin(angle+step); y =
diameter*(float)cos(angle+step);
// Gdy koczymy, uycie znanego punktu pocztkowego
// w celu zamknicia powierzchni
if(angle+step < 3 . 1 4 1 5 * 2 . 0 ) // Not Finished
{
corners[ 2 ] [ 0 ] = x;
corners [ 2 ] [ 1 ] = y;
corners[2][ 2 ] = O . O f ;

corners[ 3 ] [ 0 ] = x;
corners[ 3 ] [ 1 ] = y;
corners[ 3 ] [ 2 ] = -height;
else

// Koczymy przy uyciu punktu startowego


corners[2][0] = O.Of;
corners[ 2 ] [ 1 ] = diameter;
corners[ 2 ] [ 2 ] = O.Of;

corners[3][0] = O . O f ;
corners[ 3 ] [ 1 ] = diameter;
corners[ 3 ] [ 2 ] = -height;

// Zamiast uywa zwykych normalnych do trjktw, uyjemy


// takich, jakie by wystpoway, gdyby powierzchnia bya
// rzeczywicie zakrzywiona. Poniewa cylinder biegnie wzdu
// osi Z, normalne wybiegaj z osi Z dokadnie w kierunku
// kadego wierzchoka. W zwizku z tym moemy uy
// wierzchoka jako normalnej, pod warunkiem, e zredukujemy
// go do wektora jednostkowego

// Pierwszy trjkt //////////////////////////////////////// //


Wypenienie wektora normalnego wsprzdnymi punktu normal[ 0 ] =
corners[ 0 ] [ 0 ] normal[l] = corners[ 0 ] [ 1 ] normal[2] = corners[ 0 ] [ 2 ]
// Znormalizowanie wektora i wskazanie dla danego punktu
ReduceToUnit(normal); glNormal3fv(normal);
glVertex3fv(corners[ 0 ] );
// Pobranie wierzchoka, obliczenie normalnej,
// narysowanie go
normal[ 0 ] = corners[ 1 ] [ 0 ] ;
normal[ 1 ] = corners[ 1 ] [ 1 ] ;
T

Rozdziaf 10. * Modelowanie i kompozycja obiektw 3D_____________________331

normal[2] = corners[ 1 ] [ 2 ] ;
ReduceToUnit(normal);
glNorma!3fv(normal);
glVertex3fv(corners[ 1 ] );

// Pobranie wierzchoka, obliczenie normalnej,


// narysowanie go
normal[ 0 ] = corners [ 2 ] [ 0 ] ;
normal[ 1 ] = corners[ 2 ] [ 1 ] ;
normal[ 2 ] = corners[ 2 ] [ 2 ] ;
ReduceToUnit(normal);
glNorma!3fv(normal);
glVertex3fv(corners[ 2 ] );

// Drugi trjkt ////////////////////////////////////////

// Pobranie wierzchoka, obliczenie normalnej,


// narysowanie go
normal[ 0 ] = corners[ 2 ] [ 0 ] ;
normal[ 1 ] - corners[ 2 ] [1];
normal[ 2 ] = corners[ 2 ] [ 2 ] ;
ReduceToUnit(normal);
glNorma!3fv(normal);
glVertex3fv(corners[ 2 ] );

// Pobranie wierzchoka, obliczenie normalnej,


// narysowanie go
normal[ 0 ] = corners[ 3 ] [ 0 ] ;
normal[ 1 ] = corners[ 3 ] [ 1 ] ;
normal[2] = corners[ 3 ] [ 2 ] ;
ReduceToUnit(normal);
glNormal3fv(normal);
glVertex3fv(corners[ 3 ] );
// Pobranie wierzchoka, obliczenie normalnej,
// narysowanie go
normal[ 0 ] = corners[ 0 ] [ 0 ] ;
normal[ 1 ] = corners[ 0 ] [ 1 ] ;
normal[ 2 ] = corners[ 0 ] [ 2 ] ;
ReduceToUnit(normal);
glNorma!3fv(normal);
glVertex3fv(corners[ 0 ] );
}
g l E n d ( ) ; // Koniec ze ciankami cylindra

// Przejcie do rysowania wachlarza na doln cz


glBegin(GL_TRIANGLE_FAN);
// Normalne wskazuj w d osi Z
glNorma!3f( O . O f , O.Of, - l . O f ) ;
// rodek wachlarza w pocztku ukadu wsprzdnych
glVertex3f( O . O f , O . O f , -height);
332____________________________________Cz II Uywanie OpenGL

// Obrt dookoa zgodnie z krokiem cian cylindra


for(angle = O . O f ; angle < (2.Of*3.1415f); angle += step)
// Obliczenie pozycji x i y nastpnego wierzchoka x
= diameter*(float)sin(angle) ; y =
diameter*(float)cos(angle);
// Nastpny wierzchoek wachlarza
glVertex3f( x , y, -height);

// Ostatni wierzchoek zamyka wachlarz


glVertex3f( O . O f , diameter, -height);
glEnd(); }

Na szczcie, cylinder jest owinity symetrycznie dookoa osi z. Tak wic normalna dla
kadego wierzchoka moe zosta obliczona przez znormalizowanie (zredukowanie do
dugoci jednostkowej) samego wierzchoka. Wynik dziaania programu SHAFT przed-
stawia rysunek 10.5.

Rysunek 10.5.
Wynik dziaania programu SHAFT

Gwint
Gwint jest najbardziej
skomplikowan czci
naszej ruby. Jest zoony z
dwch paszczyzn uoonych
w ksztat V, owinitych
spiralnie wzdu cylindra.
Jest tworzony jako dwa
paskie segmenty uoone w
V. Sposb konstruowania
gwintu przedstawia rysunek 10.6, za kod OpenGL uyty do jego utworzenia zawiera listing
10.6.

Rysunek
10.6.
Sposb
konstruowania
Rozdzia 10. Modelowanie i kompozycja obiektw 3D 333

Listing 10.6. Renderowanie gwintu ruby


// Tworzy gwint ruby
void RenderThread(void) {
float x,y,z,angle;
float height = 1 5 . 0 f; // Obliczone wsprzdne i kt
float diameter = 20.O f ; // Wysoko gwintu
float // rednica gwintu
normal[ 3 ] ,corners[ 4 ] [ 3 ] , // Miejsce na wierzchoki
/ / i normalne
float step = (3.1415f/32.0f); // Jeden obrt
float revolutions = T. O f ; // Ilo obrotw dookoa trzpienia
float threadWidth = 2 . 0 f; float // Szeroko gwintu
threadThick = 3 . 0 f ; float // Grubo gwintu
zstep = .125f; // Krok w kierunku osi Z za kadym
// razem, gdy rysowany jest nowy
segment

// 360 stopni w radianach


Idefine PI2 (2.Of*3.1415 f)

// Ustawienie koloru materiau dla gwintu


glColorSf( O . O f , O . O f , 0 . 4 f ) ;

-height+2; // punkt pocztkowy prawie przy kocu

// Rysowanie cian gwintu a do osignicia koca for(angle =


O.Of; angle < PI2*revolutions; angle += step)
(
// Obliczenie pozycji x i y nastpnego wierzchoka
x = diameter*(float)sin(angle);
y = diameter*(float)cos(angle);
// Przechowanie nastpnego wierzchoka przy trzpieniu
corners[ 0 ] [ 0 ] = x;
corners[ 0 ] [ 1 ] = y;
corners[ 0 ] [ 2 ] = z;

// Obliczenie pozycji w oddaleniu od trzpienia x =


(diameter+threadWidth)*(float)sin(angle); y =
(diameter+threadWidth)*(float)cos(angle);
corners[ 1 ] [ 0 ] = x;
corners[ 1 ] [ 1 ] = y;
corners[ 1 ] [ 2 ] = z;

// Obliczenie nastpnej pozycji w oddaleniu od trzpienia x =


(diameter+threadWidth)*(float)sin(angle+step); y =
(diameter+threadWidth)*(float)cos(angle+step);
corners[ 2 ] [ 0 ] = x;
corners[ 2 ] [ 1 ] = y;
corners[ 2 ] [ 2 ] = z + zstep;

// Obliczenie nastpnej pozycji wzdu trzpienia x =


(diameter)*(float)sin(angle+step); y =
(diameter)*(float)cos(angle+step);
334____________________________________Cz II Uywanie OpenGL

corners[ 3 ] [ 0 ] = x;
corners[ 3 ] [ 1 ] = y;
corners [ 3 ] [ 2 ] = z+ zstep;
// Uywamy trjktw, wic wybierzemy kierunek
// przeciwny do ruchu wskazwek
glFrontFace(GL_CCW);
glBegin(GL_TRIANGLES); // Pocztek grnej sekcji gwintu

// Obliczenie normalnych dla tego segmentu


calcNormal(corners, normal);
glNormal3fv(norml);

// Dwa trjkty pokrywajce obszar


glVertex3fv(corners[ 0 ] ] glVertex3fv
(corners[ 1 ] ] glVertex3fv(corners[ 2 ] )
glVertex3fv(corners[ 2 J )
glVertex3fv(corners[ 3 ] )
glVertex3fv(corners[ 0 ] )
glEnd() ;
// Przesunicie krawdzi lekko w gr osi z
// w celu utworzenia dolnej czci gwintu
corners[ 0 ] [ 2 ] += threadThick;
corners[ 3 ] [ 2 ] += threadThick;
// Przeliczenie normalnej z powodu zmiany punktw,
// tym razem normalna wskazuje w przeciwnym kierunku, wic
// wystarczy j odwrci
calcNormal(corners, normal);
normal[ 0 ] = -normal[ 0 ] ;
normal[ 1 ] = -normal[ 1 ] ;
normal[ 2 ] = -normal[ 2 ] ;
// Przejcie na kierunek zgodny z ruchem wskazwek dla dolnej //
paszczyzny gwintu glFrontFace(GL_CW);
// Rysowanie dwch trjktw
glBegin(GL_TRIANGLES);
glNormal3fv(normal);
glVertex3fv(corners[ 0 ] )
glVertex3fv(corners[ 1 ] )
glVertex3fv(corners[ 2 ] )
glVertex3fv(corners[ 2 ] )
glVertex3fv(corners[3])
glVertex3fv(corners[ 0 ] )
glEnd();

// Przejcie w gr osi Z z
+= zstep;
Rozdzia 10. * Modelowanie i kompozycja obiektw 3D 335

Dziaanie programu THREAD zostao przedstawione na rysunku 10.7.

Rysunek 10.7.
Wynik dziaania
programu THREAD

Skadanie modelu w cao


ruba jest skadana przez narysowanie w odpowiednim pooeniu wszystkich trzech
czci. Wszystkie czci s odpowiednio przesuwane wzdu osi z. Trzpie i gwint s
przesuwane o t sam odlego, gdy od pocztku zajmuj to samo pooenie. Wszystko,
co musimy zrobi, to uoy czci w odpowiednim pooeniu, za bufor gbokoci
usunie za nas niepotrzebne fragmenty.
Manipulowaniem i renderowaniem trzech czci ruby zajmuje si kod przedstawiony na
listingu 10.7. Kocowy wynik dziaania programu BOLT przedstawia rysunek 10.8.

Rysunek 10.8.
Dziaanie programu BOLT
336_______________________________________Cz II Uywanie OpenGL

Listing 10.7. Kod tworzcy kompletn rub___________________________________

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie macierzy przeksztacenia i wykonanie obrotu


glMatrixMode(GL_MODELVIEW);
// Obrt i przesunicie, a nastpnie narysowanie gwki ruby
glPushMatrix();
glRotatef(xRot, l.Of, O.Of, O . O f ) ;
glRotatef(yRot, O.Of, l.Of, O . O f ) ;
glTranslatef( O . O f , O.Of, 55.O f ) ;
RenderHeadO ;
glPopMatrix();

// Zachowanie stanu macierzy, obrt, przesunicie,


// narysowanie razem trzpienia i gwintu
glPushMatrix();
glRotatef(xRot, l.Of, O.Of, O . O f ) ;
glRotatef(yRot, O.Of, l.Of, O . O f ) ;
glTranslatef( O . O f , O.Of, 40.O f ) ;
// Narysowanie trzpienia i gwintu
RenderShaft(); RenderThreadO ;
glPopMatrix();

// Zrzucenie polece graficznych


glFlushO ;

Test szybkoci
Nasz ostatni program do dobrze prezentuje metalow rub, jak chcielimy wymode-
lowa. Skadajc si z ponad 1700 trjktw, jest to jak dotd najbardziej skompliko-
wany obiekt w tej ksice. Jednak trzeba przyzna, e ta ilo trjktw jest niczym w
porwnaniu z liczbami wieloktw, z jakimi si zetkniesz komponujc wiksze sceny i
bardziej zoone obiekty. W rzeczywistoci, wydajno najnowszych kart akceleratorw
3D jest mierzona w setkach tysicy trjktw na sekund, i to ju w przypadku
taszych modeli! Jednym z celw tego rozdziau byo wprowadzenie list wywietlania w
celu przyspieszenia renderowania. Zanim jednak przejdziemy do porwna, potrze-
bujemy jakiego sposobu mierzenia szybkoci - testu szybkoci.
Gdy przechodzimy do tematu list wywietlania, chcemy wiedzie, czy wystpuje jaka
rnica, zamiast wierzy wszystkiemu na sowo. Zmodyfikujmy wic nasz program
BOLT. Zamiast obraca rub za pomoc klawiszy kursora, obracajmy j cay czas,
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________337

choby wycznie w osi y. Jak si zapewne domylasz, w ten sposb zamienimy program
w generator trjktw, ktrego moemy atwo uy do zmierzenia wydajnoci.
Zmienion funkcj RenderScene() z programu SPINBOLT przedstawia listing 10.8.

Listing 10.8. Nowa funkcja RenderScene() obracajca rub dookoa osi y__________________

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Upewnienie si, e korzystamy z waciwej macierzy


glMatrixMode(GL_MODELVIEW);

// Obrt i przesunicie ukadu wsprzdnych


glRotatef(5.0f, O.Of, l.Of, O . O f ) ;
// Przesunicie i narysowanie gwki ruby
glTranslatef(O.Of, O.Of, 55.O f ) ;
RenderHead();
// Przesunicie w ty i narysowanie trzpienia i gwintu
glTranslatef( O . O f , O . O f , -15.O f ) ; RenderShaft();
RenderThread();
// Ponowne cofnicie w przygotowaniu do nastpnego razu
glTranslatef(O.Of, O.Of, -40.O f ) ;

// Zrzucenie polece graficznych


glFlushO ;

Nowa funkcja renderowania nie zachowuje ani nie odtwarza stanu macierzy. Uywamy
funkcji glTranslate, aby rcznie odtworzy stan przesunicia macierzy, jednak efekty
funkcji glRotate si kumuluj. To powoduje, e ruba obraca si dookoa swojej osi y o
5 za kadym razem, gdy jest renderowana.

Prosta technika animacji polega na stworzeniu timera, a gdy zostanie otrzymany komunikat
WM_T1MER, uniewanieniu obszaru okna w celu odmalowania go. W ten sposb moemy
w miar potrzeby spowalnia lub przyspiesza animacj. Naszym celem nie jest jednak
prosta animacja, ale raczej poznanie tempa obrotw. Sensownym kryterium bdzie czas,
wymagany, aby ruba obrcia si o pene 360 stopni.
Uycie komunikatw WM_TIMER nie jest najlepszym rozwizaniem z dwch powodw.
Po pierwsze, nikt nie gwarantuje, e okno otrzyma wszystkie komunikaty WM_TI-MER
(system operacyjny moe by zbyt zajty). Po drugie, gdy okrelisz przedziay czasu,
jak mierzenie odstpw czasu bdzie si miao do rzeczywistej wydajnoci?

To, czego rzeczywicie potrzebujemy, to odstp czasu pomidzy pocztkiem a zako-


czeniem renderowania. Mogaby to by warto zbyt maa do praktycznego uytku, mo-
emy wic zmierzy czas zajmowany przez pewn liczb renderowa. Powtarzajc
338____________________________________Cz II Uywanie OpenGL

renderowanie sceny wiksz ilo razy i mierzc czas, jaki to zabierze, otrzymamy zu-
penie poprawny test czasu.

Uwaga: To jest tylko przyblienie!


Ten test czasu jest bardzo nieformalny i korzysta z metod naliczania
czasu, ktre s tak niedokadne, e nie pozwalaj na publikowania
wynikw. Uywamy ich tylko w celu przedstawienia zysku w wydajnoci
wynikego z uycia list wywietlania. Aby porwna prawdziwe programy (a
take dwa zamieszczone tutaj), na czas trwania testu powiniene
przynajmniej zakoczy dziaanie wszystkich innych programw w
systemie. Na szybko renderowania ma wpyw wiele rnych czynnikw,
ale jeli warunki dla obu programw bd mniej wicej jednakowe,
powiniene zauway rnic pomidzy obiema wersjami.

By moe kusi ci zebranie po prostu garci wywoa funkcji RenderScene i zmierzenie,


jak dugo bd wykonywane. To dziaa, jednak zamknicie aplikacji stawia si bardzo
trudne, gdy nie bdzie miaa szans obsugi adnych innych komunikatw (na
przykad WM_CLOSE). Najlepszym sposobem sprawienia, aby Windows wci od-
wieay obszar roboczy okna, jest pominicie zatwierdzenia obszaru po otrzymaniu
komunikatu WM_PAINT. Jeli obszar roboczy wci bdzie niewany, Windows w nie-
skoczono bd posyay aplikacji komunikat WM_PAINT. W strumieniu tych ko-
munikatw znajduj si by moe take inne komunikaty, takie jak WM_CLOSE, ktre w
dalszym cigu bd mogy zosta przetworzone.

Now procedur obsugi komunikatu WM_PAINT w programie SPINBOLT przedstawia


listing 10.9.

Listing 10.9. Obsuga komunikatu WM_PAINT w programie SPINBOLT___________________

// Miejsce na wartoci do mierzenia czasu


static unsigned long ulstart = OL; static
unsigned long ulFinish = OL; static
double dTime = 0.0;

// Miejsce na statystyk wydajnoci char


cBuffer[80]; RECT cRect;

// Funkcja rysujca. Ten komunikat j e s t wysyany p r z e z Windows // za


kadym razem, gdy okno wymaga odwieenia case WM_PAINT:
{
// Zliczanie iloci renderowa
static iRenderCount = 0;

// Pobranie czasu na pocztku obrotu


if(iRenderCount == 0)
ulstart ulGetProfileTime();
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________339

// Wywoanie kodu rysunkowego OpenGL


RenderScene();

// Wywietlenie obrazka
SwapBuffers(hDC);
// Zwikszenie licznika. Jeli >= 71 -> koniec mierzenia //
czasu iRenderCount+ + ;

if(iRenderCount > 71)


{ iRenderCount =
0;
ulFinish = ulGetProfileTime();

// Przeliczenie czasu na sekundy


dTime = ulFinish - ulStart; dTime /=
1000.0; }
// Wywietlenie czasu (nie zapominajmy o kolorze ta)
sprintf(cBuffer," % 3 . If sekund dla 360 stopni.",dTime);
GetClientRect(hWnd,icRect);
SetBkColor(hDC,RGB( O , O,255));
SetTextColor(hDC,RGB( 2 5 5 , 2 5 5 , 0 ) );
TextOut(hDC,0,cRect.bottom-20,cBuffer,strlen(cBuffer));
// Nie uniewaniamy, wymuszajc kolejne komunikaty
// WM_PAINT
}
break;

Procedura obsugi odczytuje biecy czas systemowy i zlicza ilo wywoa funkcji
renderujcej. Po 71 razach odczytuje nowy czas, oblicza rnic i wywietla czas, jaki
upyn od ostatniego pomiaru. Pamitaj, e nasza ruba obraca si za kadym razem o
5, wic uywajc tej techniki naliczamy czas trwania obrotu o 360.

Rysunek 10.9.
Dziaanie programu SPINBOLT
340 Cz II Uywanie OpenGL

Funkcja ulGetProfileTime po prostu zwraca ilo tykni zegara systemowego i zamienia je


na tysiczne czci sekundy. (Moesz to sam sprawdzi w listingu, ale teraz nie jest to
istotne dla naszej dyskusji). Dziaanie programu SPINBOLT zostao przedstawione na
rysunku 10.9. Czas obrotu ruby dookoa wasnej osi wynosi trzy sekundy (na komputerze
Pentium Celeron 333 MHz z akceleratorem Matrox Millenium G200).

Poprawianie wydajnoci
By moe dostrzege, gdzie tkwi problem z wydajnoci w programie korzystajcym z
techniki WM_PA1NT. Podczas kadego rysowania ruby naley wykona ogromn
ilo oblicze zwizanych z rysowaniem gwintu, trzpienia i gwki. W tych obliczeniach
mnstwo razy odwoujemy si do kosztownych wywoa funkcji sin() i cos().
To, czego nam potrzeba, to sposb przechowania wszystkich obliczonych wierzchokw
i normalnych, a nastpnie wykorzystanie ich bez koniecznoci kadorazowego
przechodzenia przez ca t trygonometri. Oczywicie, OpenGL moe nam w tym
wzgldzie duo zaoferowa, a mianowicie listy wywietlania. Za pomoc listy wywie-
tlania moesz zarejestrowa wywoania funkcji OpenGL (oraz ich wyniki), a nastpnie je
odtworzy. Listy wywietlania s szybsze ni ponowne odtwarzanie pojedynczych
wywoa OpenGL. Co wicej, wywoania zewntrzne dla OpenGL, takie jak obliczanie
funkcji trygonometrycznych i normalnych, nie s powtarzane, lecz s rejestrowane je-
dynie ich wyniki, przekazywane funkcjom OpenGL. Ju z tego powiniene si zorien-
towa, dlaczego listy wywietlania s tak dobrym pomysem.

Ludzie i komputery
Dobr regu podczas tworzenia dowolnego oprogramowania
jest zajcie si poprawkami, ktre daj
ponaddwudziestoprocentowy wzrost wydajnoci. Zostao
oglnie przyjte, e ludzie w wikszoci przypadkw maj
trudnoci z wykryciem" wzrostu wydajnoci oprogramowania
o mniej ni dwadziecia procent. W przypadku OpenGL te 20%
mona czsto osign wanie przez zastosowanie list
wywietlania tam, gdzie liczba wieloktw staje si znaczna.
Tak wic dobrym pomysem jest przyzwyczajenie si do
uywania list wywietlania.

Tworzenie listy wywietlania


Tworzenie listy wywietlania jest bardzo proste. Tak jak obejmujesz prymitywy OpenGL
wywoaniami funkcji glBegin/glEnd, podobnie list wywietlania obejmujesz wywo-
aniami glNewList/glEndList. List wywietlania powinna identyfikowa dostarczana
przez ciebie warto cakowita. Poniszy kod ilustruje typowy przebieg tworzenia listy
wywietlania:
Rozdzia 10. Modelowanie i kompozycja obiektw 3D_____________________341

glNewListd, GL_COMPILE);

// Jaki kod OpenGL

glEndList();

Jako drugi parametr funkcji glNewList moesz poda GL_COMPILE lub GL_COM-
PILE_AND_EXECUTE. Informuje on OpenGL o tym, czy polecenia OpenGL maj
zosta skompilowane i przechowane, czy te skompilowane, wykonane i przechowane.
Pniej, gdy chcesz odtworzy list wywietlania, wywoaj po prostu
glCallList(l);

Podawany identyfikator jest tym samym identyfikatorem, co przekazany w odpowiednim


wywoaniu funkcji glNewList.
Listing 10.10 zawiera fragment kodu z naszego nowego przykadu, SLSTBOLT, ktry do
rysowania wirujcej ruby wykorzystuje listy wywietlania. Zwr uwag na moliwo
zagniedania list wywietlania. Maksymalna ilo 64 poziomw zagniedenia stanowi
zabezpieczenie przed nieskoczon rekurencj. W tym kodzie tworzymy list
wywietlania dla kadej czci ruby, a nastpnie pojedyncz list wykonujc wszystkie
przeksztacenia wsprzdnych i wywoujc pozostae listy w celu utworzenia
kompletnej ruby.

Listing 10.10. Nowy kod wirujcej ruby, tym razem korzystajcy z list wywietlania____________

#define HEAD_LIST l
define SHAFT_LIST 2
#define THREAD_LIST 3
define BOLT_LIST 4

// Ta funkcja odpowiada za inicjowanie kontekstu renderowania //


Oprcz tego tworzy i inicjuje wiata void SetupRCO

// Utworzenie listy wywietlania dla gwki ruby


glNewList(HEAD_LIST,GL_COMPILE) ;
RenderHead();
glEndListO;
// Utworzenie listy wywietlania dla trzpienia ruby
glNewList(SHAFT_LIST,GL_COMPILE) ;
RenderShaft();
glEndListO;
// Utworzenie listy wywietlania dla gwintu ruby
glNewList(THREAD_LIST,GL_COMPILE) ;
RenderThread();
glEndList () ;
342 ____________________________________ Cz II * Uywanie OpenGL

// Utworzenie zagniedonej listy wywietlania dla caej ruby


glNewList (BOLT_LIST, GL_COMPILE) ;

// Wyczyszczenie okna biecym kolorem ta


glClear(GL_COLOR_BOFFER__BIT | GL_DEPTH_BUFFER_BIT) ;
// Zapewnienie, e korzystamy z waciwej macierzy
glMatrixMode (GL_MODELVIEW) ;

// Obrt i przesunicie ukadu wsprzdnych //


Zwr uwag, e si kumuluje glRotatef (5.0f,
O.Of, l.Of, O . O f ) ;
// Przesunicie i narysowanie gwki ruby
glTranslatef ( O . O f , O.Of, 55. O f ) ;
glCallList (HEAD_LIST) ;

// Przesunicie w ty i narysowanie trzpienia i gwintu


glTranslatef ( O . O f , O.Of, -15. O f ) ; glCallList (SHAFT_LIST)
; glCallList (THREAD_LIST) ;

// Ponowne cofnicie w przygotowaniu do nastpnego razu


glTranslatef ( O . O f , O.Of, -40. O f ) ; '
// Koniec listy dla ruby
glEndList () ;

// Wywoywane do narysowania caej ruby


void RenderScene (void)
{
glCallList (BOLT_LIST) ;

// Zrzucenie polece graficznych


glFlushO ;
Rysunek 10.10.
Wykorzystujemy listy
wywietlania -
program SLSTBOLT
I Rozdzia 10. * Modelowanie i kompozycja obiektw 3D 343

Jak widzisz, zdefiniowalimy kilka staych identyfikujcych poszczeglne listy. Te stae to


po prostu numeryczne identyfikatory list. Rysunek 10.10 przedstawia dziaanie naszego
nowego i poprawionego programu. Tym razem do wykonania caego obrotu potrzeba byo
jedynie 2,5 sekundy, czyli wynik o p sekundy jest lepszy ni w poprzednim przykadzie.
To moe nie wydawa si duo, ale poczekaj kilka rozdziaw i sprbuj ponownie z
efektami specjalnymi, takimi jak mapowanie tekstur czy powierzchnie NURJBS. Jak
ju wspominalimy, 1700 trjktw to naprawd niewielki procent tego, z czego skadaj
si wiksze i bardziej zoone sceny.

Symulator czogu
Sprbuj uruchomi symulator czogu z poprzedniego rozdziau i porwna
go z symulatorem w tym rozdziale. Ta wersja, w duym stopniu
korzystajca z list wywietlania, zawiera wiele tysicy trjktw i nie
potrzebujesz adnego programu do testowania wydajnoci, aby zauway
rnic w dziaaniu!

Podsumowanie
Wykorzystywalimy ten rozdzia do pokazania, w jaki sposb tworzy si zoone trj-
wymiarowe obiekty, poczynajc od uycia prymityww OpenGL do budowania prostych
trjwymiarowych klockw, a nastpnie skadania ich w wiksze obiekty. Sama nauka
interfejsu programowania jest atwa, ale to wanie dowiadczenie w konstruowaniu
trjwymiarowych scen i obiektw bdzie ci wyrnia spord innych osb zajmujcych
si tym zagadnieniem. Gdy obiekt lub scena zostan rozbite na mniejsze, potencjalnie
ponownie wykorzystywalne czci, moesz oszczdzi czas renderowania sceny tworzc
listy wywietlania. W sekcji podrcznika znajdziesz wicej funkcji przeznaczonych do
wykorzystania, wywietlania i zarzdzania listami. Oprcz tego, na kocu rozdziau
poznae prosty sposb mierzenia wydajnoci swojego programu, umoliwiajcy
porwnanie korzyci pyncych z optymalizacji kodu.

Podrcznik
glCallList
Przeznaczenie Wykonuje list wywietlania
Plik nagwkowy
Skadnia Opis void glCallList(GLuint list);
Wykonuje list wywietlania identyfikowan przez parametr list. Po
wywoaniu tej funkcji maszyna stanu OpenGL nie jest odtwarzana, wic
344 Cz II * Uywanie OpenGL

dobrym pomysem jest wywoanie wczeniej funkcji glPushMatrix, za


pniej funkcji glPopMatrix. Wywoania glCallList mog by zagniedone.
Funkcja glGet z argumentem GL_MAX_LIST_NESTING zwraca
maksymaln ilo poziomw zagniedenia. W przypadku Microsoft
Windows jest ni 64.
Parametry
list GLuint: Identyfikuje list wywietlania, ktra ma zosta wykonana.
Zwracana warto Brak

Przykad Poniszy kod zachowuje stan macierzy przed wywoaniem listy


wywietlania. Po wywoaniu odtwarza stan macierzy.
// Zachowanie biecego stanu macierzy
glPushMatrix();

// Narysowanie ruby zawierajcej zagniedone listy


glCallList(BOLT_HEAD);

// Odtworzenie stanu macierzy


glPopMatrix();

Patrz take glCallLists, glDeleteLists, glGenLists, glNewList

glCallLists
Przeznaczenie Wywouje list list wywietlania.
Plik nagwkowy
Skadnia Opis void glCallLists(GLsizei n, GLenum type, const GLvoid *lists);
Wywouje kolejno listy wywietlania wskazywane w tablicy *lists. Ta
tablica moe by prawie dowolnego typu. Rezultat jest zamieniany lub
obcinany do najbliszej liczby cakowitej, ktra bdzie stanowi indeks
(identyfikator) konkretnej listy wywietlania. Opcjonalnie, wartoci z listy
mog zosta przesunite o pewn warto bazow, okrelon
wywoaniem funkcji glListBase.
Parametry
n type GLsizei: Ilo elementw tablicy list wywietlania.
GLenum: Rodzaj elementw przechowywanych w licie *lists. Moe by
jedn z nastpujcych wartoci: GL_BYTE, GL_UNSIGNED_BYTE,
GL_SHORT, GL_UNSIGNED_SHORT, GLJNT, GLJJNSIGNEDJNT,
GL_FLOAT, GL_2_BYTES, GL_3_BYTES lub GL_4_BYTES.
GLvoid: Tablica elementw typu okrelanego parametrem type.
Zadeklarowanym typem danych jest void, co umoliwia uycie
dowolnego z wymienionych powyej typw.
jg OpenGl Rozdzia 10. * Modelowanie i kompozycja obiektw 3D 345

Zwracana warto Brak


Poniszy kod ilustruje wywoanie grupy list wywietlania w pojedynczym
wywoaniu funkcji:
// Miejsce na identyfikatory list wywietlania
int lists[50]; int i ;

// Stworzenie nazw list


for(i = 0; i < 50; i++)
lists[ i ] = i + 1;
// Zbudowanie pidziesiciu list wywietlania:

// Pierwsza lista
glNewList(lists[0],GL_COMPILE);

glEnd ();

// Druga lista
glNewList(listS[q],GL_COMPILE);
glEnd();
// I tak dalej.. .

// Wywoanie pidziesiciu list jedn funkcj


glCallLists(50, GL_INT, lists;
Patrz take glCallLists, glDeleteLists, glGenLists, glListBase, glNewList

glDeleteLists
Przeznaczenie Usuwa cigy zakres list wywietlania.
Plik nagwkowy
Skadnia Opis void glDeleteLists(GLuint list, GLsizei rang);
Ta funkcja usuwa zakres list wywietlania. Usuwanie rozpoczyna si od
pocztkowej listy list i trwa do momentu usunicia rang list. Usuwanie
nieuywanych list wywietlania pozwala odzyska znaczne iloci pamici.
Nieuywane listy wywietlania z podanego zakresu s ignorowane i nie
powoduj bdw.
Parametry
list GLuint: Identyfikator pierwszej usuwanej listy.
rang Zwracana GLsizei: Ilo list wywietlania, jakie maj zosta usunite.
warto Brak
Cz II Uywanie OpenGL

Przykad
Patrz take
346
Ponisza linia kodu ilustruje usuwanie wszystkich list wywietlania o
identyfikatorach pomidzy l a 50:
F
glDeleteLists(l, 5 0 ) ;

glCallLists, glCallLists, glGenLists, gllsList, glNewList

glEndList
Przeznaczenie Plik Wyznacza koniec listy wywietlania.
nagwkowy
Skadnia Opis void glEndList(void);
Zwracana warto Listy wywietlania s tworzone przez wywoanie funkcji glNewList.
Wszystkie nastpne polecenia OpenGL s kompilowane i umieszczane na
Przykad licie wywietlania. Funkcja glEndList koczy tworzenie listy wywietlania.
Brak
Poniszy kod stanowi przykad tworzenia listy wywietlania za pomoc
funkcji glNewList i glEndList. Tworzona lista skada si z dwch
zagniedonych w niej list.
// Pocztek listy wywietlania
glNewList (BOLT_LIST, GL_COMPILE) ;
// Lista wywietlania zawiera dwie zdefiniowane //
uprzednio listy wywietlania glCallList (SHftFT_LIST) ;
glCallList (THREAD_LIST) ;
// Koniec listy wywietlania
glEndList O ;
glCallList, glCallLists, glDeleteLists, glGenLists, gllsList

Patrz take
glGenLists
Przeznaczenie Generuje cigy zakres pustych list wywietlania.
Plik nagwkowy
Skadnia Opis GLuint glGenLists(GLsizei rang);
Funkcja tworzy zakres pustych list wywietlania. Ilo tworzonych list
zaley od wartoci argumentu rang. Zwracan wartoci jest
identyfikator pierwszej listy z zakresu. Celem tej funkcji jest
zarezerwowanie zakresu identyfikatorw list do pniejszego uytku.
Parametry
rang GLsizei: Ilo danych pustych list.
Rozdzia 10. * Modelowanie i kompozycja obiektw 3D 347

Zwracana warto Identyfikator pierwszej listy z zakresu. Zostaj utworzone puste listy z
Przykad zakresu od zwracanej wartoci do range-l.
Poniszy kod alokuje tablic 25 liczb cakowitych, ktre zostan uyte do
przechowania identyfikatorw 25 list wywietlania. Kademu elementowi
tablicy musi zosta przypisany poprawny identyfikator listy, ktry moe
zosta uyty pniej.
int l i s t s [ 2 5 ] ; // miejsce na 25 list wywietlania
int first; // indeks pierwszego dostpnego
// identyfikatora listy wywietlania int
x; // Licznik ptli

// Odczyt pierwszego identyfikatora listy wywietlania


first = glGenLists( 2 5 ) ;
// Przypisanie kademu elementowi tablicy poprawnego
// identyfikatora listy wywietlania
for(x = 0; x < 25; x++)
lists[x] = f i r s t + x + 1;
Patrz take glCallList, glCallLists, glDeleteLists, glNewList

gllsList
Przeznaczenie Plik Sprawdza, czy istnieje dana lista.
nagwkowy
Skadnia Opis GLboolean gl!sList(GLuint list);
Ta funkcja jest uywana do sprawdzania, czy istnieje lista wywietlania o
danym identyfikatorze. Moesz jej uy do sprawdzenia listy przed jej
Parametry zastosowaniem.
list Zwracana
warto GLuint: Identyfikator potencjalnej listy wywietlania.
GLJTRUE jeli dana lista wywietlania istnieje, lub warto GL_FALSE w
Przykad przeciwnym wypadku.
Poniszy kod przeglda tablic, ktra powinna zawiera poprawne
identyfikatory list. Jeli lista o danym identyfikatorze istnieje, zostaje
wywoana.
int l i s t s [ 2 5 ] ; // miejsce na 25 list wywietlania
int x; // Licznik ptli

for(x = 0; x < 25; x++)


if(gllsList(lists[x])
glCallList(lists[ x ] );
Patrz take glCallList, glCallLists, glDeleteLists, glGenLists, glNewList
348 Cz II Uywanie OpenGL

gllistBase
Przeznaczenie Okrela warto bazow dodawan do identyfikatorw list
wywoywanych funkcj glCallLists.
Plik nagwkowy
Skadnia void glListBase(GLuint base);
Opis Funkcja glCallLists wywouje seri list wywietlania zawartych w tablicy.
Funkcja glListBase ustawia warto bazow, ktra zostaje dodana do
kadego identyfikatora listy w tablicy. Domyln wartoci bazow jest
zero. Moesz odczyta biec warto wywoujc funkcj
glGet(GL_LIST_BASE).
GLuint: Warto, ktra zostanie dodana do identyfikatora listy w tablicy list,
Parametry wywoywanych funkcj glCallLists. Domylnie ta warto jest rwna zeru.
base Brak.
Poniszy kod tworzy 20 list wywietlania ponumerowanych od O do 19.
Zwracana warto Tworzona jest tablica identyfikatorw list (listA), zawierajca liczby od O do
Przykad 9. Nastpnie jest wywoywana funkcja glCallLists wykonujca wszystkie
listy wystpujce w tablicy listA. Nastpnie, zamiast adowania tablicy
kojejnymi dziesicioma liczbami, za pomoc funkcji glListBase zmieniana
jest warto bazowa. Po ponownym wywoaniu funkcji CallLists dla tablicy
listA, zostan wywoane listy okrelone przez elementy tablicy powikszone
o warto bazow (10).
int listA[10]; int
i;

for(i = 0; i < 10;


listA[i] = i;

// Budowanie list wywietlania od l do 20


glNewListfl, GL_COMPILE);

glEndList();

// Druga lista glNewList(2,


GL_COMPILE);

glEndList();

// I tak dalej...

// Wywoanie pierwszych dziesiciu list


glCallLists( 1 0 , GL_INT, listA);
Rozdzia 10. * Modelowanie i kompozycja obiektw 3D 349

// Wywoanie nastpnych dziesiciu list, p r z y uyciu


// tej samej tablicy
glListBase( 1 0 ) ;
glCallLists( 1 0 , GL_INT, listA);
Patrz take glCallLists

glNewlist
Przeznaczenie Rozpoczyna tworzenie nowej listy odtwarzania.
Plik nagwkowy
Skadnia Opis void glNewList(GLuint list, GLenum mod);
Lista wywietlania jest grup polece OpenGL zarejestrowanych w celu
pniejszego wywoania i wykonania. Moesz uywa list wywietlania do
przyspieszania zoonych obliczeniowo rysunkw lub wymagajcych danych
odczytywanych z dysku. Funkcja glNewList rozpoczyna tworzenie listy,
ktr jednoznacznie identyfikuje pierwszy parametr. Identyfikatory list s
uywane w funkcjach glCallList i glCallLists w celu okrelenia listy, ktra
ma by wywoana. Jeli identyfikator nie jest unikatowy, poprzednia lista
moe zosta zastpiona. W celu zarezerwowania zakresu identyfikatorw
moesz uy funkcji glGenLists. W celu sprawdzenia, czy istnieje lista o
danym identyfikatorze, moesz uy funkcji gllsList. Listy wywietlania
mog by jedynie kompilowane albo kompilowane i wykonywane. Po
wywoaniu polecenia glNewList, nastpnie polecenia OpenGL s
rejestrowane i przechowywane w licie odtwarzania w kolejnoci ich
wystpienia, a do momentu napotkania polecenia glEndList. Wykonywane,
lecz nigdy nie s rejestrowane w samej lici s poleceniem: glGenLists,
glDeleteLists, glFeedbackBuffer, glSelectBuffer, glRenderMode,
glReadPixels, glPixelStore, glFlush, glFinish, gllsEnabled oraz glGet.
Parametry
list GLuint: Numeryczny identyfikator listy wywietlania. Jeli istnieje ju lista
o takim identyfikatorze, zostanie zastpiona przez now list.
mod GLenum: Listy wywietlania mog by kompilowane w celu pniejszego
wykonania lub kompilowane i wykonywane jednoczenie. Jeli chcesz
jedynie skompilowa list, zastosuj parametr GL_COMPILE. Jeli chcesz
skompilowa i jednoczenie wykona list wywietlania, zastosuj parametr
GL_COMPILE_AND_EXECUTE.
Zwracana warto Brak.
Przykad Poniszy kod stanowi przykad tworzenia listy wywietlania za pomoc
funkcji glNewList i glEndList. Tworzona lista skada si z dwch
zagniedonych w niej list.
350 Cz II Uywanie OpenGL

// Pocztek listy wywietlania


glNewList(BOLT_LIST, GL_COMPILE);

// Lista wywietlania zawiera dwie zdefiniowane //


uprzednio listy wywietlania
glCallList(SHAFT_LIST); glCallList(THREAD_LIST)
;

// Koniec listy wywietlania


glEndList();

Patrz take glCallList, glCallLists, glDeleteLists, glGenLists, gllsList


Rozdzia 11.
Grafika rastrowa
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


Rysowa bitmapowe obrazki * glBitmap/glRasterPos
Uywa bitmapowych czcionek * wglUseFontBitmaps/glGenLists/glCallLists
Rysowa kolorowe obrazki * glDrawPixels
Odczytywa i kopiowa kolorowe * glCopyPixels/glReadPixels
obrazki na ekran
Odczytywa i zapisywa pliki * LoadDIBitmap/SaveDIBitmap
bitmap Windows

Z pewnoci syszae wiele wypowiedzi o tym, e lepiej jest pracowa z trjwymiarow


grafik ni z grafik dwuwymiarow, t z przed lat. O ile w wikszoci przypadkw jest to
prawd, to jednak te trjwymiarowe obrazki s rysowane przecie w dwch
wymiarach na ekranie monitora. Grafika rastrowa to dwuwymiarowe tablice kolorw,
uywane nie tylko do wywietlania trjwymiarowych scen, ale take do drukowania
obrazw na drukarkach rastrowych czy nawet tamie filmowej!

Oprcz funkcji zwizanych z wektorami i wieloktami, jakie poznalimy dotychczas,


OpenGL udostpnia take kilka funkcji przeznaczonych do wywietlania trjwymiaro-
wych bitmap i obrazw. Wanie te funkcje bd przedmiotem tego rozdziau.

Rysowanie bitmap
Bitmapy w OpenGL to dwukolorowe obrazy, uywane do szybkiego rysowania na ekranie
znakw lub symboli (na przykad ikon). Rni si to od (bdnej) definicji stosowanej w
Microsoft Windows, ktre do bitmap zaliczaj take obrazki posiadajce wicej kolorw.
W OpenGL do rysowania bitmap suy pojedyncza funkcja, glBitmap. Gdy za
352 Cz II * Uywanie OpenGL

jej pomoc rysujesz bitmap, pierwszy kolor (0) jest przezroczysty. Drugi (1) jest ustalany
na podstawie biecego koloru i waciwoci owietlenia dla materiau.

Rysunek 11.1 przedstawia wywietlone w OpenGL bitmapy, przedstawiajce umie-


chnite buki. Kod (listing 11.1) sucy do stworzenia takiego obrazu skada si z da-
nych bitmapy, po ktrych nastpuje wywoanie funkcji glBitmap.

Rysunek
11.1.
Przyklad bitmapy
w OpenGL

Listing 11.1. Rysowanie okna penego umiechnitych buzi

void
RepaintWindow(RECT *rect) /* Obszar roboczy */
int i;
static GLubyte sraileyt] /* buka 16x16 */

0x03, OxcO, O, O, /*
OxOf, OxfO, O, O, /*
Oxle, 0x78, O, O, /* *** ** ***
0x39, Ox9c, O, O, /*
0x77, Oxee, O, O, /* *** ****** ***
Ox6f, O x f 6 , O, O, /* **
******** **
Oxff, Oxff, O, O, /* ****************
Oxff, Oxff, O, O, /* ****************
Oxff, Oxff, O, O, /* ****************
Oxff, Oxff, O, O, /* ****************
0x73, Oxce, O, O, /* *** **** ***
0x73, Oxce, O, O, /* *** **** ***
Ox3f, Oxfc, O, O, /* ************
Oxlf, Oxf8, O, O, /* **********
OxOf, OxfO, O, O, /*
********
0x03, OxcO, O, O /* ****

glViewport( O , O, rect->right, rect->bottom);


Rozdzia 11. Grafika rastrowa__________________________________353

glClearColor( 0 . 0 , 0.0, 0.0, 1 . 0 ) ;


glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadldentity();
g!0rtho(0.0, rect->right - 1 . 0 , 0 . 0 , rect->bottom - 1 . 0 , -1 .0 , 1 . 0 ) ;

/*
* Ta bitmapa jest wyrwnana do granicy 4 bajtw...
*/
glPixelTransferi(GL_UNPACK_ALIGNMENT, 4);

glColorSf ( 1 . 0 , 0 . 0 , 0 . 0 ) ;
for (i = 0 ; i < 100; i ++) {
glRasterPos2i(rand() % rect->right, rand() % rect->bottom);
glBitmap(16, 1 6 , 8 . 0 , 8 . 0 , 0 . 0 , 0 . 0 , smiley); };
glFinish();

W tym przykadzie zdefiniowalimy bitmap 16 x 16 pikseli, przedstawiajc umie-


chnit buk. Bitmapa jest zapisana w tablicy 32 bajtw bez znaku, w ktrej sidmy bit
pierwszego bajtu odpowiada lewemu dolnemu rogowi bitmapy.

Par sw na temat bitmap


Bitmapy OpenGL zwykle s zdefiniowane do gry nogami".
To znaczy, s zapisywane od dou do gry (wida to zreszt
na listingu). Aby zdefiniowa bitmap od gry do dou, musisz
zastosowa ujemn wysoko. Ponadto, z powodu bdu w
bibliotekach OpenGL Microsoftu, musisz wyrwna kady
wiersz bitmapy do granicy czterech bajtw. Przy prawidowo
funkcjonujcej bibliotece OpenGL mgby, do zmiany
wyrwnania bitmapy uy funkcji glPixelStore, opisanej w
dalszej czci rozdziau.

Po zdefiniowaniu bitmapy, ktra ma zosta narysowana, musimy okreli poprawn


pozycj rastra, wywoujc w tym celu funkcj glRasterPos:
glRasterPos2i(ran d() % rect->right, rand() % rect->bottom);

W tym przykadzie rysujemy buki w przypadkowych miejscach w obszarze roboczym


okna, z przesuniciem bitmapy po osiem pikseli od lewej strony i od dou. Pozycja
rastra jest okrelana we wsprzdnych modelu, podobnie jak pooenia wierzchokw w
funkcji glVertex. Oprcz ustawienia biecej pozycji rastra, funkcja glRasterPos
ustawia take znacznik poprawnej pozycji rastra. Ta zmienna logiczna ma warto
True, gdy pozycja rastra ley wewntrz biecego widoku, za warto False w prze-
ciwnym wypadku.
354 Cz II Uywanie OpenGL

Uwaga na temat obcinania


Wielokty i inne wektorowe prymitywy s czciowo rysowane
nawet wtedy, gdy'wykraczaj poza biecy widok, i s
obcinane tylko do granic widoku. Obcinanie bitmap przebiega
nieco inaczej. Jeli podana pozycja rastra ley poza biecym
widokiem, bitmapa nie bdzie rysowana.

Aby narysowa bitmap, wywoujemy funkcj glBitmap:


glBitmap(16, 1 6 , 8 . 0 , 8 . 0 , 0 . 0 , 0 . 0 , smiley);

W tym przypadku rysujemy bitmap 16 x 16, ktrej rodek ley w punkcie (8,0, 8,0)
bitmapy. Po narysowaniu bitmapy, pozycja rastra jest przesuwana o (0,0, 0,0) pikseli.
Prototyp tej funkcji jest nastpujcy:
glBitmap(GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bits)

Parametry width i height okrelaj szeroko i wysoko bitmapy. Parametr bits wskazuje
bitmap przeznaczon do narysowania, wyrwnan do granicy 32 bitw. Parametry xorig i
yorig zawieraj pooenie rodka bitmapy. Po narysowaniu bitmapy, bieca pozycja
rastra jest przesuwana o (xmove, ymove) pikseli, za znacznik poprawnej pozycji rastra
pozostaje niezmieniony. Parametry xmove i ymove zwykle s uywane przy rysowaniu
bitmapowych czcionek (opisywanych w nastpnej sekcji) w celu przejcia do komrki"
nastpnego znaku.

Uwaga na temat biecej pozycji rastra


Jak ju wspomniano, gdy bieca pozycja rastra ley poza
widokiem, bitmapa nie zostanie narysowana. Poniewa jednak
po narysowaniu bitmapy znacznik pozycji rastra pozostaje
niezmieniony, moesz uy funkcji glBitmap do
rozmieszczania i rysowania bitmap czciowo obcitych
granic biecego widoku. Na przykad, oto jak moesz nary-
sowa buk na lewej krawdzi biecego widoku:
glRasterPos2i(0, 0) ;
glBitmap( O , O, 0 . 0 , 0 . 0 , -4.0, 0 . 0 , NULL);
glBitmap(16, 1 6 , 8 . 0 , 8 . 0 , 0 . 0 , 0 . 0 , smiley);
Parametr NULL w pierwszym wywoaniu funkcji glBitmap
okrela, e nie ma adnej bitmapy do narysowania. Po
pierwszym wywoaniu glBitmap, bieca pozycja rastra
zostanie przesunita, 4 piksele w lewo (-4,0) przed
narysowaniem rzeczywistej bitmapy w nastpnym wywoaniu.
To rozwizanie nadaje si take do rysowania pixmap, ktre
zostan opisane w dalszej czci rozdziau.
Rozdzia 11. Grafika rastrowa__________________________________355

Czcionki bitmapowe
Jednym z bardzo wanych zastosowa bitmap jest wywietlanie acuchw znakw. W
zwykych warunkach musiaby zdefiniowa bitmap dla kadego znaku, a nastpnie
rysowaby bitmapy konieczne do narysowania acucha. Na szczcie, biblioteka Win32 w
Windows zawiera funkcj zwan wglUseFontBitmaps, przeznaczon do generowania
bitmap na podstawie czcionek zainstalowanych w systemie.
Aby umoliwi uycie bitmap czcionek, OpenGL dostarcza trzech funkcji: glGenLists,
glListBase oraz glCallList (opisanych w rozdziale 10). Funkcja glGenLists generuje cig
seri identyfikatorw list wywietlania OpenGL, ktre bd odpowiada bitmapom
znakw utworzonych funkcj WglUseFontBitmaps.
GLuint base;
HDC hdc;
base - glGenLists ( 9 6 ) ;
wglUseFontBitmaps(hdc, 32, 9 6 , base);

Ten kod tworzy 96 bitmap znakw z biecej czcionki, poczynajc od znaku 32, kodu
ASCII spacji. Zmienna base zawiera identyfikator listy wywietlania pierwszego znaku -
w tym przypadku znaku 32 (spacji w ASCII). Aby wywietli acuch znakw za pomoc
tej bitmapy, uyj poczenia funkcji glListBase oraz glCallLists:
char *s;

glListBase(font - 3 2 ) ; glCallLists(strlen(s),
GL_UNSIGNED_BYTE, s ) ;

Funkcja glListBase ustawia warto bazow identyfikatorw list wywietlania. Funkcje


glCallList oraz glCallLists dodadz t warto do przekazywanych im identyfikatorw list
wywietlania, a w efekcie wybior zdefiniowan wanie czcionk. Funkcja glCallLists
wywouje seri list wywietlania, przekazywan w postaci tablicy znakw (unsigned
byte), zawierajcej acuch do wypisania.

Budowanie prostej biblioteki czcionek


Funkcja wglUseFontBitmaps z pewnoci upraszcza tworzenie czcionek, jednak wci
pozostaje nam wiele pracy z wypisaniem acucha. Moemy jednak cakiem atwo
stworzy uyteczn bibliotek czcionek. W tym celu musimy posiada funkcj do two-
rzenia czcionek (listing 11.2).

Listing 11.2. Pocztek funkcji FontCreateBitmaps________________________________

GLuint
FontCreateBitmaps(HDC hdc, /* We - Kontekst urzdzenia */
char *typeface, /* We - Specyfikacja czcionki */ int
height, /* We - Wysoko czcionki w
^pikselach */
356 Cz II Uywanie OpenGL

int weight, /* We - Waga czcionki (pogrubiona,


=>etc) */ DWORD italic)
/* We - Tekst jest pochyy */

GLuint base; /* Bazowa lista wywietlania dla


^czcionki */
H FONT font; /* Identyfikator czcionki
^Windows */

if ( ( b a s e = glGenLists( 9 6 ) ) == 0)
return ( 0 ) ;

Argument typeface to po prostu nazwa czcionki, taka jak Courier czy Helvetica, okre-
lajca styl znakw. Argumenty height, width oraz italic (wysoko, szeroko, pochylenie)
s przekazywane bezporednio funkcji wglUseFontBitmaps i okrelaj rozmiar i wygld
znakw.
Zanim utworzysz bitmapy znakw, musisz zdecydowa si na wybr zestawu znakw.
Zwykle uywa si zestawu ANSI lub UNICODE. Zestaw znakw ANSI (ANSI_CHA-
RSET) zawiera standardowy zestaw znakw 7-bitowego ASCII. W celu uzyskania znakw
midzynarodowych i znakw diakrytycznych, uyj zamiast niego zestawu znakw
UNICODE (UNICODE_CHARSET). Pewne czcionki zawieraj zestawy znakw spe-
cjalnych. Na przykad czcionka Symbol zawiera litery alfabetu greckiego oraz wiele
symboli naukowych.
W tej prostej implementacji uyjemy zestawu znakw ANSI_CHARSET dla zwykfych
czcionek i zestawu SYMBOL_FONTSET dla czcionki Symbol. Spjrz na listing 11.3.

Listing 11.3. Kontynuacja funkcji FontCreateBitmaps_____________________________

if (stricmpttypeface, "symbol") == 0)
font = CreateFont(height, O, O, O, weight, italic, FALSE, FALSE,
SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
DRAFT_QUALITY, DEFAULT_PITCH, typeface);
else
font
CreateFont(height, O, O, O, weight, italic, FALSE, FALSE,
ANSI_CHARSET, OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
DEFAOLT_PITCH, typeface);

SelectObject( h d c , f o n t ) ;

wglUseFontBitmaps(hdc, 32, 9 6 , b a s e ) ;

return (base);

Jeli potrzebujesz znakw midzynarodowych, zmie normalny" zestaw znakw na


zestaw UNICODE_CHARSET i zdefiniuj 224 znaki (256 minus 32):
Rozdzia 11. Grafika rastrowa__________________________________357

else
font = CreateFont(height, O, O, O, weight, italic, FALSE, FALSE,
UNICODE_CHARSET, OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
DEFAULT_PITCH, typeface);

SelectObject(hdc, font);
wglOseFontBitmaps( h d c , 32, 224, base);

Aby uzupeni funkcje biblioteki, bdziemy potrzebowali funkcji przeznaczonej do usu-


wania czcionek (listing 11.4). Wywoywana w niej funkcja glDeleteLists po prostu usuwa
podane listy wywietlania, w tym przypadku nasze bitmapy czcionek. Tak jak w przy-
padku funkcji FontCreateBitmaps, aby umoliwi dziaanie z midzynarodowym zestawem
znakw, powiniene zmieni ilo list wywietlania z 96 na 224.

Listing 11.4. Funkcja FontDelete_________________________________________

void
FontDelete(GLuint font) /* We - Czcionka do usunicia */
{
if (font == 0)
return;
glDeleteLists(font, 9 6 ) ;

Na koniec, aby uatwi sobie rysowanie znakw, moesz stworzy funkcj wypisywania
acuchw i wypisywania sformatowanych acuchw. Funkcja FontPuts (listing 11.5)
uywa funkcji glPushAttrib oraz glPopAttrib w celu zachowania i odtworzenia biecej
wartoci bazowej identyfikatorw list wywietlania. Jeliby o tym zapomnia, mgby
niechccy wpyn na inny kod rysunkowy, korzystajcy z list wywietlania!

Listing 11.5. Funkcja FontPuts_________________________________________

void
FontPuts(GLuint font, /* We - Czcionka do uycia */
char *s) /* We - acuch do wypisania */
if (font == 0)
return;
if (s == NULL)
return;

glPushAttrib(GL_LIST_BIT);
glListBase(font - 3 2 ) ;
glCallLists(strlen(s), GL_UNSIGNED_BYTE, s ) ;
glPopAttrib();
358 Cz II * Uywanie OpenGL

Uwaga na temat funkcji glCallLists i acuchw znakw


Wane jest, aby pamita, e funkcja glCallLists i funkcje czcionek
opisywane w tym rozdziale nie obsuguj znakw kontrolnych, takich jak
tabulator czy znak nowej linii. Jeli w wywietlanym acuchu znajd si
takie znaki, mog zosta wywoane inne listy wywietlania, co wpynie na
kocowy wygld sceny. To dziaanie moe by kontrolowane poprzez
przetworzenie acucha wejciowego przed wywoaniem funkcji glCallLists.
Znaki nowej linii i tabulatora mog zosta zasymulowane za pomoc
techniki korzystajcej z funkcji gIBitmap, opisywanej w poprzedniej uwadze,
a take poprzez wywoanie funkcji glGetlntegen/ (opisywanej w rozdziale
14).

Funkcja FontPrintf (listing 11.6) uywa pliku nagwkowego <stdarg.h> w celu zarz-
dzania zmienn liczb argumentw potrzebn do funkcji vsprintf, formatujc acuch,
ktry ma zosta wypisany.

Listing 11.6. Funkcja FontPrintf


_______________________________________
#define MAX_STRING 1024

void
FontPrintf(GLuint font, /* We - Czcionka do uycia */
// We - acuch formatowania w stylu funkcji printfO char *
format,
...) /* We - Inne argumenty w miar potrzeby */
{
va_list ap; /* Wskanik argumentw */
char s[MAX_STRING + 1 ] ; /* acuch wyjciowy */

if (format == NULL)
return;

va_start(ap, f o r m a t ) ; // Przetwarzanie zmiennej liczby argumentw


vsprintf( s , format, ap) ; // Sformatowanie tekstu do acucha
// wyjciowego
va_end(ap); // Koniec przetwarzania zmiennej liczby
// argumentw
FontPuts(font, s ) ;

Peny kod funkcji FontCreateBitmaps, FontDelete, FontPuts oraz FontPrintf znajduje si


w pliku FONT.C na pytce CD-ROM, w folderze do tego rozdziau. Prototypy funkcji
zostay zdefiniowane w pliku FONT.H.
Rozdziaf 11. Grafika rastrowa ________________________________ 359

Pixmapy: bitmapy z kolorem


Obrazy zawierajce wicej ni dwa kolory czsto nazywane s\pixmapami (skrt odpi-xel
maps - mapy pikseli) i najczciej su jako obrazy ta lub tekstury (patrz rozdzia 12).
W OpenGL pixmapy to zwykle obrazki z 8-bitowym indeksowanym kolorem lub 24-
bitowe obrazki RGB.

Rysowanie pixmap
Do rysowania pixmap w OpenGL suy pojedyncza funkcja, glDrawPixels. Podobnie jak
glBitmap, glDrawPixels wykorzystuje biec pozycj rastra okrelajc pooenie
lewego dolnego rogu bitmapy. Nie okrela si jednak rodka bitmapy ani przesunicia
pozycji rastra.
BITMAPINFO *BitmapInfo;
GLubyte *BitmapBits;

glRasterPos2 (xof fset, yof fset) ;


glDrawPixels (BitmapInfo->bmiHeader .biWidth, BitmapInfo-
>bmiHeader .biHeight, GL_RGB,
GL_ONSIGNED_BYTE, BitmapBits);

Funkcja glDrawPixels akceptuje pi argumentw:


glDrawPixels (GLsizei width, GLsizei height,
GLenura format, GLenum type,
GLvoid *pixels)

Parametr format okrela przestrze kolorw pixmapy; dostpne formaty zostay zebrane w
tabeli 11.1. Format GL_COLOR_INDEX okrela, e kada warto koloru w pixma-pie
stanowi indeks do biecej logicznej palety kolorw Windows. Obrazki z indeksowanym
kolorem czsto s uywane do wywietlania ikon. Format GL_LUMINANCE
odwzorowuje kad warto koloru na skal szaroci na ekranie, gdzie warto mini-
malna odpowiada zupenej czerni, za warto maksymalna odpowiada zupenej bieli.
Format GL_RGB okrela, e kady piksel w obrazie posiada wasne intensywnoci
barw skadowych: czerwonej, zielonej i niebieskiej.

Tabela 11.1.
Formaty pikseli OpenGL

Format Opis
GL_COLOR_INDEX Piksele jako indeksy kolorw
GL_LUMINANCE Piksele w skali szaroci
GL_RGB Piksele RGB

Parametr type funkcji glDrawPixels okrela typ oraz zakres wartoci kolorw w obrazie, tak
jak opisano w tabeli 1 1.2.
360 Cz II Uywanie
OpenGL

Tabela 11.2.
Typy pikseli \v OpenGL

TYP Opis
GL_BYTE 8-bitowe wartoci ze znakiem (od -128
GL_UNSIGNEDJB do 127) 8-bitowe wartoci bez znaku (od
YTE GL BITMAP O do 255) Obraz bitmapy (od O do l)

Remapowanie kolorw
Gdy uywasz kolorw w formacie GL_COLOR_INDEX, moesz przemapowa kolory
pixmapy lub bitmapy, uywajc w tym celu funkcji glPixelMap lub glPixelTransfer.
Funkcja glPixelTransfer umoliwia okrelenie przeskalowania i przesunicia indeksw
kolorw i wartoci RGB. Na przykad, poniszy kod rozjania obraz RGB o 10 procent:
glPixelTransfer(GL_RED_SCALE, 1 . 1 ) ;
glPixelTransfer(GL_GREEN_SCALE, 1 . 1 ) ;
glPixelTransfer(GL_BLUE_SCALE, 1 . 1 ) ;

Podobnie, aby przesun indeksy kolorw bitmapy na pozycje palety, ktre dla nich
zdefiniowae, uyj
glPixelTransfer(GL_INDEX_OFFSET, kolor_dla_bitmapy);

W przykadzie z umiechnit" bitmap (listing 11.7) moemy uy poniszego kodu do


odwzorowania dwch kolorw bitmapy na odpowiednie pozycje palety:

Listing 11.7. Funkcja rysujca w oknie umiechnite buki___________ ___ __


void
RepaintWindow(RECT *rect) /* We - Obszar roboczy okna */
{ /
int i ;
static GLubyte smiley[] /* Umiechnita buka 16x16 */
{
0x03, OxcO, O, O, /*
OxOf, OxfO, O, O, /*
Oxle, 0x78, O, O, /*
0x39, Ox9c, O, O, /*
0x77, Oxee, O, O, /*
Ox6f, Oxf6, O, O, /*
Oxff, Oxff, O, O, /* '
Oxff, Oxff, O, O, /* '
Oxff, Oxff, O, O, /* '
Oxff, Oxff, O, O, /* '
0x73, Oxce, O, O, /* * ***

0x73, Oxce, O, O, /* ****

Ox3f, Oxfc, O, O, /*
Oxlf, Oxf8, O, O, /*
OxOf, OxfO, O, O, /*
0x03, OxcO, O, O /*
Rozdzia 11. Grafika rastrowa__________________________________361

glViewport( O , O, rect->right, rect->bottom);


glClear!ndex(0.0) ;
glClear(GL_COLOR_BUFFER_BIT) ;

glMatrixMode(GL_PROJECTION);
glLoadldentity();
glOrtho(0.0, rect->right - 1.0, 0.0, rect->bottom - 1.0, -1.0,
1.0);

/*
* Ta bitmapa jest wyrwnana do granicy 4 bajtw...
*/
glPixelTransferi(GL_UNPACK_ALIGNMENT, 4);
glPixelTransferi(GL_INDEX_OFFSET, 1);

for (i = 0; i < 100; i + + ) {


glRasterPos2i( r a n d ( ) % rect->right, r a n d ( ) % rect->bottom);
glDrawPixels( 1 6 , 1 6 , GL_COLOR_INDEX, GL_BITMAP, smiley); };

glFinishO;

Tablice odwzorowa kolorw


Czasami konieczne jest zastosowanie korekcji kolorw bardziej skomplikowanych ni
zwyke liniowe skalowanie i przesunicie. Jednym z zastosowa jest korekcja gamma, w
ktrej intensywno kadej wartoci koloru jest dostosowywana zgodnie z krzyw
wykadnicz, kompensujc bd odwzorowania kolorw przez monitor lub drukark
(rysunek 11.2).

Rysunek 11.2.
Obraz bez korekcji
gamma (po lewej) oraz
z korekcj gamma l, 7
(po prawej)
362____________________________________Cz II Uywanie OpenGL

Funkcja glPixelMap umoliwia przeprowadzenie tego przez zastosowanie tablicy prze-


gldania (LUT - lookup table);
GLfloat lut[ 2 5 6 ] ;
GLfloat gamma_value;
int i;
gamma_value = 1 . 7 ; /* Dla monitorw wideo NTSC */
for (i = 0; i < 2 5 6 ; i++)
lut[i] = pow(i / 255.0, 1.0 / gamma_value;

glPixelTransfer(GL_MAP_COLOR, GL_TRUE);
glPixelMap(GL_PIXEL_MAP_R_TO_R, 256, l u t ) ;
glPixelMap(GL_PIXEL_MAP_G_TO_G, 256, l u t ) ;
glPixelMap(GL_PIXEL_MAP_B_TO_B, 256, l u t ) ;

Skalowanie pixmapy
Poza dostosowywaniem kolorw pixmapy, moesz dopasowa jej rozmiar, uywajc w
tym celu funkcji glPixelZoom. Ta funkcja przyjmuje dwa parametry zmiennoprzecin-kowe,
okrelajce wspczynniki skalowania obrazu w poziomie i w pionie:
glPixelZoom(l.O, 1 . 0 ) ; // Bez skalowania glPixelZoom(-l.O, 1 . 0 ) ;
// Odbicie lustrzane w poziomie glPixelZoom(l. 0 , - 2 . 0 ) ; // Odbicie
lustrzane w pionie i podwojenie
// wysokoci glPixelZoom(0.33, 0 . 3 3 ) ; //
Zmniejszenie obrazka do 1/3 wielkoci

Jak wida, funkcja glPixelZoom pozwala na skalowanie i odwracanie obrazka prawie


dowolnie. Jednak aby osign efekty nieliniowe, takie jak efekt pofalowanej wody czy
korekcj perspektywy, musisz uy mapowania tekstury (rozdzia 12).

Wykrawanie obszarw
Funkcja glPixelStore moe zosta uyta do wydzielenia jedynie czci obrazu. Na przykad,
aby wywietli centralny obszar o rozmiarze 300 x 300 pikseli z obrazu o rozmiarze 540 x
480 pikseli, mgby uy poniszego kodu:
glPixelStore(GL_UNPACK_ROW_LENGTH, 640);
glPixelStore(GL_UNPACK_SKIP_PIXELS, ( 6 4 0 - 300) / 2 ) ;
glPixelStore(GL_UNPACK_SKIP_ROWS, (480 - 300) / 2 ) ;
glDrawPixels(300, 300, GL_RGB, GL_ONSIGNED_BYTE, BitmapBits);

W tym przykadzie warto GL_UNPACK_ROW_LENGTH okrela szeroko orygi-


nalnego obrazu w pikselach. Ustaw j, gdy szeroko okrelona w funkcji glDrawPixels
rni si od szerokoci obrazu.
GL_UNPACK_SKIP_PIXELS okrela ilo pikseli do pominicia z lewej strony obrazu.
Pomijamy pierwsze (640 - 300) / 2, czyli 170 pikseli z lewej strony, w celu wywietlenia
rodka obrazu.
Rozdzia 11. * Grafika rastrowa__________________________________363

GL_UNPACK_SKIP_ROWS jest podobne, z tym e okrela ilo wierszy pikseli do


pominicia. Zwykle ta warto reprezentuje ilo wierszy do pominicia z dou obrazu, ale
moesz to zmieni okrelajc w funkcji glPixelZoom ujemn warto skalowania w
pionie.

UWAGA:
Atrybuty GL_UNPACK_ROW_LENGTH,
GL_UNPACK_SKIP_PIXELS oraz GL_UNPACK_SKIP_ROWS
odnosz si do oryginalnych rozmiarw pixmapy, nie do
rozmiarw po przeskalowaniu!

Odczytywanie pixmap z ekranu


OpenGL posiada funkcj o nazwie glReadPixels, przeznaczon do odczytywania obrazu z
ekranu. Poza jej oczywistym zastosowaniem do zachowania utworzonego obrazu na
dysku, ta funkcja moe zosta uyta w celu osignicia ciekawych efektw mapowania
tekstury.
W odrnieniu od glDrawPixels, funkcja glReadPixels ignoruje biec pozycj rastra i
wymaga podania wsprzdnych (x, y) widoku dla lewego dolnego rogu obrazu, ktry ma
zosta odczytany. Sposb odczytania widoku do bitmapy Windows, nadajcej si do
zapisania na dysku lub uycia jako tekstury, przedstawia listing 11.8.

Listing 11.8. Funkcja ReadDIBitmap_______________________________________

'ReadDIBitmap()' - Odczytuje biecy widok OpenGL do


24-bitowej bitmapy RGB.
Przy sukcesie zwraca piksele bitmapy, a NULL w razie niepowodzenia i

void *
ReadDIBitmap(BITMAPINFO **info) /* Wy - Nagwek bitmapy */

long i, j,
bitsize, /* Cakowity rozmiar bitmapy */
width; /* Wyrwnana szeroko wiersza */
GLint viewport[ 4 ] ; /* Biecy widok */
void *bits; /* Bity RGB */
GLubyte *rgb, /* Zmienne ptli RGB */
temp; /* Zmienna tymczasowa */
/*
* Odczyt biecego w i d o k u . . .
*/
glGet!ntegerv(GL_VIEWPORT, viewport);

/*
* Zaalokowanie pamici na nagwek
*/
364 Cz II Uywanie OpenGL

if ( ( * i n f o (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER)))
NULL)

V Za mao pamici na nagwek

return (NULL) ;
width = viewport[2] * 3; /* Rzeczywista szeroko
^wiersza */ /* Wyrwnanie do 4 bajtw
width (width + 3) & ~ 3 ;
*/
bitsize = width * viewport [ 3 ] ; /* Rozmiar wyrwnanej bitmapy */

if ( (bits = calloc (bitsize, D) == NULL)


/*
Brak pamici na bitmap
*/
free(*info) ;
return (NULL) ;

* Odczytanie pikseli z bufora ramki


*/
glFinishO; /* Zrzut polece OpenGL */
glPixelStorei(GL_PACK_ALIGNMENT, 4 ) ; // Wymuszenie 4-bajtowego
// wyrwnania
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0) ;
glReadPixels( O , O, viewport[2], viewport[3], GL_RGB,
GL_UNSIGNED_BYTE, bits);

Zamiana czerwieni z niebieskim w bitmapie

for (i = 0; i < v i e w p o r t [ 3 ] ; i + + )
for (j = O, rgb = ((GLubyte * ) b i t s ) + i * width; j
< viewport[ 2 ] ; j + + , rgb += 3)
temp = rgb[0];
rgb[0] = rgb[ 2 ] ;
rgb[ 2 ] = temp;

Na koniec wypenienie nagwka bitmapy


(*info)->bmiHeader.biSize sizeof(BITMAPINFOHEADER)
(*info)->bmiHeader.biwidth yiewport[ 2 ] ;
(*info)->bmiHeader.biHeight viewport[ 3 ] ;
Rozdzia 11. Grafika rastrowa __________________________________ 365

(*info) ->bmiHeader .biPlanes = 1; (*info) -


>bmiHeader .biBitCount = 24; (*info) ->bmiHeader
.biCompression = BI_RGB; (*info) ->bmiHeader .biSizelmage
= bitsize; (*info)->bmiHeader.biXPelsPerMeter = 2952; /*
75 DPI */ (*info)->bmiHeader.biYPelsPerMeter = 2952; /* 75
DPI */ (*info)->bmiHeader .biClrUsed = 0; (*inf o) -
>bmiHeader .biClrlmportant = 0;
return (bits) ;

Pierwsz rzecz, ktr powiniene zrobi, jest wyznaczenie rozmiarw biecego widoku,
jak pokazano poniej, za pomoc funkcji glGetlntegery. (Ta funkcja zostanie opisana w
rozdziale 14). Powoduje to umieszczenie pocztku X, pocztku Y, rozmiaru X oraz
rozmiaru Y w tablicy widoku, opisanej w tabeli 1 1.3.
/*
* Odczyt biecego widoku. . .
*/
glGet!ntegerv(GL_VIEWPORT, viewport) ;

Tabela 11.3.
Definicje tablicy widoku

Indeks Opis
O Pocztek widoku X (w pikselach)
1 Pocztek widoku Y (w pikselach)
2 Szeroko widoku (w pikselach)
3 Wysoko widoku (w pikselach)

Gdy masz ju rozmiar widoku, moesz zaalokowa pami dla pixmapy. Wane jest,
aby pamita, e bitmapy Windows (i domylnie pixmapy OpenGL) musz zaczyna kad
lini na granicy czterech bajtw. Aby to zapewni, wykonujemy ponisz sztuczk:
width = viewport[2] * 3; /* Rzeczywista szeroko wiersza */ width
= (width + 3 ) & ~ 3 ; /* Wyrwnanie do 4 bajtw */

Musimy zaokrgli wyliczon rzeczywist szeroko widoku (w tym przypadku 3 bajty


dla kadego piksela szerokoci) do najbliszej 32-bitowej (czyli 4-bajtowej) granicy.
Tak wic cakowitym rozmiarem bitmapy staje si
bitsize = width * viewport [ 3 ] ; /* Rozmiar wyrwnanej bitmapy */

Po zaalokowaniu pamici dla pixmapy, wywoujemy funkcj glReadPixels w celu od-


czytania zawartoci biecego widoku, po czym wypeniamy struktur BITMAPINFO-
HEADER wszystkimi potrzebnymi informacjami.
366____________________________________Cz II Uywanie OpenGL

Kopiowanie pixmap
OpenGL udostpnia take funkcj przeznaczon do kopiowania obszaru na ekranie w
inne miejsce - na przykad w celu przewinicia widoku lub zastosowania efektu szka
powikszajcego:
int mousex, mousey;

glReadBuffer(GL_FRONT) ;
glDrawBuffer(GL_FRONT);
glPixelZoom(2.0, 2 . 0 ) ;
glRasterPos2i( O , 0) ;
glCopyPixels(mousex - 8, mousey - 8, 1 6 , 1 6 , GL_COLOR) ;

Funkcja glCopyPixels kopiuje piksele ze wskazanego miejsca do biecej pozycji rastra:


void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
^GLenum type)

Parametry x i y okrelaj lewy dolny rg obszaru, ktry ma zosta skopiowany. Parametry


width i height okrelaj rozmiar kopiowanego obrazu. Piksele s kopiowane z podanej
pozycji (x, y) w miejsce okrelone biec pozycj rastra. Argument type okrela, jakie
wartoci bd kopiowane. Dla wikszoci aplikacji typem pikseli bdzie warto
GL_COLOR, oznaczajca kopiowanie indeksw kolorw lub wartoci RGB.
Skalowanie pikseli odnosi si do pikseli wyjciowych, a nie docelowych. W powyszym
przykadzie, obraz 16 x 16 pikseli zostanie skopiowany do lewego dolnego rogu okna, po
czym zostanie przeskalowany do rozmiarw 32 x 32 piksele. Przesunicia i rozmiary
podane w wywoaniu funkcji glPixelStore nie wpywaj na dziaanie funkcji glCopyPixels;
wpywaj za to zmiany dokonane funkcjami glPixelTransfer i glPixelMap,

Przegldarka plikw bitmap


Gdy poznalimy ju wszystkie dostpne funkcje zwizane z bitmapami, sprbujmy na-
pisa program OpenGL bdcy przegldark plikw .BMP w Windows. Zadania naszego
programu s atwe do opisania:
* adowanie dowolnego pliku .BMP Windows;
* Skalowanie obrazka do biecego rozmiaru okna;
* Dostarczenie prostych kontrolek do zmiany jasnoci obrazu i korekcji gamma;
* Pokazywanie powikszonego widoku obszaru pod wskanikiem myszy;
* Zapisywanie wywietlanego obrazka na dysku;
* Wydrukowanie wywietlanego obrazka.
Peny kod tego programu znajduje si w pliku OGLYIEW.C na pytce CD-ROM, w fol-
derze tego rozdziau.
mGL Rozdzia 11. Grafika rastrowa 367

Pliki bitmap w Windows


mi Zanim zaczniemy tworzy kod, przyjrzyjmy si formatowi plikw bitmap w Windows.
ka Mimo swoich ogranicze, pliki .BMP w Windows s prawdopodobnie najpowszechniej
uywanymi plikami graficznymi w komputerach osobistych, mogcymi przechowywa
obrazy zawierajce od 2 do ponad szesnastu milionw kolorw. Z kilkoma wyjtkami, w
plikach .BMP nie stosuje si kompresji danych, dziki czemu mona je bardzo atwo
odczytywa i zapisywa w programach, take w programach OpenGL.
Plik .BMP jest podzielony na trzy lub cztery sekcje, w zalenoci od iloci wystpujcych
w nim kolorw (Rysunek 11.3). Wszystkie pliki .BMP rozpoczynaj si od struktury
BITMAPFILEHEADER, zawierajcej sygnatur (acuch BM"), cakowity rozmiar pliku
oraz offset do danych obrazu. Ta struktura jest zdefiniowana nastpujco:
typedef struct tagBITMAPFILEHEADER

WORD bfTyep; DWORD // "BM"


bfSize; WORD // Rozmiar pliku w bajtach
bfReservedl; WORD // Zarezerwowane, zawsze O
bfReserved2; // Zarezerwowane, zawsze O
DWORD bfOffBits; // Offset do danych obrazu, w bajtach
BITMAPFILEHEADER;

Rysunek 11.3. Plik bitffiopy RGB Plik bitmapy i pdelq


Organizacja pliku
BITMAPFILEHEADER BITMAPFILEHEADER
.BMP
BITMAPINFO BITMAPINFO
Dane bitmapy/pxeli Pozycje PALETTENTRY
Dane bitmapy/pxeli

Po nagwku pliku nastpuje struktura BITMAPINFOHEADER, opisujca zawarto


pliku:
typedef struct tagBITMAPINFOHEADER

DWORD biSize; LONG // Rozmiar struktury w bajtach


biWidth; LONG // Szeroko obrazka w pikselach
biheight; WORD // Wysoko obrazka w pikselach
biPlanes; WORD // Ilo planw koloru (zawsze 0)
biBitCount; DWORD // Ilo bitw koloru
biCompression; DWORD // Rodzaj zastosowanej kompresji
biSizelmage; LONG // Rozmiar obrazka w bajtach
biKPelsPerMeter; LONG // Ilo pikseli na metr w poziomie
biYPelsPerMeter; DWORD // Ilo pikseli na metr w pionie
biClrUsed; DWORD // Ilo wykorzystanych kolorw
biClrlmportant; // Ilo kolorw znaczcych
BITMAPINFOHEADER;
368____________________________________Cz II Uywanie OpenGL

W przypadku obrazw z indeksowanymi kolorami (z palet kolorw), po strukturze


BITMAPINFOHEADER wystpuje paleta definiujca kady kolor w obrazku. Zaraz
potem nastpuj dane obrazu.

Odczyt plikw .BMP


Poniewa format pliku .BMP jest tak prosty, odczyt takich plikw jest prawie banalny.
Zaczynamy od otwarcia pliku i wczytania struktury BITMAPFILEHEADER.
if ( ( f p = fopen(filename, " r b " ) ) == NULL)
return (NULL);

freadlsheader, sizeof(BITMAPFILEHEADER), l, fp) ;

if (header.bfType != ' M B ' ) /* Sprawdzenie sygnatury M B . . . */ {


/*
* To nie jest plik bitmapy - zwr NULL...
*/
fclose(fp); return
(NULL); };

Jeli nagwek wyglda poprawnie, moemy odczyta struktur BITMAPINFO, cznie z


definicj palety.
infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER);
fread(*info, l, infosize, f p ) ;

Na koniec za odczytujemy dane bitmapy i zamykamy plik.


if ((bitsize = (*info)->bmiHeader.biSizelmage) == 0)
bitsize = ((*info)->bmiHeader.biWidth *
(*info)->bmiHeader.biBitCount + 7 ) / 8 *
abs((*info)->bmiHeader.biHeight);

fread(bits, l, bitsize, f p ) ;
fclose(fp);

Listing l .9 zawiera peny kod funkcji LoadDlBitmap, uzupeniony o sprawdzanie bdw.

Listing 11.9. Funkcja LoadDIBitmap_____________________________________

void *
LoadDlBitmap(char *filename, /* We - Plik do wczytania */
BITMAPINFO **info) /* We - Informacje o bitmapie */ {
FILE *fp; /* Wskanik pliku */
void *bits; /* Bity bitmapy */ long
bitsize, /* Rozmiar bitmapy */
infosize; /* Rozmiar nagwka */
BITMAPFILEHEADER header; /* Nagwek pliku */
Rozdzia 11. Grafika rastrowa_________________________________369

/*
* Prba otwarcia pliku w trybie binarnym
*/
if ( ( f p = fopenffilename, " r b " ) ) -- NULL)
return (NULL);
/*
* Odczyt nagwka i informacji o bitmapie
*/
if (fread(Sheader, sizeof(BITMAPFILEHEADER), l, fp) < 1) { /*
* Nie powiodo si odczytanie nagwka
*/
fclose( f p ) ; return
(NULL); };

if (header.bfType != ' M B ' ) /* Sprawdzenie sygnatury M B . . . */ {


/*
* To nie jest plik bitmapy - zwr NULL... V
fclose(fp); return
(NULL); };
infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER); if
*info = (BITMAPINFO *)malloc(infosize)) == NULL) { /*
* Brak pamici na nagwek bitmapy
*/
fclose(fp); return
(NULL); };
if (fread(*info, l, infosize, fp) < infosize) {
/*
* Nie powiodo si odczytanie nagwka bitmapy
*/
free(*info);
fclose(fp); return
(NULL); );
/*
* Gdy mamy wszystkie informacje, alokowanie pamici na
* bitmap i jej odczyt z dysku
*/
370 Cz II * Uywanie OpenGL

if ((bitsize = (*info)->bmiHeader.biSizelmage) == 0)
bitsize = ((*info)->bmiHeader.biwidth *
(*info)->bmiHeader.biBitCount + 7 ) / 8 *
abs((*info)->bmiHeader.biHeight);
if ((bits = malloc(bitsize)) == NULL) {
/*
* Brak pamici
*/

free(*info);
fclose(fp);
return (NULL);

if ( f r e a d ( b i t s , l, bitsize, fp) < bitsize) { /*


* Nie da si odczyta bitmapy - zwolnij pami
* i zwr warto NULL
*/
free(*info);
free(bits);
fclose( f p ) ;
return (NULL);

* OK, wszystko w porzdku, zwr wskanik do bitmapy


*/

fclose (fp); return


(bits) ;

Zapis pliku .BMP


Aby zapisa plik .BMP, po prostu dodamy struktur BITMAPFILEHEADER do bitmapy
w pamici i wszystko razem zapiszemy na dysk. Funkcj SaveDIBitmap zawiera listing
11.10.

Listing 11.10. Funkcja SaveDIBitmap__________ ________ ___

int
SaveDIBitmap(char *filename, /* We - Plik do zapisu */
BITMAPINFO *info, /* We - Informacje o bitmapie */
void *bits) /* We - Bity bitmapy */
FILE *fp; /* Wskanik pliku */
long size, /* Rozmiar pliku */
infosize, /* Rozmiar nagwka bitmapy */
bitsize; /* Rozmiar danych bitmapy */
BITMAPFILEHEADER header; /* Nagwek pliku */

l
Rozdzia 11. Grafika rastrowa_________________________________371

/*
* Prba otwarcia pliku do zapisu w trybie binarnym V
if ( ( f p = fopen(filename, "wb")) NULL)
return ( - 1 ) ;
if (info->bmiHeader.bisizelmage == 0) /* Wyznaczenie rozmiaru
<=>bitmapy */
bitsize = (info->bmiHeader.biWidth *
info->bmiHeader.biBitCount + 7 ) / B * abs(info-
>bmiHeader.biHeight); else
bitsize = info->bmiHeader.bisizelmage;
infosize = sizeof(BITMAPINFOHEADER);
switch (info->bmiHeader.biCompression) {
case BI_BITFIELDS :
infosize += 12; /* Dodanie trzech masek RGB doubleword */ if
(info->bmiHeader.biClrUsed == 0) break; case BI_RGB :
if (info->bmiHeader.biBitCount > 8 &&
info->bmiHeader.biClrUsed == 0)
break;
case BI_RLE8 :
case BI_RLE4 :
if (info->bmiHeader.biClrUsed == 0)
infosize += (l info->bmiHeader.biBitCount) * 4;
else
infosize += info->bmiHeader.biClrUsed * 4;
break; };
size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;
/*
* Zapis nagwka pliku, nagwka bitmapy i danych bitmapy
*/
header.bfType = ' M B ' ; /* Nie przenona... ech */
header.bfSize = size;
header.bfReservedl = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + infosize;
if (fwrite(Sheader, l, sizeof(BITMAPFILEHEADER), fp) <
sizeof(BITMAPFILEHEADER))
{
/*
* Nie powiodo si zapisanie nagwka pliku V
fclose( f p ) ;
return ( - 1 ) ;
372___________________________________Cz II Uywanie OpenGL

if (fwrite( i n f o , l, infosize, fp) < infosize) (


/*
* Nie powiodo si zapisanie nagwka bitmapy
*/
fclose( f p ) ;
return (-1) ; };
if (fwrite(bits, l, bitsize, fp) < bitsize) {
/*
* Nie powiodo si zapisanie bitmapy
*/
fclose(fp);
return ( - 1 ) ;
>;
/*
* OK, wszystko w porzdku
*/
fclose(fp);
return ( 0 ) ;

Drukowanie bitmap
Poniewa Windows dostarcza kilku wygodnych funkcji do drukowania, dostpnych z
wntrza aplikacji, nie pozostaje nam nic innego jak wydrukowa nasz obrazek wy-
wietlany w przegldarce. W tym przykadowym programie bdziemy korzysta ze stan-
dardowych usug druku GDI.
Pierwsz rzecz, jak musimy zrobi, jest wywietlenie standardowego okna dialogo-
wego Drukuj w Windows. Suy do tego poniszy fragment kodu:
memsetl&pd, O, sizeof(pd));
pd.lStructSize = sizeof(pd);
pd.hwndOwner = owner; pd.Flags
= PD_RETURNDC; pd.hlnstance =
NULL; if (IPrintDlg(Spd)) return
(0);

Jeli funkcja PrintDlg zwrci warto O, oznacza to, e uytkownik klikn na przycisk
Anuluj. W przeciwnym wypadku struktura PRINTDLG bdzie zawieraa uchwyt kontekstu
urzdzenia (HDC), ktrego bdziemy mogli uy do drukowania.
Teraz musimy rozpocz zadanie drukowania.
di.cbSize - sizeof(DOCINFO);
di.lpszDocName = "OpenGL Image";
di.lpszOutput = NULL;
StartDoc(pd.hDC,
Rozdzia 11. Grafika rastrowa_________________________________373

Nastpnie musimy narysowa bitmap za pomoc funkcji StretchBlt, po czym zamkn


zadanie drukowania.
StretchBlt(pd.hDC, xoffset, yoffset, xsize, ysize, hdc,
O, O, info->bmiHeader.biwidth, info c*-
>bmiHeader. biHeight, SRCCOPY);

EndPage( p d . hDC);
EndDoc(pd.hDC);

Pierwsze cztery parametry funkcji StretchBlt obliczamy na podstawie rozmiaru druko-


wanej strony. Chcemy przeskalowa obraz do rozmiarw strony, jednak z zachowaniem
niezmiennego stosunku dugoci bokw.
xsize = rect.right;
ysize = xsize * info->bmiHeader.biHeight / info->bmiHeader.biwidth;
if (ysize > rect.bottom)
{
ysize = rect.bottom;
xsize = ysize * info->bmiHeader.biwidth / info->bmiHeader.biHeight; };

Przesunicia s obliczane jako poowa rnicy pomidzy szerokociami a wysokociami:


xoffset = (rect.right - xsize) / 2;
yoffset = (rect.bottom - ysize) / 2;

Zwykle wywietliby jeszcze dialog informujcy o drukowaniu, ale w tym wypadku


drukowanie w programie odbywa si tak szybko, e nie byoby to uyteczne.
Peny kod funkcji PrintDIBitmap zosta przedstawiony na listingu 11.11.
Listing 11.11. Funkcja PrintDIBitmap____________________________
int
PrintDIBitmap(HWND owner, /* We - Okno nadrzdne */
BITMAPINFO *info, /* We - Nagwek bitmapy */ void *bits)
/* We - Dane bitmapy*/ {
PRINTDLG pd; /* Okno dialogu Drukuj */ long
xsize, /* Rozmiar drukowanego obrazka */ ysize,
xoffset,/* Odstp od krawdzi obrazka */
yoffset;
RECT rect; /* Prostokt strony */ DOCINFO di;
/* Informacje o dokumencie */ HDC hdc; /*
Kontekst urzdzenia dla bitmapy */ HBITMAP bitmap; /*
Obraz bitmapy */ HBRUSH brush; /* Pdzel ta strony
*/ HCURSOR busy, /* Kursor zajtoci */ oldcursor; /*
Stary kursor */
/*
* Sprawdzenie zakresu
*/

if (info == NOLL || bits = NULL)


return ( 0 ) ;
374 Cz II Uywanie OpenGL

/*
* Inicjowanie struktury PRINTDLG przed wywietleniem standardowego
* okna dialogowego Drukuj w Windows
*/
memsetl&pd, O, sizeof ( p d ) ) ;
pd.lStructSize sizeof ( p d ) ;
pd.hwndOwner = owner;
pd.Flags = PD_RETURNDC;
pd.hlnstance = NULL; if (
IPrintDlg(spd) )
return ( 0 ) ; /* Uytkownik wybra A n u l u j . . . */
/*
* OK, uytkownik chce drukowa, ustawmy wic kursor zajtoci
* i zacznijmy drukowanie
*/
busy = LoadCursor (NULL, IDC_WAIT) ;
oldcursor = SetCursor (busy) ;

SetMapModel pd.hDC, MM_TEXT) ;


di.cbSize = sizeof (DOCINFO) ; di
.IpszDocName = "OpenGL Image";
di.lpSzOutput = NULL;

StartDoc (pd.hDC, sdi) ;


StartPage (pd.hDC) ;
/*
* Wyczyszczenie ta biaym kolorem
*/
rect.top = 0;
rect.left - 0;
rect.right = GetDeviceCaps (pd.hDC, HORZRES);
rect.bottom = GetDeviceCaps (pd.hDC, YERTRES);
brush = CreateSolidBrush(OxOOffffff ) ;
FillRect (pd.hDC, Srect, brush);
/*
* Rozcia.gniecie bitmapy do rozmiarw kartki
*/
hdc = CreateCompatibleDC (pd.hDC) ;
bitmap = CreateDIBitmap (hdc, S (info->bmiHeader) , CBM_INIT, bits,
Oinfo,
DIB_RGB_COLORS) ;
SelectObject (hdc, bitmap);

xsize = rect.right;
ysize = xsize * inf o->bmiHeader .biHeight / info->bmiHeader .biwidth;
if (ysize > rect.bottom)
{
ysize = rect.bottom;
xsize = ysize * info->bmiHeader .biwidth / info-
>bmiHeader. biHeight;

x o f f s e t = ( r e c t. r i g h t - x s i z e ) / 2;
Rozdzia 11. Grafika rastrowa 375

yoffset = (rect.bottom - ysize) / 2;


StretchBlt(pd.hDC, xoffs et, yoffset, xsize, ysize, hdc,
O, O, info->bmiHeader.biWidth, info *-
>bmiHeader. biHeight, SRCCOPY);

/*
* To wszystko. Koniec drukowanie i zwolnienie zaalokowanych zasobw.
*/
EndPage(pd.hDC);
EndDoc(pd.hDC);
DeleteDC(pd.hDC);
DeleteObject(bitmap);
DeleteObject(brush);
DeleteObject(busy);
DeleteDC(hdc);
/*
* Odtworzenie kursora i powrt
*/

SetCursor(oldcursor);

return ( 1 ) ;

Wywietlanie bitmapy
Cz OpenGL naszego przykadowego programu rozpoczyna si od wywietlenia pliku
.BMP. Podobnie jak wikszo programw OpenGL, take ten zaczyna si od ustalenia
biecego widoku i przeksztace widoku.
glViewport ( O , O, rect->right, rect->bottom) ;

glMatrixMode (GL_PROJECTION) ;
glLoadldentity () ;
glOrtho(0.0, rect->right - 1 . 0 , 0 . 0 , rect->bottom - 1 . 0 , -1.0, 1 . 0 ) ;
glMatrixMode (GL_MODELVIEW) ;

Zaraz po tym rysujemy bitmap. Skalujemy j w celu dopasowania do okna, z zachowaniem


stosunku bokw 1:1. Poniszy kod powinien wyglda bardzo znajomo uywae go w
opisanej powyej funkcji PrintDIBitmap:
xsize = rect->right;
ysize = BitmapInfo->bmiHeader. biHeight xsize /
Bitmaplnf o->bmiHeader . biWidth; if (ysize
> rect->bottom)

ysize = rect->bottom;
xsize = BitmapInfo->bmiHeader .biWidth * ysize /
Bitmaplnf o->bmiHeader . biHeight;
}; (float)xsize / (float)Bitmaplnfo->bmiHeader.biWidth;
xscale
376____________________________________Cz II Uywanie OpenGL R

yscale = (float)ysize / (float)BitmapInfo->bmiHeader.biHeight;


xoffset = (rect->right - xsize) * 0 . 5 ;
yoffset = (rect->bottom - ysize) * 0 . 5 ;
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixe!Zoom(xscale, yscale);
glRasterPos2i(xoffset, yoffset);
glDrawPixels(BitmapInfo->bmiHeader.biWidth, Bitmaplnfo-
>bmiHeader.biHeight, GL_RGB,
GL_UNSIGNED_BYTE, BitmapBits);

Co ciekawe, funkcja Windows StretchBlt wywietla bitmapy szybciej ni funkcja glDrawPi-xels.


Oczywicie, StretchBlt nie uwzgldnia dziaania funkcji glPixelMap i glPixelTransfer.

Pebiy kod funkcji RepaintWindow przedstawia listing 11.12. Listing 11.12. Funkcja

RepaintWindow_____________________________________

void
RepaintWindow(RECT *rect) /* We - Obszar roboczy okna */
{
GLint xoffset, /* Przesunicie obrazu w poziomie */
yoffset; /* Przesunicie obrazu w pionie */ GLint
xsize, /* Szeroko przeskalowanego obrazu */
ysize; /* Wysoko przeskalowanego obrazu */ GLfloat
xscale, /* Skalowanie w poziomie */ yscale; /*
Skalowanie w pionie */

/*
* Wyzerowanie widoku i wyczyszczenie okna biaym tem
*/
glViewport( O , O, rect->right, rect->bottom);
glMatrixMode(GL_PROJECTION);
glLoadldentity();
glOrtho(0.0, rect->right - 1 . 0 , 0 . 0 , rect->bottom - 1 . 0 , - 1 .0 , 1 . 0 ) ;
glMatrixMode(GL_MODELVIEW);

glClearColord.O, 1 . 0 , 1 . 0 , 1 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT);

/*
* Jeli zaadowalimy obraz bitmapy, przeskalowanie go do rozmiarw
* okna
*/
if (BitmapBits != NOLL) {
xsize = rect->right; ysize = BitmapInfo-
>bmiHeader.biHeight * xsize /
Bitmaplnfo->bmiHeader.biWidth; if
(ysize > rect->bottom) {
ysize = rect->bottom;
xsize = Bitmaplnfo->bmiHeader.biWidth * ysize /
Rozdzia 11. Grafika rastrowa_________________________________377

BitmapInfo->bmiHeader.biHeight;
};
xscale = (float)xsize / (float)BitmapInfo->bmiHeader.biwidth;
yscale - (float)ysize / (float)BitmapInfo->bmiHeader.biHeight;

xoffset = (rect->right - xsize) * 0 . 5 ;


yoffset = (rect->bottom - ysize) * 0 . 5 ;

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelZoom(xscale, yscale); glRasterPos2i(xoffset,
yoffset); glDrawPixels(BitmapInfo->bmiHeader.biwidth,
Bitmaplnfo->bmiHeader.biHeight, GL_RGB,
GL_UNSIGNED_BYTE, BitmapBits); };
glFinishO ;

Podsumowanie
W tym rozdziale poznae wikszo zagadnie dotyczcych funkcji OpenGL operujcych
na bitmapach. Poza prostymi zastosowaniami zwizanymi z wywietlaniem bitma-powych
znakw, bitmapy mog by wykorzystywane jako penokolorowe obrazy do tworzenia
ta okna lub tekstur (ktre zostan omwione w nastpnym rozdziale). Funkcje OpenGL,
takie jak glPixelMap, glPixelTransfer czy glPixelZoom pozwalaj take na uzyskanie
wielu specjalnych efektw.

Podrcznik
glCopyPixels
Przeznaczenie Kopiuje prostoktny blok pikseli w buforze ramki.
Plik nagwkowy <gl.h>
Skadnia void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum type);
Opis Ta funkcja kopiuje dane pikseli ze wskazanego obszaru w buforze ramki
do obszaru wskazywanego przez biec pozycj rastra. Jeli bieca
pozycja rastra nie jest poprawna, adne dane nie s kopiowane.

Na dziaanie funkcji glCopyPixels wpywaj wywoania funkcji


glPixelMap, glPixelTransfer oraz glPixelZoom.
378 Cz II * Uywanie OpenGL

Parametry x
width GLint: Wsprzdna pozioma lewego dolnego rogu kopiowanego
obszaru.
height
GLint: Wsprzdna pionowa lewego dolnego rogu kopiowanego
type
obszaru.
Zwracana warto GLsizei: Szeroko kopiowanego obszaru w pikselach.
Przykad Patrz GLsizei: Wysoko kopiowanego obszaru w pikselach.
take GLenum: Typ danych, ktre maj zosta skopiowane. Dostpne s
ponisze wartoci:
GL_COLOR Wartoci bufora kolorw
GL_STENCIL Wartoci bufora szablonu
GL_DEPTH Wartoci bufora gbokoci
Brak.
Przejrzyj kod programu OGLYIEW.C
glPixelMap, glPixelStore, glPixelTransfer, glPixelZoom

glDrawPixels
Przeznaczenie Rysuje prostoktny blok pikseli w buforze ramki.
Plik nagwkowy
Skadnia void glDrawPixels(GLsizei width, GLsizei height, GLenum formay,
GLenum type, const GLvoid *pixels);
Opis Ta funkcja kopiuje dane pikseli z pamici do obszaru wskazywanego przez
biec pozycj rastra w buforze ramki. Do ustawiania pozycji rastra suy
funkcja glRasterPos. Jeli bieca pozycja rastra nie jest poprawna, adne
dane nie s kopiowane.
Poza argumentami/O/Twa/ i type, na kodowanie pikseli i przetwarzanie ich
przed umieszczeniem w buforze ramki wpywa take kilka innych
parametrw. Zajrzyj do opisu funkcji glPixelMap, glPixelStore,
glPixelTransfer oraz glPixelZoom.
Parametry
width GLsizei: Szeroko obrazu w pikselach.
height GLsizei: Wysoko obrazu w pikselach.
Rozdzia 11. Grafika rastrowa 379

format GLenum: Przestrze kolorw rysowanych pikseli. Dostpne s ponisze


wartoci:
GL_COLOR_INDEX Piksele indeksu koloru
GL_LUMINANCE Piksele skali szaroci
GL_LUMINANCE_ALPHA Skala szaroci + piksele alfa (dwa
komponenty)
GL_RGB Piksele RGB (trzy komponenty)
GL_RGBA Piksele RGBA (cztery komponenty)
GL_RED Piksele czerwieni
GL_GREEN Piksele zieleni
GL_BLUE Piksele niebieskiego
GL_ALPHA Piksele kanau alfa
GL_STENCIL JNDEKS Wartoci bufora szablonu
GL_DEPTH_COMPONENT Wartoci bufora gbokoci
type GLenum: Typ danych, ktre maj zosta skopiowane. Dostpne s
ponisze wartoci:
GLJ3YTE 8-bitowe wartoci ze znakiem (od -128 do 127)
GL_UNSIGNED_BYTE 8-bitowe wartoci bez znaku (od O do 255)
GL_BITMAP Obraz bitmapy (od O do 1) GL_SHORT 16-bitowe
wartoci ze znakiem (od -32 768 do 32 767)
GL_UNSIGNED_SHORT 16-bitowe wartoci bez znaku (od O do 65
535)
GLJNT 32-bitowe wartoci ze znakiem (od -2 147 483 648 do 2
147 483 647)
GL_UNSIGNED_INT 32-bitowe wartoci bez znaku (od O do 4
294 967 295)
GL_FLOAT 32-bitowe wartoci zmiennoprzecinkowe (GLfloat)
pbcels GLvoid*: Wskanik do danych obrazka.
Zwracana warto Brak.
Znane bdy Obecnie parametr GL_UNPACK_ALIGNMENT funkcji glPixelStore jest
ignorowany przez funkcj glDrawPixels.
Przykad Przejrzyj kod programu OGLYIEW.C
Patrz take glPixelMap, glPixelStore, glPixelTransfer, glPixelZoom

glPixelMap
Przeznaczenie Definiuje tablic przegldania dla funkcji operujcych na pikselach.
Plik nagwkowy <gl.h>
380 Cz II Uywanie OpenGL

Skadnia void glPixelMapfv(GLenum map, GLtnt mapsize, const GLfloat *values);


Opis void glPixelMapuiv(GLenum map, GLint mapsize, const GLuint
*values);
void glPixeIMapusv(GLenum map, GLint mapsize, const GLushort
*values);
Ta funkcja przygotowuje tablic przegldania (lookup table - LUT) dla
funkcji glReadPixels, glTexImagelD oraz glTexImage2D. Tablice
przegldania, czyli tzw. odwzorowania, s uywane tylko wtedy, gdy w
funkcji glPixelTransfer zostanie wczona odpowiednia opcja,
GL_MAP_COLOR lub GL_MAP_STENCIL. Odwzorowania s
stosowane przed rysowaniem i po odczycie wartoci z bufora ramki.
Parametry
map GLenum: Rodzaj definiowanego odwzorowania. Dostpne s ponisze
wartoci:
GL_PIXEL_MAP_I_TO_I Odwzorowanie do indeksw kolorw
GL_PIXEL_MAP_S_TO_S Odwzorowanie do wartoci szablonu
GL_PIXEL_MAP_I_TO_R Odwzorowanie z indeksw kolorw na
wartoci czerwieni
GL_PIXEL_MAP_I_TO_G Odwzorowanie z indeksw kolorw na
wartoci zieleni
GL_PIXEL_MAP_I_TO_B Odwzorowanie z indeksw kolorw na
wartoci niebieskiego
GL_PIXEL_MAP_I_TO_A Odwzorowanie z indeksw kolorw na
wartoci alfa
GL_PIXEL_MAP_R_TO_R Odwzorowanie do wartoci czerwieni
GL_PIXEL_MAP_G_TO_G Odwzorowanie do wartoci zieleni
GL_PIXEL_MAP_B_TO_B Odwzorowanie do wartoci bkitu
GL_PIXEL_MAP_A_TO_A Odwzorowanie do wartoci alfa
mapslze GLint: Rozmiar tablicy przegldania.
values GLfloat*, GLuint*, GLushort*: Tablica przegldania.
Zwracana warto Brak.
Przykad Patrz Przejrzyj kod programu OGLYIEW.C
take glCopyPixels, glDrawPixels, glPixelStore, glPixelTransfer, glReadPixels,
glTex!magelD, glTex!mage2D

glPixelStore
Przeznaczenie Okrela sposb zapisu i odczytu pikseli z pamici.
Plik nagwkowy <gl.h>
Rozdzia 11. * Grafika rastrowa 381
void gIPixeIStorei(GLenum pname, GLint param); void glPixelStoref(GLenum
Skadnia pname, GLfloat param);
Ta funkcja okrela sposb zapisu pikseli do pamici funkcj glReadPixels oraz sposb
Opis ich odczytu funkcjami glDrawPixels, glTex!magelD oraz glTex!mage2D. Nie wpywa
na dziaanie funkcji glCopyPixels.
GLenum: Parametr do ustawienia. Dostpne wartoci s nastpujce:
Parametry GL_PACK_SWAP_BYTES* GLJTRUE Jeli True, bajty
wszystkich wielobajtowych wartoci zostaj zamienione w pamici.
pname
GL PACK LSB FIRST GL FALSE Jeli True, lewe bity w
bitmapach znajduj si
w pikselu O, a nie 7.
Ustala szeroko
GL PACK RW LENGTH obrazu w pikselach.
O Jeli O, uywany jest
argument width.
Ustala ilo pikseli
obrazu do pominicia
GL PACK SKIP PDCELS O w poziomie.
Ustala ilo pikseli
obrazu do pominicia
GL PACK SKIP ROWS w pionie.
Ustala wyrwnanie dla
linii obrazu. Patrz
GL PACK ALIGNMENT 4 sekcja Znane bdy
poniej.
Jeli True, bajty
wszystkich
GL_UNPACK_SWAP_BYTES GLJTRUE wielobajtowych
wartoci s zamieniane
(GLJTRUE dla little-endian, miejscami podczas
GL_FALSE dla big-endian) odczytu.
Jeli True, lewy piksel
bitmap odczytywany
GL UNPACK LSB FIRST GL FALSE jest z bitu O, a nie 7.
382 Cz II Uywanie OpenGL

GL UNPACK RW LENGTH O Ustala szeroko


obrazu w pikselach.
Jeli O, uywany jest
argument width.
GL UNPACK SKIP PIXELS O Ustala ilo pikseli
obrazu do pominicia
w poziomie.
GL UNPACK SKIP ROWS Ustala ilo pikseli
obrazu do pominicia
w pionie.
GL UNPACK ALIGNMENT Ustala wyrwnanie
dla linii obrazu. Patrz
param sekcja Znane bdy
Zwracana warto poniej.
Znane bdy GLint, GLfloat: Warto parametru. Brak.
W obecnej chwili parametry GL_PACK_ALIGNMENT i
Przykad GL_UNPACK_ALIGNMENT s ignorowane przez funkcj glPixelStore.
Patrz take Przejrzyj kod programu BITMAP.C
glDrawPixels, glReadPixels, glTexImagelD, glTex!mage2D

glPixelTransfer
Przeznaczenie Ustala opcje i tryb przenoszenia pikseli dla funkcji glCopyPixels,
glDrawPixels, glReadPixels, glTex!magelD oraz glTexImage2D.
Plik nagwkowy
Skadnia void glPixelTransferi(GLenum pname, GLint param); void
glPixelTransferf(GLenum pname, GLfloat param);
Opis Ta funkcja ustala opcje i tryb przenoszenia pikseli dla funkcji
glCopyPixels, glDrawPixels, glReadPixels, glTexImagelD oraz
glTex!mage2D.
Parametry
pname GLenum: Parametr do ustawienia. Dostpne s ponisze wartoci:
GL_MAP_COLOR Gdy ustawiony na GLJTRUE, wcza pixmapy
zdefiniowane funkcj glPixelMap dla indeksw kolorw i wartoci
RGBA.
GL_MAP_STENCIL Gdy ustawiony na GLJTRUE, wcza pixmapy
zdefiniowane funkcj glPixelMap dla wartoci szablonu.
nGL Rozdzia 11. * Grafika rastrowa 383

GL_INDEX_SHIFT Okrela wielko bitowego przesunicia indeksw


kolorw. Wartoci dodatnie przesuwaj indeksy w lewo, wartoci dodatnie -
w prawo.
GL_INDEX_OFFSET Okrela warto, jaka zostanie dodana do kadego
indeksu koloru.
GL_RED_SCALE Okrela zmiennoprzecinkowy wspczynnik
skalowania dla czerwonej skadowej koloru.
GL_RED_BIAS Okrela warto dodawan do kadej czerwonej
skadowej koloru.
GL_GREEN_SCALE Okrela zmiennoprzecinkowy wspczynnik
skalowania dla zielonej skadowej koloru.
GL_GREEN_BIAS Okrela warto dodawan do kadej zielonej
skadowej koloru.
GL_BLUE_SCALE Okrela zmiennoprzecinkowy wspczynnik
skalowania dla niebieskiej skadowej koloru.
GL_BLUE_BIAS Okrela warto dodawan do kadej niebieskiej
skadowej koloru.
GL_ALPHA_SCALE Okrela zmiennoprzecinkowy wspczynnik
skalowania dla wartoci alfa.
GL_ALPHA_BIAS Okrela warto dodawan do kadej wartoci alfa.
GL_DEPTH_SCALE Okrela zmiennoprzecinkowy wspczynnik
skalowania dla wartoci bufora gbokoci.
GL_DEPTH_BIAS Okrela warto dodawan do kadej wartoci bufora
gbokoci.
param GLint, GLfloat: Warto parametru.
Zwracana warto Brak.
Przykad Patrz Przejrzyj kod programu OGLYIEW.C
take glCopyPixels, glDrawPixels, glPixelMap, glReadPixels, glTex!magelD,
glTex!mage2D

glPixelZoom
Przeznaczenie Okrela skal przy rysowaniu obrazka.
Plik nagwkowy
Skadnia Opis void glPixelZoom(GLfloat xfactor, GLfloat yfactor);
Ta funkcja ustala wspczynniki skalowania dla funkcji glCopyPixels,
glDrawPixels, glReadPixels, glTex!magelD oraz glTex!mage2D.
W przypadku odczytu obrazu z pamici lub bufora ramki, piksele s
skalowane przy uyciu algorytmu najbliszy ssiad". W przypadku funkcji
glCopyPixels i glDrawPixels, przeskalowane piksele s rysowane
384 Cz II Uywanie OpenGL

w buforze ramki w miejscu okrelonym biec pozycj rastra.


W przypadku funkcji glReadPixels, piksele s zapisywane do wskazanego
bufora w pamici. Podczas odczytu powikszonego obrazka, jego rozmiar
powiniene obliczy nastpujco:
int nowa_wysokosc, nowa_szerokosc;
int szeroko, wysoko;
nowa_szerokosc = xfactor * szeroko + 0 . 5 ;
nowa_wysokosc = yfactor * wysoko + 0.5;

Parametry
xfactor GLfloat: Wspczynnik skalowania w poziomie (1,0 oznacza brak
skalowania).
yfactor GLfloat: Wspczynnik skalowania w pionie (1,0 oznacza brak
skalowania).
Zwracana warto Brak.
Przykad Patrz Przejrzyj kod programu OGLYIEW.C
take glCopyPixels, glDrawPixels, glReadPixels, glTex!magelD,
glTex!mage2D

glReadPixels
Przeznaczenie Odczytuje blok pikseli z bufora ramki.
Plik nagwkowy
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
format, GLenum type, const GLvoid *pixels);
Skadnia
Ta funkcja kopiuje dane pikseli z bufora ramki do pamici. Poza argumentami
format i type, na kodowanie pikseli i przetwarzanie ich przed umieszczeniem w
Opis pamici wpywa take kilka innych parametrw. Zajrzy] do opisu funkcji
glPixelMap, glPixelStore oraz glPixelTransfer.
Parametry GLint: Pozioma wsprzdna lewego dolnego rogu obszaru obrazu. GLint:
x Pionowa wsprzdna lewego dolnego rogu obszaru obrazu. GLsizei: Szeroko
y obrazu w pikselach. GLsizei: Wysoko obrazu w pikselach.
GLenum: Przestrze kolorw odczytywanych pikseli. Dostpne s ponisze
width
wartoci:
height
GL_COLOR_INDEX Piksele indeksu koloru GL
format LUMINANCE Piksele skali szaroci
Rozdzia 11. Grafika rastrowa 385

GL_LUMINANCE_ALPHA Skala szaroci + piksele alfa (dwa


komponenty)
GL_RGB Piksele RGB (trzy komponenty)
GL_RGBA Piksele RGBA (cztery komponenty)
GL_RED Piksele czerwieni
GL_GREEN Piksele zieleni
GL_BLUE Piksele niebieskiego
GL_ALPHA Piksele kanau alfa
GL_STENCIL JNDEKS Wartoci bufora szablonu
GL_DEPTH_COMPONENT Wartoci bufora gbokoci
type GLenum: Typ danych, ktre maj zosta skopiowane. Dostpne s
ponisze wartoci:
GL_BYTE 8-bitowe wartoci ze znakiem (od -128 do 127)
GL_UNSIGNED_BYTE 8-bitowe wartoci bez znaku (od O do 255)
GL_BITMAP Obraz bitmapy (od O do l) GL_SHORT 16-bitowe
wartoci ze znakiem (od -32 768 do 32 767)
GL_UNSIGNED_SHORT 16-bitowe wartoci bez znaku (od O do 65
535)
GLJNT 32-bitowe wartoci ze znakiem (od -2 147 483 648 do 2
147 483 647)
GL_UNSIGNED_INT 32-bitowe wartoci bez znaku (od O do 4 294
967 295)
GL_FLOAT 32-bitowe wartoci zmiennoprzecinkowe (GLfloat)
pbcels GLvoid*: Wskanik do bufora na dane obrazu.
Zwracana warto Brak.
Znane bdy Obecnie parametr GL_PACK_ALIGNMENT funkcji glPixelStore jest
ignorowany przez funkcj glReadPixels.
Przykad Przejrzyj kod programu BITMAP.C
Patrz take glPixelMap, glPixelStore, glPixelTransfer
Rozdzia 12.
Mapowanie tekstur
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Owija obrazki na wieloktach * glTexImagelD/glTexImage2D
(mapowanie tekstur)
* Uywa plikw .BMP jako tekstur * TextureLoadBitmap/TextureLoadMipmap
* Uywa automatycznej generacji * glTexGen
wsprzdnych tekstur

Mapowanie tekstur stanowi chyba najwikszy postp grafiki komputerowej w cigu


ostatnich kilku lat. OpenGL posiada funkcje mapowania tekstur, umoliwiajce nakadanie
obrazw na wielokty w scenie. O tym, jak te obrazy zostan naoone, decydujesz
wycznie ty.

Mapowanie tekstur jest stosowane w grach, wcznie z gr DOOM, w celu uzyskania


realistycznych obrazw pomieszcze i potworw. W odrnieniu od OpenGL, w tych
grach tekstury nakadane s metod tzw. raycastingu. Cho w przypadku standardo-
wych kart 2D raycasting jest duo szybszy ni techniki nakadania stosowane w OpenGL,
ogranicza si jednak do paskich powierzchni w dwuwymiarowej paszczynie, tzn.
przy jego uyciu nie mona spoglda w gr i w d. Mapowanie tekstur w OpenGL
nie ma tych ogranicze, lecz na standardowych kartach graficznych dziaa duo wolniej.
Dobr wiadomoci jest to, e nowe, stosunkowo tanie karty z akceleratorami 3D,
sprztowo wspieraj OpenGL i nakadanie tekstur. Gdy karta sprztowo wspiera mapo-
wanie tekstur, procesor nie musi zajmowa si obliczeniami zwizanymi z przygotowaniem
i nakadaniem obrazw - wszystkim zajmuje si karta graficzna.

Przykady w tym rozdziale dziaaj na wszystkich kartach graficznych zgodnych z Win-


dows. Jeli twoja karta obsuguje 16- lub 24-bitowe tryby graficzne, powiniene uywa
wanie ich. Poza lepszym wygldem scen, okazuje si, e w trybach 16- i 24-bitowych
nakadanie tekstur przebiega szybciej.
388____________________________________Cz II Uywanie OpenGL

Podstawy nakadania tekstur


Nakadanie tekstur w OpenGL jest do proste. Na pocztku moemy stwierdzi, e
kada tekstura jest jakim obrazkiem.
Tekstura ID (jednowymiarowa) jest obrazkiem nieposiadajcym wysokoci lub szero-
koci; tekstury ID to obrazki w postaci paska o szerokoci lub wysokoci jednego pi-
ksela. By moe sdzisz, e takie tekstury nie s zbyt uyteczne, ale w rzeczywistoci
mog zastpi bardziej konwencjonalne techniki kolorowania i cieniowania, przy tym
znacznie przyspieszajc proces renderowania! Rysunek 12.1 przedstawia jednowymiarow
tekstur ROY-G-BIV" (Red, Orange, Yellow - Green - Blue, Indigo, Yiolet) uyt do
wywietlenia tczy. Obrazek tej tekstury to pasek pikseli (wartoci kolorw)
pokrywajcy spektrum kolorw w tczy. Odpowiadajca temu scena nie korzystajca z
tekstury zawieraaby siedem razy wicej wieloktw i wymagaaby duo wicej czasu do
wyrenderowania.

Rysunek 12.1.
Tcza stworzona za pomoc
jednowym iarowej tekstury

Tekstura 2D
(dwuwymiarowa)
to obrazek szerszy i
wyszy ni jeden
piksel; zwykle jest
adowana z pliku
.BMP Windows.
Tekstury 2D s
powszechnie
uywane w celu
zastpienia powierzchni o skomplikowanej geometrii (mnstwie wieloktw),
budynkw, drzew itd. Tekstury 2D s uywane take w celu stworzenia realistycznego ta,
na przykad chmur na niebie, pokazanych na rysunku 12.2.
Uyte przez nas jedno- i dwuwymiarowe tekstury skaday si z wartoci koloru RGB.
Tekstury mog by tworzone take z indeksw kolorw lub poziomw szaroci (lumi-
nancji), mog take zawiera wartoci alfa (przezroczystoci). Te ostatnie s uyteczne
przy definiowaniu naturalnych obiektw, takich jak drzewa, gdy warto alfa moe
by uyta do uczynienia drzewa widocznym, a jednoczenie umoliwi przewitywanie ta.
Nauczymy si tego w rozdziale 16.
Niektre karty obsuguj w OpenGL take tekstury trjwymiarowe (wolumetryczne).
Tekstury wolumetryczne s uywane w rnych aplikacjach skanerw" trzeciego wy-
miaru. Niestety, maa tekstura 256 x 256 x 256 pikseli w skali szaroci zajmuje cae 16
MB pamici.
Rozdzia 12. * Mapowanie tekstur 389

Rysunek 12.2.
Dwuwymiarowa
tekstura imitujca
niebo

Cho obecnie stanowi rozszerzenie, by moe teksturowanie 3D bdzie obowizkowym


elementem specyfikacji OpenGL 1.1.

Definiowanie obrazw tekstur


Oczywicie, zanim zaczniesz rysowa wielokty, musisz w jaki sposb zdefiniowa te-
kstur. Obrazy tekstur s przechowywane tak samo jak bitmapy (omawiane w rozdziale 11 .)

Uwaga na temat obrazw tekstur


Standard OpenGL wymaga, aby rozmiary obrazw tekstur
odpowiaday potgom liczby 2. Obrazy tekstur mog posiada
take jeden lub dwa piksele ramki dookoa krawdzi,
okrelajce kolor wieloktw poza obrazem tekstury.

Definiowanie tekstur ID
W OpenGL do definiowania jednowymiarowych tekstur suy pojedyncza funkcja:
glTex!magelD. Funkcja wymaga przekazania omiu argumentw:
void glTexImagelD(GLenum target, GLint level, GLint components,
GLsizei width, GLint border, GLenum format,
GLenum type, const GLvoid *pixels)

Argument target okrela, ktra tekstura powinna zosta zdefiniowana; musi nim by
GL_TEXTURE_1D. Argument level wskazuje poziom szczegw obrazu tekstury i
zwykle wynosi 0. Inne wartoci s uywane przy tekturach typu mipmap (opisywanych
w dalszej czci rozdziau). Argument components okrela ilo wartoci koloru uytych
dla kadego piksela. W przypadku tekstur z indeksami kolorw, t wartoci musi by l.
Wartoci 3 i 4 s uywane, odpowiednio, dla obrazw tekstur RGB i RGB A.
390 Cz II Uywanie OpenGL

Argumenty width i border okrelaj rozmiar obrazu tekstury. Warto border okrela
ilo pikseli ramki, ktrych OpenGL moe oczekiwa (i uywa) i moe mie warto O, l
lub 2. Parametr width okrela szeroko gwnego obrazu tekstury (bez pikseli ramki) i musi
stanowi potg liczby 2.

Argument format wskazuje rodzaj wartoci koloru w teksturze - GL_COLOR_INDEX,


GLJJUMINANCE, GL_RGB lub GL_RGBA.

Przykad definiowania jednowymiarowej tekstury znajdziesz na listingu 12.1; ten kod


pochodzi z programu TEX1D na pytce CD-ROM.

Listing 12.1. Definiowanie jednowymiarowej tekstury____

void
LoadAllTextures( v o i d )
{
static unsigned char roygbiv_image[ 8 ] [ 3 ] =
{ Ox3f, 0x00, Ox3f t, Ciemny fiolet (dla 8 k o l o r w . . . ) */
{ Ox7f, 0x00, Ox7f ;, Fiolet */
{ Oxbf, 0x00, Oxbf }, Indy go */
{ 0x00, 0x00, Oxff }, Bkit */
{ 0x00, Oxff, 0x00 }, Ziele */
{ Oxff, Oxff, 0x00 },
{ Oxff, Ox7f, 0x00 }, */
{ Oxff, 0x00, 0x00 } * P
/ o
m
aracz
Czerwie

glNewList(RainbowTexture = glGenLists( 1 ) , GL_COMPILE);


glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ,
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ,
glTex!magelD(GL_TEXTURE_lD, O, 3, 8, O, GL_RGB, roygbiv_image);
GL_UNSIGNED_BYTE,
glEndList O;

Ten przykadowy kod tworzy list wywietlania zawierajc obraz tekstury oraz dany
filtr powikszania i pomniejszania, GL_LINEAR. Filtr pomniejszania jest uywany,
gdy rysowany wielokt jest mniejszy ni obraz tekstury, w tym przypadku 8 pikseli.
Filtr powikszania jest uywany, gdy wielokt jest wikszy ni obraz tekstury. Stosujc
filtr GL_LINEAR, informujemy OpenGL, e przed narysowaniem czegokolwiek na
ekranie, wartoci kolorw obrazu tekstury powinny zosta liniowo zinterpolowane. Inne
filtry, ktrych moesz uy jako parametru GL_TEXTURE_MIN_FILTER, zostay zebrane
w tabeli 12.1.

Filtr GL_NEAREST zamiast interpolowa wartoci kolorw pikseli, pobiera najbliszy


piksel obrazu tekstury. Filtrowaniem tekstur zajmiemy si w dalszej czci rozdziau.
Rozdzia 12. Mapowanie tekstur_________________________________393^

Tabela 12.1.
Filtry obrazu tekstury

Filtr______________________Opis___________________________
GL_NEAREST Filtrowanie najbliszy ssiad"
GLJJNEAR Liniowa interpolacja
GL_NEAREST_MIPMAP_NEAREST Filtr mipmapy najbliszy ssiad"
GL_NEAREST_MIPMAP_LINEAR Liniowo interpolowana mipmapa
GL_LINEAR_MIPMAP_NEAREST Liniowa interpolacja mipmap
GL_LINEAR_MIPMAP_LINEAR Liniowa interpolacja interpolowanych mipmap

Definiowanie tekstur 2D
W celu zdefiniowania dwuwymiarowej tekstury naley wywoa funkcj glTex!mage2D. Ta
funkcja, oprcz argumentw przekazywanych funkcji glTex!magelD, wymaga dodatkowo
podania argumentu height (wysoko):
void glTex!mage2D(GLenum target, GLint level, GLint components,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels)

Podobnie jak w przypadku funkcji glTex!magelD, argumenty width i height musz by


potgami liczby 2.

Listing 12.2 zawiera przykad adowania obrazu tekstury zachmurzonego nieba Listing

12.2. Definiowanie tekstury 2D______________________________________

void
LoadAllTextures(void)
{
BITMAPINFO *info; /* Nagwek bitmapy */
void *bits; /* Dane bitmapy */
GLubyte *rgb; /* Piksele RGB bitmapy */
/*
* Prba zaadowania bitmapy i zamiany jej na R G B . . .
*/

bits = LoadDIBitmap("sky.bmp", Sinfo); if


(bits == NULL) return;
rgb = ConvertRGB(info, bits);
if (rgb == NULL)
(
free(info) ;
free(bits) ;
return;
392 Cz II Uywanie OpenGL

glNewList(SkyTexture = glGenLists( 1 ) , GL_COMPILE) ;


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

/*
* Definiowanie obrazu tekstury 2D
*/
/* Wymuszenie wyrwnania do 4 bajtw */
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) ;

glTex!mage2D(GL_TEXTURE_2D, O, 3, info->bmiHeader.biwidth,
info->bmiHeader.biHeight, O, GL_RGB, GL_UNSIGNED_BYTE, rgb);
glEndList() ;

* Zwolnienie bitmapy i obrazw RGB,


* Zwrcenie wartoci O (bez bdu)
*/
free( r g b ) ;
free( i n f o ) ;
free( b i t s ) ;

Uwaga na temat tekstur


Jak si przekonasz, we wszystkich przykadach w tym
rozdziale do przechowywania obrazw tekstur wykorzystuje
si listy wywietlania. Listy wywietlania przyspieszaj
dziaanie statycznych polece graficznych, co dotyczy take
obrazw tekstur. Dodatkowo, w nadchodzcym API OpenGL
1.1 zoptymalizowano obsug tekstur przechowywanych na
listach wywietlania przez umieszczenie ich, jeli to moliwe,
w pamici karty graficznej.

Rysowanie wieloktw z
naoon tekstur
Gdy ju zdefiniujesz tekstur, musisz jeszcze wczy teksturowanie. Aby wczy te-
ksturowanie ID, uyj poniszego kodu:
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_1D);
glTexEnvi(GL_TEXTURE_ENW, GL_TEXTORE_ENW_MODE, GL_DECAL);
Rozdzia 12. Mapowanie tekstur_________________________________393

Wywoanie glEnable wcza teksturowanie ID. Jeli zapomnisz wczy teksturowanie,


tekstura nie zostanie naoona na aden z wieloktw! Funkcja glTexEnvi ustawia te-
ksturowanie w tryb kafelkw", co oznacza, e tekstury zostan naoone na wielokty jak
kafelki.
Inne tryby teksturowania zostay zebrane w tabeli 12.2.

Tabela 12.2.
Tryby teksturowania dla parametru GL_TEXTURE_ENV_MODE

Tryb Opis
GL_MODULATE Piksele tekstury filtruj" kolory istniejcych pikseli na ekranie.
GL_DECAL Piksele tekstury zastpuj istniejce piksele na ekranie.
GL_BLEND Piksele tekstury filtruj" kolory istniejcych pikseli na ekranie, bdc
przy tym
czone ze staym kolorem.

W trybie teksturowania GL_MODULATE biecy kolor piksela tekstury (lub jego


luminancja) s mnoone przez kolor piksela na ekranie. W przypadku tekstur z jednym
komponentem (luminancji), powoduje to otrzymanie filtra jasnoci, zmieniajcego jasno
pikseli na ekranie w zalenoci od obrazu tekstury. W przypadku tekstur z trzema
komponentami (RGB), moesz generowa efekt kolorowych soczewek".
W odrnieniu od teksturowania GL_MODULATE, teksturowanie w trybie GL_BLEND
umoliwia poczenie sceny ze staym kolorem, na podstawie obrazu tekstury. Trybu
GL_BLEND bdziesz uywa zwykle przy rysowaniu obiektw takich jak chmury; staym
kolorem bdzie biel, za obrazem tekstury bdzie chmura.
Gdy zdefiniujesz tryb teksturowania, moesz przej do rysowania wieloktw. Listing
12.3 przedstawia sposb rysowania tczy z rysunku 12.1.

Listing 12.3. Rysowanie tczy za pomoc tekstury J D__________________

glEnable(GL_TEXTURE_1D);
glCallList(RainbowTexture);
glBegin(GL_QUAD_STRIP);
for (th = 0 . 0 ; th <= M_PI; th += (0.03125 * M_PI
{
// Dolna krawd tczy

x = cos( t h ) * 5 0 . 0 ; y
= si n ( th ) * 5 0 . 0 ; z =
-50.0;
glTexCoordlf( 0 . 0 ) ;
glVertx3f( x , y, z);

// Grna krawd tczy

x = cos( t h ) * 5 5 . 0 ;
y = sin(th) * 5 5 . 0 ;
z = -50.0;
394 Cz II * Uywanie OpenGL

glTexCoordlf ( 1 . 0 ) ;
glVertex3f ( x , y, z ) ;
glEnd ( ) ;

Aby umieci tekstur na tczy, wywoalimy funkcj glTexCoord. W przypadku tekstur


ID, moesz wywoa jedn z funkcji: glTexCoordlf, glTexCoordld, glTexCoords lub
glTexCoordli. Warto 0,0 reprezentuje piksel po lewej stronie obrazu, za warto 1,0
reprezentuje piksel po prawej stronie. Wartoci spoza zakresu s interpretowane rnie,
zalenie od wartoci parametru GL_TEXTURE_WRAP_S. Jeli ten parametr ma warto
GL_CLAMP (domyln), wsprzdne tekstury s ograniczone do zakresu od 0,0 do 1,0
wcznie. Gdy wielokt wystaje poza obraz tekstury, jest rysowany w kolorze (kolorach)
krawdzi obrazu tekstury (patrz rysunek 12.3) lub w kolorze pikseli ramki tekstury, jeli
jest zdefiniowana. Wsprzdne tekstur tradycyjnie okrela si jako S i T lub (s, t) zamiast
X i Y.

Rysunek 12.3. Obszar poczenia


Tekstury GL
CLAMP

Jeli natomiast uyjesz wartoci GL_REPEAT, obraz tekstury zostanie powtrzony na


powierzchni wielokta. Wsprzdne tekstury s uywane modulo l ,0 - to znaczy, e
tekstura powtarza si w regularnych odstpach. Teksturowania GL_REPEAT mona
uy w celu zredukowania rozmiarw obrazw tekstur na powtarzalnych powierzchniach.
Wyzwaniem przy tego rodzaju teksturach jest zapewnienie, by krawdzie jednego kafelka
idealnie pokryway si z krawdziami nastpnego.

Automatyczne generowanie wsprzdnych tekstury


Generowanie wsprzdnych tekstur moe by bardzo
nucym zadaniem. W dalszej czci rozdziau poznasz
funkcj glTexGen, automatycznie generujc wsprzdne
tekstur.

Mipmapy
Dotychczas posugiwalimy si jedynie obrazami z pojedynczymi teksturami. To znaczy,
przy kadym rysowaniu wielokta posugiwalimy si pojedynczym jedno- lub
dwuwymiarowym obrazem. W przypadku wikszoci scen to w zupenoci wystarcza,
jednak w scenach animowanych czsto potrzebny jest zmienny poziom szczegw,
Rozdzia 12. Mapowanie tekstur 395

w zalenoci od odlegoci wielokta od obserwatora. Na przykad, podczas spacero-


wania po wirtualnym pokoju mgby zastosowa obraz w wysokiej rozdzielczoci przy
patrzeniu na niego z bliska i jedynie szkic obrazu, przy patrzeniu na niego z daleka.

OpenGL obsuguje tekstury zawierajce wiele obrazw, zwanych mipmapami. Przy sto-
sowaniu mipmapowania wybierany jest obraz tekstury najbliszy rozmiarowi wielokta na
ekranie. adowanie mipmap trwa nieco duej ni zwykych tekstur, ale efekty wizualne
robi wraenie. Dodatkowo, mipmapy mog poprawi wydajno renderowania, gdy
zmniejszaj konieczno stosowania filtru GL_LINEAR.

Co oznacza mip" w sowie mipmap?


Sowo mip" to po acinie wiele". Tak wic mipmapping"
oznacza wiele obrazw".

Mipmapy definiuje si przez okrelenie specyficznego parametru level dla kadego z


obrazw tekstury. W przypadku naszej tekstury ROY-G-BIY z poprzedniego przykadu,
mgby uy poniszego kodu:
static unsigned char roygbiv_imageO[ 1 6 ] [ 3 ] ;
static unsigned char roygbiv_imagel[ 8 ] [ 3 ] ;
static unsigned char roygbiv_image2[ 4 ] [ 3 ] ;
static unsigned char roygbiv_image3[ 2 ] [ 3 ] ;
static unsigned char roygbiv_image4[ 1 ] [ 3 ] ;
glNewList(RainbowTexture = glGenLists( 1 ) , GL_COMPILE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ;
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_LINEAR);

glTex!magelD(GL_TEXTURE_lD, O, 3, 1 6 , O, GL_RGB, GL_UNSIGNED_BYTE,


roygbiv_imageO); glTexImagelD(GL_TEXTURE_lD, l, 3, 8,
O, GL_RGB, GL_UNSIGNED_BYTE,
roygbiv_imagel); glTexImagelD(GL_TEXTURE_lD, 2, 3, 4,
O, GL_RGB, GL_UNSIGNED_BYTE,
roygbiv_image2); glTexImagelD(GL_TEXTURE_lD, 3, 3, 2,
O, GL_RGB, GL_UNSIGNED_BYTE,
roygbiv_image3); glTexImagelD(GL_TEXTURE_lD, 4, 3, l,
O, GL_RGB, GL_UNSIGNED_BYTE,
roygbiv_image4);
glEndList();

Poziom obrazu jest okrelany jako drugi parametr funkcji glTexImagelD(). Obraz o po-
ziomie O to obraz podstawowy tekstury, o najwyszej rozdzielczoci. Obraz o poziomie l
ma poow rozmiaru obrazu podstawowego, itd. Rysujc wielokty za pomoc
bitmap, powiniene uy jednego z filtrw zmniejszania (GL_TEXTURE_MIN_FIL-
TER) z tabeli 12.3.
396_______________________________________Cz II Uywanie OpenGL

Tabela 12.3.
Filtry zmniejszania

Filtr___________________Opis______________________________
GL_NEAREST_MIPMAP_NEAREST Uywa obrazu najbliszego pod wzgldem rozmiaru
do
wielokta na ekranie. Przy teksturowaniu tego obrazu
stosuje filtr GL_NEAREST.
GL_NEAREST_MIPMAP_L1NEAR Uywa obrazu najbliszego pod wzgldem
rozmiaru do
wielokta na ekranie. Przy teksturowaniu tego obrazu
stosuje filtr GL_LINEAR.
GL_LINEAR_MIPMAP_NEAREST Liniowo interpoluje pomidzy dwoma obrazami
najbliszymi
pod wzgldem rozmiaru do wielokta na
ekranie. Przy teksturowaniu tego obrazu stosuje
filtr GL_NEAREST.
GL_LINEAR_MIPMAP_LINEAR Liniowo interpoluje pomidzy dwoma obrazami
najbliszymi
pod wzgldem rozmiaru do wielokta na
ekranie. Przy teksturowaniu tego obrazu stosuje
filtr GL_LINEAR.

Filtry GL_LINEAR_MIPMAP_NEAREST oraz GL_LINEAR_MIPMAP_LINEAR mog


by bardzo drogie w sensie obnienia wydajnoci. Filtr GL_NEAREST_ MIP-
MAP_NEAREST wydajnoci odpowiada mniej wicej filtrowi GL_NEAREST, lecz
zwykle daje duo lepsze rezultaty. Obrazy z mipmapy s wybierane przez porwnanie
rozmiaru wielokta na ekranie z rozmiarami obrazw w mipmapie.

Aby uatwi ci nieco ycie, biblioteka narzdziowa OpenGL (GLU32.LIB) zawiera dwie
funkcje automatycznie generujce mipmapy na podstawie pojedynczej tekstury o wysokiej
rozdzielczoci. W poniszym kodzie, funkcje gluBuildlDMipmaps oraz gluBuild2-
DMipmaps zajmuj miejsce funkcji glTex!magelD i glTex!mage2D:
// Tekstura ID

glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_LINEAR);
gluBuildlDMipmaps(GL_TEXTURE1D, 3, 8, O, GL_RGB, GL_UNSIGNED_BYTE,
roygbiv_image);

// Tekstura 2D

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTDRE_MIN_FILTER,
GL_NEAREST_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE2D, 3, info->bmiHeader.biwidth,
info->bmiHeader.biHeight, O, GL_RGB,
GL_UNSIGNED_BYTE, rgb);

Poniewa funkcje gluBuildlDMipmaps i gluBuildlDMipmaps tworz obrazy z jednego,


podstawowego obrazu, wygld pewnych obrazw w mniejszych rozdzielczociach moe
nie by najlepszy. Przypomina to rysowanie znakw tekstu w rnych rozdzielczociach
- przeskalowanie bitmapy nie zawsze daje dobrze wygldajce rezultaty! Gdy natrafisz na
tego rodzaju problem, utwrz mipmap rcznie.
Rozdzia 12. * Mapowanie tekstur_________________________________397

Program ogldania terenu


Naszym projektem w tym rozdziale bdzie program ogldania terenu, korzystajcy z
pewnych omawianych technik nakadania tekstur. W tym programie zamierzamy osign
nastpujce cele:
* Ogldanie scen obrazujcych teren;
* Interaktywn edycj terenu w trjwymiarowej scenie;
+ Przelot nad terenem;
* Wydruk biecej sceny;
* Zapisanie biecej sceny do pliku .BMP.

Kod caego programu zosta przedstawiony na kocu rozdziau, tu przed sekcj po-
drcznika. Kopia programu znajduje si na pytce CD-ROM, w folderze tego rozdziau.
Dwukrotnie kliknij na ikon programu TEXSCENE.EXE i sam sprawd, jak dziaa!

Definiowanie terenu
W celu zachowania prostoty, nasz teren zdefiniujemy jako siatk punktw wysoko-
ciowych z dodatkow informacj o teksturze, tak jak to jest woda" czy to jest gra".
Kady punkt siatki bdzie take posiada odpowiedni normaln, w celu zachowania
realistycznego owietlenia.
#define TERRAIN_SIZE 21

int TerrainType[TERRAIN_SIZE][TERRAIN_SIZE];
GLfloat TerrainHeight[TERRAIN_SIZE][TERRAIN_SIZE];
GLfloat TerrainNormal[TERRAIN_SIZE][TERRAIN_SIZE][ 3 ] ;

Tablica TerrainType zawiera rodzaj terenu w kadym punkcie, czyli jeden z poniszych
identyfikatorw kontrolek z pliku definicji zasobw:
IDC_GRASS Trawa
IDC_WATER Woda
IDCJTREES Drzewa
IDC_ROCKS Skay
IDC_MOUNTAINS Gry

Rysowanie terenu
Na kontrolki rysowania terenu skada si okno dialogowe z paskiem narzdzi, zawiera-
jcym pi przyciskw sucych do wybierania rodzaju terenu. Aby narysowa teren, po
prostu kliknij i przecignij przycisk do gwnego okna (rysunek 12.4).
398 Cz II * Uywanie OpenGL

Rysunek 12.4.
Okno edycji terenu

Serce interfejsu rysowania znajduje si w funkcji DrawTerrain. Uywamy w niej mecha-


nizmu selekcji OpenGL w celu wyznaczenia punktw terenu, lecych pod wskanikiem
myszy. Zamiast rysowa teren na ekranie, renderowanie selekcji rejestruje trafienia"
wewntrz obszaru selekcji (w tym przypadku wskanika myszy) do wskazanego bufora. W
funkcji DrawTerrain rejestrujemy pooenie (x, y) terenu w buforze selekcji, tak jak w
dziecicej kolorowance, wedug numerkw (rysunek 12.5). Selekcje w OpenGL zostan
szerzej omwione w rozdziale 19.

Rysunek 12.5. J.
Wybr komrki
terenu

Gdy znamy pooenie (x, y) terenu, w funkcji draw_cell ustalamy wysoko i typ jego
punktw (listing 12.4).

Listing 12.4. Funkcja draw_cell_______________

void
draw_cell (int x, /* We - Pooenie terenu X */
int y) /* We - Pooenie terenu Y */ { /*
* Sprawdzenie zakresu terenu
*/
if (x < O X >= TERRAIN_SIZE |
y < O y >= TERRAIN_SIZE)
return;
Rozdzia 12. * Mapowanie tekstur 399

if (TerrainType[ y ] [ x ] == TerrainCurrent)
return; /* Ju jest poprawnego typu */
TerrainType[ y ] [ x ] = TerrainCurrent;

Wymuszenie odwieenia o k n a . . .

InvalidateRect(SceneWindow, NULL, TRUE);

Ustawienie wysokoci "komrki" terenu. Dla wody wysoko jest


staa, WATER_HEIGHT. Dla innych typw dodajemy losowe
odchylenie w celu uzyskania realistycznego obrazu.

switch (TerrainCurrent) {
case IDC_WATER :
TerrainHeight [ y ] [ x ] = WATER_HEIGHT;
break; case
IDC_GRASS :
TerrainHeight [ y ] [ x ] = GRASS_HEIGHT + O.lf * ( r a n d ( ) % 5 ) ;
break; case
IDC_TREES :
TerrainHeight [y] [ x ] = TREES_HEIGHT + 0.1 * (randf) % 5) ;
break; case
IDC_ROCKS :
TerrainHeight [ y ] [ x ] = ROCKS_HEIGHT + O . l f * ( r a n d ( ) % 5 ) ;
break; case
IDC_MOUNTAINS :
TerrainHeight [ y ] [ x ] = MOUNTAINS_HEIGHT + 0 . 1 5 f * ( r a n d ( ) % 5) ;
break;

Wysoko punktw terenu typu IDC_WATER (wody jest ustawiana po prostu na WA-
TER_HEIGHT (wysoko wody, 0,0). Dla innych typw terenu dodajemy przypadkow
warto odchylenia, dziki czemu teren wyglda bardziej realistycznie. Gdy wybrana
komrka zostanie narysowana, na podstawie nowych wysokoci, za pomoc funkcji
UpdateNormals przeliczamy normalne. Kada normalna jest obliczana przy uyciu punktw
powyej i na prawo od biecego punktu, wedug poniszego wzoru:
N = normalna
H = wysoko biecego punktu
Hu = wysoko punktu powyej Hr
= wysoko punktu na prawo
Nx = ( H r - H) / | N |
Ny = l / |N|
Nz = ( H u - H) / | N |

To po prostu uproszczone obliczanie iloczynu wektorowego dla przystajcych komrek


siatki terenu. Gdy zostan przeliczone wszystkie normalne, ekran jest odrysowywany.
400 Cz II Uywanie OpenGL

Rysowanie sceny
Gdy zajlimy si ju obowizkow prac, moemy skoncentrowa si na wywietlaniu
terenu. Pamitajmy, e oprcz wywietlania adnego teksturowanego obrazka, chcemy
take polata nad terenem. Aby to osign, musimy rysowa teren bez teksturowania -
gwnie dlatego, e teksturowanie na zwykym komputerze PC przebiega zbyt wolno jak
na potrzeby animacji. Gdy uytkownik nie lata (i nie rysuje terenu), zastosujemy
teksturowanie. Zadbamy o to za pomoc paru linii warunkowych i kilku parametrw
owietlenia.
Ponadto, poniewa rysowanie teksturowanej sceny przebiega wolniej ni podczas przelotu
nad scen, sprbujemy w jaki sposb wskaza uytkownikowi, e program cokolwiek robi.
Dla uproszczenia, podczas teksturowania bdziemy rysowa po prostu w przednim buforze
(widocznym), za podczas lotu lub rysowania - w tylnym (niewidocznym). W ten sposb,
gdy program bdzie aktualizowa teksturowan scen, uytkownik bdzie widzia postpy
w rysowaniu. Wicej informacji na temat buforw znajdziesz w rozdziale 15.
Funkcja RepaintWindow obsuguje odrysowywanie terenu. Rozpoczyna od wybrania
przedniego lub tylnego bufora (jak wspominalimy powyej). Nastpnie czyci bity koloru
i gbokoci:
glViewport( O , O, rect->right, rect->bottom);

glClearColor( 0 . 5 , 0 . 5 , 1 . 0 , 1 . 0 ) ;

glEnable(GL_DEPTH_TEST);

if (Moving || Drawing) {
glDisable(GL_TEXTURE_2D);
glDrawBuffer(GL_BACK) ;
}
else
{
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glDrawBuffer(GL_FRONT); };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Nastpnie jest rysowane niebo. Ze wzgldu na wydajno, niebo jest rysowane tylko
wtedy, gdy uytkownik nie lata i nie rysuje terenu. Poniewa to jest czyszczone ko-
lorem jasnoniebieskim, nie ma z tym wikszego problemu. Niebo ma ksztat piramidy z
naoon tekstur SKY.BMP. przedstawiajc przyjemne, lekko zachmurzone niebo.
Po narysowaniu nieba, funkcja RepaintWindow zaczyna rysowa teren. Uyty algorytm jest
bardzo prosty i polega na generowaniu paskw czworoktw (kwadratw) wzdu
punktw terenu. Kady pasek uywa innej tekstury lub materiau, wic dla kadego z
nich musimy uy pary funkcji glBegin/glEnd. Graficzny opis tego algorytmu przedstawia
rysunek 12.6.
Rozdzia 12. Mapowanie tekstur_________________________________401

Rysunek 12.6.
Algorytm rysowania terenu

Jak wida, algorytm nie


ledzi terenu dokadnie,
jednak jest szybki i prosty
w implementacji.
Przeglda teren od lewej do
prawej strony, od gry do
dou, zaczynajc nowy prymityw GL_QUAD_STRIP za kadym razem, gdy zmienia si
typ terenu. Po drodze ustala normaln i wsprzdn tekstury dla kadego punktu terenu.

Automatyczne generowanie wsprzdnych tekstur


Generowanie wszystkich tych wsprzdnych tekstur moe by bardzo mudne. Na
szczcie, OpenGL ma dla nas rozwizanie! W kodzie rysunkowym zawarlimy wywoania
funkcji glTexCoord2i:
glTexCoord2i(x * 2, y * 2 ) ;

dla kadego punktu terenu. Jednak zamiast robi to dla kadego punktu, moemy uy
funkcji glTexGen w celu zdefiniowania wsprzdnych S i T oznaczajcych pooenie X
i Z w scenie (Y jest uywane do okrelania wysokoci). W celu wygenerowania wsp-
rzdnych dla naszego terenu, moemy zastosowa poniszy kod:
static GLint s_vector[4] = { 2, O, O, O }
static GLint t_vector[4] = { O, O, 2, O }

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);


glTexGeniv(GL_S, GL_OBJECT_PLANE, s_vector);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);


glTexGeniv(GL_T, GL_OBJECT_PLANE, t_vector);

Tryb mapowania GL_OBJECT_LINEAR odwzorowuje wsprzdne tekstury ze wsp-


rzdnych obiektu:
coordinate = X * vector[0] + Y * vector[l] + Z *
vector[2] + W * vector[3]

Tablica wektor jest okrelona za pomoc funkcji glTexGen:


void glTexGeniv(GLenum coord, GLenum pname, GLint *params)

gdzie parametr coord okrela, ktra wsprzdna tekstury ma zosta wygenerowana,


GL_S czy GL_T, za parametr pname wskazuje definiowany wektor; w tym przypadku
GL_OBJECT_PLANE. Na koniec, tablica params okrela wektor planu obiektu, uy-
wany do obliczania wsprzdnych tekstury.
402_______________________________________Cz II Uywanie OpenGL

Poprzedni kod dla naszego terenu wygenerowaby nastpujce wsprzdne:


S = 2 * XT
= 2 * Z

Aby OpenGL mg uy wygenerowanych wsprzdnych, musimy wczy generowanie


wsprzdnych tekstury:
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);

Plik TEXSCENE.C zawiera wersj przegldarki terenu korzystajc z wygenerowanych


wsprzdnych tekstury. Ta sama technika moe zosta zastosowana w przypadku je-
dnowymiarowych obrazw tekstur. Dla obrazu ID wsprzdn S wygenerujesz najpra-
wdopodobniej z wysokoci (Y), a dla koloru terenu, na podstawie wysokoci terenu.
Generowanie wsprzdnych tekstur trwa zwykle krcej ni okrelanie ich rcznie w trybie
natychmiastowym, jednak trwa nieco duej w przypadku uycia list wywietlania.

Lot nad terenem


Gdy uytkownik przelatuje nad terenem, musimy regulowa prdkoci jego lotu biorc
pod uwag szybko odwieania sceny. Zamiast stara si zachowa sta prdko
aktualizacji - ktra moe si zmienia w zalenoci od karty graficznej i procesora - b-
dziemy mierzy czas, jaki upyn od ostatniej aktualizacji do chwili obecnej. Funkcja
FlyTerrain mierzy czas w sekundach pomidzy kadym wywoaniem, po czym przesuwa
punkt obserwacji w przd z okrelon szybkoci, zalen od czasu, jaki upyn.

Podsumowanie
W tym rozdziale nauczye si nakada obrazy tekstur na wielokty i inne prymitywy.
Teksturowanie moe w znacznym stopniu podnie realizm tworzonych scen, a wanie to
sprawia, e praca z grafik komputerow jest taka pasjonujca.
Dziki uyciu funkcji glTexParameter moemy w znacznym stopniu wpyn na jako
obrazw tekstur nakadanych na wielokty. Dziki uyciu mipmap moemy zastosowa
wiele poziomw szczegw tekstury, z zachowaniem duej precyzji i szybkoci rende-
rowania. Liniowa interpolacja tekstur moe poprawi pewne rodzaje obrazw, na przykad
takich jak obraz nieba uywany w przykadach w tym rozdziale.
Funkcja glTextGen znacznie uatwia generowanie wsprzdnych tekstur, gdy oszczdza
nam mudnych lub niepotrzebnych oblicze. Poprzez zastpienie duej iloci wa-
runkowych wywoa funkcji glTexCoord, automatyczne generowanie wsprzdnych
upraszcza take programy, ktre musz wywietla zarwno teksturowane, jak i niete-
ksturowane wielokty.
Rozdzia 12. Mapowanie tekstur 403

W przypadku gier i innych interaktywnych, animowanych scen, moesz stworzy wersj z


teksturowaniem lub bez, przynajmniej do czasu a sprztowe akceleratory 3D stan si
bardziej powszechne.
Na koniec, pozostaje nam listing 12.5, zawierajcy kompletny kod programu przegldarki
terenu, TEXSCENE.C.

Listing 12.5. Przegldarka teksturowanego


terenu______________________________
tinclude "texture.h"
#include "texscene.h"
#include <stdarg.h>
#include <math.h>

#ifndef M_PI
define M_PI (double)3.14159265358979323846
ttendif /* !M PI */

Stae. . .
*/
define TERRAIN_SIZE 21
tdefine TERRAIN_EDGE ((TERRAIN_SIZE - 1) / 2)
#define TERRAIN_SCALE (500.0 / TERRAIN_EDGE)

define GRASS_HEIGHT 0.
ttdefine WATER_HEIGHT 0
tdefine TREES_HEIGHT 0.
ttdefine ROCKS_HEIGHT 0
tfdefine MOUNTAINS HEIGHT 0.
0
0.
5
1.
0
Zmienne globalne...
*/ SceneWindow;
ScenePalette;
HWND SceneDC; SceneRC; Okno sceny */
HPALETTE SkyTexture, Paleta kolorw (jeli potrzebna) */
HDC GrassTexture, Kontekst rysowania */
HGLRC RocksTexture, Kontekst renderowania OpenGL */
WaterTexture,
GLuint TreesTexture, /* Obraz tekstury nieba
MountainsTexture; /* Trawa. . */
/* Skaa. . */
/* Woda. . */
/* Drzewa. . . */
/* Gry. . */
HBITMAP GrassDownBitmap, /* Obraz wcinitego przycisku trawy */
GrassUpBitmap, /* Obraz zwolnionego przycisku trawy */
GrassSelectBitmap, /* Obraz zaznaczonego przycisku trawy */
RocksDownBitmap, /* ... V
RocksUpBitmap,
RocksSelectBitmap,
WaterDownBitmap,
404 Cz II Uywanie OpenGL

WaterUpBitmap,
WaterSelectBitmap,
TreesDownBitmap,
TreesOpBitmap,
TreesSelectBitmap,
MountainsDownBitmap,
MountainsUpBitmap,
MountainsSelectBitmap;
HWND TerrainWindow; /* Dialog terenu */ int
TerrainCurrent = IDC_WATER; int
TerrainType[TERRAIN_SIZE][TERRAIN_SIZE]; GLfloat
TerrainHeight[TERRAIN_SIZE][TERRAIN_SIZE]; GLfloat
TerrainNormal[TERRAIN SIZE][TERRAIN SIZE][ 3 ]

double MoveTime; /* Ostatni czas aktualizacji */


GLboolean Moving - GL_FALSE, /* GLJTRUE jeli lecimy */
Drawing = GL_FALSE; /* GL_TRUE jeli rysujemy */
POINT
GLfloat Position[3] = { 0 . 0 , TERRAIN SCAL, 0.0
/* Pozycja obserwatora */ Pocztkowa pozycja myszy */
GLfloat Heading = 0 . 0 ,
Pitch = 0 . 0 , Roli = 0 . 0 ;

CenterMouseKY; /*

Funkcje l o k a l n e . . .
*/ DisplayErrorMessage(char *, .. . ) ;
MakePalette(int);
void SceneProc(HWND, UINT, WPARAM, LPARAM);
void TerrainDlgProclHWND, UINT, WPARAM, LPARAM),
LRESULT CALLBACK InitializeTerrain(void);
UINT CALLBACK LoadAllTextures(void);
void LoadAllBitmaps(HINSTANCE);
void DrawTerrain(int, i n t ) ;
void FlyTerrain(int, i n t ) ;
void RepaintWindow(RECT * ) ;
void SaveBitmapFile(void);
void PrintBitmap(void);
void GetClock(void);
void
double
/*
* 'WinMainO '
*/
int APIENTRY
WinMain (HINSTANCE hlnst,
HINSTANCE hPrev!nstance,
LPSTR IpCmdLine, int
nCmdShow)

MSG msg;
WNDCLASS we;
POINT pos;
Rozdzia 12. Mapowanie tekstur_________________________________405

/*
* Inicjowanie terenu dla trawy V
InitializeTerrain();
we.style = 0;
wc.lpfnWndProc = (WNDPROC)SceneProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hlnstance = hlnst;
wc.hlcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = 0;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
we.IpszClassName = "Textured S c e n " ;
if (RegisterClass( s w e ) == 0)
{
DisplayErrorMessage( " N i e mog zarejestrowa klasy o k n a ! " ) ;
return (FALSE);
};
Scenewindow = Createwindow("Textured S c e n " , "Teksturowany t e r e n " ,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
OWS_CLIPSIBLINGS,
32, 32, 400, 300,
NULL, NULL, hlnst, NULL);

if (Scenewindow == NULL)
{
DisplayErrorMessage( " N i e udao si utworzy o k n a ! " ) ;
return (FALSE);
};
ShowWindow(Scenewindow, nCmdShow);
UpdateWindow(Scenewindow);
/*
* adowanie bitmap przyciskw, utworzenie okna dialogowego
* edycji terenu
*/
LoadAllBitmaps(hlnst);
TerrainWindow = CreateDialog(hlnst,
<=>MAKEINTRESOURCE (IDD_TERRAIN_DIALOG) ,
Scenewindow, (DLGPROC)TerrainDlgProc);

// Gwna ptla komunikatw


while (TRUE)
{
while (!Moving ||
PeekMessagetsmsg, NULL, O, O, PM_NOREMOVE) == TRUE) if
(GetMessaget&msg, NULL, O, 0 ) )
406____________________________________Cz II Uywanie OpenGL

{
TranslateMessage(&msg);
DispatchMessage(&msg);
else
return ( 1 ) ;

/* * Jeli trzeba, obsuga lotu...

GetCursorPos(ipos);
FlyTerrain(pos. x , p o s . y ) ;
};
return (msg.wParam);
}

/*
* 'DisplayErrorMessage()' - Wywietla okno komunikatu bdu.

void
DisplayErrorMessage(char *format,// acuch formatowania w stylu
=>printf ()
...) // Pozostae argumenty

va_list ap; /* Wskanik argumentu */


char s[ 1 0 2 4 ] ; /* acuch wyjciowy */

if (format == NOLL)
return;
va_start(ap, format);
vsprintf(s, format, ap) ;
va_end(ap) ;
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(NULL, s, "Bd", MB_OK | MB_ICONEXCLAMATION); }

/*
* 'MakePalette()' - Jeli trzeba, tworzy palet kolorw.
*/
void
MakePalette(int p f ) /* We - ID formatu pikseli */

PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE *pPal;
int nColors;
int i,
rmax,
gmax,
bmax;
Rozdzia 12. * Mapowanie tekstur _________________________________ 407

/*
* Sprawdzenie, czy paleta jest potrzebna...
*/
DescribePixelFormat (SceneDC, pf, sizeof (PIXELFORMATDESCRIPTOR) ,

if ( ! (pfd.dwFlags & PFD_NEED_PALETTE) ) {


ScenePalette = NULL;
return;

/*
* Alokowanie pamici dla palety.
*/
nColors = l pfd.cColorBits;
pPal = (LOGPALETTE *) malloc (sizeof (LOGPALETTE) +
nColors * sizeof (PALETTEENTRY) );

pPal->palVersion = 0x300;
pPal->palNumEntries = nColors;
/*
* Odczyt maksymalnych wartoci barw skadowych i budowanie nColors
^kolorw
*/
rmax = (l pfd. cRedBits) - 1;
gmax = (l pfd.cGreenBits) - 1;
bmax = (l pfd.cBlueBits) - 1;
for (i = 0; i < nColors; i ++)
{
pPal->palPalEntry[i] .peRed = 255 * ( (i pfd.cRedShift) & rmax) /
rmax;
pPal->palPalEntry[i] .peGreen = 255 * ( ( i pfd.cGreenShift) &
t
*gmax) /
gmax;
pPal->palPalEntry[i] .peBlue = 255 * ( (i pfd.cBlueShift) & ^bmaK)
/
bmax ;
pPal->palPalEntry [ i ] .peFlags = 0;

/*
* Uworzenie, wybranie i realizacja palety
*/
ScenePalette = CreatePalette (pPal) ;
SelectPalette (SceneDC, ScenePalette, FALSE) ;
RealizePalette (SceneDC) ;
free(pPal) ;
408____________________________________Cz II Uywanie OpenGL

/*
* 'SceneProc()' - Obsuga komunikatw okna sceny.
*/
LRESULT CALLBACK
SceneProc(HWND hWnd, OINT
uMsg, WPARAM wParam, LPARAM
IParam) (
int pf; /* ID formatu pikseli */
PIKELFORMATDESCRIPTOR pfd; /* informacje o formacie pikseli */
PAINTSTRUCT ps;
RECT rect;

switch (uMsg)
{
case WM_CREATE :
// Pobranie kontekstu urzdzenia i renderowania, //
przygotowanie obszaru klienta dla OpenGL

SceneDC = GetDC(hWnd);

pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
// Dla OpenGL
pfd.dwLayerMask = PFD_MAIN_PLANE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 0; pfd.cDepthBits
= 32; pfd.cStencilBits = 0;
pfd.cAccumBits = 0;

pf = ChoosePixelFormat(SceneDC, Spfd); if
( p f == 0)
DisplayErrorMessage("Program nie mg znale
^odpowiedniego formatu p i k s e l i ! " ) ;
else if (!SetPixelFormat(SceneDC, pf, pfd))
DisplayErrorMessage("Program nie mg ustawi
^odpowiedniego formatu p i k s e l i ! " ) ;
MakePalette(pf);

SceneRC = wglCreateContext(SceneDC);
wglMakeCurrent(SceneDC, SceneRC);
// adowanie obrazw tekstur do list wywietlania...

LoadAllTextures();
break;
Rozdzia 12. * Mapowanie tekstur_________________________________409

case WM_SIZE :
case WM_PAINT :
// Odrysowanie obszaru klienta...
BeginPaint (hWnd, sps);

GetClientRect(hWnd, Srect);
RepaintWindow(srect);

EndPaint(hWnd, & p s ) ;
break;
case WM_COMMAND : /*
* Obsuga menu...
*/
switch (LOWORD(wParam)) {
case IDM_FILE_SAVEAS :
SaveBitmapFile();
break; case
IDM_FILE_PRINT :
PrintBitmapt);
break; case
IDM_FILE_EXIT :
DestroyWindow(SceneWindow);
break;
case IDM_WINDOW_TERRAIN : /*
* Wczenie lub wyczenie okna t e r e n u . . .
*/
if (GetMenuState(GetMenu(SceneWindow), IDM_WINDOW_TERRAIN,
MF_BYCOMMAND) S MF_CHECKED)
{
CheckMenuItem(GetMenu(SceneWindow),
OIDM_WINDOW_TERRAIN,
MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(TerrainWindow, SW_HIDE); } else {
CheckMenuItem(GetMenu(SceneWindo
w), OIDM_WINDOW_TERRAIN,
MF_BYCOMMAND | MF_CHECKED);
ShowWindow(TerrainWindow, SW_SHOW); };
break;
}; break;
case WM_QUIT :
case WM_CLOSE :
/*
* Zniszczenie okna, bitmap i wyjcie...
*/
DestroyWindow(SceneWindow);
DestroyWindow(TerrainWindow);
410____________________________________Cz II Uywanie OpenGL

DeleteObject(GrassDownBitmap);
DeleteObject(GrassSelectBitmap);
DeleteObject(GrassUpBitmap);
DeleteObject(WaterDownBitmap);
DeleteObject(WaterSelectBitmap);
DeleteObject(WaterUpBitmap);
DeleteObject(RocksDownBitmap);
DeleteObject(RocksSelectBitmap);
DeleteObject(RocksUpBitmap);
DeleteObject(TreesDownBitmap);
DeleteObject(TreesSelectBitmap);
DeleteObject(TreesDpBitmap);
DeleteObject(MountainsDownBitmap);
DeleteObject(MountainsSelectBitmap);
DeleteObject(MountainsUpBitmap);
exit( 0 ) ;
break;
case WM_DESTROY : /*
* Zwolnienie kontekstu urzdzenia, kontekstu
* renderowania i palety
*/
if (SceneRC)
wglDeleteContext(SceneRC);
if (SceneDC)
ReleaseDC(SceneWindow, SceneDC);
if (ScenePalette)
DeleteObject(ScenePalette);

PostQuitMessage(0);
break;
case WM_QUERYNEWPALETTE :
/*
* W razie potrzeby realizacja palety...
*/

if (ScenePalette) {
SelectPalette(SceneDC, ScenePalette, FALSE);
RealizePalette(SceneDC);

InvalidateRect(hWnd, NULL, F A L S E ) ;
return (TRUE);
); break;
case WM_PALETTECHANGED: /*
* W razie potrzeby ponowne wybranie palety...
*/
Rozdzia 12. * Mapowanie tekstur_________________________________411

if (ScenePalette && (HWND)wParara != hWnd) {


SelectPalette(SceneDC, ScenePalette, FALSE);
RealizePalette(SceneDC);
UpdateColors(SceneDC); };
break;
case WM_LBUTTONDOWN :
/*
* Wcinito lewy przycisk myszy. Jeli by otwarty dialog
* terenu, oznacza to pocztek rysowania.
* W przeciwnym razie ustawienie znacznika 'Moving' w celu
* wskazania, e lecimy
*/
SetCapture(SceneWindow);
if (IsWindowVisible(TerrainWindow))
(
DrawTerrain(LOWORD(IParam), HIWORD(IParam));
Drawing = GL_TRUE; }
else
{
GetCursorPos(&CenterMouseXY);
Moving = GLJTRUE;
MoveTime = GetClockf); };
break;

case WM_MOUSEMOVE :
/*
* Poruszy si wskanik myszy. Jeli rysujemy teren,
* zrbmy to.
* Jeli nie, ignorujemy to, bo lecimy w gwnej ptli
*/
if (Drawing)
DrawTerrain(LOWORD(IParam), HIWORD(IParam));
break;
case WM_LBUTTONUP :
/*
* Uytkownik zwolni lewy przycisk myszy. Przestajemy
* rysowa lub lecie.
*/
Moving = GL_FALSE;
Drawing = GL_FALSE;
ReleaseCapture();

InvalidateRect(SceneWindow, NULL, TRUE);


break;
412__________________________________ Cz II Uywanie OpenGL

default : /*
* Standardowa obsuga wszystkich innych komunikatw
* procedury...
*/
return (DefWindowProc(hWnd, uMsg, wParam, IParam)); };
return ( F A L S E ) ;

* 'TerrainDlgProc()' - Przetwarza komunikaty okna dialogowego terenu.


*/

UINT CALLBACK
TerrainDlgProc(HWND hWnd,
UINT uMsg, WPARAM wParam,
LPARAM IParam) {
HDC hdc; /* Kontekst rysowania dla przyciskw */
LPDRAWITEMSTRUCT Ipdis; /* Informacja o stanie przyciskw */
UINT idCtl; /* Identyfikator przycisku */

switch ( u M s g )
{
case WM_DRAWITEM :
/*
* Windows chce narysowa przycisk. Sprawd, ktry i narysuj go
*/
idCtl - (UINT)wParam;
Ipdis - (LPDRAWITEMSTROCT)IParam;
hdc = CreateCompatibleDC(lpdis->hDC) ;

switch (idCtl)
{
case IDC_WATER :
if (lpdis->itemState S ODS_SELECTED)
SelectObject(hdc, WaterDownBitmap); else
if (TerrainCurrent == IDC_WATER)
SelectObject(hdc, WaterSelectBitmap);
else
SelectObject(hdc, WaterUpBitmap); break;
case IDC_GRASS :
if (lpdis->itemState & ODS_SELECTED)
SelectObject(hdc, GrassDownBitmap);
else if (TerrainCurrent == IDC_GRASS)
SelectObject(hdc, GrassSelectBitmap);
else
SelectObject(hdc, GrassUpBitmap);
break;
Rozdzia 12. Mapowanie tekstur_________________________________413

case IDCJTREES :
if (lpdis->itemState S, ODS_SELECTED)
SelectObject(hdc, TreesDownBitmap);
else if (TerrainCurrent == IDC_TREES)
SelectObject(hdc, TreesSelectBitmap);
else
SelectObject(hdc, TreesUpBitmap); break;
case IDC_ROCKS :
if (lpdis->itemState i ODS_SELECTED)
SelectObject(hdc, RocksDownBitmap);
else if (TerrainCurrent == IDC_ROCKS)
SelectObject(hdc, RocksSelectBitmap);
else
SelectObject( h d c , RocksUpBitmap); break;
case IDC_MOUNTAINS :
if (lpdis->itemState & ODS__SELECTED)
SelectObject(hdc, MountainsDownBitmap);
else if (TerrainCurrent == IDC_MOUNTAINS)
SelectObject( h d c, MountainsSelectBitmap);
else
SelectObject(hdc, MountainsUpBitmap);
break;

* Rozcignicie bitmapy na obszar przycisku...


*/
StretchBlt(lpdis->hDC, lpdis->rcltem.left,
lpdis->rcltem.top, lpdis->rcltem.right,
lpdis->rcltem.bottom,
hdc, O, O, 24, 24, SRCCOPY);
DeleteDC(hdc);
break;

case WM_CLOSE :
/*
* Zamknicie okna (ukrycie g o ) i wyczenie znaczka w menu
*/
ShowWindow(TerrainWindow, SW_HIDE);
CheckMenuItem(GetMenu(SceneWindow), IDM_WINDOW_TERRAIN,
MF_BYCOMMAND | MF_UNCHECKED);
break;

case WM_COMMAND :
/*
* Kliknito na przycisk - wybierz nowy typ terenu.
*/
switch (LOWORD(wParam))
{
case IDC_GRASS :
case IDCJTREES :
case IDC ROCKS :
414 ____ _________________________ Cz II Uywanie OpenGL

case IDC_WATER : case


IDC_MOUNTAINS :
TerrainCurrent = LOWORD(wParam);
InvalidateRect(TerrainWindow, NULL, T R U E ) ;
UpdateWindow(TerrainWindow); return (TRUE);
};
break;
};
return ( F A L S E ) ;

/*
* 'LoadAllBitmaps()' - aduje bitmapy przyciskw.
*/
void
LoadAllBitmaps(HINSTANCE hinstance)
{
GrassDownBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_GRASS_DOWN));
GrassSelectBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_GRASS_SELECT))
GrassUpBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_GRASS_UP));

WaterDownBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_WATER_DOWN));
WaterSelectBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOORCE(IDB_WATER_SELECT))
WaterUpBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_WATER_UP));

RocksDownBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOORCE(IDB_ROCKS_DOWN));
RocksSelectBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_ROCKS_SELECT))
RocksDpBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_ROCKS_UP));

TreesDownBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOORCE(IDB_TREES_DOWN));
TreesSelectBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_TREES_SELECT))
TreesDpBitmap = LoadBitmap((HANDLE)hinstance,
MAKEINTRESOURCE(IDB_TREES_UP));

MountainsDownBitmap = LoadBitmap((HANDLE)hinstance,

MAKEINTRESOURCE(IDB_MOUNTAINS_DOWN));
MountainsSelectBitmap = LoadBitmap((HANDLE)hinstance,

MAKEINTRESOURCE(IDB_MOONTAINS_SELECT));
MountainsUpBitmap = LoadBitraap((HANDLE)hinstance,

MAKEINTRESOURCE(IDB_MOONTAINS_UP));
Rozdzia 12. Mapowanie tekstur 415

'LoadAllTextures() aduje tekstury dla sceny.

void
LoadAllTextures(void)
{
glNewList(SkyTexture = glGenLists( 1 ) , GL_COMPILE);
glTexParameteri(GL_TEXTORE_2D, GL_TEXTORE_WRAP_S, GL_REPEAT) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTORE_WRAP_T, GL_REPEAT);
TextureLoadBitmap("sky.bmp");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEndList();

glNewList(RocksTexture = glGenLists( 1 ) , GL_COMPILE);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ;
TextureLoadMipmap("rock.bmp");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTORE_MIN_FILTER,
OGL_NEAREST_MIPMAP_LINEAR);
glEndList( ) ;

glNewList(GrassTexture = glGenLists( 1 ) , GL_COMPILE);


glTexPararaeteri(GL_TEXTURE_2D GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL REPEAT);
GL_TEXTURE_WRAP_T, _
TextureLoadMipmap( " g r a s s . b m p " ) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
C
>GL_NEAREST_MIPMAP_LINEAR) ; glEndList O;
glNewList(WaterTexture = glGenLists( 1 ) , GL_COMPILE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTORE_WRAP_S, GL_REPEAT) ;
glTexParameteri(GL_TEXTURE_2D, GL TEXTDRE WRAP T, GL REPEAT);
TextureLoadMipmap("water.bmp");
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST) GL TEXTURE MIN FILTER,
, glTexParameteri(GL_TEXTURE_2D,
C
*GL_NEAREST_MIPMAP_LINEAR) ; glEndListO;

glNewList(TreesTexture = glGenLists( 1 ) , GL_COMPILE);


glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
TextureLoadMipmap("trees. b m p " ) ;
glTexParameteri(GL_TEXTURE_2D GL_TEXTDRE_MAG_FILTER, GL_NEAREST) ;
glTexParameteri(GL_TEXTORE_2D GL TEXTURE MIN FILTER,
OGL_NEAREST_MIPMAP_LINEAR);
glEndListO; glNewList(MountainsTexture =
glGenLists( 1 ) , GL_COMPILE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ;
TextureLoadMipmap("mountain.bmp");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTORE_MIN_FILTER,
C
>GL_NEAREST_MIPMAP_LINEAR) ;
glEndList O;
416____________________________________Cz II Uywanie OpenGL

/*
* 'UpdateNormals()' - Aktualizuje normalne punktw s c e n y . . .
*/
void
UpdateNormals(void)
{
int x, y; /* Wsprzdne x i y terenu */
GLfloat ( * n ) [ 3 ] , /* Bieca normalna terenu */
nx, ny, nz, /* Skadowe normalnej */ d, /*
Wielko normalnej */ *height; /* Bieca wysoko
terenu */

/*
* Przejcie przez tablice terenu i odtworzenie normalnych
* na podstawie wysokoci terenu
*/
n = TerrainNormal[ 0 ] ;
height = TerrainHeight[ 0 ] ;
for (y = 0; y < (TERRAIN_SIZE - 1) ; y ++, n ++, height ++)
{
for (x = 0; x < (TERRAIN_SIZE - 1 ) ; x ++, n + + , height ++)
{ /*
* Iloczyn wektorowy wektorw w gr i na prawo
* (uproszczone w tym specjalnym przypadku)
*/
nx = height[ 0 ] - height[ 1 ] ;
ny = -1.0;
nz = height[ 0 ] - height[TERRAIN_SIZE];
d = (float)-sqrt(nx * nx + ny * ny + nz * nz) ;
n [ 0 ] [ 0 ] = nx / d; /* Normalizacja wektora */
n [ 0 ] [ 1 ] = ny / d; n [ 0 ] [ 2 ] = nz / d; };
/*
* Iloczyn wektorowy wektorw w gr i na lewo
* (uproszczone w tym specjalnym przypadku) dla ostatniej
* kolumny siatki
*/
nx = height[ 0 ] - height[-l];
ny = -1.0;
nz = height[ 0 ] - height[TERRAIN_SIZE];

d = (float)-sqrt (nx * nx -t- ny * ny + nz * nz) ;


n[0][0] = nx / d; /* Normalizacja wektora */
n[0] [1] = ny / d;
n[0] [2] = nz / d;
Rozdzia 12. * Mapowanie tekstur_________________________________417

/*
* Ustawienie grnego wiersza normalnych tak samo jak
* normalnych drugiego wiersza od gry.
*/
for (x = 0; x < TERRAIN_SIZE; x ++, n + + ) {
n [ 0 ] [ 0 ] = n[-TERRAIN_SIZE][ 0 ] ;
n [ 0 ] [ l ] = n[-TERRAIN_SIZE][1];
n [ 0 ] [ 2 ] = n[-TERRAIN S I Z E ] [ 2 ] ;

/*
* 'InitializeTerrain( ) ' - Inicjuje tablice t e r e n u . . .
*/
void
InitializeTerrain(void)
{
int x, y; /* Pooenie terenu ( x , y) */

/*
* Wypenienie terenu traw.
*/
TerrainCurrent = IDC_WATER;

for (y = 0; y < TERRAIN_SIZE; y ++) for


(x = 0; x < TERRAIN_SIZE; x ++) {
TerrainType [y ] [ x ] = IDC_GRASS;
TerrainHeight[y] [ x ] = GRASS_HEIGHT + O.lf * (rand() % 5 ) ,

/*
* Aktualizacja normalnych
*/
UpdateNormals ( ) ;

/*
* 'draw_cell()' - Rysowanie (wypenienie) pojedynczej komrki
^terenu...
*/
void
draw_cell(int x, /* We - Pooenie terenu X */
int y) /* We - Pooenie terenu Y */ { /*
* Sprawdzenie zakresu terenu
*/
418 ___________________________________ Cz II Uywanie OpenGL

if (X < O | | X >= TERRAIN_SIZE | |


y < O || y >= TERRAIN_SIZE)
return;

if (TerrainType [ y ] [ x ] == TerrainCurrent)
return; /* Ju jest poprawnego typu */
TerrainType [ y ] [ x ] = TerrainCurrent;

/*
* Wymuszenie odwieenia o k n a . . .
*/
InvalidateRect (SceneWindow, MOLL, TRUE) ;

/*
* Ustawienie wysokoci "komrki" terenu. Dla wody wysoko
* jest staa, WATER_HEIGHT. Dla innych typw dodajemy losowe
* odchylenie w celu uzyskania realistycznego obrazu.
*/
switch (TerrainCurrent)
{
case IDCJSATER :
TerrainHeight [ y ] [ x ] = WATER_HEIGHT;
break; case
IDC_GRASS :
TerrainHeight [y] [ x ] = GRASS_HEIGHT + O.lf * (randt) % 5 ) ;
break; case
IDCJTREES :
TerrainHeight [ y ] [ x ] = TREES_HEIGHT + 0.1 * (rand() % 5 ) ;
break; case
IDC_ROCKS :
TerrainHeight [ y ] [ x ] = ROCKS_HEIGHT + O.lf * (rand() % 5 ) ;
break; case
IDC_MOUNTAINS :
TerrainHeight [ y ] [ x ] = MOUNTAINS_HEIGHT + 0.15f * (rand() % 5 ) ;
break;

/*
* ' DrawTerrain ( ) ' - Rysuje komrk terenu na pozycji myszy
*/
void
DrawTerrain (int mousex, /* We - pozioma pozycja myszy */
int mousey) /* We - pionowa pozycja myszy */ {
int i,
count, /* Licznik selekcji */ x, y; /* Pooenie
terenu ( x , y) */ GLfloat *height; /* Bieca
wysoko */ GLuint b u f f e r f l O O ] ; /* Bufor selekcji
*/ GLint viewport[4]; /* Widok OpenGL */
Rozdzia 12. Mapowanie tekstur_________________________________419

/*
* Pobranie biecego widoku OpenGl i rozpoczcia liczenia
* pionowej wsprzdnej myszy od krawdzi widoku.
*/
glGet!ntegerv(GL_VIEWPORT, viewport);
mousey = viewport[3] - l - mousey;
/*
* Umoliwienie wyboru w granicach 4 pikseli od pozycji myszy
*/
glSelectBuffer(100, buffer);
glRenderMode(GL_SELECT);
gllnitNames();
glMatrixMode(GL_PROJECTION);
glLoadldentity();
gluPickMatrix((GLdouble)mousex, (GLdouble)mousey, 4 . 0 , 4 . 0 ,
viewport);
gluPerspective( 4 5 . O, (float)viewport[ 2 ] / (float)viewport[ 3 ] ,
0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); /*
* Obrt/translacja biecego punktu obserwacji
*/
glRotatef(Roli, 0 . 0 , 0 . 0 , 1 . 0 ) ;
glRotatef(Pitch, -1.0, 0 . 0 , 0 . 0 ) ;
glRotatef(Heading, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glTranslatef(-Position[ 0 ] ,
-Positionfl],
-Position[ 2 ] ); glScalef(TERRAIN_SCALE,
TERRAIN_SCALE, TERRAIN_SCALE);

Narysowanie terenu do bufora selekcji. Dzieje si to inaczej


ni w funkcji RepaintWindowO , wiec moemy wybra pojedyncze
komrki, a nie cae paski jednego typu.
Wybrany bufor zosta umieszczony na stosie zarwno dla pooe X,
jak i Y. /
height = TerrainHeight[ 0 ] ;
glPushName( 0 ) ;
for (y = 0 ; y < (TERRAIN_SIZE - 1 ) ; y ++, height ++)

glLoadName( y ) ;
glPushName( 0 ) ;
for (x = 0; x < (TERRAIN_SIZE - 1 ) ; x ++, height ++)

glLoadName( x ) ;
glBegin(GL_POLYGON);
glVertex3f((GLfloat)(x - TERRAIN_EDGE),
height[ 0 ] ,
(GLfloat)(y - TERRAIN_EDGE));
420____________________________________Cz II Uywanie OpenGL

glVertex3f((GLfloat)(x - TERRAIN_EDGE),
height[TERRAIN_SIZE], (GLfloat) (y -
TERRAIN_EDGE + D ) ;

glVertex3f((GLfloat)(x - TERRAIN_EDGE + 1 ) ,
height[ 1 ] ,
(GLfloat)(y - TERRAIN_EDGE));
glVertex3f((GLfloat)(x - TERRAIN_EDGE + 1 ) ,
height[TERRAIN_SIZE + 1 ] ,
(GLfloat)(y - TERRAIN_EDGE + l));
glEnd(); };

glPopName O;
};
glPopName();
glPopMatrix O;
glFinishO ;
/*
* Odczyt trafie w buforze selekcji
*/
count = glRenderMode(GL_RENDER);
for (i = 0; i < count; i += 3) {
if ( b u f f e r [ i ) == 0)
continue;
/*
* Kade trafienie zawiera nastpujce parametry:
*
* O - ilo ( 2 )
* l - Minimalna warto Z
* 2 - Maksymalna warto Z
* 3 - Pooenie X w terenie
* 4 - Pooenie Y w terenie
*/
x = buffer[i + 4];
y = buffer[i + 3];
i += buffer[ i ] ;
/*
* Wypenienie 4 rogw wybranej komrki...
*/
draw_cell( x , y);
draw_cell(x + l, y);
draw_cell(x, y + 1 ) ;
draw_cell(x + 1 , y + 1 ) ;
/*
* Aktualizacja normalnych terenu.
*/
UpdateNormals();
Rozdzia 12. Mapowanie tekstur_________________________________421

/*
* 'FlyTerrain()' - Lot na podstawie biecej pozycji myszy.
*/
void
FlyTerrain(int mousex, /* We - pozioma wsprzdna myszy */ int
mousey) /* We - pionowa wsprzdna myszy */ {
RECT rect;
GLfloat movex, movey; /* Przemieszczenie myszy */
double curtime, /* Biecy czas w sekundach */
distance; /* Dystans do przeniesienia */ GLfloat
cheading, /* Cosinus kierunku */ sheading, /* Sinus
kierunku */ cpitch, /* Cosinus pochylenia */ spitch;
/* Sinus pochylenia */

/*
* Pobranie biecego czasu systemowego
*/
curtime = GetClockO;
distance = 10.0 * (curtime - MoveTime);
MoveTime = curtime;
/*
* Obliczenie odlegoci wskanika myszy od "rodka" (kliknicia)
*/
movex = 0.05 * (mousex - CenterMouseXY.x);
movey = 0.05 * (mousey - CenterMouseKY.y);
/*
* Dostosowanie kierunku pochylenia do biecego pooenia myszy
*/
Roli += movex;
Pitch += movey * cos(Roli * M_PI / 1 8 0 . 0 ) ;
Heading += movey * sin(Roli * M_PI / 180.0);
if (Heading < 0 . 0 )
Heading += 360.0; else if
(Heading >= 360.0)
Heading -= 360.0;
if (Pitch < -180.0)
Pitch += 360.0; else if
(Pitch >= 180.0)
Pitch - 360.0;
if (Roli < -180.0)
Roli += 360.0; else if
(Roli >= 180.0)
Roli -= 360.0;
422 Cz II Uywanie OpenGL

/*
* Przeniesienie w biecym kierunku
*/

cheading = cos(Heading * M_PI / 180.0);


sheading = sin(Heading * M_PI / 180.0);
cpitch = cos(Pitch * M_PI / 180.0);
spitch = sin(Pitch * M_PI / 180.0);

Position[0] += distance * sheading * cpitch;


Position[2] -= distance * cheading * cpitch;
Position[l] += distance * spitch;
/* Odrysowanie okna z nowymi wsprzdnymi

GetClientRect(SceneWindow, srect);
Repaintwindow(irect);

'RepaintWindowO ' - Odrysowuje obszar roboczy okna sceny.


*/
void
Repaintwindow(RECT " r e c t ) /* We - Obszar roboczy okna */

int i;
int x, y; /* Pooenie terenu ( x , y) */
int last_type; /* Poprzedni typ terenu */
int *type; /* Biecy typ terenu */
GLfloat *height, /* Bieca wysoko terenu *
(*n)[31; /* Bieca normalna terenu *
static GLfloat
sky_top[4][ 3 ] =
( /* Wsprzdne nieba */ 0.8, -
{ -TERRAIN_EDGE, TERRAIN_SIZE TERRAIN_EDGE
{ TERRAIN_EDGE, TERRAIN_SIZE ),
{ TERRAIN_EDGE, TERRAIN_SIZE 0.8, -
{ -TERRAIN EDGE, TERRAIN SIZE TERRAIN_EDGE

static GLfloat sky_bottom[4][ 3 ]

{ -TERRAIN_EDGE, 0 . 0 , -TERRAIN_EDGE },
( TERRAIN_EDGE, 0 . 0 , -TERRAIN_EDGE },
{ TERRAIN_EDGE, 0 . 0 , TERRAIN_EDGE ),
{ -TERRAIN EDGE, 0 . 0 , TERRAIN EDGE }

static GLfloat sunpos[4] = { 0.0, 1 . 0 , 0.0, 0.0 };


static GLfloat suncolor[4] = { 6 4 . 0 , 6 4 . 0 , 6 4 . 0 , 1.0 };
static GLfloat sunambient[4] = { 0.001, 0.001, 0.001, 1 . 0
Rozdzia 12. Mapowanie tekstur _________________________________ 423

/*
* Wyzerowanie widoku i wyczyszczenie okna na jasny bkit
*/
glViewport ( O , O, rect->right, rect->bottom) ;
glClearColor(0.5, 0.5, 1.0, 1 . 0 ) ; glEnable
(GL_DEPTH_TEST) ;
if (Moving | | Drawing) {
/*
* Bez tekstur podczas rysowania lub lotu; jest za w o l n e . . .
* Rysowanie tylnego bufora dla pynnej animacji
*/
glDisable (GL_TEXTURE_2D) ;
glDrawBuf fer (GL_BACK) ;

else

Wczenie tekstur, gdy przestaniemy rysowa lub lata W


ten sposb tworzymy scen, ktra mona wydrukowa lub
zachowa w pliku.

Poniewa to trwa duej, rysujemy w przednim buforze, aby


uytkownik widzia przebieg rysowania. . .

glEnable (GL_TEXTURE_2D) ;
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_DECAL) ;
glDrawBuffer (GL_FRONT) ;

glClear (GL_COLOR_BOFFER_BIT | GL_DEPTH_BUFFER_BIT) ;

/*
* Przygotowanie przeksztacenia widoku dla biecego
* punktu obserwacji
*/

glMatrixMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(45.0, (float) rect->right / (float) rect->bottom,
0 . 1 , 1000.0);

glMatrixMode (GL_MODELVIEW) ;
glPushMatrix() ;
glRotatef (Roli, 0 . 0 , 0.0, 1 . 0 ) ;
glRotatef (Pitch, -1.0, 0.0, 0 . 0 ) ;
glRotatef (Heading, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glTranslatef |-Position[0] ,
-Position[l] ,
-Position[2] ) ; glScalef (TERRAIN_SCALE,
TERRAIN_SCALE, TERRAIN_SCALE) ;
424____________________________________Cz II Uywanie OpenGL

if (!(Moving l| Drawing)) {
/*
* Rysowanie n i e ba .. .
*/
g!Disable(GL_LIGHTING);
glCallList(SkyTexture);
glBegin(GL_QDAD_STRIP); for
(i = 0; i < 4; i ++) {
glTexCoord2f((float)i, 0 . 0 ) ;
glVertex3fv(sky_bottom[i]);

glTexCoord2f((float)i, 0 . 8 ) ;
glVertex3fv(sky_top[i]); };
glTexCoord2f( 4 . 0 , 0 . 0 ) ;
glVertex3fv(sky_bottom[0]);
glTexCoord2f(4. 0 , 0 . 8 ) ;
glVertex3fv(sky_top[0]);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( 0 . 5 , 1.0);
glVertex3f( 0 . 0 , TERRAIN_SIZE, 0 . 0 ) ;

for (i = 0; i < 4; i ++) {


glTexCoord2f((float)i, 0 . 8 ) ;
glVertex3fv(sky_top[i]); };
glTexCoord2f( 4 . 0 , 0 . 8 ) ;
glVertex3fv(sky_top[0]);
glEnd(); };
/*
* Przygotowanie owietlenia...
*/
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TROE);

glEnable(GL_LIGHTO);
glLightfv(GL_LIGHTO, GL_POSITION, sunpos);
glLightfv(GL_LIGHTO, GL_DIFFUSE, suncolor);
glLightfv(GL_LIGHTO, GL_AMBIENT, sunambient);

if (Moving l l Drawing)
glEnable(GL_COLOR_MATERIAL);
else
glDisable(GL_COLOR_MATERIAL);
Rozdzia 12. Mapowanie tekstur_________________________________425

/*
* Teraz teren...
*/
type = TerrainType[ 0 ] ;
height = TerrainHeight[ 0 ] ;
n = TerrainNormal[ 0 ] ;
for (y = 0; y < (TERRAIN_SIZE - 1 ) ; y ++)
{
last_type = -1;

for (x 0; x < TERRAIN_SIZE; x ++, type ++, height + + , n ++) {


if (last_type 1= *type)
{ /*
* Jeli zmienia si typ terenu, zakocz istniejcy pasek
* i wyzeruj parametry tekstury/koloru
*/
if (last_type != - 1 )
glEnd();
switch (*type)
{
case IDCJATER :
if (Moving || Drawing)
glColor3f( 0 . 0 , 0.0,
0 . 5 ) ; else
glcallList(WaterTexture); break;
case IDC_GRASS :
if (Moving l l Drawing)
glColor3f( 0 . 0 , 0 . 5 , 0 . 0 ) ;
else
glCallList(GrassTexture); break;
case IDC_ROCKS :
if (Moving || Drawing)
glColor3f(0.25, 0.25, 0 . 2 5 ) ;
else
glCallList(RocksTexture); break;
case IDC_TREES :
if (Moving l l Drawing)
glColorSf(0.0, 0.25,
0 . 0 ) ; else
glCallList(TreesTexture); break;
case IDC_MOUNTAINS :
if (Moving || Drawing)
glColorSf( 0 . 2 , 0 . 1 ,
0 . 0 5 ) ; else
glCallList(MountainsTexture); break;
};
glBegin(GL_QOAD_STRIP);
if (last_type != -1)
426 ____________________________________ Cz II Uywanie OpenGL

/*
* Zaczniemy od poprzedniego miejsca, aby nie byo dziur
*/

glTexCoord2i (x * 2 - 2, y * 2 ) ;
glNorma!3fv(n[-l] ) ;
glVertex3f ( (GLfloat) (X - TERRAIN_EDGE - 1 ) ,
heightt-1] , (GLfloat) (y -
TERRAIN_EDGE) ) ;
glTexCoord2i(x * 2 - 2, y * 2 + 2 ) ;
glNorma!3fv(n[TERRAIN_SIZE - 1] ) ;
glVertex3f( (GLfloat) (x - TERRAIN_EDGE - 1 ) ,
height[TERRAIN_SIZE - 1 ] , (GLfloat)
(y - TERRAIN_EDGE + l ) ) ;
};
last_type = *type; >;
glTexCoord2i(x * 2, y * 2 ) ;
glNormal3fv(n[0] ) ;
glvertex3f( (GLfloat) (x - TERRAIN_EDGE) ,
height[0] ,
(GLfloat) (y - TERRAIN_EDGE) ) ;
glTexCoord2i(x * 2, y * 2 + 2) ;
glNormal3fv(n[TERRAIN_SIZE] ) ; glVertex3f(
(GLfloat) (x - TERRAIN_EDGE) ,
height [TERRAIN_SIZE] ,
(GLfloat) (y - TERRAIN_EDGE + D ) ;
};
glEnd ( ) ; };
glPopMatrix () ;

/*
* Gdy lecimy lub rysujemy, uywamy podwjnego buforowania.
* Jeli trzeba, przerzu bufory
*/
glFinish ( ) ;
if (Moving l l Drawing)
SwapBuf fers (SceneDC) ;

/*
* 'SaveBitmapFile () ' - Zapis wywietlanej sceny na dysku.
*/
void
SaveBitmapFile (void)
{
char t i t l e [ 2 5 6 ] , /* Tytu pliku */ filename[256] ,
/* Nazwa pliku */ directory[256] ; /* Bieca kartoteka */
OPENFILENAME ofn; /* Struktura okna dialogowego */ void
*bits; /* Dane bitmapy na ekranie */ BITMAPINFO
*info; /* Nagwek bitmapy na ekranie */
Rozdzia 12. Mapowanie tekstur_________________________________427

/*
* Zrzut ekranu...
*/
bits = ReadDIBitmap(sinfo);
if (bits == NULL)
{
DisplayErrorMessage( " N i e powiodo si odczytanie obrazu z
ekranu!");
return;
>;
/*
* Wywietlenie okna dialogowego...
*/
strcpy(directory, " . " ) ;
strcpy(filename, "bez nazwy.bmp");
strcpyltitle, " " ) ;
memset(sofn, O, sizeof(ofn));
ofn.lstructsize = sizeof( o f n ) ;
ofn.hwndOwner = SceneWindow;
ofn.lpstrFilter = "Bitmapy\0*.BMP\0\0";
ofn.nFilter!ndex = 1;
ofn.lpstrFile = filename;
ofn.nMaxFile = sizeof(filename) - 1;
ofn.lpstrFileTitle = title;
ofn.nMaxFileTitle = sizeof(title) - 1;
ofn.lpstrlnitialDir = directory;
ofn.IpstrTitle = "Zapisz plik bitmapy";
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST l
OFN_NONETWORKBUTTON;

if (GetSaveFileName( S o f n ) ) {
/*
* Zapis pliku na dysku...
*/
if (SaveDIBitmap(filename, info, b i t s ) )
DisplayErrorMessage("Could not save to file \ ' % s \ ' -\n%s",
filename, strerror(errno));
};
/*
* Zwolnienie pamici i p o w r t . . .
*/
free(info);
free(bits);
428 Cz II Uywanie OpenGL

* 'PrintBitmap()' - Wydruk wywietlanej sceny.


*/

void
PrintBitmap(void)
{
void *bits; /* Dane obrazu */
BITMAPINFO *info; /* Nagwek bitmapy */

/*
* Zrzut ekranu. . .
*/

bits = ReadDIBitmap (sinf o) ;


if (bits == NULL)
{
DisplayErrorMessage ( " N i e powiodo si odczytanie bitmapy ^z
ekranu! ") ;
return;

/*
* Wydruk bitmapy. . .
*/
PrintDIBitmap (Scenewindow, info, b i t s ) ;

/*
* Zwolnienie pamici i powrt...
*/

free (info) ;
free(bits) ;

/*
* 'GetClockO 1 - Czas, jaki upyn, w milisekundach...
*/
double
GetClock(void)
{
SYSTEMTIME curtime; /* Biecy czas systemowy */

GetSystemTime(icurtime);
return (curtime.wHour * 3600.0 +
curtime.wMinute * 6 0 . 0 +
curtime.wSecond +
curtime.wMilliseconds * 0 . 0 0 1 ) ;
Rozdzia 12. * Mapowanie tekstur 429

Podrcznik
glTexCoord
Przeznaczenie Okrela wsprzdne tekstury dla wielokta, na ktry nakadamy tekstur.
Plik nagwkowy <gl.h>
Skadnia void glTexCoordl {dfis}(TYPE s);
void glTexCoordl {dfis}v(TYPE *s);
void glTexCoord2{dfis}(TYPE s, TYPE t);
void glTexCoord2{dfis}v(TYPE *st);
void glTexCoord3 {dfis}(TYPE s, TYPE t, TYPE r);
void glTexCoord3{dfis}v(TYPE *str);
void glTexCoord4{dfis}(TYPE s, TYPE t, TYPE r, TYPE q);
void glTexCoord4{dfis}v(TYPE *strq);
Opis Ta funkcja ustala biece wsprzdne obrazu tekstury, dla jednego,
Parametry s t dwch, trzech lub czterech wymiarw. Na przykad, parametry s i t
odpowiadaj poziomej i pionowej wsprzdnej dwuwymiarowego
r obrazu tekstury.
Zwracana warto
Przykad Patrz Pozioma wsprzdna obrazu tekstury.
take Pionowa wsprzdna obrazu tekstury.
Wsprzdna gbokoci obrazu tekstury.
Wsprzdna czasu" obrazu tekstury
Brak.
Przejrzyj kod programu TEXSCENE.C na pytce CD-ROM.
glTextEnv, glTexGen, glTex!magelD, glTex!mage2D. glTexParameter

glTexEnv
Przeznaczenie Okrela parametry teksturowania.
Plik nagwkowy <gl.h>
Skadnia void glTexEnvf(GLenum target, GLenum pname, GLfloat param);
void glTexEnvfv(GLenum target, GLenum pname, GLfloat *param);
void glTexEnvi(GLenum target, GLenum pname, GLint param);
void glTexEnviv(GLenum target, GLenum pname, GLint *param);
430 Cz II * Uywanie OpenGL

Opis Funkcja glTexEnv ustawia parametry mapowania tekstury, sterujce


sposobem nakadania obrazw tekstur na wielokty. W trybie teksturowania
GL_DECAL obraz tekstury jest bezporednio nakadany na wielokty. W
trybach GL_BLEND i GL_MODULATE przy wyznaczaniu docelowego
koloru piksela uczestnicz take ju narysowane piksele oraz kolor
ustawiony parametrem GL_TEXTURE_ENV_COLOR.
Parametry
target GLenum: Definiowane rodowisko teksturowania, musi nim by
GL_TEXTURE_ENV.
GLenum: Nazwa definiowanego parametru. Dostpne parametry to:
pname GL_TEXTURE_ENV_MODE Okrela tryb teksturowania.
GL_TEXTURE_ENV_COLOR Okrela kolor do poczenia z tekstur
Warto parametru. Dla parametru GL_TEXTURE_ENV_COLOR
param param jest wskanikiem do wartoci koloru RGBA. Dla parametru
GL_TEXTURE_ENV_MODE moe by jedn z poniszych staych:
GL_DECAL Obraz tekstury jest bezporednio nakadany na wielokt.
GL_BLEND Przed naoeniem na wielokt, obraz tekstury jest mieszany z
okrelonym kolorem (GL_TEXTURE_ENV_COLOR).
GL_MODULATE Przed naoeniem na wielokt, obraz tekstury jest
mnoony przez istniejcy obraz w buforze ramki.
Zwracana Brak.
warto Przejrzyj kod programu TEXSCENE.C na pytce CD-ROM.
Przykad Patrz glTexCoord, glTexGen, glTex!magelD, gITex!mage2D. glTexParameter

glTexGen
Przeznaczenie Definiuje parametry generowania wsprzdnych tekstur.
Plik <gl.h>
nagwkowy void glTexGend(GLenum coord, GLenum pname, GLdouble param);
void glTexGenf(GLenum coord, GLenum pname, GLfloat param);
void glTexGeni(GLenum coord, GLenum pname, GLint param);
void glTexGendv(GLenum coord, GLenum pname, GLdouble *param);
void glTexGenfv(GLenum coord, GLenum pname, GLfloat *param);
void glTexGeniv(GLenum coord, GLenum pname, GLint *param);
Opis Gdy funkcj glEnable zostanie wczona jedna z opcji,
GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T,
GL_TEXTURE_GEN_R lub GL_TEXTURE_GEN_Q, funkcja
glTexGen ustawia parametry generowania wsprzdnych tekstur.
Rozdzia 12. Mapowanie tekstur 431

Gdy parametr GL_TEXTURE_GEN_MODE zostanie ustawiony na


GL_OBJECT_LINEAR, wsprzdne tekstur s generowane w wyniku
przemnoenia wsprzdnych biecego obiektu (wierzchoka) przez stay
wektor okrelony przez GL_OBJECT_PLANE:
coordinate = v [ 0 ] * p [ 0 ] + v [ l ] * p [ l ] + v [ 2 ] * p [ 2 ] + v [ 3 ] * p [ 3 ]
W przypadku GL_EYE_LINEAR s uywane wsprzdne obserwatora
(wsprzdne obiektu przemnoone przez macierz GL_MODELVIEW).
Gdy parametr GL_TEXTURE_GEN_MODE zostanie ustawiony na
GL_SPHERE_MAP, wsprzdne s generowane jako kula dookoa
biecego punktu obserwacji lub pocztku okadu.
Parametry
coord GLenum: Wsprzdna tekstury do wygenerowania. Musi ni by GL_S,
GL_T, GL_R lub GL_Q.
GLenum: Nazwa definiowanego parametru. Dostpne parametry to:
pname GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE lub
GL_EYE_PLANE.
Warto parametru. Dla parametru GL_TEXTURE_GEN_MODE param
param moe by jedn ze staych:
GL_OBJECT_LINEAR Wsprzdne tekstury s obliczane na podstawie
wsprzdnych obiektu (wierzchoka).
GL_EYE_LINEAR Wsprzdne tekstury s obliczane na podstawie
wsprzdnych punktu obserwacji (wsprzdnych obiektu przemnoonych
przez macierz GL_MODELVIEW).
GL_SPHERE_MAP Wsprzdne tekstury s generowane jako kula
dookoa punktu obserwacji.
Dla parametrw GL_OBJECT_PLANE i GL_EYE_PLANE, param jest
czteroelementow tablic uywan jako mnonik dla wsprzdnych
obiektu lub punktu obserwacji.
Zwracana warto Brak.
Przykad Patrz Przejrzyj kod programu TEXSCENE.C na pytce CD-ROM.
take glTexCoord, glTexEnv, glTex!magelD, glTex!mage2D. gITexParameter

glTexlmagelD
Przeznaczenie Definiuje jednowymiarowy obraz tekstury.
Plik nagwkowy
Skadnia void glTexImagelD(GLenum target, GLint Ievel, GLint components,
GLsizei width, GLint border, GLenum format, GLenum type, const
GLvoid *pixels);
432 Cz II Uywanie
OpenGL

Opis Ta funkcja definiuje jednowymiarowy obraz tekstury. Dane obrazu


podlegaj dziaaniu funkcji glPixelMap, glPixelStore oraz
glPixelTransfer.
Parametry
target level GLenum: Musi by GL_TEXTURE_1D.
GLint: Poziom szczegw mipmapy. Jeli nie s uywane mipmapy,
component zwykle wynosi zero.
wldth GLint: Ilo komponentw koloru, od l do 4.
GLsizei: Szeroko obrazu tekstury. Musi by potg liczby 2 lub by
border zgodna ze wzorem 2" + 2*border.
format GLint: Szeroko ramki dookoa obrazu tekstury. Musi by O, l lub 2.
GLenum: Format danych pikseli. Poprawne formaty to:
GL_COLOR_INDEX Wartoci pikseli s indeksami kolorw GL_RED
Wartoci pikseli s intensywnociami czerwieni GL_GREN Wartoci
pikseli s intensywnociami zieleni GL_BLUE Wartoci pikseli s
intensywnociami niebieskiego GL_ALPHA Wartoci pikseli s
wartociami alfa GL_RGB Wartoci pikseli s wartociami RGB
GLJR.GBA Wartoci pikseli s wartociami RGB A GL_LUMINANCE
Wartoci pikseli s kolorami w skali szaroci
GL_ALPHA_LUMINANCE Wartoci pikseli s wartociami alfa i
kolorami w skali szaroci
GLenum: Typ danych dla wartoci pikseli (patrz glDrawPixels).
type GLvoid*: Dane pikseli.
pbcels Brak.
Zwracana warto Przejrzyj kod programu TEX1D.C na pytce CD-ROM.
Przykad Patrz glPixe!Map, glPixelStore, glPixelTransfer, glTex!mage2D
take

glTexlmage2D
Przeznaczenie Definiuje jednowymiarowy obraz tekstury.
Plik nagwkowy
Skadnia void glTexImage2D(GLenum target, GLint level, GLint components,
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum
type, const GLvoid *pixels);
Rozdzia 12. o Mapowanie tekstur 433

Opis Ta funkcja definiuje dwuwymiarowy obraz tekstury. Dane obrazu


podlegaj dziaaniu funkcji glPixeIMap, glPixelStore oraz
glPixelTransfer.
Parametry
target level GLenum: Musi by GL_TEXTURE_2D.
GLint: Poziom szczegw mipmapy. Jeli nie s uywane mipmapy,
component zwykle wynosi zero.
width GLint: Ilo komponentw koloru, od l do 4.
GLsizei: Szeroko obrazu tekstury. Musi by potg liczby 2 lub by
height zgodna ze wzorem 2" + 2*border.
GLsizei: Wysoko obrazu tekstury. Musi by potg liczby 2 lub by
border zgodna ze wzorem 2" + 2*border.
format GLint: Szeroko ramki dookoa obrazu tekstury. Musi wynosi O, l lub 2.
GLenum: Format danych pikseli. Poprawne formaty to:
GL_COLOR_INDEX Wartoci pikseli s indeksami kolorw GL_RED
Wartoci pikseli s intensywnociami czerwieni GL_GREEN Wartoci
pikseli s intensywnociami zieleni GL_BLUE Wartoci pikseli s
intensywnociami niebieskiego GL_ALPHA Wartoci pikseli s
wartociami alfa GL_RGB Wartoci pikseli s wartociami RGB
GL_RGBA Wartoci pikseli s wartociami RGBA GL_LUMINANCE
Wartoci pikseli s kolorami w skali szaroci
GL_ALPHA_LUMINANCE Wartoci pikseli s wartociami alfa i
kolorami w skali szaroci
GLenum: Typ danych dla wartoci pikseli (patrz glDrawPixel).
type GLvoid*: Dane pikseli.
pucels Brak.
Zwracana Przejrzyj kod programu TEX2D.C na pytce CD-ROM.
warto glPixelMap, glPixelStore, glPixelTransfer, glTex!magelD
Przykad Patrz

Przeznaczenie glTexParameter
Plik Ustala parametry obrazu tekstury.
434 Cz II Uywanie OpenGL

Skadnia void glTexParameterf(GLenum target, GLenum pname, GLfloat param);


Opis void glTexParameterfv(GLenum target, GLenum pname, GLfloat
*param);
Parametry void glTexParameteri(GLenum target, GLenum pname, GLint param); void
target glTexParameteriv(GLenum target, GLenum pname, GLint *param);
pname Ta funkcja ustala filtr oraz parametry powtarzania obrazu tekstury.

GLenum: Musi to by GL_TEXTURE_1D lub GL_TEXTURE_2D.


GLenum: Ustawiany parametr tekstury. Poprawne nazwy to:
GL_TEXTURE_MIN_FILTER Okrela metod lub filtr stosowany przy
zmniejszaniu tekstury.
GL_TEXTURE_MAX_FILTER Okrela metod lub filtr stosowany przy
powikszaniu tekstury.
GL_TEXTURE_WRAP_S Okrela sposb traktowania wsprzdnych S
tekstury poza zakresem od 0,0 do l ,0.
GL_TEXTURE_WRAP_T Okrela sposb traktowania wsprzdnych T
tekstury poza zakresem od 0,0 do 1,0.
GL_BORDER_COLOR Okrela kolor ramki do tekstur bez ramki.
param Dla GL_TEXTURE_MIN_FILTER wartoci/wa/w moe by
GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR
oraz
GL_LINEAR_MIPMAP_LINEAR. Dla GL_TEXTURE_MAX_FILTER
param moe przybiera warto GL_NEAREST lub GL_LINEAR. Dla
GL_TEXTURE_WRAP_S i GL_TEXTURE_WRAP_T, mona go ustawi
na GL_REPEAT lub GL_CLAMP. GL_REPEAT powoduje powtarzanie
tekstury na caej powierzchni wielokta. W przypadku uycia GL_CLAMP
poza obszarem obrazu tekstury (zakresem od 0,0 do 1,0) jako koloru tekstury
uywa si koloru ramki lub okrelonego staego koloru (patrz poniej).
Dla GL_BORDER_COLOR param to tablica koloru RGB A uywanego jako
kolor ramki w przypadku, gdy obraz tekstury nie ma zdefiniowanych pikseli
ramki.
Zwracana warto Brak.
Przykad Przejrzyj kod programu TEXSCENE.C na pytce CD-ROM.
Patrz take glTexCoord, glTexEnv, glTexGen, glPixelTransfer, glTex!magelD
Rozdzia 13.
Kwadryki: sfery,
cylindry i dyski
W tym rozdziale:
Dowiesz si, jak... Uywane funkcje
* Tworzy kwadryki w celu narysowania * glNewQuadrics
prostych geometrycznych ksztatw
* Kontrolowa jako rysowanych
ksztatw
* Rysowa ksztaty uywajc innych * gluQuadricDrawStyle
prymityww OpenGL
+ Stosowa owietlenie i tekstury dla 4 gluQuadricNormals/ gluQuadricTexture
kwadryk

Ju sysz, jak pytasz, czym s kwadryki. C, kwadryki1 to cz biblioteki OpenGL


Utility Library (GLU32.LIB), obsugujcej rysowanie prostych trjwymiarowych ksztatw
geometrycznych. W szczeglnoci, zawarte w niej funkcje umoliwiaj rysowanie
stokw, cylindrw, dyskw i sfer. W tym rozdziale poznamy praktyczne zastosowania
funkcji kwadryk w naszych programach.

W rzeczywistoci kwadryki to rodzina powierzchni drugiego stopnia, takich jak


elipsoida, pa-raboloida itd. Za pomoc tych powierzchni mona budowa
opisywane w tym rozdziale obiekty. (Przyp. tum.)
436 Cz II * Uywanie OpenGL

Tworzenie kwadryk
Kada tworzona kwadryka ma pewien stan (kolekcj powizanych ze sob ustawie).
Funkcja gluNewQuadric tworzy zmienn stanu, opisujc aktualny styl rysowania,
orientacj, tryb owietlenia, tryb teksturowania oraz funkcj zwrotn:
GLUuadricObj *obj; obj

gluNewOuadric() ;

Zwr uwag, e stan kwadryki nie okrela ksztatu geometrycznego, jaki zostanie
utworzony. Zamiast tego opisuje, jak rysowa taki ksztat. Dziki temu mona stosowa
kwadryki przy tworzeniu wielu rnych rodzajw ksztatw.

Zmiana sposobu rysowania kwadryki


Gdy utworzysz kwadryk, moesz dostosowa sposb jej rysowania zmieniajc jej stan.
Su do tego funkcje biblioteki GLU: gluQuadricDrawStyle, gluQuadricNormals, glu-
QuadricOrientation oraz gluQuadricTexture.
void gluOuadricDrawStyle(GLUuadricObj * o b j , GLenum drawStyle); void
gluQuadricNormals(GLUuadricObj * o b j , GLenum normals); void
gluOuadricOrientation(GLUuadricObj * o b j , GLenum orientation); void
gluQuadricTexture(GLUuadricObj *obj, GLboolean textureCoords);

Funkcja gluQuadricDrawStyle suy do wyboru prymityww OpenGL uywanych do


konstruowania kwadryki. Domylnie ksztat kwadryki jest wypeniany wieloktami i pa-
skami prymityww(GLU_FILL). Inne dostpne style tworzenia zawiera tabela 13.1.

Tabela 13.1.
Style rysowania kwadryk

Styl______________Opis___________________________________

OLU_FILL Tworzone kwadryki s wypeniane przy uyciu wieloktw i


paskw
prymityww.
GLU_LINE Tworzone kwadryki s rysowane jako siatka, za pomoc
odcinkw.
GLU_SILHOUETTE Tworzone kwadryki s rysowane za pomoc odcinkw, z tym e
rysowane sjedynie zewntrzne krawdzie.
GLU_POINT Tworzone kwadryki s rysowane jako zbir punktw.

W przypadku kwadryk, normalne s zwykle generowane automatycznie. Obliczaniem


normalnych steruje funkcja gluQuadricNormals. Dostpne sposoby generowania nor-
malnych zawiera tabela 13.2.
Rozdzia 13. Kwadryki: sfery, cylindry i dyski__________________________437

Tabela 13.2.
Tryby obliczania normalnych

Tryb obliczania Opis


GLU_NONE Nie s generowane normalne.
GLU_FLAT Normalne s generowane dla wieloktw, przez co powstaj paskie
cianki.
GLU_SMOOTH Normalne s generowane dla wierzchokw, przez co powstaje
gadka
powierzchnia.

Do sterowania kierunkiem normalnych suy funkcja gluQuadricOrientation, okrelajca,


czy normalne wskazuj na zewntrz (GLU_OUTSIDE) czy do wewntrz kwadryki
(GLU_INSIDE). Ma to szczeglne znaczenie w przypadku sfer (czy znajdujesz si we-
wntrz lub na zewntrz sfery).

Na koniec, w przypadku kwadryk mona zayczy sobie automatycznego generowania


wsprzdnych tekstury. Do wczania i wyczania generowania wsprzdnych tekstury
suy funkcja gluQuadricTexture. Do wczania generowania wsprzdnych tekstur suy
staa GLUJTRUE, za do wyczenia - staa GLU_FALSE. O wyborze wsprzdnych
tekstur powiemy sobie wicej w momencie, gdy zaczniemy rysowa kwadryki na ekranie.

Jak zapewne pamitasz, wsprzdne tekstur s uywane przy nakadaniu obrazw te-
kstur na wielokty (rozdzia 12).

Rysowanie cylindrw
Do rysowania cylindrw suy funkcja gluCylinder. Cylinder rysowany za pomoc tej
funkcji to po prostu tuba uoona wzdu osi z (rysunek 13.1). Podstawy cylindra nie s
wypeniane!

Rysunek 13.1. baseRadius


Cylinder
(0,0,height)

^P-^ M ^^^"Tk:
(0,0,0)
topRodius
void gluCylider(GLUuadricObj
*obj,
GLdouble baseRadius,
GLdouble topRadius,
GLdouble height, GLint
slices, GLint stacks)
438____________________________________Cz II Uywanie OpenGL

Parametry baseRadius i topRadius okrelaj promie cylindra przy dolnej i grnej pod-
stawie. Parametr height okrela wysoko (czy te dugo) cylindra.
Parametry slices i stacks okrelaj,, z ilu czci (cian) oraz z ilu segmentw (piter) bdzie
si skada cylinder. Oglnie, aby nada cylindrom gadkie ciany, powiniene uy
okoo 20 cian. Mniejsze wartoci powoduj, e cylinder zaczyna przypomina
graniastosup, za wartoci wiksze mog powodowa powstawianie mieci na rysunku.
Gdy stosujesz wiato punktowe lub wiato odbyskw, powiniene take wybra wiksz
ilo segmentw. W przeciwnym razie wybierz dwa segmenty, odpowiadajce obu
podstawom cylindra.
Cylindry mona wykorzysta take do tworzenia graniastosupw foremnych, takich jak
owek czy szecian.

Rysowanie stokw
Biblioteka GLU nie posiada specjalnej funkcji do rysowania stokw, mona jednak
uy w tym celu funkcji gluCylinder. W tym celu wystarczy poda warto 0,0 jako pa-
rametr topRadius lub bottomRadius.

Teksturowanie cylindrw
Podczas teksturowania cylindra, obraz tekstury jest na nim zawijany poczwszy od przedniej
krawdzi (O, promie, 0). To oznacza, e obraz tekstury powinien by odwrcony do gry
nogami". Nakadanie tekstury na cylinder przeprowadzimy w programie projektu w tym
rozdziale.

Rysowanie dyskw
Dyski to okrge, paskie ksztaty, ktre mog zawiera dziury. Przykadami dyskw
mog by monety lub piercienie.
void gluDisk(GLUquadricObj *obj,
GLdouble innerRadius,
GLdouble outerRadius,
GLint slices, GLint
loops)

Parametry outerRadius i innerRadius okrelaj promie caego dysku oraz zawartej w


nim dziury. Jeli argument innerRadius ma warto 0,0, dysk jest rysowany jako jednolity
okrg (rysunek 13.2).
Parametr slices okrela ilo cianek dysku i powinnien wynosi okoo 20, jeli chcemy,
aby dysk wyglda na gadki,. Parametr loops okrela ilo koncentrycznych okrgw
tworzcych dysk (pomidzy wewntrznym a zewntrznym promieniem); powinien by
Rozdzia 13. Kwadryki: sfery, cylindry i dyski_________________________439

rwny l dla okrgw i 2 dla piercieni. Tak jak w przypadku cylindrw, uycie wi-
kszych wartoci poprawia efekt wiata punktowego i odbyskw.

Rysunek 13.2. InnerRodius


Dysk

Teksturowanie dysku
Obrazy tekstur s nakadane tak,
aby krawdzie obrazu OuterRodius

pokryway si z krawdziami
dysku. Grna krawd tekstury
pokrywa si z grn krawdzi dysku, lewa krawd tekstury pokrywa si z lew
krawdzi dysku itd.

Rysowanie czciowych dyskw


Biblioteka GLU zawiera funkcj przeznaczon do rysowania czci dysku. Podczas ry-
sowania takiego obiektu podaje si kt pocztkowy oraz kt zataczany przez powie-
rzchni dysku. Parametr startAngle okrela pocztkowy kt, liczony zgodnie z ruchem
wskazwek zegara od gry dysku. Argument sweepAngle okrela ilo stopni uku, ktry ma
zosta utworzony. Na przykad, 90 oznacza jedn czwart dysku, itd.
void gluPartialDisk(GLUuadricObj *obj,
GLdouble innerRadius,
GLdouble outerRadius, GLint
slices, GLint loops,
GLdouble startAngle,
GLdouble sweepAngle)

Rysowanie sfer
Kule to puste piki. Gdy rysujesz sfer, okrelasz jej promie oraz ilo cianek.
void gluSphere(GLUuadricObj *obj,
GLdouble radius,
GLint slices, GLint
stacks)

Jeli potraktujesz sfer jak sfer ziemsk, parametr slices reprezentuje ilo poudnikw,
za parametr stacks - ilo rwnolenikw (rysunek 13.3).
440 Cz II * Uywanie OpenGL

Rysunek 13.3.
Sfera
Rwnoleniki

Poudniki

Teksturowanie sfer
Obrazy tekstur s nakadane zgodnie z poudnikami i rwnolenikami. Tak wic obraz
mapy wiata zostanie poprawnie naoony na sfer.

Rysowanie owka
Aby zamkn ten rozdzia, napiszemy may program, sucy do przedstawienia obraca-
jcego si owka (rysunek 13.4). Owek bdzie si skada z trzech cylindrw i dwch
obrazw tekstur. Pierwszy obraz zawiera typowe symbole dla owka nr 2 oraz napis
OpenGL Country Club". Jako zaostrzony koniec owka zastosujemy drugi obrazek,
przedstawiajcy drewno z wystajcym grafitem.
Rysunek 13.4.
Owek stworzony
przy uyciu kwadryk

Czubek owka to oczywicie stoek. Drugi koniec owka nie jest ju taki oczywisty.
Poniewa jest paski, mgby oczekiwa, e do jego utworzenia uyjemy dysku. Niestety,
w przypadku uytej tekstury (rysunek 13.5) efekt jej naoenia nie wygldaby
najlepiej. Tak wic, zamiast dysku uyjemy cylindra o zerowej wysokoci i zerowym
grnym promieniu.
Rozdzia 13. Kwadryki: sfery, cylindry i dyski
441
Rysunek
13.5.
Obrazy tekstur na
ciany owka i

Poniewa kwadryki s rysowane w pocztku ukadu wsprzdnych, przed ich naryso-


waniem musimy przesun wsprzdne. Na przykad, aby narysowa cianki owka,
musimy wykona to:
glPushMatrix();
glTranslatef( 0 . 0 , 0 . 0 , - 2 0 . 0 ) ;
gluCylinder(PencilObj, 5.0, 5.0, 4 . 0 , 6 , 2 ) ;
glPopMatrix();

W programie rysujcym program (listing 13.1) za rysowanie caego owka odpowiada


funkcja RepaintWindow. Pierwsz rysowan czci s cianki owka, utworzone z
cylindra posiadajcego sze stron.
gluQuadricNormals(PencilObj, GLU_FLAT);
glCallList(PencilTexture) ;
glPushMatrix() ;
glTranslatef( 0 . 0 , 0 . 0 , - 2 0 . 0 ) ;

gluCylinder(PencilObj, 5 . 0 , 5 . 0 , 40.0, 6, 2 ) ;
glPopMatrix();

Nastpnie rysujemy czubek i koniec owka uywajc tekstury grafitu". Take rym
razem stosujemy cylindry skadajce si z szeciu stron.
gluOuadricNormals(PencilObj, GLU_SMOOTH);
glCallList(LeadTexture) ;
442____________________________________Cz II Uywanie OpenGL

glPushMatrix();
glTranslatef (0.0, 0.0, 2 0 . 0 ) ;

gluCylinder(PencilObj, 5 . 0 , 0 . 0 , 7 . 5 , 6, 2);
glPopMatrix();
glPushMatrix();
glTranslatef ( 0 . 0 , 0.0, -20.0);

gluCylinder(PencilObj, 5 . 0 , 0 . 0 , 0 . 0 , 6, 2 ) ;
glPopMatrix();

Podsumowanie
W tym rozdziale poznalimy funkcje suce do rysowania kwadryk. Kwadryki w OpenGL
to geometryczne ksztaty tworzce podstawowe klocki" do budowy wielu innych obiektw,
zarwno sztucznych, jak naturalnych. Uycie kwadryk jest wygodnym sposobem uniknicia
koniecznoci tworzenia dodatkowego kodu budujcego tego typu ksztaty.
Przejdmy teraz do listingu 13.1, programu rysujcego owek. Listing
13.1. Program rysujcy owek______________________________________
/*
* Niezbdne nagwki.
*/
include "texture.h"
include "pencil.h"
tinclude <stdarg.h>

/*
* Zmienne globalne...
*/
HWND PencilWindow; /* Okno sceny */
HPALETTE PencilPalette; /* Paleta kolorw (jeli potrzebna) */
HDC PencilDC; /* Kontekst rysowania */
HGLRC PencilRC; /* Kontekst renderowania OpenGL */

GLuint PencilTexture, /* Obraz tekstury owka */


LeadTexture; /* Grafit... */
GLfloat PencilRoll = 0 . 0 , /* Pooenie owka */
PencilPitch = 9 0 . 0 ,
PencilHeading = 0 . 0 ;
GLUuadricObj *PencilObj;

/*
* Funkcje lokalne...
*/
Rozdzia 13. Kwadryki: sfery, cylindry i dyski_________________________443

void DisplayErrorMessage(char *, . . . ) ;
void MakePalette( i n t ) ;
LRESOLT CALLBACK PencilProc(HWND, UINT, WPARAM, LPARAM);
void LoadAllTextures(void);
void RepaintWindow(RECT * ) ;
void PrintBitmap(void);

/*
* 'WinMainO '
*/
int APIENTRY
WinMain(HINSTANCE hlnst,
HINSTANCE hPrevInstance, LPSTR
IpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS we; RECT
rect;

w e . style = 0;
wc.lpfnWndProc = (WNDPROC)PencilProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hlnstance = hlnst;
wc.hlcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = 0;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.lpszClassName = "Textured Quadric Pencil";
if (RegisterClass( S w e ) == 0) {
DisplayErrorMessage( " N i e udao si zarejestrowanie o k n a ! " } ;
return ( F A L S E ) ;
};
PencilWindow = CreateWindow("Textured Quadric Pencil",
"Owek stworzony z teksturowanych
kwadryk",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS, 32, 32, 400, 300, NOLL,
NULL, hlnst, NULL);

if (PencilWindow == NULL) {
DisplayErrorMessage( " N i e udao si utworzenie o k n a ! " ) ;
return ( F A L S E ) ;
};
ShowWindow(PencilWindow, nCmdShow);
OpdateWindow(PencilWindow);
444 Cz II Uywanie OpenGL

// Gwna ptla komunikatw


while (TRUE)

while (PeekMessagetsmsg, NULL, O, O, PM_NOREMOVE) == TRUE) if


(GetMessage (smsg, NULL, O, 0 ) ) {
TranslateMessage ( smsg) ;
DlspatchMessage (&msg) ; }
else
return ( 1 ) ;

* Obrt owka. . .
*/

PencilRoll += 1 . 0 ;
PencilPitch += 2 . 0 ;
PencilHeading += 3 . 0 ;

GetclientRect (Pencilwindow, Srect) ;


RepaintWindow (Srect) ;
return (msg.wParam) ;

* 'DisplayErrorMessage()' - Wywietla okno komunikatu bdu.


*/

void DisplayErrorMessage(char *format,


// We - acuch formatowania w stylu printfO . . . ) //We -
Pozostae argumenty {
va_list ap; /* Wskanik argumentu */
char s[1024]; /* acuch wyjciowy */

if (format == NULL)
return;

va_start(ap, format);
vsprintf(s, format, ap);
va_end(ap);

MessageBeep(MB_ICONEXCLAMATION);
MessageBox(NULL, s, " E r r o r " , MB_OK | MB_ICONEXCLAMATION) ,

/*
* 'MakePalette () ' - Jeli trzeba, tworzy palet kolorw.
*/
Rozdzia 13. Kwadryki: sfery, cylindry i dyski__________________________445

void
MakePalette(int p f ) /* We - ID formatu pikseli */
{
PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE *pPal;
int nColors;
int i,
r
max,
gmax,
brn x;

/*
* Sprawdzenie, czy paleta jest potrzebna... V
DescribePixelFormat(PencilDC, pf, sizeof(PIKELFORMATDESCRIPTOR) ,
spfd);
if (!(pfd.dwFlags & PFD_NEED_PALETTE))
{
PencilPalette = NULL;
return;
};
/*
* Alokowanie pamici dla palety.
*/
nColors = l pfd.cColorBits;

pPal = (LOGPALETTE *)malloc(sizeof(LOGPALETTE) +


nColors * sizeof(PALETTEENTRY));

pPal->palVersion = 0x300; pPal-


>palNumEntries = nColors;

/*
* Odczyt maksymalnych wartoci barw skadowych i budowanie nColors
* kolorw
*/
rmax = (l pfd.cRedBits) - 1;
gmax = (l pfd.cGreenBits) - 1;
bmax = (l pfd.cBlueBits) - 1;
for (i = 0 ; i < nColors; i ++) {
pPal->palPalEntry[i].peRed = 255 * ( (i pfd.cRedShift) S rmax) /
rmax ;
pPal->palPalEntry[i].peGreen = 255 * ((i pfd.cGreenShift) 4
^gmaK) /
gmax;
pPal->palPalEntry[i].peBlue = 255 * ((i pfd.cBlueShift) &
c
>bmax) /
bmax ;
pPal->palPalEntry[ i ] .peFlags = 0;
446 ____________________________________ Cz II Uywanie OpenGL

/*
* Utworzenie, wybranie i realizacja palety
*/
PencilPalette = CreatePalette (pPal) ;
SelectPalette(PencilDC, PencilPalette, FALSE) ;
RealizePalette (PencilDC) ;
free (pPal) ;

/*
* ' PencilProc ( ) ' - Obsuga komunikatw okna sceny.
*/
LRESULT CALLBACK
PencilProc (HWND hWnd,
UINT uMsg, WPARAM wParam,
LPARAM IParam) (
int p f ; /* ID formatu pikseli */
PIXELFORMATDESCRIPTOR pfd; /* informacje o formacie pikseli */
PAINTSTRUCT ps;
RECT rect;

switch (uMsg) {
case WM_CREATE :
// Pobranie kontekstu urzdzenia i renderowania,
// przygotowanie obszaru klienta dla OpenGL
PencilDC = GetDC(hWnd) ;

pfd.nSize sizeof (pfd) ;


pfd.nVersion = i;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL
PFDJ30UBLEBUFFER;
// Dla OpenGL
pfd.dwLayerMask = PFD_MAIN_PLANE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 0; pfd.cDepthBits
= 32; pfd.cStencilBits = 0;
pfd.cAccumBits = 0;

pf = ChoosePixelFormat (PencilDC, spfd) ; if


( p f == 0)
DisplayErrorMessage (
"Program nie mg znale odpowiedniego formatu
pikseli ! ") ;
else if ( !SetPixelFormat (PencilDC, pf, S p f d ) )
DisplayErrorMessage (
"Program nie mg ustawi odpowiedniego formatu
pikseli! ") ;
MakePalettetpf ) ;
PencilRC = wglCreateContext (PencilDC) ;
Rozdzia 13. Kwadryki: sfery, cylindry i dyski_________________________447

wglMakeCurrent(PencilDC, PencilRC);
// adowanie obrazw tekstur do list wywietlania...

LoadAllTextures(); PencilObj =
gluNewQuadric();
gluQuadricTexture(PencilObj, GL_TRHE);
break;
case WM_SIZE :
case WM_PAINT :
// Odrysowanie obszaru klienta...
BeginPaint(hWnd, ips);

GetClientRect(hWnd, srect);
RepaintWindow(Srect);
EndPaint(hWnd, & p s ) ;
break;

case WM_COMMAND :
/*
* Obsuga menu...
*/

switch (LOWORD(wParam))
{
case IDM_FILE_PRINT :
PrintBitmap();
break; case
IDM_FILE_EXIT :
DestroyWindow(PencilWindow);
break;
}; break;
case WM_QUIT :
case WM_CLOSE :
/*
* Zniszczenie okna,'bitmap i wyjcie...
*/
DestroyWindow(PencilWindow);

exit(0);
break;

case WM_DESTROY :
/*
* Zwolnienie kontekstu urzdzenia, kontekstu
* renderowania i palety
*/
if (PencilRC)
wglDeleteContext(PencilRC);
if (PencilDC)
ReleaseDC(PencilWindow, PencilDC);
448____________________________________Cz II Uywanie OpenGL

if (PencilPalette)
Deleteobject(PencilPalette) ;

PostQuitMessage( 0 ) ;
break;
case WM_QUERYNEWPALETTE :
/*
* w razie potrzeby realizacja palety...
*/
if (PencilPalette)
{
SelectPalette(PencilDC, PencilPalette, FALSE);
RealizePalette(PencilDC);

InvalidateRect(hWnd, NULL, FALSE);


return (TRUE);
}; break;
case WM_PALETTECHANGED: /*
* W razie potrzeby ponowne wybranie palety...
*/
if (PencilPalette SS (HWND)wParam != hWnd) {
SelectPalette(PencilDC, PencilPalette, FALSE);
RealizePalette(PencilDC);

UpdateColors(PencilDC);
}; break;
default :
/*
* Standardowa obsuga wszystkich innych komunikatw
*/
return (DefWindowProc(hWnd, uMsg, wParam, IParam)); };
return (FALSE);

/*
* 'LoadAllTextures()' - aduje tekstury dla sceny.
*/

void
LoadAllTextures(void)
{
glNewList(PencilTexture = glGenLists( 1 ) , GL_COMPILE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT),
TextureLoadBitmap("pencil.bmp"); glEndList();
Rozdzia 13. Kwadryki: sfery, cylindry i dyski _________________________ 449

glNewList (LeadTexture = glGenLists ( 1 ) , GL_COMPILE) ;


glTexParameteri(GL_TEXTURE_2D, GL_TEXTORE_WRAP_S , GL_REPEAT) ;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAPJT, GL_REPEAT) ;
TextureLoadBitmap("lead.bmp") ;
glEndList () ;

/*
* ' RepaintWindow ( ) ' - Odrysowuje obszar roboczy okna sceny.
*/
void
RepaintWindow (RECT *rect) /* We - Obszar roboczy okna */ {
/*
* Wyzerowanie widoku i wyczyszczenie okna na jasny bkit
*/
glYiewport ( O , O, rect->right, rect->bottom) ;
glClearColor ( 0 . 7 , 0.7, 1 . 0 , 1 . 0 ) ;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;

/*
* Przygotowanie przeksztacenia widoku dla biecego
* punktu obserwacji
*/
glMatrixMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective ( 4 5 . O, (float) rect->right / (float) rect->bottom,
0 . 1 , 1000.0);
glEnable (GL_LIGHTING) ;
glEnable (GL_LIGHTO) ;
glEnable (GL_DEPTH_TEST) ;
glEnable (GL_TEXTURE_2D) ;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) ;

glMatrixMode(GL_MODELVIEW) ;
glPushMatrix ( ) ;
glTranslatef ( 0 . 0 , 0 . 0 , - 8 0 . 0 ) ;
glRotatef (PencilHeading, 0 . 0 , -1.0, 0 . 0 ) ;
glRotatef (PencilPitch, 1 . 0 , 0 . 0 , 0 . 0 ) ;
glRotatef (PencilRoll, 0 . 0 , 0 . 0 , - 1 . 0 ) ;

/*
* Najpierw cianki owka - cylinder z szecioma ciankami
*/
gluOuadricNormals (PencilObj , GLU_FLAT) ;
glCallList (PencilTexture) ;
glPushMatrix () ;
glTranslatef ( 0 . 0 , 0.0, -20.0);

gluCylinder (PencilObj , 5 . 0 , 5 . 0 , 40.0, 6, 2 ) ;


glPopMatrix() ;
450 ____________________________________ Cz II Uywanie OpenGL

/*
* Koce owka - stoek na czubku i piaski stoek na kocu
*/

gluQuadricNormals (PencilObj , GLU_SMOOTH) ;


glCallList (LeadTexture) ;
glPushMatrix() ;
glTranslatef (0.0, 0.0, 2 0 . 0 ) ;

gluCylinder (PencilObj, 5 . 0 , 0 . 0 , 7 . 5 , 6, 2 ) ;
glPopMatrix () ;
glPushMatrix ( ) ;
glTranslatef ( 0 . 0 , 0 . 0 , - 2 0 . 0 ) ;

/*
* Normalnie uylibymy dysku, ale niestety, nie pasuj
* wsprzdne tekstury
*/
gluCylinder (PencilObj, 5 . 0 , 0 . 0 , 0 . 0 , 6, 2 ) ;
glPopMatrix () ; glPopMatrix ( ) ;
/*
* Przerzucenie buforw i powrt
*/
glFinish ( ) ;
SwapBuf fers (PencilDC) ;

/*
* 'PrintBitmapO ' - Wydruk wywietlanej sceny.
*/
void
PrintBitmap (void)
{
void *bits; /* Dane obrazu */
BITMAPINFO *info; /* Nagwek bitmapy */

/*
* Zrzut ekranu. . .
*/
bits = ReadDIBitmap (sinf o) ;
if (bits == NULL)
{
DisplayErrorMessage ( " N i e powiodo si odczytanie bitmapy z
ekranu! ") ;
return;

* Wydruk bitmapy.
*/
Rozdzia 13. Kwadryki: sfery, cylindry i dyski 451

PrintDIBitmap (PencilWindow, info, bits)

* Zwolnienie pamici i p o w r t . . .
*/
free (info) ;
free(bits) ;

Podrcznik
gluCylinder
Przeznaczenie Rysuje cylinder.
Plik nagwkowy <glu.h>
Skadnia void gluCylinder(GLUquadricObj *obj, GLdouble baseRadius, GLdouble
topRadius, GLdouble height, GLint slices, GLint stacks);
Opis Ta funkcja tworzy pusty cylinder bez podstaw, uoony wzdu osi z. Jeli
parametr topRadius lub bottomRadius wynosi zero, tworzony jest stoek.
Cylinder ma dugo height jednostek wzdu osi z. Parametr slices okrela
ilo cian cylindra, za parametr stacks - ilo segmentw wzdu cylindra.
Parametry obj
GLUuadricObj*: Informacje o stanie kwadryki, uywane podczas
baseRadius rysowania.
topRadius GLdouble: Promie dolnej podstawy cylindra (Z = 0).
height GLdouble: Promie grnej podstawy cylindra (Z = height).
slices GLdouble: Wysoko (dugo) cylindra wzdu osi z.
height GLint: Ilo bocznych cian cylindra.
Zwracana warto GLint: Ilo segmentw cylindra (wzdu osi z).
Przykad Patrz Brak.
take Przejrzyj kod programu PENCIL.C na pytce CD-ROM.
gluDeleteCjuadric, gluNewQuadric, gluQuadricCallback,
gluCjuadricDrawStyle, gIuQuadricNormals, gluQuadricOrientation,
gluQuadricTexture
452 Cz II Uywanie OpenGL

gluDeletepuadric
Przeznaczenie Plik Usuwa obiekt stanu kwadryki.
nagwkowy <glu.h>
Skadnia Opis void gluDeleteQuadric(GLUquadricObj *obj);
Ta funkcja usuwa obiekt stanu kwadryki. Po usuniciu obiektu nie mona
Parametry go ponownie uy do rysowania.
obj
Zwracana warto GLUuadricObj*: Obiekt stanu przeznaczony do usunicia. Brak.
Patrz take gluNewQuadric, gluQuadricCallback, gluQuadricDrawStyle,
gluQuadricNormals, glupuadricOrientation, gluQuadricTexture

gluDisk
Przeznaczenie Plik Rysuje dysk.
nagwkowy <glu.h>
Skadnia void gluDisk(GLUquadricObj *obj, GLdouble innerRadius, GLdouble
outerRadius, GLint slices, GLint loops);
Opis Ta funkcja tworzy dysk prostopady do osi z. Jeli parametr innerRadius
wynosi zero, zamiast dysku tworzony jest piercie. Parametr slices okrela
ilo cian cylindra, za parametr loops ilo piercieni dysku.
Parametry obj
GLUuadricObj*: Informacje o stanie kwadryki, uywane podczas
innerRadius rysowania.
outerRadius GLdouble: Wewntrzny promie dysku.
slices GLdouble: Zewntrzny promie dysku.
height GLint: Ilo bocznych cian dysku. GLint:
Zwracana warto Ilo piercieni dysku. Brak.
Patrz take gluDeleteQuadric, gluNewQuadric, gluQuadricCallback,
gluQuadricDrawStyle, gluQuadricNormals, gluQuadricOrientation,
gluQuadricTexture
Rozdzia 13. Kwadryki: sfery, cylindry i dyski 453

gluNewQuadric
Przeznaczenie Plik Tworzy nowy obiekt stanu kwadryki.
nagwkowy <glu.h>
Skadnia Opis GLUuadricObj *gluNewQuadric(void);
Ta funkcja tworzy nowy obiekt stanu kwadryki. Obiekt stanu kwadryki
Parametry zawiera informacje okrelajce sposb rysowania kwadryk.
Zwracana warto Brak.
GLUuadricObj *: NULL w przypadku braku pamici; w przeciwnym
Przykad razie wskanik do obiektu stanu kwadryki.
Patrz take Kod programu PENCIL.C na pytce CD-ROM.
gluDeleteQuadric, gluQuadricCallback, gluQuadricDrawStyle,
gluQuadricNormals, gluQuadricOrientation, g!uQuadricTexture

gluPartialDisk
Przeznaczenie Rysuje czciowy dysk.
Plik nagwkowy <glu.h>
Skadnia voidgluPartialDisk(GLUquadricObj *obj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops, GLdouble startAngle,
GLdouble sweepAngle);
Opis Ta funkcja tworzy cz dysku prostopadego do osi z. Jeli parametr
innerRadius wynosi zero, zamiast dysku tworzony jest piercie. Parametr
slices okrela ilo cian cylindra, za parametr loops - ilo piercieni
dysku. Parametr startAngle okrela pocztkowy kt dysku (kt 0 to gra
dysku, za 90 to prawa strona dysku). Parametr sweepAngle okrela uk
zajmowany przez dysk, w stopniach.
Parametry obj
GLUuadricObj*: Informacje o stanie kwadryki, uywane podczas
innerRadlus rysowania.
outerRadius slices GLdouble: Wewntrzny promie dysku.
height startAngle GLdouble: Zewntrzny promie dysku.
sweepAngle GLint: Ilo bocznych cian dysku. GLint:
Zwracana warto Ilo piercieni dysku. GLdouble:
Pocztkowy kt czci dysku. GLdouble:
Ktowy rozmiar czci dysku. Brak.
454 Cz II Uywanie OpenGL

Patrz take gluDeleteQuadric, gluNewQuadric, gluQuadricCallback,


gluQuadricDrawStyle, gluQuadricNormals, gluQuadricOrientation,
gluQuadricTexture

gluQuadricCallback
Przeznaczenie Definiuje funkcj zwrotn kwadryki.
Plik nagwkowy <glu.h>
Skadnia void gluQuadricCallback(GLUquadricObj *obj, GLenum which, void

Opis Ta funkcja definiuje funkcj zwrotn wywoywan podczas rysowania


ksztatu kwadryki. Obecnie jedyn zdefiniowan funkcj zwrotn jest
GLU_ERROR, wywoywana w momencie wystpienia bdu biblioteki
OpenGL lub biblioteki GLU.
Parametry obj
which GLUuadricObj *: Wskanik do obiektu informacji o stanie kwadryki.
Zwracana warto GLenum: Definiowana funkcja zwrotna. Musi ni by GLU_ERROR.
Patrz take void (*)(): Funkcja zwrotna. (Otrzymuje parametr typu GLenum
zawierajcy kod bdu).
Brak.
gluDeleteQuadric, gluNewQuadric, gluQuadricDrawStyle,
gluQuadricNormals, gluQuadricOrientation, gluQuadricTexture

gluQuadricDrawStyle
Przeznaczenie Okrela styl rysowania kwadryki.
Plik nagwkowy <glu.h>
Skadnia Opis void gluQuadricDrawStyle(GLUquadricObj *obj, GLenum drawStyle);
Parametry Ta funkcja suy do wyboru stylu rysowania kwadryki.
obj
drawStyle GLUuadricObj *: Wskanik do obiektu informacji o stanie kwadryki.
GLenum: Styl rysowania. Dostpne style to:
GLU_FILL Kwadryki s tworzone za pomoc wieloktw i paskw
prymityww.
GLU_LINE Kwadryki s rysowane jako siatka odcinkw.
GLU_SILHOUETTE Kwadryki s rysowane jako siatka odcinkw, z tym
e rysowane s jedynie zewntrzne krawdzie.
GLU_POINT Kwadryki s tworzone jako zbir punktw.
Rozdzia 13. * Kwadryki: sfery, cylindry i dyski 455

Zwracana warto Brak.


Patrz take gluDeletepuadric, gluNewQuadric, glQuadricCallback,
gluQuadricNormals, gluQuadricOrientation, gluQuadricTexture

gluQuadricNormals
Przeznaczenie Okrela sposb generowania normalnych dla punktw kwadryki.
Plik nagwkowy <glu.h>
Skadnia Opis void gluQuadricNormals(GLUquadricObj *obj, GLenum normals);
Ta funkcja okrela sposb generowania normalnych dla kwadryk
Parametry rysowanych z uyciem tego obiektu stanu.
obj
normals GLUuadricObj *: Wskanik do obiektu informacji o stanie kwadryki.
GLenum: Sposb generowania normalnych. Dostpne style to:
GLU_NONE Normalne nie s generowane.
GLU_FLAT Normalne s generowane dla caych wieloktw, co
powoduje, e kwadryka wyglda na zbudowan ze cianek.
GLU_SMOOTH Normalne s generowane dla poszczeglnych
wierzchokw, co powoduje, e powierzchnia kwadryki wydaje si
gadka.
Zwracana warto Brak.
Przykad Patrz Przykadowy program PENCIL.C na pytce CD-ROM.
take gluDeleteQuadric, gluNewQuadric, glQuadricCallback,
gluQuadricDrawStyle, gluQuadricOrientation, gluQuadricTexture

gluQuadricOrientation
Przeznaczenie Okrela kierunek normalnych kwadryki.
Plik nagwkowy <glu.h>
Skadnia Opis void gluQuadricOrientation(GLUquadricObj *obj, GLenum orientation);
Ta funkcja okrela kierunek normalnych dla pustych obiektw. Jeli
normalne maj wskazywa na zewntrz obiektu, parametr orientation
powinien mie warto GLU_OUTSIDE. Jeli normalne maj wskazywa
do wntrza obiektu, parametr orientation powinien mie warto GLU
INSIDE.
Parametry
obj GLUquadricObj *: Wskanik do obiektu informacji o stanie kwadryki.
456 Cz II Uywanie OpenGL

orientation GLenum: Kierunek normalnych. Dostpne kierunki to GLU_INSIDE


i GLU_OUTSIDE. Domylnym kierunkiem jest GLU_OUTSIDE.
Zwracana warto Brak.
Patrz take gluDeleteQuadric, gluNewQuadric, glQuadricCallback,
gluQuadricDrawStyle, gluQuadricNormals, gluQuadricTexture

gluQuadricTexture
Przeznaczenie Plik Wcza lub wycza generowanie wsprzdnych tekstury dla kwadryk.
nagwkowy <glu.h>
Skadnia void gluQuadricTexture(GLUquadricObj *obj, GLboolean
textureCoords);
Opis Ta funkcja okrela, czy bd generowane wsprzdne tekstury dla
kwadryki.
Parametry obj
textureCoords GLUuadricObj *: Wskanik do obiektu informacji o stanie kwadryki.
GLboolean: GLU_TRUE, jeli wsprzdne tekstury maj by
Zwracana warto generowane, GLU_FALSE w przeciwnym wypadku.
Patrz take Brak.
gluDeleteQuadric, gluNewQuadric, glQuadricCallback,
gluQuadricDrawStyle, gluQuadricNormals, gluQuadricOrientation

gluSphere
Przeznaczenie Plik Rysuje sfer.
nagwkowy <glu.h>
Skadnia void gluSphere(GLUquadricObj *obj, GLdouble radius, GLint slices,
GLint stacks);
Opis Ta funkcja tworzy sfer, uoon w rodku ukadu wsprzdnych.
Parametr slices okrela ilo poudnikw sfery, za parametr stacks -
ilo jej rwnolenikw sfery.
Parametry obj
GLUuadricObj*: Informacje o stanie kwadryki, uywane podczas
slices height rysowania.
Zwracana warto Glint: Ilo poudnikw sfery. GLint:
Ilo rwnolenikw sfery. Brak.
Rozdzia 13. Kwadryki: sfery, cylindry i dyski_________________________457

Przykad Przejrzyj kod programu PENCIL.C na pytce CD-ROM.


Patrz take gluDeleteQuadric, gluNewQuadric, gluQuadricCallback,
gluQuadricDrawStyle, gluQuadricNormals, gluQuadricOrientation,
gluQuadricTexture
Tematy zaawansowane i efekty specjalne
Jeli czytasz t ksik jak podrcznik, od pocztku do koca, masz ju cakiem solidne podstawy, aby
uywa OpenGL do rnych celw. W trzeciej czci tej ksiki omwimy kilka zagadnie, ktre uzupeni
twoj wiedz i zrozumienie OpenGL. Ponadto poruszymy tematy zwizane z efektami specjalnymi oraz
moliwociami biblioteki, ktre mog wymaga wicej czasu na opanowanie ni zagadnienia opisywane w
poprzednich czciach ksiki.
Najpierw, w rozdziale 14, zajmiemy si Maszyn stanu OpenGL. Dotd jakby mimochodem poznalimy kilka
zmiennych stanu, omawiajc je tylko o tyle, o ile byo to niezbdne do opanowania materiau. Teraz
spojrzymy na t koncepcj jako cao i sprbujemy j wykorzysta. Nastpnie przejdziemy do omawiania
buforw stosowanych w OpenGL (rozdzia 15).
Wiele scen i obiektw moe wiele zyska dziki zastosowaniu pewnych technik dostosowywania obrazu,
opisywanych w rozdziale 16. Dowiesz si w nim, jak wyostrzy lub zagodzi obraz, a take jak tworzy efekty
przezroczystoci obiektw.
Generowanie zoonych powierzchni moe niejednego przyprawi o bl gowy. W rozdziale 17 poznamy kilka
narzdzi wysokiego poziomu, uatwiajcych tworzenie takich powierzchni. Uyteczne techniki rozbijania
wieloktw na trjkty zostan z kolei przedstawione w rozdziale 18, za w rozdziale 19 nauczysz si interakcji
ze scen i jej obiektami, korzystajc ze wsparcia oferowanepo przez OpenGL. Przegld API zakoczymy
przyjrzeniem si z bliskaiedM|^^pastosowa OpenGL. Zobaczysz w jaki
iti(P^ronionawan
liotece klas C++, zwanej

sposb rzeczywisto wirtualna w Internecie jesl Open


lnventor.
Rozdzia 14.
Maszyna stanu OpenGL
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Wcza i wycza opcje renderowania * glEnable/glDisable
* Odczytywa stan opcji renderowania * gllsEnabled/glGetlnteger/glGetFloat/glG
etDouble
* Zachowywa i odtwarza zmienne stanu * glPushAttrib/glPopAttrib

Stan renderowania to wanie ten mechanizm, ktry sprawia, e OpenGL jest tak szybki i
efektywny w renderowaniu trjwymiarowej grafiki. Zmienne stanu s podzielone na
rne kategorie, dotyczce koloru, owietlenia, teksturowania itd. Kady tworzony kontekst
renderowania (HRC) posiada wasny stan renderowania, specyficzny dla okna lub bitmapy
w pamici.
W odrnieniu od wikszoci rozdziaw, w tym nie ma ani jednego przykadowego
programu. Sposb uycia opisywanych funkcji znajdziesz we wszystkich innych roz-
dziaach w ksice.

Podstawowe zmienne stanu OpenGL


Dwie podstawowe funkcje suce do wczania lub wyczania opcji renderowania
OpenGL to glEnable i glDisable. Przy wywoaniu tych funkcji przekazywany jest po-
jedynczy argument typu wyliczeniowego, na przykad taki jak GL_DEPTH_TEST:
glEnable(GL_DEPTH_TEST); // Wcza testowanie bufora gbokoci
glDisable(GL_DEPTH_TEST); // Wycza testowanie bufora gbokoci
462______________________Cz III Tematy zaawansowane i efekty specjalne

Do odczytu biecego stanu su funkcje gllsEnabled, gllsDisabled oraz glGetBooleanv:


// GL_TRUE jeli jest wczone testowanie bufora gbokoci...
state~= gllsEnabled(GL_DEPTH_TEST);

// GL_TRUE jeli jest wyczone testowanie bufora gbokoci...


state = gllsDisabled(GL_DEPTH_TEST);

// Zwraca warto logiczn okrelajc warto zmiennej stanu state


= glGetBooleanv(GL_DEPTH_TEST, Sstate);

Wikszo zmiennych stanu OpenGL to wartoci logiczne, wczone lub wyczone. Inne,
na przykad biecy widok, to tablice liczb cakowitych lub tablice liczb zmienno-
przecinkowych dla kolorw RGBA. Do odczytu zmiennych tego typu su funkcj
glGetDoublev, glGetFloatv i glGet!ntegerv:
GLint istate[ 4 ] ;
GLfloat fstate[ 4 ] ;
GLdouble dstate[3];

glGet!ntegerv(GL_VIEWPORT, istate);
glGetFloatv(GL_CURRENT_COLOR, fstate);
glGetDoublev(GL_CURRENT_NORMAL, dstate);

Na temat zmiennych stanu porozmawiamy szerzej w dalszej czci rozdziau.

Zachowywanie i odtwarzanie
zmiennych stanu
Podobnie jak w przypadku macierzy rzutowania, widoku modelu i tekstury, OpenGL
posiada stos do przechowywania zmiennych stanu. Jednak w odrnieniu od stosu ma-
cierzy, stos stanu umoliwia precyzyjne wybranie zmiennych, ktre zostan odoone na
stos i z niego zdjte (rysunek 14.1).
Rysunek Informocje o sonie Szczyt stosu
14.1. Informacje o sonie
Stos atrybutw w Informacje o stanie
OpenGL
Informacje o sonie
Informacje o sanie
Informacje o sonie
Informacje o stanie
Informacje o sonie

Funkcje OpenGL przeznaczone do odkadania i zdejmowania atrybutw ze stosu to


glPushAttrib oraz glPopAttrib. Funkcja glPushAttrib dziaa podobnie do funkcji glPush-
Matrix, z tym e moesz wybra zmienn stanu, ktr chcesz odoy na stos. Aby za-
chowa jednoczenie wszystkie zmienne stanu renderowania, moesz uy wywoania
glPushAttrib(GL_ALL_ATTRIB_BITS);
Rozdzia 14. * Maszyna stanu OpenGL 463

Zwykle jednak bdziesz chcia zachowa jedynie okrelony zestaw informacji, takich
jak biecy kolor, szeroko linii itd. OpenGL definiuje wiele staych dla rnych
rodzajw informacji (zebrano je w tabeli 14.1), na przykad:
glPushAttrib(GL_CURRENT_BIT); // Zachowuje biecy kolor rysowania
// itd.
glPushAttrib(GL_LIGHTING_BIT); // Zachowuje biece ustawienia
// owietlenia
glPushAttrib(GL_TEXTURING_BIT); // Biece ustawienia teksturowania

Gdy wykonasz renderowanie, moesz przywrci bity stanu wywoujc funkcj glPop-
Attrib. Ta funkcja nie posiada argumentu i odtwarza jedynie to, co zostao odoone na
stos ostatnim poleceniem glPushAttrib.

Tabela 14.1.
Bity atrybutw funkcji glPushAttrib

Bit atrybutu Opis


GL_ACCUM_BUFFER_ Warto zerowania bufora akumulacji.
BIT GL COLOR Stan testowania alfa, funkcja oraz wartoci. Stan mieszania
kolorw, funkcja i wartoci. Stan GL_DITHER. Biece
bufory rysowania. Stan i funkcja operacji logicznych.
Biecy kolor RGBA / indeks koloru czyszczenia ta oraz
maski zapisu pikseli.
GL CURRENT BIT
Biecy kolor RGBA lub indeks koloru. Bieca
normalna i wsprzdne tekstury. Bieca pozycja
rastra, stan
GL_CURRENT_POSITION_VALIDGL_EDGE_FLA
G, GL_DEPTH_BUFFER oraz GLJDEPTHJTEST,
funkcja bufora gbokoci, warto zerowania bufora
GL ENABLE BIT gbokoci, stan GL_DEPTH_WRITEMASK.
Stan GL_ALPHA_TEST, GL_AUTO_NORMAL oraz
GL_BLEND. Stan zdefiniowanych przez uytkownika
paszczyzn obcinania. Stan GL_COLOR_MATERIAL,
GL_CULL_FACE, GL_DEPTH_TEST, GL_DITHER,
GLJFOG, GL_LIGHTi, GL_LIGHTING,
GL_LINE_SMOOTH, GL_LINE_STIPPLE,
GL_LOGIC_OP, GL_MAPl_x, GL_MAP2_x,
GL_NORMALIZE, GL_POINT_SMOOTH,
GL_EVAL_B GL_POLYGON_SMOOTH, GL_POLYGON_STIPPLE,
GL_SCISSOR_TEST, GL_STENCIL_TEST,
GL_TEXTURE_1D, GL_TEXTURE_2D oraz
IT GL_TEXTURE_GEN.
Stan GL_MAPl_x oraz GL_MAP2_x, koce i podzia
GL_FOG_BI jedno-i dwuwymiarowej siatki, stan
GL_AUTO_NORMAL.
Stan GL_FOG, warto koloru mgy, gstoci mgy,
pocztku liniowej mgy, koca liniowej mgy, indeksu mgy
464 Cz III Tematy zaawansowane i efekty specjalne

Tabela 14.1.
Bity atrybutw funkcji glPushAttrib - cig dalszy

Bit atrybutu Opis

GL LIGHTING BIT Stan GL_COLOR_MATERIAL. Warto


GL_COLOR_MATERIAL_FACE. Parametry koloru materiau
ledzce kolor wiata otaczajcego sceny. Wartoci
GL_LIGHT_MODEL_LOCAL_VIEWER oraz
GL_L1GHT_MODEL_TWO_SIDE. Stany GLJJGHTING oraz
GL_LIGHTx. Wszystkie parametry wiata. Warto
GL_SHADE_MODE.
GL_LINE_BIT Stany GL_LINE_SMOOTH oraz GL_LINE_STIPPLE. Dese
przerywania linii oraz licznik powtrze. Szeroko linii.
GL_LIST_BIT Warto GL_LIST_BASE.
GL PIXEL MOD BIT Ustawienia GL_RED_BIAS, GL_RED_SCALE, GL_GREEN_BIAS,
GL_GREEN_SCALE, GL_BLUE_BIAS, GL_BLUE_SCALE,
GL_ALPHA_BIAS, GL_ALPHA_SCALE, GL_DEPTH_BIAS,
GL_DEPTH_SCALE, GL_INDEX_OFFSET, GL_INDEX_SHIFT,
GL_MAP_COLOR, GL_MAP_DEPTH, GL_ZOOM_X, GL_ZOOM_Y
oraz GL_READ_BUFFER.
GL_POINT_BIT Stan GL_POINT_SMOOTH, rozmiar punktu.
GL_POLYGON_BIT GL_CULL_FACE, GL_CULL_FACE_MODE, GL_FRONT_FACE,
GL_POLYGON_MODE, GL_POLYGON_SMOOTH,
GL_POLYGON_STIPPLE.
GL_POLYGON_STIPPLE_BIT Obraz desenia dla wieloktw.
GL_SCISSOR_B1T_BIT Stan GL_SCISSOR_TEST, brya noyc.
GL_STENCIL_BUFFER_BIT Stan GL_STENCIL_TEST. Funkcja szablonu i warto odniesienia.
Maska wartoci szablonu. Warto zerowania bufora szablonu oraz
maska zapisu.
GL TEXTURE BIT Stan wczenia dotyczcy wszystkich wsprzdnych tekstur. Kolor
ramki obrazu tekstury. Filtr powikszania i pomniejszania. Wsprzdne
tekstur i tryby powtarzania tekstur. Kolor i tryb dla kadego rodowiska
tekstury. Ustawienia GL_TEXTURE_GEN_x i
GL_TEXTURE_GEN_MODE. Rwnania dla glTexGen.
GL TRANSFORM BIT Wspczynniki szeciu paszczyzn obcinania, stan wczenia
paszczyzn obcinania. Ustawienie GL_MATRIX_MODE, stan
GL_NORMALIZE.
GL YIEWPORT BIT Zakres gbokoci, pocztek i rozcigo ukadu wsprzdnych.

Stan rysowania
OpenGL posiada wiele zmiennych stanu zwizanych z rysowaniem prymityww we-
wntrz pary wywoa glBegin/glEnd. Wikszo z nich jest zachowywanych w wyniku
wywoania glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); opis poszczeglnych
zmiennych tej grupy zawiera tabela 14.2.
Rozdzia 14. Maszyna stanu OpenGL______________________________465

Tabela 14.2.
Zmienne stanu rysowania

Zmienna stanu Opis


GL_ALPHA_TEST Test wartoci alfa.
GL_BLEND Operacje mieszania kolorw pikseli.
GL_CLIP_PLANEx Obcinanie prymityww poza okrelon paszczyzn obcinania.
GL_CULL_FACE Usuwanie wieloktw zwrconych tyem (lub przodem).
GL_DITHER Roztrzsanie kolorw.
GL_LINE_SMOOTH Antyaliasing linii.
GL_LINE_STIPPLE Rysowanie linii przerywanych.
GL_LOGIC_OP Operacje logiczne na rysowanych pikselach.
GL_POINT_SMOOTH Antyaliasing punktw.
GL_POLYGON_SMOOTH Antyaliasing wieloktw.
GL_POLYGON_STIPPLE Dese na wieloktach.
GL_SCISSOR_TEST Obcinanie rysunku poza regionem glScissor.

Stan bufora gbokoci


Najczstszym bdem popenianym przez pocztkujcych programistw OpenGL jest
pominicie wczenia testowania bufora gbokoci wywoaniem glEnable(GL_DE-
PTH_TEST). Bez testowania bufora gbokoci nie mog by usuwane niewidoczne
powierzchnie (rozdzia 15). Do zachowania stanu testowania bufora gbokoci (zmienna
GL_DEPTH_TEST) suy wywoanie funkcji glPushAttrib z parametrem GL_DEP-
TH_BUFFER_BIT.

Stan bufora szablonu


Bufor szablonu suy do uzyskiwania wielu efektw specjalnych, na przykad cieni. Po-
dobnie jak w przypadku bufora gbokoci, mona bardzo atwo sterowa jego dziaa-
niem. Aby zachowa stan bufora szablonu, wywoaj funkcj glPushAttrib(GL_STEN-
CIL_BUFFERJ3IT). Odkadana na stos zmienna stanu to GL_STENCIL_TEST.

Stan owietlenia
Ze wszystkich zmiennych stanu OpenGL, zmienne zwizane z owietleniem s najli-
czniejsze. Informacje o stanie owietlenia obejmuj ustawienia biecego trybu koloru i
wiata dla rodowiska owietlenia (modelu), definicj materiau, kolor, pooenie i
kierunek rde wiata, a take kilka innych parametrw. Co wicej, przy wczonym
466 Cz III Tematy zaawansowane i efekty specjalne

automatycznym generowaniu normalnych, OpenGL wykorzystuje jeszcze dodatkowe


zmienne stanu owietlenia.
Wszystkie dostpne zmienne stanu owietlenia wymieniono w tabeli 14.3. Jako mini-
mum, musisz wywoa przynajmniej funkcje glEnable(GL_LIGHTING) oraz glEna-
ble(GL_LIGHTO). Aby zachowa biecy stan owietlenia, wywoaj funkcj glPushAt-
trib(GL_LIGHTING_BIT | GL_EVAL_BIT).

Tabela 14.3.
Zmienne stanu owietlenia

Zmienna stanu Opis


GL_AUTO_NORMAL Automatyczne generowanie normalnych na podstawie parametrw funkcji
glMap.
GL_COLOR_MATERIAL Przypisywanie koloru materiau na podstawie biecego koloru
rysowania.
GLJJGHTING Wczanie oblicze zwizanych z owietleniem.
GL_LIGHTx Wczenie rda wiata x.
GL_MAP1_NORMAL Wczenie odwzorowania normalnych na podstawie wsprzdnych ID.
GL_MAP2_NORMAL GL Wczenie odwzorowania normalnych na podstawie wsprzdnych 2D.
NORMALIZE Normalizowanie wszystkich normalnych przed wykonywaniem oblicze.

Stan teksturowania
Jeli chodzi o zoono, teksturowanie niewiele ustpuje owietleniu. Dostpne zmienne
stanu teksturowania zawiera tabela 14.4.
Aby zachowa biece parametry teksturowania, wywoaj funkcj glPushAttrib z para-
metrami GL_TEXTUR_BIT oraz GL_EVAL_BIT. Gdy wczasz teksturowanie, pa-
mitaj, aby wczy tylko jeden z dwch trybw - albo GL_TEXTURE_1D, albo
GL_TEXTURE_2D. Specyfikacja OpenGL wymaga, aby teksturowanie 2D zastpowao
teksturowanie ID, ale niektre implementacje nie speniaj tego zaoenia.

Tabela 14.4.
Zmienne stanu teksturowania

Zmienna stanu Opis

GL MAPI TEXTURE COORD l W wyniku wywoa funkcji glEvalPointl,


glEvalMeshl orazglEvalCoordl bdzie generowana
wsprzdna s tekstury.
GL MAPI TEXTURE COORD 2 W wyniku wywoa funkcji glEvalPointl,
glEvalMeshl oraz glEvalCoordl bd generowane
wsprzdne s i t tekstury.
Rozdzia 14. Maszyna stanu OpenGL 467

Tabela 14.4.
Zmienne stanu teksturowania - cig dalszy
Zmienna stanu Opis
W wyniku wywoa funkcji glEvalPointl,
GL_MAP1_TEXTURE_COORD_3 glEvalMeshl orazglEvalCoordl bd generowane
wsprzdne s, t oraz r tekstury.
W wyniku wywoa funkcji glEvalPointl,
GL_MAP 1_TEXTURE_COORD_4 glEvalMeshl orazglEvalCoordl bd generowane
wsprzdne s, t, r oraz q tekstury.
W wyniku wywoa funkcji glEvalPoint2,
glEvalMesh2 oraz glEvalCoord2 bdzie generowana
GL_MAP2_TEXTURE_COORD_1
wsprzdna s tekstury.
W wyniku wywoa funkcji glEvalPoint2,
g!Eva!Mesh2 oraz glEvalCoord2 bd generowane
GL_MAP2_TEXTURE_COORD_2
wsprzdne s i t tekstury.
W wyniku wywoa funkcji glEvalPoint2,
glEvalMesh2 oraz glEvalCoord2 bd generowane
GL_MAP2_TEXTURE_COORD_3
wsprzdne s, t oraz r tekstury.
W wyniku wywoa funkcji glEvalPoint2,
glEvalMesh2 oraz glEvalCoord2 bd generowane
GL_MAP2_TEXTURE_COORD_4 wsprzdne s, t, r oraz q tekstury.
Wczenie teksturowania ID, chyba e zostanie
wczone teksturowanie 2D.
GL_TEXTURE_1D
Wczenie teksturowania 2D.
GL_TEXTURE_2D Przy wywoaniach funkcji glVertex automatyczne
generowanie wsprzdnej q tekstury.
GL_TEXTURE_GEN_Q
Przy wywoaniach funkcji glVertex automatyczne
generowanie wsprzdnej r tekstury.
GL_TEXTURE_GEN_R
Przy wywoaniach funkcji glVertex automatyczne
generowanie wsprzdnej s tekstury.
GL_TEXTURE_GEN_S
Przy wywoaniach funkcji glVertex automatyczne
generowanie wsprzdnej t tekstury.
GL TEXTURE GEN T

Stan pikseli
Transfer pikseli, przechowywanie oraz tryby odwzorowania s najczciej najmniej
zrozumiaymi i najmniej zoptymalizowanymi elementami OpenGL. Do zachowania ich
stanu suy wywoanie glPusriAttrib(GL_PIXEL_BIT). Dla tych trybw nie ma zmiennych
ustawianych funkcjglEnable.
468 Cz III Tematy zaawansowane i efekty specjalne

Podrcznik
glDisable / glEnable
Przeznaczenie Wcza lub wycza wskazan opcj OpenGL.
Plik nagwkowy <gl.h>
Skadnia void glDisable(GLenum feature);
glEnable
Opis glDisable wycza wskazan opcj OpenGL. glEnable wcza wskazan
opcj OpenGL.
Parametry
feature GLenum: Opcja przeznaczona do wczenia lub wyczenia. Dostpne
opcje zebrano w tabeli 14.5.
Zwracana warto Brak.
Patrz take gllsEnabled, glPopAttrib, glPushArtrib

Tabela 14.5.
Opcje -wczane i wytaczane funkcjami glEnable i glDisable

Opcja Opis

GL_AUTO_NORMAL Automatyczne generowanie normalnych na podstawie


parametrw
funkcjiglMap.
GL_COLOR_MATERIAL Przypisywanie koloru materiau na podstawie biecego
koloru
rysowania.
GL_LIGHTING Wczanie oblicze zwizanych z
owietleniem.
GL_LIGHTx Wczenie rda wiata x.
GL_MAP 1_NORMAL Wczenie odwzorowania normalnych na podstawie
wsprzdnych ID.
GL_MAP2_NORMAL Wczenie odwzorowania normalnych na podstawie
wsprzdnych 2D.
GL_NORMALIZE Normalizowanie wszystkich normalnych przed
wykonywaniem
oblicze.
GL_MAP1_TEXTURE_COORD_1 W wyniku wywoa funkcji glEvalPointl,
glEvalMeshl oraz
glEvalCoordl bdzie generowana wsprzdna s tekstury.
GL_MAP 1_TEXTURE_COORD_2 W wyniku wywoa funkcji glEvalPointl,
glEvalMeshl oraz
glEvalCoordl bd generowane wsprzdne s i t tekstury.
GL_MAP1_TEXTURE_COORD_3 W wyniku wywoa funkcji glEvalPointl,
glEvalMeshl oraz
glEvalCoord l bd generowane wsprzdne s, t oraz r
tekstury.
Rozdzia 14. * Maszyna stanu OpenGL 469

Tabela 14.5.
Opcje wczane i wyczane funkcjami glEnable i glDisable - cig dalszy

Opcja Opis
W wyniku wywoa funkcji glEvalPointl, glEvalMeshl oraz
GL_MAP1_TEXTURE_COORD_4 glEvalCoordl bd generowane wsprzdne s, t, r oraz q tekstury.
W wyniku wywoa funkcji glEvalPoint2, glEvalMesh2 oraz
GL_MAP2_TEXTURE_COORD_1 glEvalCoord2 bdzie generowana wsprzdna s tekstury.
W wyniku wywoa funkcji glEvalPoint2, glEvalMesh2 oraz
GL_MAP2_TEXTURE_COORD_2 glEvalCoord2 bd generowane wsprzdne s i t tekstury.
W wyniku wywoa funkcji glEvalPoint2, glEvalMesh2 oraz
GL_MAP2_TEXTURE_COORD_3 glEvalCoord2 bd generowane wsprzdne s, t oraz r tekstury.
W wyniku wywoa funkcji glEvalPoint2, glEvalMesh2 oraz
GL_MAP2_TEXTURE_COORD_4 glEvalCoord2 bd generowane wsprzdne s, t, r oraz q tekstury.
Wczenie teksturowania l D, chyba e zostanie wczone
GL_TEXTURE_1D teksturowanie 2D.
Wczenie teksturowania 2D.
GL_TEXTURE_2D
Przy wywoaniach funkcji glVertex automatyczne generowanie
GL_TEXTURE_GEN_Q wsprzdnej q tekstury.
Przy wywoaniach funkcji glVertex automatyczne generowanie
GL_TEXTURE_GEN_R wsprzdnej r tekstury.
Przy wywoaniach funkcji glVertex automatyczne generowanie
GL_TEXTURE_GEN_S wsprzdnej s tekstury.
Przy wywoaniach funkcji glVertex automatyczne generowanie
GL_TEXTURE_GEN_T wsprzdnej t tekstury.
Test bufora szablonu.
GL_STENCIL_TEST
Test bufora gbokoci.
GL_DEPTH_TEST
Test wartoci alfa.
GL_ALPHA_TEST
Operacje mieszania kolorw pikseli.
GL_BLEND
Obcinanie prymityww poza okrelon paszczyzn obcinania.
GL_CLIP_PLANEx
Usuwanie wieloktw zwrconych tyem (lub przodem).
GL_CULL_FACE
Roztrzsanie kolorw.
GLJ3ITHER
Antyaliasing linii.
GL_LINE_SMOOTH
Rysowanie linii przerywanych.
GL_LINE_STIPPLE
Operacje logiczne na rysowanych pikselach.
GL_LOGIC_OP
Antyaliasing punktw.
GL_POINT_SMOOTH
Antyaliasing wieloktw.
GL_POLYGON_SMOOTH
Dese na wieloktach.
GL_POLYGON_STIPPLE
Obcinanie rysunku poza regionem glScissor.
GL SCISSOR TEST
470 Cz III Tematy zaawansowane i efekty specjalne

gllsEnabled
Przeznaczenie Plik Sprawdza, czy dana opcja OpenGL jest wczona.
nagwkowy
Skadnia Opis GLboolean gl!sEnabled(GLenum feature);
Ta funkcja zwraca warto GL_TRUE, jeli wskazana opcja jest
Parametry wczona, za warto GL_FALSE w przeciwnym wypadku.
feature
Zwracana warto GLenum: Sprawdzana opcja. Dostpne opcje zebrano w tabeli 14.5.
GLboolean: GLJTRUE, jeli dana opcja jest wczona, a GL_FALSE w
Patrz take przeciwnym wypadku.
glDisable, glEnable, glPopAttrib, glPushAttrib

glPopAttrib
Przeznaczenie Plik Odtwarza zmienne stanu zachowane uprzednio funkcj glPushAttrib.
nagwkowy
Skadnia Opis void glPopAttrib(void);
Parametry glPopAttrib odtwarza warto zmiennych stanu zachowanych uprzednim
wywoaniem funkcji glPushAttrib. Jeli stos atrybutw jest pusty,
Zwracana warto ustawiany jest znacznik bdu OpenGL, za samo wywoanie jest
Patrz take ignorowane.
Brak. Brak. glDisable, glEnable, gllsEnabled,
glPushAttrib

glPushAttrib
Przeznaczenie Odkada na stos zmienne stanu OpenGL.
Plik nagwkowy
Skadnia Opis void glPushAttrib(GLuint bits);
Ta funkcja zachowuje zmienne stanu OpenGL okrelone bitami parametru
bits. Jeli stos atrybutw jest peny, ustawiany jest znacznik bdu OpenGL,
za odkadane zmienne s umieszczane na szczycie stosu, zastpujc
istniejce tam dane.
1
Rozdzia 14. Maszyna stanu OpenGL_____________________________471

Parametry
bits GLuint: Zestaw zmiennych przeznaczonych do odoenia na stos (patrz
tabela 14.1).
! Zwracana warto Brak.
Patrz take glDisable, glEnable, gllsEnabled, glPopAttrib
Rozdzia 15.
Bufory: nie tylko
do animacji
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


+ Przygotowa bufory * ChoosePixelFormat/SetPixelFormat
* Uy bufora gbokoci * glEnable/glDepthFunc/glDepthRange
* Uy bufora szablonu * glEnable/glStencilFunc
* Uy bufora akumulacji * glEnable/glAccum

W poprzednich rozdziaach korzystalimy z bufora koloru i gbokoci. OpenGL posiada


kilka rodzajw buforw, zwizanych z kontekstem urzdzenia graficznego:
+ Bufor koloru;
* Bufor gbokoci;
* Bufor szablonu;
* Bufor akumulacji.
Jak zobaczysz w tym rozdziale, kady bufor posiada okrelone waciwoci, wykorzy-
stywane nie tylko przy podwjnie buforowanej animacji i podczas usuwania niewido-
cznych powierzchni.

Czym s bufory?
Bufor w OpenGL to w zasadzie dwuwymiarowa tablica wartoci powizanych z pikse-
lami okna lub bitmapy w pamici. Kady bufor zawiera t sam liczb kolumn i wierszy
474 Cz III Tematy zaawansowane i efekty specjalne

(ma t sam szeroko i wysoko) co obszar roboczy biecego okna, z tym e w buforze
przechowywane s dane innego rodzaju i z innego zakresu. Spjrz na rysunek 15.1.

Rysunek 15.1.
Organizacja
buforw w OpenGL

Konfigurowanie buforw
Zanim uyjesz OpenGL, musisz skonfigurowa kontekst urzdzenia okna (HDC), przy-
gotowujc wymagane bufory i tryb koloru. Te informacje zawiera struktura PIXEL-
FORMATDESCRIPTOR. Oto typowy sposb przygotowywania buforw:
// Ta struktura przechowuje informacje o buforach, warstwach i trybie //
koloru PIXELFORMATDESCRIPTOR pfd;

// Najpierw zainicjujemy rozmiar i wersj struktury...


pfd.nSize = sizeof(pfd); pfd.version = 1;

// Nastpnie informacje o warstwach i buforach... pfd.dwFlags


= PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; pfd.dwLayerMask =
PFD_MAIN_PLANE; pfd.iLayerType = PFD_MAIN_PLANE;

// Typ pikseli wskazuje czy chcemy uy indeksw kolorw czy RGBA


pfd.iPixelType = PFD_TYPE_RGBA;

// Teraz moemy okreli *minimaln* ilo potrzebnych nam bitplanw


// dla kadego bufora. Windows wybierze format pikseli najbardziej
// zbliony do opisanego
pfd.cColorBits = 8;
pfd.cDepthBits = 1 6 ;
pfd.cAccumBits = 0;
pfd.cStencilBits = 0;

Pole bitowe dwFlags okrela, czy chcemy rysowa w oknie za pomoc OpenGL. Oprcz
tego informuje Windows o iloci buforw koloru, jakiej wymagamy. Spjrz na tabel 15.1.
Rozdzia 15. Bufory: nie tylko do animacji____________________________475

Tabela 15.1.
Znaczniki opcji w strukturze PKELFORMATDESCRIPTION

Znacznik Opis
PFD_DRAW_TO_W1NDOW Rysowanie w oknie.
PFD_DRAW_TO_BITMAP Rysowanie na bitmapie w pamici.
PFD_SUPPORT_GDI Bufor kolorw obsuguje funkcje GDI.
PFD_SUPPORT_OPENGL Bufor kolorw obsuguje polecenia OpenGL.
PFD_DOUBLEBUFFER Wartoci kolorw s podwjnie buforowane.
PFD_STEREO Dostpne s dwa zestawy buforw (lewy i
prawy).
PFD_DOUBLE_BUFFER_DONT_CARE Nie ma znaczenia, czy wartoci kolorw s
podwjnie buforowane.
PFD_STEREO_DONTCARE Nie ma znaczenia, czy obraz jest
stereoskopowy.

Pola dwLayerMask i iLayerType okrelaj plan rysowania, ktry ma zosta uyty, i zwykle
s ustawiane na PFD_MAIN_PLANE. Niektre karty graficzne OpenGL umoliwiaj
wykorzystywanie pomocniczych buforw pod lub nad normalnym planem kolorw
Windows, pozwalajc na tworzenie menu lub innych obiektw graficznych bez niszczenia
zawartoci gwnego planu. Oglna implementacja OpenGL w Windows nie obsuguje
pomocniczych planw rysunkowych.

Pole iPixelType okrela sposb reprezentowania wartoci kolorw i moe zawiera jedn
z dwch wartoci z tabeli 15.2.

Tabela 15.2.
Typypikseli

Typ pikseli Opis

PFD_TYPE_RGBA Kolory s zoone ze skadowych czerwonej, zielonej,


niebieskiej i alfa.
PFD_TYPE_COLORINDEX Kolory s reprezentowane jako indeksy biecej palety
logicznej.

Pola cColorBits, cDepthBits, cAccumBits oraz cStencilBits okrelaj rozmiar kadego z


buforw. Umieszczenie w jednym z tych pl wartoci O powoduje wyczenie danego
bufora, z wyjtkiem pola cColorBits. Jeli w polu cColorBits umiecisz warto O, Win-
dows zastosuje najmniejsz moliw ilo bitw na kolor, zwykle 4 lub osiem (16 lub
256 kolorw). Gdy iPixelType zostanie ustawione na PFD_TYPE_RGBA, pole cColorBits
okrela czn ilo bitw czerwieni, zieleni i niebieskiego. Obecna oglna implementacja
OpenGL Microsoftu nie obsuguje bitw kanau alfa.

Gdy wypenisz struktur PIKELFORMATDESCRIPTOR koniecznymi informacjami, za


pomoc kilku prostych wywoa moesz ustawi format pikseli dla okna:
// Uchwyt kontekstu urzdzenia dla okna
HDC hdc;
476_______________________Cz III Tematy zaawansowane i efekty specjalne

// Kod formatu pikseli Windows


int pf;
// Wybr i ustawienie formatu p i k s e l i . . .
pf = ChoosePixelFormat( h d c , &pfd); i f ( p f
== 0) {
// Nie powiodo si znalezienie odpowiedniego formatu p i k s e l i . . .
MessageBox( N U L L , " N i e powiodo si wybranie formatu p i k s e l i ! " ,
"Bd!",
MB_OK); }
else if (!SetPixelFormat( h d c , p f , spfd) {
// Nie powiodo si ustawienie formatu p i k s e l i . . .
MessageBox(NULL," Nie powiodo si ustawienie formatu p i k s e l i ! " ,
" B d ! " , MB_OK);
}

Po wywoaniu funkcji ChoosePixelFormat, struktura P1XELFORMATDESCRIPTOR


jest wypeniana dostpnymi w systemie wartociami, najbardziej zblionymi do wyma-
ganych. Przy powrocie, pole dwFlags moe zawiera dodatkowe znaczniki, na ktre po-
winiene zwrci uwag. Te znaczniki zostay zebrane w tabeli 15.3.

Tabela 15.3.
Znaczniki ustawiane przez funkcj ChoosePixelFormat

Ustawiany znacznik Opis

PFD_GENERIC_FORMAT dany format jest obsugiwany przez ogln


implementacj.
PFD_NEED_PALETTE Bufor kolorw RGBA bdzie wywietlany na urzdzeniu
korzystajcym z palety, wic musi istnie paleta logiczna.
PFD_NEED_SYSTEM_PALETTE Wartoci kolorw do poprawnego wywietlenia
wymagaj palety
systemowej. Wywoaj funkcj SetSystemPaletteUse() w
celu wymuszenia jednoznacznego odwzorowania palety
logicznej na systemow.

Jeli znacznik PFD_NEED_PALETTE bdzie ustawiony, powiniene zdefiniowa palet


logiczn okrelon wartociami pl cRedBits, cRedShift, cGreenBits, cGreenShift,
cBlueBits oraz cBlueShift. Oto przykad definiowania palety:
HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE *pal; int i,
Pf,
num_colors,
red, num_reds,
green, num_greens,
blue, num_blues;

// Pobranie indeksu formatu pikseli oraz deskryptora formatu pikseli


pf = GetPixelFormat(hdc);
DescribePixelFormat(hdc, p f , sizeof(PIKELFORMATDESCRIPTOR), s p f d ) ;
Rozdzia 15. Bufory: nie tylko do animacji____________________________477

// C z y ten format pikseli wymaga palety?


if(pfd .dw Flags & PFD_NEED_PALETTE)
{
// Tak. Paleta jest potrzebna.
// Zaalokowanie pamici na struktur logicznej palety
// i wszystkie j e j pozycje
num_colors = l pfd.cColorBits;
pal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
num_colors*sizeof(PALETTEENTRY));

// Wypenienie nagwka palety pal->palVersion = 0x300;


// Windows 3 . 0 pal->palNumEntries = num_colors; //
rozmiar palety

num_reds = (l p f d . cRedBits) - 1 ;
num_greens = (l pfd.cGreenBits) - 1;
num_blues = (l pfd.cBlueBits) -1;
for(blue = 0 , i = 0; blue <= num_blues; blue++)
for(green = 0; green <= num_greens; green++)
for(red = 0; red <= num_reds; red++) {
pal->palPalEntry[ i ] .peRed = 255 * red / num_reds; pal-
>palPalEntry[ i ] .peGreen = 255 * green / num_greens; pal-
>palPalEntry[ i ] .peBlue = 255 * blue / num_blues; pal-
>palPalEntry[ i ] .peFlags = 0; }
palette = CreatePalette( p a l ) ;
SelectPalettefhdc, palette, FALSE);
RealizePalette(hdc);

Bufor koloru
Bufor koloru przechowuje informacje o kolorze pikseli. Kady piksel moe zawiera indeks
koloru lub skadowe RGBA (red/green/lue/alpha) opisujce kolor danego piksela. Piksele
RGBA s wywietlane bezporednio przy uyciu najbliszego dostpnego koloru na
ekranie. Oglna implementacja OpenGL Microsoftu nie obsuguje obecnie skadowej koloru
alfa.

Wygld pikseli indeksu kolorw jest okrelany przez pobranie koloru RGB z pozycji
palety wyznaczonej przez dany indeks. W Windows palety s zaimplementowane jako
logiczne palety kolorw. Tryb indeksu koloru jest bardzo przydatny przy graficznej
reprezentacji danych tabelarycznych, na przykad miernikw siy lub natenia, co
przedstawimy w drugim przykadzie zastosowania bufora gbokoci, w sekcji Inne
zastosowanie bufora gbokoci".

Podwjne buforowanie
Podwjne buforowanie wykorzystuje dodatkowy bufor koloru w pamici, czsto uywany
w animacji. Przy podwjnym buforowaniu moesz narysowa ca scen w pa-
478______________________Cz III Tematy zaawansowane i efekty specjalne

mici, poza ekranem, a nastpnie szybko przerzuci" j na ekran, eliminujc w ten sposb
nieprzyjemne migotanie obrazu. Podwjne buforowanie wpywa jedynie na bufor
koloru; nie ma drugiego bufora dla gbokoci, szablonu czy akumulacji. Jeli wybie-
rzesz format pikseli z podwjnym buforowaniem, OpenGL wybierze do rysowania
tylny" bufor. Moesz zmieni to domylne zachowanie uywajc funkcji glDrawBuf-fer
z jednym z parametrw z tabeli 15.4.

Tabela 15.4.
Dostpne parametry funkcji glDrawBuffer

Bufor Opis
GL_FRONT OpenGL rysuje w przednim (widocznym) buforze.
GL BACK OpenGL rysuje w tylnym (niewidocznym) buforze.
GL_FRONT_AND_BACK OpenGL rysuje w obu buforach naraz.

Buforowanie stereo
Buforowanie stereo wykorzystuje dodatkowy bufor koloru w trybie pojedynczego bufo-
rowania oraz dwa dodatkowe bufory w trybie podwjnego buforowania, w celu prze-
chowania obrazu osobno dla lewego i prawego oka (tabela 15.5). Poprzez wygenerowanie
osobnych trjwymiarowych obrazw, przesunitych o kilka centymetrw" w stosunku do
siebie dla zasymulowania rozstawu oczu, mona wygenerowa prawdziwe trjwy-
miarowe obrazy. W przypadku wikszoci kart graficznych PC buforowanie stereo nie jest
jednak dostpne.
Oprcz wyboru przedniego lub tylnego bufora, za pomoc funkcji glDrawBuffer mona
wybra take bufor dla lewego lub prawego oka.

Tabela 15.5.
Bufory stereo

Bufor Opis
GL_LEFT_FRONT Rysowanie w lewym przednim buforze.
GL_LEFT_BACK Rysowanie w lewym tylnym buforze.
GL_RIGHT_FRONT Rysowanie w prawym przednim buforze.
GL_R1GHT_BACK Rysowanie w prawym tylnym buforze.
GL_FRONT Rysowanie w obu przednich buforach.
GL_BACK Rysowanie w obu tylnych buforach.

Przerzucanie buforw
OpenGL obsuguje podwjne buforowanie, lecz w samym OpenGL nie ma adnej funkcji
przerzucajcej zawarto przedniego i tylnego bufora! Na szczcie, w kadej im-
Rozdzia 15. Bufory: nie tylko do animacji___________________________479

plementacji OpenGL wystpuje pomocnicza funkcja umoliwiajca wywietlenie za-


wartoci bufora na ekranie. W Windows jest ni
SwapBuffers(hdc);

gdzie hdc to kontekst urzdzenia okna, w ktrym rysujesz. Jeli wybrae format pikseli z
buforowaniem stereo, obrazy dla lewego i prawego oka s przerzucane jednoczenie.

Bufor gbokoci
Bufor gbokoci przechowuje warto gbokoci dla kadego piksela. Kada warto
reprezentuje odlego piksela od obserwatora, przeskalowan do biecej bryy obcinania, a
waciwie jej bliszej i dalszej paszczyzny. Programowa implementacja OpenGL w
Windows obsuguje zarwno 16-, jak i 32-bitowe wartoci bufora gbokoci.
Bufor gbokoci zwykle jest wykorzystywany w celu usuwania niewidocznych po-
wierzchni. Usuwanie niewidocznych powierzchni jest procesem, ktry w rzeczywistym
wiecie odbywa si w sposb naturalny; gdy nieprzezroczysty obiekt zostanie umie-
szczony przed innym obiektem, obiekt bliszy zasania cz lub cao obiektu lecego
dalej.
W OpenGL, bufora gbokoci mona uy w celu uzyskania interesujcych efektw,
takich jak na przykad usunicie przedniej czci obiektu w celu przedstawienia jego
wntrza.

Porwnywanie gbokoci
Gdy rysujesz w oknie posugujc si OpenGL, pozycja Z kadego piksela jest porwnywana
z wartoci w buforze gbokoci. Jeli wynik porwnania wynosi True, piksel, wraz ze
swoj gbokoci, jest umieszczany w buforze kolorw. OpenGL definiuje osiem
funkcji porwna wartoci w buforze gbokoci (tabela 15.6). Domyln funkcj
porwnania jest GL_LESS. Aby j zmieni, wywoaj funkcj glDepthFunction.
glDepthFunction(function);

Jeli jest uywana funkcja GL_LESS, piksele wielokta s rysowane wtedy, gdy warto
gbokoci piksela jest mniejsza ni warto piksela w buforze gbokoci (rysunki
15.2ail5.2b).

Tabela 15.6.
Funkcje porwnywania gbokoci

Nazwa Funkcja

GL_NEVER Zawsze False


GL_LESS True jeli Z piksela < Z bufora
480 Cz III Tematy zaawansowane i efekty specjalne

Tabela 15.8.
Funkcje porwnywania gbokoci - cig dalszy

Nazwa Funkcja

QL_EQUAL True jeli Z piksela = Z bufora


GL_LEQUAL True jeli Z piksela <= Z bufora
GL_GREATER True jeli Z piksela > Z bufora
GL_NOTEQUAL True jeli Z piksela != Z bufora
GL_GEQUAL True jeli Z piksela >= Z bufora
GL ALWAYS Zawsze True

Rysunek 15.2a.
Typowe dziaanie
bufora gbokoci
przy porwnaniach
GL LESS

Rysunek 15.2b.
Typowe dziaanie
bufora gbokoci
przy porwnaniach
GL GREATER
Rozdzia 15. Bufory: nie tylko do animacji___________________________481

Wartoci gbokoci
Gdy uywasz porwna gbokoci GL_EQUAL i GL_NOTEQUAL, czasem konieczna
jest zmiana zakresu wykorzystywanych wartoci gbokoci, w celu zredukowania liczby
dostpnych wartoci (zmniejszenia iloci wartoci do minimum). W tym celu moesz uy
funkcji glDepthRange:
glDepthRange(nera, f a r ) ;

Parametry near i far to liczby zmiennoprzecinkowe z zakresu od 0,0 do 1,0 wcznie.


Domylne ustawienia to 0,0 dla near i 1,0 dla/ar. Zwykle near jest mniejsze ni far, ale
moesz zmieni t kolejno w celu uzyskania specjalnego efektu (lub uy funkcji
GL_GRATER lub GL_GEQUAL). Zredukowanie zakresu wartoci przechowywanych w
buforze gbokoci nie wpywa na obcinanie, lecz powoduje, e bufor gbokoci staje
si mniej dokadny, i moe prowadzi do bdw w usuwaniu niewidocznych powierzchni
na ekranie.

W niektrych porwnaniach gbokoci potrzebna jest inna pocztkowa warto gbo-


koci. Domylnie, bufor gbokoci jest czyszczony przez wpisanie funkcj glColor
wartoci 1,0. Aby okreli inn warto, uyj funkcji glClearDepth:
glClearDepth(depth);

Parametr depth to liczba zmiennoprzecinkowa z zakresu od 0,0 do 1,0 wcznie, chyba e


za pomoc funkcji glDepthRange zdefiniujesz mniejszy zakres. Oglnie, w przypadku
porwna GL_GREATER lub GL_GEQUAL uyj wartoci 0,0, za w przypadku
porwna GL_LESS lub GL_LEQUAL - wartoci 1,0.

Zastosowania bufora gbokoci


Powszechnym zastosowaniem bufora gbokoci jest usuwanie niewidocznych powie-
rzchni. Ten rodzaj aplikacji zaprezentowano na listingu 15.1. Kluczem do tego programu
jest uycie funkcji glDepthFunc i glClearDepth:
glDepthFunc(depth_func);

Uywamy tu zmiennej globalnej przechowujcej biec funkcj porwnywania gbo-


koci. W momencie uruchomienia programu zmiennej depth_func jest przypisywana
warto GL_LESS. Gdy uytkownik wcinie klawisz D, funkcja zwrotna toggie_depth
przecza funkcj porwnywania gbokoci pomidzy GLJLESS a GL_GREATER.
if (depth_function == GL_LESS)
depth_function = GL_GREATER;
else
depth_function = GL_LESS;

Wywoanie glClearDepth jest potrzebne do ustawienia poprawnej pocztkowej wartoci


gbokoci dla okna, gdy domyln wartoci gbokoci jest 1,0. Gdyby funkcja por-
wnywania zostaa ustawiona na GL_GREATER, nie zostaby narysowany aden piksel,
gdy aden piksel nie miaby wartoci wikszej ni 1,0.
482 ______________________ Cz III Tematy zaawansowane i efekty specjalne

Listing 15.1. Przykad uycia bufora gbokoci _________________________________


/*
* "depth.c" - Program demonstracyjny ilustrujcy uycie
* funkcji glDepthFunc () .
*
* Wcinij klawisz ' d ' w celu przeczenia si pomidzy funkcjami
* porwna GL_LESS i GL_GREATER. Wcinij 'Esc1 w celu zakoczenia
* programu.
*/
include <GL/glaux.h>

/*
* Te definicje zostay wprowadzone w celu zapewnienia zgodnoci
* pomidzy MS Windows a reszt wiata.
*
* CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.
*/
ifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* IWIN32 */

GLenum depth_function = GL_LESS; // Bieca funkcja porwnywania


// gbokoci

/*
* 'reshape_scene () ' - Zmiana rozmiaru s c e n y . . .
*/
void CALLBACK
reshape_scene (GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glYiewport ( O , O, width, height);

glMatrixMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(22.5, (float) width / (float) height, 0.1, 1000.0);
glMatrixMode (GL_MODELVIEW) ;

/*
* 'draw_scene () ' - Rysowanie sceny zawierajcej kostk
* i przesaniajc j kul.
*/
Rozdzia 15. Bufory: nie tylko do animacji____________________________483

void CALLBACK
draw_scene(void)
{
static float red_light[4] = { 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 };
static float red_pos[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 0 . 0 };
static float blue_light[ 4 ] = { 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 };
static float blue_pos[4] = { - 1 . 0 , - 1 . 0 , - 1 . 0 , 0 . 0 );

/*
* Wczenie buforw i owietlenia
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
glEnable(GL_LIGHT1);

glshadeModel(GL_SMOOTH);
glDepthFunc(depth_function);

/*
* Wyczyszczenie bufora koloru i gbokoci.
*/
if (depth_function == GL_LESS)
glClearDepth(l.O);
else
glClearDepth( 0 . 0 ) ;

glClearColor{ 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT l GL_DEPTH_BUFFER_BIT);

/*
* Rysowanie kostki i kuli w rnych kolorach
*
* W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone
* i zostao umieszczone u gry z prawej strony, za obserwatorem.
* Drugie jest niebieskie i znajduje si u dou po lewej stronie,
* przed obserwatorem.
*/
glLightfv(Gt_LIGHTO, GL_DIFFUSE, red_light);
glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glPushMatrix();
glTranslatef(-1.0, 0 . 0 , -20.0);
auxSolidSphere(1.0) ;
glPopMatrix() ;

glPushMatrix();
glTranslatef( 1 . 0 , 0.0, -20.0);
glRotatef(15.0, 0.0, 1 . 0 , 0 . 0 ) ;
glRotatef(15.0, 0 . 0 , 0 . 0 , 1 . 0 ) ;
auxSolidCube( 2 . 0 ) ;
glPopMatrix();
484 ______________________ Cz III Tematy zaawansowane i efekty specjalne

glFlushO ;

/*
* ' toggle_depth() ' - Przecza porwnywanie gbokoci pomidzy
* funkcjami GL_LESS i GL_GREATER.
*/
V0id CALLBACK
toggle_depth (void)
{
if (depth_function == GL_LESS)
depth_function = GL_GREATER;
else
depth_function = GL_LESS;

/*
* ' m a i n ( ) ' - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza ' E s c ' .
*/
void
main(void)
(
aUKlnitDisplayMode (AOX_RGB | AUX_SINGLE | AUX_DEPTH) ;
auxlnitwindow( "Funkcje gbokoci") ;
auxKeyFunc (AUX_d, toggle_depth) ;
auxReshapeFunc (reshape_scene) ;
auxMainLoop (draw_scene) ;

* Koniec pliku " d e p t h . c "


*/

Inne zastosowanie bufora gbokoci


Bufor gbokoci moe zosta uyty do wygenerowania konturu sceny, przedstawiajcego
rne kolory dla rnych gbokoci. Mapy konturowe mog by generowane przy uyciu
funkcji glReadPixels w celu odczytania komponentu gbokoci:
glReadPixels(x, y, width, height, GL_DEPTH_COMPONENT, type, pixels);

Zwrcona warto gbokoci moe zosta przeskalowana i przypisana wartociom ko-


lorw, wywietlanych jako kontury obrazu, szczeglnie w trybach indeksu kolorw, na
przykad tak:
define WIDTH 320
#define HEIGHT 200
GLfloat pixels[WIDTH * HEIGHT];
int i;
Rozdzia 15. Bufory: nie tylko do animacji____________________________48S

// Rysowanie sceny...
glEnable(GL_DEPTH_TEST);

// Odczyt bufora gbokoci


glReadPixels( O , O, WIDTH, HEIGHT, GL_DEPTH_COMPONENT, GL_FLOAT,
pixels);
// Zamiana wartoci gbokoci na indeksy kolorw
for(i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = pixels[i] * 2 5 5 . 0 ; // Zakadamy palet z 256 pozycjami //
Wywietlenie nowych pikseli na ekranie glDisable(GL_DEPTH_TEST);
glDrawPixels( O , O, WIDTH, HEIGHT, GL_COLOR_INDEX, GL_FLOAT, p i x e l s ) ;

W rzeczywistych aplikacjach, prawdopodobnie umoliwiby uytkownikowi sterowanie


palet kolorw i zakresem wartoci. Moesz uy wartoci kolorw RGBA do po-
prawienia wygldu sceny, posugujc si funkcj glBlendFunc w celu wymieszania
normalnego" obrazu z obrazem gbokoci".

Wycinanie fragmentw sceny


Zobaczmy, jak mona wyci fragmenty sceny - na przykad blok silnika - w celu po-
kazania wewntrznego dziaania, ktrego normalnie nie moglibymy zobaczy. Przykad
takiego zastosowania bufora gbokoci zawiera listing 15.2. Sercem programu jest funkcja
draw_scene, rysujca obraz kostki i kuli przecitych ruchom paszczyzn. Aby wyci
fragment sceny, najpierw rysujemy paszczyzn obcinajc. Zamiast jednak rysowa
j w buforze koloru, za pomoc funkcji glDrawBuffer blokujemy rysowanie w buforze
kolorw:
glDrawBuffer(GL_NONE);

glColor3i(0, O, 0);
glBegin(GL_POLYGON);
glVertex3f(-100.0, 100.0, cutting_plane);
glVertex3f( 1 0 0 . 0 , 100.0, cutting_plane);
glVertex3f(100.0, -100.0, cutting_plane);
glVertex3f( - 1 0 0 . 0 , -100.0, cutting_plane);
glEnd();
glDrawBuffer(GL_BACK);

Po narysowaniu paszczyzny cicia, wczamy rysowanie w buforze koloru i normalnie


rysujemy kostk i kul. Narysowana niewidoczna paszczyzna ogranicza rysowane pi-
ksele jedynie do tych, ktre le poza ni, przez co uzyskujemy efekt usunicia fra-
gmentu sceny.

Listing 15.2. Uycie funkcji glDrawBuffer w celu wycicia wy branych fragmentw obiektw__

"depthcut.c" - Testowy program demonstrujcy uycie funkcji


glDepthFunc()i glDrawBuffer() w celu wycicia
fragmentw sceny.
486 ______________________ Cz III Tematy zaawansowane i efekty specjalne

* Wcinij klawisz ' d ' w celu przeczenia si pomidzy funkcjami


* porwna GL_LESS i GLJ3REATER. Wcinij 'Esc' w celu zakoczenia
* programu.
*/
#include <GL/glaux.h>

/*
* Te definicje zostay wprowadzone w celu zapewnienia zgodnoci
* pomidzy MS Windows a reszt wiata.
*

* CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.


*/
ifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* IWIN32 */

GLenum depth_function = GL_LESS; //Bieca funkcja porwnywania


//gbokoci
GLfloat cutting_plane = - 1 5 . 0 , /* Odlego paszczyzny obcinania */
cutting_dir = - 1 . 0 ; /* Kierunek paszczyzny obcinania */

/*
* ' reshape_scene ( ) ' - Zmiana rozmiaru s c e n y . . .
*/

void CALLBACK
reshape_scene (GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glviewport ( O , O, width, height);
glMatrixMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(22.5, (float)width / (float)height, 0 . 1 , 1 0 0 0 . 0 ) ;
glMatrixMode (GL_MODELVIEW) ;

/*
* 'draw_scene ( ) ' - Rysowanie sceny zawierajcej kostk
* i przesaniajc j kul.
*/
void CALLBACK
draw_scene (void)
{
static float red_light[4] = ( 1 . 0 , 0 . 0 , 0 . 0 , 1.0 };
static float red_pos[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 0.0 };
static float blue_light [ 4 ] = { 0.0, 0 . 0 , 1 . 0 , 1.0 };
static float blue_pos[4] = { -1.0, -1.0, -1.0, 0.0 };
Rozdzia 15. * Bufory: nie tylko do animacji___________________________487

/*
* Wczenie buforw i owietlenia
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
glEnable(GL_LIGHTl);
glShadeModel(GL_SMOOTH);
glDepthFunc(depth_function);

/*
* Wyczyszczenie bufora koloru i gbokoci.
*/
if (depth_function == GL_LESS)
glClearDepth(l.O);
else
glClearDepth( 0 . 0 ) ;
glClearColor( 0 . 0 , 0 . 0 , 0.0, 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/*
* Rysowanie paszczyzny cicia. Zwr uwag, e na ten czas
* wyczamy zwykle rysowanie w buforze koloru...
*/
glDrawBuffer(GL_NONE);

glColor3i(0, O, 0);
glBegin(GL_POLYGON);
glVertex3f( - 1 0 0 . 0 , 100.0, cutting_plane);
glVertex3f( 1 0 0 . 0 , 100.0, cutting_plane);
glVertex3f( 1 0 0 . 0 , -100.0, cutting_plane);
glVertex3f(-100.0, -100.0, cutting_plane);
glEnd();
g!DrawBuffer(GL_BACK);

/*
* Rysowanie kostki i kuli w rnych kolorach
*
* W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone
* i zostao umieszczone u gry z prawej strony, za obserwatorem.
* Drugie jest niebieskie i znajduje si u dou po lewej stronie,
* przed obserwatorem.
*/
glLightfv(GL_LIGHTO, GL_DIFFUSE, red_light);
glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glPushMatrix();
glTranslatef (-1.0, 0.0, -20.0);
auxSolidSphere( 1 . 0 ) ;
glPopMatrix();
488 _______________________ Cz III Tematy zaawansowane i efekty specjalne

glPushMatrix ( ) ;
glTranslatef ( 1 . 0 , 0 . 0 , -20.0);
glRotatef ( 1 5 . 0 , 0 . 0 , 1 . 0 , 0 . 0 ) ;
glRotatef (15.0, 0 . 0 , 0.0, 1 . 0 ) ;
auxSolidCube ( 2 . 0 ) ;
glPopMatrix() ;
auxSwapBuf f ers ( ) ;

/*
* ' toggle_depth () ' - Przecza porwnywanie gbokoci pomidzy
* funkcjami GL_LESS i GL_GREATER.
*/

V0id CALLBACK
toggle_depth (void) {
if (depth_function == GL_LESS)
depth_function = GLJ3REATER; else
depth_function = GL_LESS;

/*
* 'move_plane ( ) ' - W wolnym czasie przesuwanie paszczyzny cicia.
*/
void CALLBACK
move_plane (void) {
cutting_plane += cutting_dir;
/*
* W miar potrzeby zmiana kierunku...
*/

if (cutting_plane <= -30.0 ||


cutting_plane >= -15.0)
cutting_dir = -cutting_dir;
draw_scene ( ) ;

/*
* ' m a i n ( ) ' - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza ' E s c ' .
*/

void main( ) {
aux!nitDisplayMode(AOX_RGB | AUX_DOUBLE | AOX_DEPTH) ;
auxlnitwindow ( "Depth Function") ;

auxKeyFunc (AUX_d, toggl_depth) ;


auxReshapeFunc (reshape_scene) ;
aux!dleFunc (mov_plane) ;
Rozdzia 15. Bufory: nie tylko do animacji ___________________________ 489

auxMainLoop(draw_scene) ;

/*
* Koniec pliku "depthcut . c "
*/

Bufor szablonu
Bufor szablonu suy do ograniczenia rysowania na okrelonych obszarach ekranu i ma
wiele zastosowa, do ktrych bufor gbokoci po prostu si nie nadaje. W najpro-
stszym przypadku, bufora szablonu mona uy do zablokowania pewnych obszarw
ekranu. Na przykad, w programie symulatora lotu mona wykorzysta bufor szablonu do
ograniczenia operacji rysunkowych do wntrza okrgych wskanikw w kokpicie, takich
jak sztuczny horyzont czy wskanik wysokoci.

Jednak chyba najbardziej ekscytujcym zastosowaniem bufora szablonu jest tworzenie


cieni. W zalenoci od moliwoci karty graficznej mona tworzy twarde i mikkie
cienie, pochodzce od wielu rde wiata, nadajce scenie du dawk realizmu.

Korzystanie z bufora szablonu


Aby uy bufora szablonu, najpierw musisz zada jego utworzenia. W przypadku
Windows oznacza to ustawienie pola cStencilBits struktury PIXELFORMATDESCRI-
PTOR (PFD) danego okna:
pfd.cStencilBits = 1;

Gdy zadasz utworzenia bufora szablonu, musisz jeszcze wczy uywanie szablonu,
wywoujc w tym celu funkcj glEnable(GL_STENCIL_TEST). Bez tego wywoania,
bufor szablonu nie zostaby w ogle uwzgldniony.

Funkcje bufora szablonu


W OpenGL wystpuj cztery funkcje bufora szablonu:
void glClearStencil(GLint s ) ;
void glStencilFunc(GLenum func, GLint r e f , GLuint mask);
void glStencilMask(GLuint m a s k ) ;
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);

Funkcja glClearStencil dziaa podobnie do funkcji glClearColor, glClearDepth i glClear-


Index; suy do ustawienia wartoci uywanej do zerowania bufora szablonu w momencie
wywoania funkcji glCIear(GL_STENCIL_BIT); Domylnie w buforze szablonu
umieszczana jest warto 0. W odrnieniu od buforw gbokoci i koloru, bufor
szablonu nie musi by czyszczony przed kadym rysowaniem sceny. We wspomnianym
490______________________Cz III Tematy zaawansowane i efekty specjalne

wczeniej symulatorze lotw, wskaniki kokpitu prawdopodobnie nigdy nie zmieni


pooenia ani rozmiaru, wic odwieanie zawartoci bufora szablonu moe nie by
konieczne.

Rysowanie w buforze szablonu


Gdy za pomoc funkcji glEnable wczysz atrybut GL_STENCIL_TEST, musisz okreli
sposb dziaania bufora szablonu. Domylnie nie robi on nic, umoliwiajc rysowanie
na caej powierzchni ekranu bez aktualizowania zawartoci bufora szablonu. Aby bufor
szablonu zacz dziaa, musimy w nim umieci jakie wartoci. Kontroluj to funkcje
glStencilFunc oraz glStencilDepth.
Funkcja glStencilFunc definiuje funkcj porwnania, warto odniesienia oraz mask dla
wszystkich operacji na buforze szablonu. Rysowanie jest moliwe tylko wtedy, gdy
funkcja porwnujca zwrci warto True. Dostpne funkcje porwnania zostay zebrane w
tabeli 15.7.

Tabela 15.7.
Funkcje bufora szablonu

Funkcja Opis
GL_NEVER Zawsze False (zablokowanie rysowania).
GL_LESS True, jeli warto odniesienia < warto szablonu.
GL_LEQUAL True, jeli warto odniesienia <= warto szablonu.
GL_GREATER True, jeli warto odniesienia > warto szablonu.
GL_GEQUAL Truejeli warto odniesienia >= warto szablonu.
GL_EQUAL True, jeli warto odniesienia = warto szablonu.
GL_NOTEQUAL True, jeli warto odniesienia != warto szablonu.
GL_ALWAYS Zawsze True (mona rysowa bez ogranicze).

Z funkcj szablonu wi si operacje szablonu, definiowane za pomoc funkcji


glStencilOp. Dostpne operacje zostay zebrane w tabeli 15.8.

Tabela 15.8.
Operacje szablonu

Operacja Opis
GL_KEEP Pozostawiana jest bieca zawarto bufora szablonu.
GL_ZERO Zawarto bufora szablonu jest zerowana.
GL_REPLACE Zawarto bufora szablonu jest zastpowana wartoci odniesienia.
Rozdzia 15. Bufory: nie tylko do animacji____________________________491

Tabela 15.8.
Operacje szablonu - cig dalszy

Operacja Opis
GL_INCR Zawarto bufora szablonu jest inkrementowana.
GL_DECR Zawarto bufora szablonu jest dekrementowana.
GL_INVERT Zawarto bufora szablonu jest negowana bitowo.

Zwykle obraz maski jest uywany do okrelenia obszaru, w ktrym bdzie dozwolone
rysowanie. Oto przykad przygotowania do rysowania maski w buforze szablonu:
glStencilFunc(GL_ALWAYS, l, 1); glStencilOp(GL_REPLACE,
GL_REPLACE, GL_REPLACE);

Nastpnie za pomoc polece rysunkowych moesz wpisa jedynki do bufora szablonu.


Aby rysowa z zastosowaniem maski w buforze szablonu, przed przystpieniem do ry-
sowania sceny wywoaj ponisze funkcje:
glStencilFunc(GL_EQUAL, l, 1 ) ;
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

Poniewa dziaa to ze wszystkimi poleceniami rysunkowymi OpenGL, wcznie z glBit-


map, moesz uy bufora szablonu do uzyskania wielu efektw dziur", take na po-
trzeby animacji! Listing 15.3 zawiera zmodyfikowan wersj poprzedniego przykadu,
program STENCILCT.C, wykorzystujcy bufor szablonu, zamiast bufora gbokoci, w
celu wycicia rodka kostki.
Oto serce tego programu, wykorzystujce opisane powyej funkcje:
glStencilFunc(GL_ALWAYS, l, 1 ) ;
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

glPushMatrix();
glTranslatef( -1 . 0 , 0 . 0 , - 2 0 . 0 ) ;
auxSolidSphere( 1 . 0 ) ;
glPopMatrix();

Po narysowaniu obrazu w buforze szablonu, rysujemy kostk w tych miejscach, w ktrych


kula nie jest narysowana:
glStencilFunc(GL_NOTEQUAL, l, 1 ) ;
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glPushMatrix();
glTranslatef( 1 . 0 , 0 . 0 , - 2 0 . 0 ) ;
glRotatef(15.0, 0.0, 1.0, 0 . 0 ) ;
glRotatef(15.0, 0.0, 0.0, 1 . 0 ) ;
auxSolidCube( 2 . 0 ) ;
glPopMatrix();
492_______________________Cz III Tematy zaawansowane i efekty specjalne

Listing 15.3. STENCILCT.C, przykad wykorzystania bufora szablonu_____________________

/*
* "stencilct. c " - Testowy program demonstrujcy uycie funkcji
* glStencilFunc() i glStencilOp() w celu wycicia fragmentw sceny.
*/
ttinclude <GL/glaux.h>

/*
* Te definicje zostay wprowadzone w celu zapewnienia zgodnoci
* pomidzy MS Windows a reszt wiata.
*
* CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.
*/

ttifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* 1WIN32 */

/*
* 'reshape_scene()' - Zmiana rozmiaru s c e n y . . .
*/
void CALLBACK
reshape_scene(GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ ( /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glYiewport( O , O, width, h eight);

glMatrixMode(GL_PROJECTION);
glLoadldentity();
gluPerspective(22.5, (float)width / (float)height, 0 . 1 , 1 0 0 0 . 0 ) ;
glMatrixMode(GL_MODELVIEW);

/*
* 'draw_scene()' - Rysowanie sceny zawierajcej kostk i
* przesaniajc j kul.
*/
void CALLBACK
draw_scene(void)
{
static float red_light[4] = { 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 };
static float red_pos[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 0 . 0 };
static float blue_light[ 4 ] = { 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 };
static float blue_pos[4] = { - 1 . 0 , - 1 . 0 , - 1 . 0 , 0 . 0 };
Rozdzia 15. Bufory: nie tylko do
animacji____________________________493

/*
* Wczenie buforw i owietlenia
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
glEnable(GL_LIGHT1);

glShadeModel(GL_SMOOTH);

/*
* Wyczyszczenie bufora koloru, szablonu i gbokoci.
*/
glClearColor( 0 . 0 , 0 . 0 , 0.0, 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);

/*
* Rysowanie kuli, ktra wytnie cz k o s t k i . . .
*/

glstencilFunc(GL_ALWAYS, l, 1 ) ; glStenci!Op(GL_REPLACE,
GL_REPLACE, GL_REPLACE);

glPushMatrix();
glTranslatef (-1.0, 0 . 0 , -20.0);
auxSolidSphere( 1 . 0 ) ;
glPopMatrix();

/*
* Ponowne wyczyszczenie bufora koloru i gbokoci...
*/
glClearColor( 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/*
* Rysowanie kostki w rnych kolorach
*k

* W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone


* i zostao umieszczone u gry z prawej strony, za obserwatorem.
* Drugie jest niebieskie i znajduje si u dou po lewej stronie,
* przed obserwatorem.
*/
glstencilFunc(GL_NOTEQUAL, l, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glLightfv(GL_LIGHTO, GL_DIFFUSE, red_light);


glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glPushMatrix();
glTranslatef( 1 . 0 , 0 . 0 , - 2 0 . 0 ) ;
glRotatef(15.0, 0 . 0 , 1 . 0 , 0 . 0 ) ;
494_______________________Cz III Tematy zaawansowane i efekty specjalne

glRotatef( 15 .0 , 0 . 0 , 0 . 0 , 1 . 0 ) ;
auxSolidCube ( 2 . 0 ) ; glPopMatrix();

auxSwapBuffers();

/*
* 'mainO' - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza 'Esc'.
*/

void main() {
aux!nitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH l AUX_STENCIL) ,
auxlnitwindow("Rysowanie od szablonu");

auxReshapeFunc(reshape_scene);
auxMainLoop(draw_scene);

/*
* Koniec pliku "stencilct.c".
*/

Bufor akumulacji
Bufor akumulacji umoliwia uzyskanie wiele efektw specjalnych, takich jak na przykad
rozmycie ruchu. Posugujc si nim, mona przeprowadza penoekranowy anty-aliasing,
cho lepiej nadaj si do tego raczej inne metody, choby multisampling.

Bufor akumulacji jest zdecydowanie mniej skomplikowany ni pozostae, omawiane


dotd bufory. Posiada pojedyncz funkcj, glAccum, sterujc jego dziaaniem. Dostpne
operacje zostay zebrane w tabeli 15.9.

Tabela 15.9.
Operacje akumulacji

Operacja Opis

GL_ACCUM Dodaje przeskalowane wartoci z bufora koloru do wartoci w buforze


akumulacji.
GL_LOAD aduje przeskalowane wartoci z bufora koloru do bufora akumulacji,
zastpujc
przechowywane w nim dotd wartoci.
GL_ADD Dodaje sta warto koloru do wartoci w buforze akumulacji.
GL_MULT Mnoy wartoci w buforze akumulacji przez sta warto koloru (efekt
filtrowania).
GL_RETURN Kopiuje zawarto bufora akumulacji do gwnego bufora koloru.
Rozdzia 15. Bufory: nie tylko do animacji ____________________________ 495

Zwyky sposb uycia bufora akumulacji polega na wyrenderowaniu do niego kilku


widokw, a nastpnie wywietleniu zoonej sceny za pomoc funkcji glAccum(GL_
RETURN, 1.0);

Uycie bufora akumulacji


w celu zasymulowania rozmycia ruchu
Jak kiedy stwierdzi jeden z naszych wsppracownikw, atwo jest tak wykorzysta
bufor akumulacji, aby scena wygldaa na poruszon! Ten efekt wystpuje wtedy, gdy
podczas robienia zdjcia poruszysz aparatem - zbyt due drgnicie rki powoduje roz-
mycie obrazu.
Renderowanie rozmycia ruchu jest czym bardziej skomplikowanym ni po prostu na-
rysowanie sekwencji klatek, w ktrej kamera zmienia pooenie pomidzy kolejnymi
klatkami. Rozmycie ruchu dostrzegamy wtedy, gdy obiekt porusza si szybciej, ni mog
za nim nady oczy. Obraz zmienia si szybciej, ni mzg moe go przetworzy", mimo
e cay czas mamy na nim skupiony wzrok. W przypadku aparatu, wiato padajce na film
nawietla go przez pewien okrelony czas. W zalenoci od aparatu i fotografa, rozmycie
moe ogranicza si jedynie do ostrych krawdzi lub rozciga si na cae zdjcie.
Gdy symulujesz rozmycie ruchu w grafice komputerowej, wane jest, aby pamita, e
bieca (czy ostatnia) posta rozmywanego obiektu musi wyglda na bardziej skupion ni
na pozostaych klatkach. Najprostszym sposobem osignicia tego efektu jest uycie w
ostatniej klatce wikszego wspczynnika przeskalowania kolorw, tak aby wicej
kolorw ostatniej klatki zostao umieszczonych w buforze akumulacji. Zwykle wyglda to
mniej wicej tak:
// Rysowanie biecej klatki
draw_frame (0) ;
// Zaadowanie do bufora akumulacji 50% biecej klatki
glAccum(GL_LOAD, 0 . 5 ) ;

// Narysowanie ostatnich 10 klatek, akumulacja po 5% kada ford


= 1; i <= 10;

draw_frame (-i) ;
glAccum(GL_ACCUM, 0 . 0 5 ) ; >;

// Wywietlenie kocowej sceny


glAccum(GL_RETURN, 1 . 0 ) ;

Zwr uwag, e w celu zainicjowania zawartoci bufora akumulacji nie trzeba uywa
funkcji glClear, tak jak to byo konieczne w przypadku buforw koloru, gbokoci i
szablonu. Zamiast niej, zwykle bdziesz stosowa funkcj glAccum(GL_LOAD, s) w
odniesieniu do pierwszej klatki sceny. Rozmycie ruchu dla kuli i kostki demonstruje
program z listingu 15.4.
496 _______________________ Cz III Tematy zaawansowane i efekty specjalne

Listing 15.4. MOTION.C: Rozmycie ruchu przy uyciu bufora akumulacji ___________________

/*
* "motion.c" - Testowy program demonstrujcy uycie funkcji glAccumO
* dla uzyskania efektu rozmycia ruchu.
*/
tinclude <GL/glaux.h>

/*
* Te definicje zostay wprowadzone w celu zapewnienia zgodnoci
* pomidzy MS Windows a reszt wiata.
Tt

* CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.


*/

ifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* 1WIN32 */
GLfloat rotation = 0 . 0 ;

/*
* ' reshape_scene ( ) ' - Zmiana rozmiaru s c e n y . . .
*/
void CALLBACK
reshape_scene (GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glViewport ( O , O, width, height);

glMatriKMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(22.5, (float) width / (f loat) height, 0 . 1 , 1000.0);
glMatrixMode (GL_MODELVIEW) ;

/*
* 'draw_scene ( ) ' - Rysowanie sceny zawierajcej kostk
* i przesaniajc j kul.
*/
void CALLBACK
draw_scene (void) {
GLfloat f ram;
static float red_light[4] = { 1.0, 0.0, 0.0, 1.0 };
static float red_pos[4] = { 1.0, 1.0, 1.0, 0.0 };
static float blue_light [4] = { 0.0, 0.0, 1.0, 1.0 };
static float blue_pos[4] = { -1.0, -1.0, -1.0, 0 . 0 };
Rozdzia 15. Bufory: nie tylko do animacji___________________________497

/*
* Wczenie buforw i owietlenia
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
glEnable(GL_LIGHT1);

glShadeModel(GL_SMOOTH);

/*
* Wyczyszczenie bufora koloru i gbokoci.
*/

glClearColor( 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/*
* Rysowanie kostki i kuli w rnych kolorach
*
* W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone
* i zostao umieszczone u gry z prawej strony, za obserwatorem.
* Drugie jest niebieskie i znajduje si u dou po lewej stronie,
* przed obserwatorem.
*/
glLightfv(GL_LIGHTO, GL_DIFFOSE, red_light);
glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

/*
* Rysowanie obiektw 11 razy, poczwszy od biecego kta obrotu...
*/
for (fram = 0 . 0 ; fram <= 1 1 . 0 ; fram ++) {
glPushMatrix();
glTranslatef( 0 . 0 , 0 . 0 , - 2 0 . 0);
glRotatef(rotation - frame, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glPushMatrix();
glTranslatef(-1.O, 0 . 0 , 0 . 0 ) ;
auxSolidSphere( 1 . 0 ) ;
glPopMatrix();
glPushMatrix();
glTranslatef( 1 . 0 , 0. 0 , 0 . 0 ) ;
glRotatef(15.0, 0.0, 1.0, 0 . 0 ) ;
glRotatef(15.0, 0.0, 0.0, 1 . 0 ) ;
auxSolidCube( 2 . 0 ) ; glPopMatrix();
glPopMatrix();
/*
* Akumulacja 50% pierwszej klatki i po 5% dla nastpnych
*/
498_______________________Cz III Tematy zaawansowane i efekty specjalne

if (fram == 0 . 0 )
glAccum(GL_LOAD, 0 . 5 ) ;
else
glAccum(GL_ACCUM, 0 . 0 5 ) ;
>;
/*
* Skopiowanie zakumulowanego wyniku do bufora k o l o r u . . . V

g!Accum(GL_RETORN, 1 . 0 ) ;

auxSwapBuffers();

/*
* ' rotate_objects ( ) ' - W wolnych chwilach obrt s c e n y . . .
*/
void CALLBACK
rotate_objects (void)
{
rotation += 2 . 0 ;
if (rotation >= 3 6 0 . 0 )
rotation -= 3 6 0 . 0 ;
draw_scene ( ) ;

/*
* ' m a i n O ' - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza ' E s c 1 .
*/
void main( ) {
aux!nitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH | AUX_ACCOM) ;
auxlnitwindow( "Rozmycie ruchu") ;

auxReshapeFunc (reshape_scene) ;
auxIdleFunc (rotate_objects) ;
auxMainLoop(draw_scene) ;

/*
* Koniec pliku " m o t i o n . c " .
*/

Uycie bufora akumulacji do antyaliasingu


Kolejnym zastosowaniem bufora akumulacji jest penoekranowy antyaliasing. Podsta-
wow technik jest poruszenie obrazu po p piksela w rnych kierunkach, w celu roz-
mycia krawdzi bez rozmywania jednolitych obszarw. Akumulacja czterech takich
obrazw daje znaczny efekt wygadzenia. Kompilator Yisual C++ zawiera wiele przy-
Rozdzia 15. Bufory: nie tylko do animacji 499

kadw OpenGL, w ktrych zastosowano takie poruszenie obrazu w celu uzyskania


antyaliasingu. Wiele rnych zestaww wartoci przesunicia znajdziesz w pliku
OpenGL\Book\Jitter.h na instalacyjnej pytce Yisual C++.
Antyaliasing przy uyciu bufora akumulacji nie jest jednak zbyt szybki. Jeli rzeczy-
wicie chcesz uzyska antayaliasing w czasie rzeczywistym, powiniene poszuka karty
graficznej, ktra dziki zastosowaniu multisamplingu sama wykona antyaliasing. Bufor
akumulacji jest do tego zbyt wolny.
Jeli generujesz statyczne obrazy, bufor akumulacji umoliwia uzyskanie efektw anty-
aliasingu i gbokoci pola, ktrych po prostu nie da si osign za pomoc samego m
ultisamplingu.

Podrcznik
glAccum
Przeznaczenie Steruje dziaaniem bufora akumulacji.
Plik
nagwkowy void glAccum(GLenum func, GLfloat value);
Skadnia Opis Ta funkcja steruje buforem akumulacji. Z wyjtkiem operacji
GL_RETURN, wartoci koloru s skalowane przez parametr value i
dodawane lub umieszczane w buforze akumulacji. W przypadku
operacji GL_RETURN, wartoci kolorw z bufora akumulacji s
skalowane przez parametr value i umieszczane w biecym buforze
koloru.
Paramet
ry GLenum: Operacja na buforze akumulacji. Dostpne s nastpujce
operacje:
GL_ACCUM Dodaje przeskalowane wartoci z bufora koloru do
wartoci w buforze akumulacji.
GL_LOAD aduje przeskalowane wartoci z bufora koloru do
bufora akumulacji, zastpujc przechowywane w nim
dotd wartoci.
GL_ADD Dodaje sta warto koloru do wartoci w buforze
akumulacji.
GL_MULT Mnoy wartoci w buforze akumulacji przez sta
warto koloru (efekt filtrowania).
GL_RETURN K opiuje zawarto bufora akumulacji do gwnego
bufora koloru.
500 Cz III Tematy zaawansowane i efekty specjalne

value GLfloat: Warto, przez ktr s skalowane wartoci umieszczane w


buforze.
Zwracana warto Brak.
Przykad Kod programu MOTION.C na pytce CD-ROM.
Patrz take ChoosePixelFormat, SetPixelFormat

glCIearColor
Przeznaczenie Plik Okrela warto uywan do czyszczenia bufora koloru.
nagwkowy
Skadnia void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat
alpha);
Opis Ta funkcja ustawia warto koloru, uywan podczas czyszczenia bufora
koloru funkcj glClear(GL_COLOR_BUFFER_BIT).
Parametry
red GLfloat: Czerwona skadowa koloru czyszczenia bufora.
green GLfloat: Zielona skadowa koloru czyszczenia bufora.
blue GLfloat: Niebieska skadowa koloru czyszczenia bufora.
alpha GLfloat: Skadowa alfa koloru czyszczenia bufora.
Zwracana warto Brak.
Patrz take ChoosePixelFormat, SetPixelFormat

glCIearDepth
Przeznaczenie Plik Okrela warto uywan do czyszczenia bufora gbokoci.
nagwkowy
Skadnia Opis void glClearDepth(GLclampd depth);
Ta funkcja ustawia warto gbokoci, uywan podczas czyszczenia
Parametry bufora gbokoci funkcj glClear(GL_DEPTH_BUFFER_BIT).
depth
Zwracana warto GLclampd: Warto czyszczenia bufora gbokoci.
Patrz take Brak.
ChoosePixelFormat, SetPixelFormat
Rozdzia 15. Bufory: nie tylko do animacji 501

glClearlndex
Przeznaczenie Okrela warto uywan do czyszczenia bufora koloru.
Plik nagwkowy <gl.h>
Skadnia void glClear!ndex(GLfloat index);
Opis Ta funkcja ustawia indeks koloru, uywany podczas czyszczenia bufora
kolorw funkcj glClear(GL_COLOR_BUFFER_BIT).
Paramet
ry GLfloat: Indeks koloru czyszczenia bufora koloru.
Zwracana warto Brak.
Patrz take ChoosePixelFormat, SetPixelFormat

glClearStencil
Przeznaczenie Okrela warto uywan do czyszczenia bufora szablonu.
Plik
nagwkowy void glClearStencil(GLint value);
Skadnia Opis Ta funkcja ustawia warto uywan podczas czyszczenia bufora
szablonu funkcj glClear(GL_STENCIL_BUFFER_BIT).
Parametry
value GLint: Warto czyszczenia bufora szablonu.
Zwracana Brak.
warto Patrz ChoosePixelFormat, SetPixelFormat

gIDrawBuffer
Przeznaczenie Wybiera bufor przeznaczony do rysowania.
Plik
nagwkowy void glDrawBuffer(GLenum mod);
Skadnia Opis Ta funkcja suy do wyboru bufora, do ktrego bd si odnosi nastpne
operacje rysunkowe. Zwykle jest uywana do wyboru przedniego lub
tylnego bufora przy podwjnym buforowaniu.
502 Cz III Tematy zaawansowane i efekty specjalne

Parametry
mod Glenum: Staa (patrz tabela 15.10) okrelajca bufor, ktry ma zosta
wykorzystany. Na przykad, aby wybra do rysowania tylny bufor, uyj
Zwracana warto
wywoania:
Znane bdy glDrawBuffer(GL_BACK);

Brak.
Przykad
Oglna implementacja Microsoftu nie obsuguje buforw stereo ani
Patrz take parametru mod rwnego GL_NONE.
Kod programu DEPTHCUT.C na pytce CD-ROM.
ChoosePixelFormat, SetPixelFormat

Tabela 15.10.
Dostpne tryby w wywoaniu funkcji glDrawBuffer

Bufor Opis

GL_NONE GL_FRONT Bez rysowania w adnym buforze. Rysowanie w


GL_BACK przednim (widocznym) buforze. Rysowanie w
GL_FRONT_AND_BACK tylnym (niewidocznym) buforze.
Rysowanie w obu buforach naraz (tylko w kontekstach z podwjnym
buforowaniem).
GLJ.EFT
Rysowanie w buforze koloru dla lewego oka (tylko w kontekstach z
buforowaniem stereo, przy podwjnym buforowaniu wybr obu
buforw naraz, przedniego i tylnego).
GL_RIGHT
Rysowanie w buforze koloru dla prawego oka (tylko w kontekstach z
buforowaniem stereo, przy podwjnym buforowaniu wybr obu
buforw naraz, przedniego i tylnego).
GL_BACK_LEFT
Rysowanie w buforze koloru dla lewego oka (tylko w kontekstach z
buforowaniem stereo i przy podwjnym buforowaniu).
GL_RIGHT_BACK
Rysowanie w buforze koloru dla prawego oka (tylko w kontekstach z
buforowaniem stereo i przy podwjnym buforowaniu).
GL_FRONT LEFT GL
Rysowanie w buforze koloru dla lewego oka (tylko w kontekstach z
buforowaniem stereo i przy podwjnym buforowaniu).
FRONT RIGHT
Rysowanie w buforze koloru dla prawego oka (tylko w kontekstach z
buforowaniem stereo i przy podwjnym buforowaniu).

glDepthFunc
Przeznaczenie Wybiera funkcj porwnywania dla bufora gbokoci.
Plik nagwkowy <gl.h>
Skadnia void glDepthFunc(GLenum func);
Rozdzia 15. Bufory: nie tylko do animacji 503

Opis Ta funkcja suy do wyboru funkcji uywanej przy porwnywaniu


wartoci w buforze gbokoci.
Paramet
ry GLenum: Staa okrelajca funkcj porwnywania. Dostpne funkcje to:
GLJNEYER Zawsze False
GL_LESS True, jeli Z piksela < Z bufora
GL_EQUAL True, jeli Z piksela = Z bufora
GL_LEQUAL True, jeli Z piksela <= Z bufora
GL_GREATER True, jeli Z piksela > Z bufora
GL_NOTEQUAL True, jeli Z piksela != Z bufora
GL_GEQUAL True, jeli Z piksela >= Z bufora
GL_ALWAYS Zawsze True
Zwracana Brak.
warto Kod programu DEPTH.C na pytce CD-ROM.
Przykad Patrz ChoosePixelFormat, SetPixelFormat

glDepthRange
Przeznaczenie Ustawia zakres wartoci przechowywanych w buforze gbokoci.
Plik
nagwkowy void glDepthRange(GLclampd near, GLclampd far);
Skadnia Opis Ta funkcja ustala zakres wartoci przechowywanych w buforze
gbokoci, uywanych przy porwnaniach gbokoci w celu usuwania
niewidocznych powierzchni. Parametr near moe by wikszy ni/ar.
Parametry
near GLclampd: Blisza warto gbokoci.
far GLclampd: Dalsza warto gbokoci.
Zwracana Brak.
warto Kod programu DEPTH.C na pytce CD-ROM.
Przykad Patrz ChoosePixelFormat, SetPixelFormat

Rozdzia 16.
Efekty
specjalne:
przezrocz
ysto i
mga
W tym rozdziale:
Dowiesz si, jak... Uywane funkcje
* Wywietla przezroczyste linie i wielokty. * glBlendFunc
* Stworzy efekt pyu lub mgy + glFog

W tym rozdziale poznamy funkcje


OpenGL umoliwiajce stworzenie
efektw przezroczystoci i mgy.

Funkcje przezroczystoci pozwalaj na


tworzenie przejrzystych obiektw, takich
jak szyby, szklanki, pyny i inne tego typu
rzeczy. Funkcje mgy dodaj do sceny
pewn zmienn ilo koloru, powodujc
powstanie efektu zamglenia lub wrcz
mgy, bardzo wpywajcej na atmosfer
caej sceny.

Przy stosowaniu przezroczystoci i mgy


naley jednak pamita o jednej rzeczy.
Te efekty nie wychodz zbyt dobrze w
trybach omiobitowych. Pamitaj, aby
uzupeni swoje programy o opcj
umoliwiajc wyczenie tych efektw w
przypadku wykorzystywania 8-bitowych
kart graficznych.

Blending
Blending (czenie kolorw) w OpenGL
polega na kontrolowaniu wartoci
RGBA poszczeglnych pikseli w scenie na
podstawie pikseli ju istniejcych. Operacje
czenia kolorw nie s dostpne w trybie
indeksu kolorw.

Aby wczy czenie kolorw w oknach


RGBA, musisz najpierw wywoa
funkcj glEnable(GL_BLEND). Potem
powiniene wywoa funkcj glBlendFunc
z dwoma ar-
506 Cz III Tematy zaawansowane i efekty specjalne

gumentami: funkcjami czenia koloru rdowego i docelowego (tabela 16.1 i 16.2).


Domylnie, tymi argumentami s odpowiednio funkcje GL_ONE i GL_ZERO, co stanowi
odpowiednik wyczenia czenia kolorw wywoaniem glDisable(GL_BLEND).

Tabela 16.1.
Funkcje czenia koloru rdowego

Funkcja Wspczynnik czenia koloru

GL_ZERO
GL_DST_ALPHA
GL_ONE
GLJ)ST_COLOR GL_ONE_MINUS _DST_ALPHA GL SRC ALPHA SATURATE
GL_ONE_MINUS_DST_COLOR
GL_SRC_ALPHA
GL_ONE_MINUS_SRC_ALPHA
Kolor rdowy = O, O, O, 0. Kolor rdowy jest mnoony przez rdow skadow alfa.
Uywa <?> koloru rdowego. Kolor rdowy jest mnoony przez (l - rdowa skadowa alfa).
Kolor rdowy jest mnoony przez Kolor rdowy jest mnoony przez docelow skadow alfa.
Nieobsugiwane w Microsoft OpenGL.
kolor piksela docelowego.
Kolor rdowy jest mnoony przez (l - docelowa skadowa alfa).
Kolor rdo wy jest mnoony Nieobsugiwane w Microsoft OpenGL.
przez (l, l, l, l, l - kolor docelowy). Kolor rdowy jest mnoony przez mniejsz z wartoci: rdow
skadow alfa i (l - docelowa skadowa alfa). Nieobsugiwane w
Microsoft OpenGL.

Tabela 16.2.
Funkcje czenia koloru docelowego

Funkcja Wspczynnik czenia koloru

GL_ZERO Kolor docelowy = O, O, O, 0.


GLJDNE Uywa <?> koloru docelowego.
GL_DST_COLOR Kolor docelowy jest mnoony przez kolor piksela rdowego.
GL_ONE_MINUS_DST_COLOR Kolor docelowy jest mnoony przez (l, l, l, l, l - kolor rdowy).
GL_SRC_ALPHA Kolor docelowy jest mnoony przez rdow skadow alfa.
GL_ONE_MINUS_SRC_ALPHA Kolor docelowy jest mnoony przez (l - rdowa skadowa alfa).
Kolor docelowy jest mnoony przez docelow skadow alfa.
GLJ)ST_ALPHA Nieobsugiwane w Microsoft OpenGL.
Kolor docelowy jest mnoony przez (l - docelowa skadowa alfa).
GL_ONE_MINUS _DST_ALPHA Nieobsugiwane w Microsoft OpenGL.
Kolor docelowy jest mnoony przez mniejsz ze rdowej skadowej
GL SRC ALPHA SATURATE alfa i (l - docelowa skadowa alfa). Nieobsugiwane w Microsoft
OpenGL.
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________507

Efekt przezroczystoci przez czenie kolorw


Przezroczysto jest najbardziej typowym wykorzystaniem czenia kolorw, czsto
uywanym w celu stworzenia szyb, butelek i innych przezroczystych trjwymiarowych
obiektw. Dziki przezroczystoci mona take czy ze sob kilka obrazw lub te
osign efekt mikkiego pdzla" w programach graficznych.

Oto funkcje czenia kolorw wywoywane we wszystkich tego typu programach:


glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Powysza kombinacja powoduje pobranie koloru piksela rdowego i przeskalowanie go


zgodnie z wartoci skadowej alfa, a nastpnie dodanie koloru piksela docelowego
przeskalowanego przez l minus warto skadowej alfa. Mwic prociej, funkcja -
czca bierze uamek biecego koloru rysowania i nakada go na piksel na ekranie.
Skadowa alfa koloru moe mie warto od O (cakowicie przezroczysty) do l (cakowicie
nieprzezroczysty):
Rd = Rs * As + Rd * (l - A s )
Gd = Gs * As + Gd * (l - A s )
Bd = Bs * As + Bd * (l - A s )

Poniewa uywana jest jedynie rdowa skadowa alfa, nie musisz posiada karty prze-
chowujcej w buforze koloru take bity kanau alfa. To jest wane, gdy standardowa
implementacja OpenGL Microsoftu nie obsuguje kanau alfa w buforze koloru.

Przy stosowaniu czenia kolorw naley pamita, e testowanie bufora gbokoci


moe wpyn na efekt, ktry chcesz osign. Aby mie pewno, e przezroczyste
wielokty i linie bd poprawnie narysowane, zawsze rysuj je od tyu do przodu.

Rysunek 16.1.
Przezroczysty imbryk do
herbaty narysowany przy
uyciu czenia kolorw
508 ______________________ Cz III Tematy zaawansowane i efekty specjalne

Listing 16.1 przedstawia kod uyty do narysowania przezroczystego imbryka do herbaty z


rysunku 16.1. W funkcji draw_scene rysujemy dwa imbryki do herbaty, od tyu do przodu,
w celu zapewnienia, e przedni imbryk bdzie widzia. Jak wida, na ekranie pozostaj
rne artefakty (niepodane efekty), w miejscach, gdzie przecinaj si wielokty.
Nie da si ich kompletnie wyeliminowa, ale mona zredukowa ich ilo sortujc
wstpnie wielokty wedug ich gbokoci oraz wczajc usuwanie odwrconych
wieloktw funkcj glEnable(GL_CULL_FACE).

Pierwsz rzecz, jak robimy w funkcji draw_scene, jest wczenie mieszania kolorw w
celu osignicia przezroczystoci na podstawie wartoci alfa koloru rysowania
(rdowego):
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;

Nastpnie rysujemy nieprzezroczysty imbryk przy wyczonym mieszaniu kolorw, tak


abymy go zawsze widzieli:
glDisable (GL_BLEND) ; glColor3f
(1.0, 1.0, 0 . 0 ) ;
auxSolidTeapot ( 1 . 0 ) ;

Na koniec wczamy mieszanie kolorw i rysujemy przezroczysty imbryk, z wartoci


alfa (przezroczystoci) wynoszc 0,25:
glEnable (GL_BLEND) ;
glColor4f ( 1 . 0 , 1.0, 1 . 0 , 0 . 2 5 ) ;
auxSolidTeapot ( 1 . 0 ) ;

Listing 16.1. BLENDPOT.C: uycie funkcji glBlendFunc \v celu stworzenia efektu przezroczystoci _____

* "blendpot.c" - Testowy program demonstrujcy uycie funkcji


* glBlendFunc () w celu osignicia przezroczystoci.
V
linclude <GL/glaux.h>

Te definicje zostay wprowadzone w celu zapewnienia zgodnoci


pomidzy MS Windows a reszt wiata.
CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.

#ifndef WIN32
define CALLBACK
# define APIENTRY
ttendif /* 1WIN32 */
GLfloat rotation = 0 . 0 ;

/*
* 'reshape_scene () ' - Zmiana rozmiaru s c e n y . . .
*/
Rozdzia 16. * Efekty specjalne: przezroczysto i mga____________________509

void CALLBACK
reshape_scene(GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
giviewport( O , O, width, h e i g h t ) ;

glMatrixMode(GL_PROJECTION);
glLoadldentity();
gluPerspective(22.5, (float)width / (float)height, 0 . 1 , 1000.0);
glMatrixMode(GL_MODELVIEW);

/*
* 'draw_scene()' - Rysowanie sceny zawierajcej dwa imbryki do
* herbaty
*/
void CALLBACK
draw_scene(void)
{
GLfloat frame;
static float red_light[4] = ( 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 };
static float red_pos[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 0 . 0 };
static float blue_light[ 4 ] = { 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 };
static float blue_pos[4] = { - 1 . 0 , - 1 . 0 , - 1 . 0 , 0 . 0 };

/*
* Wczenie buforw i owietlenia
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
glEnable(GL_LIGHTl);
glShadeModel(GL_SMOOTH);

/*
* Wyczyszczenie bufora koloru i gbokoci.
*/
glClearColor(0.0, 0.0, 0.0, 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BOFFER_BIT);

/*
* W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone
* i zostao umieszczone u gry z prawej strony, za obserwatorem.
* Drugie jest niebieskie i znajduje si u dou po lewej stronie,
* przed obserwatorem.
*/
glLightfv(GL_LIGHTO, GL_DIFFUSE, red_light);
glLightfv(GL_LIGHTO, GL_POSITION, red_pos);
510_______________________Cz III Tematy zaawansowane l efekty specjalne

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glEnable(GL_COLOR_MATERIAL);
g!BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glPushMatrix();
glTranslatef( 0 . 0 , 0 . 0 , - 1 5 . 0 ) ;
glRotatef(-rotation, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glDisable(GL_BLEND);
glColor3f( 1 . 0 , 1 . 0 , 0 . 0 ) ;
auxSolidTeapot( 1 . 0 ) ;
glPopMatrix();
glPushMatrix();
glTranslatef( 0 . 0 , 0 . 0 , - 1 0 . 0 ) ;
glRotatef(rotation, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glEnable(GL_BLEND); glColor4f( 1 . 0 ,
1.0, 1.0, 0.25);
auxSolidTeapot( 1 . 0 ) ; glPopMatrix();
auxSwapBuffers();

/*
* ' rotate_objects ( ) ' - w wolnych chwilach obrt s c e n y . . .
*/
void CALLBACK
rotate_objects (void) {
rotation += 2 . 0 ;
if (rotation >= 3 6 0 . 0 )
rotation -= 3 6 0 . 0 ;
draw_scene ( ) ;

/*
* ' m a i n f ) 1 - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza ' E s c ' .
*/
void
main (void)
{
auxInitDisplayMode (AUX_RGB | AUX_DOUBLE | AUX_DEPTH) ;
auxlnitwindow( "Przezroczysty imbryk do h e r b a t y " ) ;

auxReshapeFunc (reshape_scene) ;
aux!dleFunc(rotate_objects) ;
auxMainLoop (draw_scene) ;
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________511

/*
* Koniec pliku "blendpot. c " .
*/

czenie kolorw przy antyaliasingu


Uywajc tych samych funkcji - co przy przezroczystoci GL_SRC_ALPHA i GL_
ONE_MINUS_SRC_ALPHA - mona poprawi wygld punktw, linii i wieloktw
rysowanych przy wczonym antyaliasingu. W systemach ze sprztowym antyaliasin-
giem i czeniem kolorw, czenie kolorw daje rezultaty podobne do penoekranowe-go
antyaliasingu za pomoc bufora akumulacji. Przy tym wszystkim, czenie kolorw jest
kilka razy szybsze ni uycie bufora akumulacji, gdy caa scena musi by narysowana
tylko raz.

Aby narysowa scen przy uyciu czenia kolorw i prymityww z antyaliasingiem,


wywoaj ponisze funkcje:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);

czenie kolorw w programach rysunkowych


Te same techniki, co w grafice 3D, mog zosta wykorzystane take w grafice 2D. W
przypadku programw malarskich", moemy zastosowa czenie kolorw w celu
uzyskania pdzla" o mikkich krawdziach. Zaczniemy od zdefiniowania obrazw alfa dla
kadego z pdzli. Obraz alfa zawiera wartoci alfa bez wartoci koloru (RGB) i definiuje, ile
koloru pdzla pozostanie na rysunku (rysunek 16.2).

Rysunek 16.2.
Rysunek wykonany pdzlem "
wykorzystujcym obraz alfa

Aby malowa" przy


uyciu tego obrazu pdzla,
musimy uy nieco innego
zestawu funkcji czenia
kolorw:
glBlendFunc(GL_SRC_CO
LOR,
GL_ONE_MINUS_SRC_ALPH
A);
512 Cz III Tematy zaawansowane i efekty specjalne

Zamiast funkcji GL_SRC_ALPHA dla koloru rdowego, uyjemy funkcji GL_SRC_


COLOR, uwzgldniajcej biecy kolor, a nie skadow alfa. Tak wic kolor bdzie na-
kadany nastpujco:
Rd = Rs * Ap + Rd * (l - Ap)
Gd = GS * Ap + Gd * (l - Ap)
Bd = Bs * Ap + Bd * (l - Ap)

To znaczy, wartoci alfa z obrazu pdzla zostan uyte zamiast biecych wartoci alfa
rysowanych pikseli.
Listing 16.2 przedstawia prosty program malarski" uywajcy do rysowania obrazu
pdzla o rozmiarach 7 x 7 pikseli. Gwna ptla komunikatw obsuguje rysowanie w
oknie. Gdy przytrzymasz lewy przycisk myszy, zostanie wywoana funkcja DrawXY,
rysujca obraz pdzla w biecym pooeniu myszy:
glRasterPos2i(mousex, mousey);
glDrawPixels(7, 7, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
*BlendBrush[0] ) ;

Funkcja RepaintWindow czyci obszar roboczy okna za kadym razem, gdy okno zmieni
rozmiar lub wymaga odwieenia:
glViewport( O , O, rect->right, rect->bottom);
glOrtho(0.0, (float)rect->right, (float)rect->bottom, 0 . 0 , -1.0,
1.0);

glClearColor(0.0, 0 . 0 , 0 . 0 , 1 . 0 ) ;
glColorMask(GL_TRUE, GLJTRUE, GLJTRUE, GLJTRUE) ;
glClear(GL_COLOR_BUFFER_BIT);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Niestety, oznacza to, e utracisz swj rysunek. W prawdziwej aplikacji rysunkowej


mgby funkcj glReadPixels skopiowa piksele ekranu do bufora, z ktrego mogyby by
pniej odtworzone przy uyciu funkcji glDrawPixels.

Listing 16.2. BLENDRA W. C: Program rysunkowy wykorzystujcy funkcj glBlendFunc

"Sld$"

Demonstracja uycia obrazw alfa.

Contents:
WinMainO - Gwne w e j c i e . . .
DisplayErrorMessage () - Wywietla okno komunikatu
bdu.
MakePalette () - Tworzy palet kolorw RGB.
BlendProcO - Obsuguje komunikaty okna widoku.
RepaintWindow () - Odrysowuje obszar roboczy okna.
DrawKY ( ) - Rysuje w obszarze roboczym.

Revision History:

$Log$
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________513

/*
* Niezbdne nagwki.
*/
flinclude <windows.h>
tfinclude <GL/gl.h>
#include "blendraw.h"
tfinclude <stdarg.h>
include <math.h> tfifndef
M_PI
# define M_PI (double)3.14159265358979323846
#endif /* !M_PI */

/*
* Zmienne globalne...
*/
HWND BlendWindow; /* Okno rysunku */
HPALETTE BlendPalette; /* Paleta kolorw (jeli potrzebna) */
HDC BlendDC; /* Kontekst rysowania */
HGLRC BlendRC; /* Kontekst renderowania OpenGL */

unsigned char BlendBrush[7][ 1 6 ] = {


{ Oxff, 0x00, Oxff, 0x00, Oxff, 0x08, Oxff, 0x10, Oxff, 0x08, Oxff,
00x00, Oxff, 0x00 ), { Oxff, 0x00, Oxff, 0x08, Oxff, 0x10, Oxff, 0x20,
Oxff, 0x10, Oxff,
00x08, Oxff, 0x00 }, { Oxff, 0x08, Oxff, 0x10, Oxff, 0x20, Oxff, 0x40,
Oxff, 0x20, Oxff,
00x10, Oxff, 0x08 }, { Oxff, 0x10, Oxff, 0x20, Oxff, 0x40, Oxff, 0x80,
Oxff, 0x40, Oxff,
00x20, Oxff, 0x10 }, { Oxff, 0x08, Oxff, 0x10, Oxff, 0x20, Oxff, 0x40,
Oxff, 0x20, Oxff,
00x10, Oxff, 0x08 }, { Oxff, 0x00, Oxff, 0x08, Oxff, 0x10, Oxff,
0x20, Oxff, 0x10, Oxff,
00x08, Oxff, 0x00 }, { Oxff, 0x00, Oxff, 0x00, Oxff, 0x08, Oxff, 0x10,
Oxff, 0x08, Oxff,
00x00, Oxff, 0x00 }, };
GLboolean Drawing = GL_FALSE; /* GL_TRUE jeli rysujemy */

/*
* Funkcje lokalne...
*/
void DisplayErrorMessage(char *, .. . ) ;
void MakePalette( i n t ) ;
LRESULT CALLBACK BlendProc(HWND, UINT, WPARAM, LPARAM);
void DrawXY(int, int);
void RepaintWindow(RECT * ) ;

/*
* 'WinMainO ' V
514 ______________________ Cz III Tematy zaawansowane l efekty specjalne

int APIENTRY
WinMain(HINSTANCE hlnst,
HINSTANCE hPrev!nstance, LPSTR
IpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS we;
POINT pos; /* Bieca pozycja myszy */

w e . style = 0;
wc.lpfnWndProc = (WNDPROC) BlendProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hlnstance = hlnst;
wc.hlcon = NULL;
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wc.hbrBackground = 0;
wc.lpszMenuName = MAKEINTRESOURCE (IDR_MENU1) ;
wc.lpszClassName = "Blend Paint";

if (RegisterClass (Swe) == 0) {
DisplayErrorMessage ( " N i e udao si zarejestrowanie o k n a ! " ) ;
return ( F A L S E ) ;

Blendwindow = CreateWindowf "Blend Paint", "Rysowanie z czeniem


^kolorw",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
WS_CLIPSIBLINGS,
32, 32, 400, 300,
NULL, NULL, hlnst, NULL) ;

if (Blendwindow == NULL) {
DisplayErrorMessage ( " N i e udao si stworzenie o k n a ! " ) ;
return (FALSE);

ShowWindow( Blendwindow, nCmdShow) ;


UpdateWindow (Blendwindow) ;
// Gwna ptla komunikatw
while (GetMessage (smsg, NULL, O, O J )
{
TranslateMessage ( smsg) ;
DispatchMessag (Smsg) ;

return (msg.wParam) ;

/*
* ' DisplayErrorMessage ( ) ' - Wywietla okno komunikatu bdu.
*/
Rozdzia 16. Efekty specjalne: przezroczysto i mga ____________________ 515

void DisplayErrorMessage (char *format,


// We - acuch formatowania w stylu printfO . . . ) //We -
Pozostae argumenty {
va_list ap; /* Wskanik argumentu */
char s [1024]; /* acuch wyjciowy */

i f (format == NULL)
return;

va_start (ap, format) ;


vsprintf(s, format, ap) ;
va_end(ap) ;
MessageBeep (MB_ICONEXCLAMATION) ;
MessageBox(NULL, s, " E r r o r " , MB_OK | MB_ICONEXCLAMATION) ;

/*
* 'MakePalette () ' - Jeli trzeba, tworzy palet kolorw.
*/
void
MakePalette (int p f ) /* We - ID formatu pikseli */
{
PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE *pPal;
int nColors;
int i,
rmax,
gmax,
bmax
;

/*
* Sprawdzenie, czy paleta jest potrzebna. . .
*/
DescribePixelFormat (BlendDC, pf, sizeof (PIKELFORMATDESCRIPTOR) ,

if ( ! (pfd.dwFlags i PFD_NEED_PALETTE) ) {
BlendPalette = NULL;
return;

/*
* Alokowanie pamici dla palety.
*/
nColors = l pfd.cColorBits;

pPal = (LOGPALETTE * Jmalloc (sizeof (LOGPALETTE) +


nColors * sizeof (PALETTEENTRY) );

pPal->palVersion = 0x300;
pPal->palNumEntries = nColors;
Rozdzia 16. Efekty specjalne: przezroczysto i mga____________________517

pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;


// Dla OpenGL
pfd.dwLayerMask = PFD_MAIN_PLANE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 0;
pfd.cDepthBits = 0;
pfd.cStencilBits = 0;
pfd.cAccumBits = 0 ;
pf = ChoosePixelForrnat (BlendDC, spfd) ;
if ( p f == 0)
DisplayErrorMessage(
"Program nie mg znale odpowiedniego formatu
^pikseli!");
else if (!SetPixelFormat(BlendDC, pf, s p f d ) )
DisplayErrorMessage(
"Program nie mg ustawi odpowiedniego formatu
Opikseli! ") ;
MakePalette(pf) ;
BlendRC = wglCreateContext(BlendDC);
wglMakeCurrent(BlendDC, BlendRC); break;
case WM_SIZE :
case WM_PAINT :
// Odrysowanie obszaru klienta nasz bitmap
BeginPaint(hWnd, &ps);

GetClientRectthWnd, Srect);
RepaintWindow(Srect);
EndPaint(hWnd, sps);
break;
case WM_COMMAND : /*
* Obsuga menu...
*/
switch (LOWORD(wParam))
{
case IDM_FILE_EXIT :
DestroyWindow(BlendWindow);
break;
}; break;
case WM_QUIT :
case WM_CLOSE :
/*
* Zniszczenie okna, bitmap i w y j c i e . . .
*/
DestroyWindow(BlendWindow);
exit( 0 )
; break;
518______________________Cz III Tematy zaawansowane i efekty specjalne

case WM_DESTROY:
/*
* Zwolnienie kontekstu urzdzenia, kontekstu
* renderowania i palety
*/
if (BlendRC)
wglDeleteContext(BlendRC) ;

if (BlendDC)
ReleaseDC(BlendWindow, BlendDC);
if (BlendPalette)
Deleteobject(BlendPalette);

PostOuitMessage( 0 ) ;
break;
case WM_QUERYNEWPALETTE: /*
* W razie potrzeby realizacja palety...
*/

if (BlendPalette) {
SelectPalette(BlendDC, BlendPalette, FALSE);
RealizePalette(BlendDC);

InvalidateRect(hWnd, NULL, FALSE);


return (TRUE);
}; break;
case WM_PALETTECHANGED: /*
* W razie potrzeby ponowne wybranie p a l e t y . . .
*/

if (BlendPalette && (HWND)wParam != hWnd) {


SelectPalette(BlendDC, BlendPalette, FALSE);
RealizePalette(BlendDC);

UpdateColors(BlendDC); };
break;

case WM_LBUTTONDOWN : /* Lewy przycisk = czerwony */


Drawing = GL_TRUE;
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
DrawXY(LOWORD(lParam), HIWORD(lParam)); break;

case WM_MBUTTONDOWN : /* rodkowy przycisk = zielony */


Drawing = GL_TRUE;
glColorMask(GL_FALSE, GLJTRUE, GL_FALSE, GL_TRUE);
DrawKY(LOWORD(IParam), HIWORD(IParam)); break;
Rozdzia 16. Efekty specjalne: przezroczysto i mga ____________________ 519

case WM_RBOTTONDOWN : /* Prawy przycisk = niebieski */


Drawing = GLJTRUE;
glColorMask(GL_FALSE, GL__FALSE, GL_TRUE, GLJTRUE) ;
DrawXY(LOWORD(lParara) , HfwORD(lParam) ) ; break;

case WM_MOUSEMOVE :
if (Drawing)
DrawXY (LOWORD(lParam) , HIWORD(lParam) ) ;
break;

case WM_LBOTTONUP :
case WM_MBUTTONUP :
case WM_RBUTTONUP :
Drawing = GL_FALSE;
break;

default : /*
* Standardowa obsuga wszystkich innych komunikatw
*/

return (DefWindowProc (hWnd, uMsg, wParam, IParam) ) ; };


return (FALSE) ;

/*
* 'DrawXYO' - Rysuje w biecej pozycji myszy.
*/
void
DrawXY(int mousex, /* We - pooenie myszy w poziomie */
int mousey) /* We - pooenie myszy w pionie */ {
glRasterPos2i (mousex, mousey);
glDrawPixels ( 7 , 7, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
^BlendBrushfO] ) ;
glFinish ( ) ;

/*
* ' RepaintWindow ( ) ' - Odrysowuje obszar roboczy okna.
*/
void
RepaintWindow (RECT *rect) /* We - Obszar roboczy okna */ {
/*
* Wyzerowanie widoku i wyczyszczenie okna na jasny bkit
*/
glviewport ( O , O, rect->right, rect->bottom) ;
g!0rtho(0.0, (float) rect->right, (float) rect->bottom, 0 . 0 , - 1 . 0 ,
520 ______________________ Cz III Tematy zaawansowane i efekty specjalne

glClearColor ( 0 . 0 , 0.0, 0.0, 1 . 0 ) ;


glColorMask(GL_TRUE, GL_TRUE, GLJTRUE, GLJTRUE) ;
glClear(GL,_COLOR_BUFFER_BIT) ;

glEnable (GL_BLEND) ;
glBlendFunc(GL_SRC_ALPHA, GL__ONE_MINUS__SRC_ALPHA) ;

glFinishf ) ;

/*
* End of "Sld$".
*/

Mga
W OpenGL mona uzyska cieniowanie sceny w zalenoci od gbokoci, w celu uzy-
skania pewnych efektw atmosferycznych, gwnie mgy. Suy do tego funkcja glFog.
Tworzenie mgy polega na dodaniu (wymieszaniu) pewnego okrelonego koloru do
kadego wierzchoka lub obrazu tekstury, w iloci zalenej od odlegoci tego wierz-
choka od obserwatora. Efekt mgy czsto wykorzystuje si w symulatorach lotw i
animacjach w celu uzyskania bardziej realistycznego wygldu scen.

W OpenGL mona stosowa trzy rodzaje mgy: GL_LINEAR - cieniowanie w zale-


noci od gbokoci, GL_EXP gst mg lub chmury oraz GL_EXP2 dymy i mgieki;
nieco dalej, na rysunku 16.5, wida efekt zastosowania mgy typu GL_EXP.

Do wyboru rodzaju mgy (trybu mgy) suy funkcja glFogi:


glFogi(GL_FOG_MODE, GL_LINEAR);

glFogi(GL_FOG_MODE, GL_EXP);

glFogi(GL_FOG_MODE, GL_EXP2);

Gdy ju wybierzesz typ mgy, za pomoc funkcji glFogfy lub glFogiv musisz wybra jej
kolor, ktry bdzie mieszany z kolorami sceny:
GLfloat fog_color[4] = { r, g, b, a } ;
glFogfv(GL_FOG_COLOR, fog_color);
GLint fog_color[4] - { r, g, b, a ) ;
glFogiv(GL_FOG_COLOR, fog_color);

W przypadku cieniowania zalenie od gbokoci, zwykle kolor mgy bdzie odpowiada


kolorowi ta (czerni na rysunku 16.3). W ten sposb mga bdzie wyglda po-
prawnie" dla oka - czyli dalsze obiekty bd sprawia wraenie, e wtapiaj si w to. W
pewnych sytuacjach moesz zastosowa jaskrawy kolor mgy, na przykad ty, przez
co obiekty bd si znacznie rni od ta.
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________521

Rysunek 16.3.
Imbryki cieniowane w
zalenoci od gbokoci

Rysowanie
imbrykw
cieniowanych w
zalenoci od
gbokoci
Listing 16.3
rysuje dwa
imbryki przy
wczonym
cieniowaniu w
zalenoci od gbokoci. Wszystkimi operacjami graficznymi zajmuje si funkcja
draw_scene, rozpoczynajc od ustawienia koloru mgy na czer oraz trybu mgy na
GL_LINEAR:
static floatfog_color[4] = { 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 };

glEnable(GL_FOG) ;
glFogf(GL_FOG_DENSITY, 0 . 0 5 ) ;
glFogfv(GL_FOG_COLOR, fog_color);

Na koniec rysuje dwa imbryki do herbaty, umieszczone w rnych odlegociach od ob-


serwatora. Rezultat wida doskonale.

Listing 16.3. Program FOGPOT.C: imbryki cieniowane w zalenoci od


gbokoci____________
/*
* "fogpot.c" - Testowy program demonstrujcy zastosowanie funkcji
* glFogOprzy cieniowaniu w zalenoci od gbokoci.
*/
#include <GL/glaux.h>

/*
* Te definicje zostay wprowadzone w celu zapewnienia zgodnoci
* pomidzy MS Windows a reszt wiata.
*
* CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.
*/
522 _______________________ Cz III Tematy zaawansowane i efekty specjalne

#ifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* IWIN32 */
GLfloat rotation = 0 . 0 ;

/*
* 'reshape_scene () ' - Zmiana rozmiaru s c e n y . . .
*/
V0id CALLBACK
reshape_scene (GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glViewport ( O , O, width, height);

glMatrixMode(GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(22.5, (float) width / (float) height, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW) ;

/*
* 'draw_scene () ' - Rysowanie sceny zawierajcej dwa imbryki do
* herbaty
*/
void CALLBACK
draw_scene (void)
{
static float red_light[4] = { 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 };
static float red_pos[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 0 . 0 };
static float blue_light [ 4 ] = { 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 };
static float blue_pos[4] = ( - 1 . 0 , - 1 . 0 , - 1 . 0 , 0 . 0 } ;
static float fog_color[4] = { 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 };

/*
* Wczenie buforw i owietlenia
*/
glEnable (GL_DEPTH_TEST) ;
glEnable (GL_LIGHTING) ;
glEnable (GL_LIGHTO) ; glEnable
(GL_LIGHT1) ;
glShadeModel (GL_SMOOTH) ;

/*
* Wyczyszczenie bufora koloru i gbokoci. V
Rozdzia 16. * Efekty specjalne: przezroczysto i mga ____________________ 523

glClearColor ( 0 . 0 , 0.0, 0.0, 0 . 0 ) ;


glClear (GL_COLOR_BUFFER_BIT l GL_DEPTH_BUFFER_BIT) ;

W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone i


zostao umieszczone u gry z prawej strony, za obserwatorem. Drugie
jest niebieskie i znajduje si u dou po lewej stronie, przed
obserwatorem. /

glLightfv(GL_LIGHTO, GL_DIFFUSE, red_light) ;


glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

g!Lightfv(GL_LIGHTl, GL_DIFFOSE, blue_light) ;


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glEnable(GL_FOG) ;
glFogf (GL_FOG_DENSITY, 0 . 0 5 ) ;
glFogfv(GL_FOG_COLOR, fog_color) ;
glPushMatrix() ;
glTranslatef (-1.0, 0.0, -15.0);
glRotatef (-rotation, 0 . 0 , 1.0, 0 . 0 ) ;
auxSolidTeapot ( 1 . 0 ) ;
glPopMatrix() ;
glPushMatrix () ;
glTranslatef ( 1 . 0 , 0.0, -10.0);
glRotatef (rotation, 0 . 0 , 1 . 0 , 0 . 0 ) ;

auxSolidTeapot ( 1 . 0 ) ;
glPopMatrix () ;
auxSwapBuf f ers ( ) ;

/*
* 'rotate_objects () ' - W wolnych chwilach obrt sceny.
*/
void CALLBACK
rotate_objects (void)
{
rotation += 2.0;
if (rotation >= 3 6 0 . 0 )
rotation -= 3 6 0 . 0 ;
draw_scene ( ) ;

' m a i n ( ) ' - Inicjowanie okna i wywietlanie sceny do momentu


* wcinicia klawisza ' E s c ' .
/
524 ______________________ Cz III Tematy zaawansowane i efekty specjalne

void
main (void)
{
auxInitDisplayMode (AUX_RGB | AUX_DOUBLE | AUX_DEPTH) ;
auxlnitwindow("lmbryki we m g l e " ) ;
auxReshapeFunc (reshape_scene) ;
aux!dleFunc (rotate_objects) ;
auxMainLoop (draw_scene) ;

/*
* Koniec pliku " f o g p o t . c " .
*/

Inne rodzaje mgy


W przypadku innych rodzajw mgy, jej kolorem najczciej bdzie biel lub jaki inny
jasny kolor. Oprcz koloru, mga typu GL_EXP i GL_EXP2 posiada take gsto:
glFogf(GL_FOG_DENSITY, density) ;

Parametr density moe by dowoln wartoci wiksz od 0,0, lecz zwykle bdziesz na-
dawa mu warto poniej O, l. Wpyw tego parametru na mieszanie koloru mgy przed-
stawia rysunek 16.4.

Rysunek 16.4.
GL_EXP2 ,,-' //
density=0.25 ,''' tt
gbokoci ^V/ ,''''
Kolor mgy /
, A^. / /
/ *' XGLJXP
* *
Gsto mgy w
zalenoci od

Gboko^

Gboko mgy
Gboko mgy to przetransformowana wsprzdna Z wywoa glVertex. Ta wsprzdna
Z naley do przedziau od 0,0 do 1,0, tak samo jak w przypadku bufora gbokoci.
Gboko mgy oraz jej gsto okrelaj sposb mieszania koloru mgy z kolorami
sceny, przy zastosowaniu nastpujcych wzorw:
r _ -(</L'.v//yr) /exp ~
"

r _ -(demityzy J
exp 2

koniec z
J linear
koniec - pocztek
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________525

Domylnie, mga jest dodawana na wszystkich gbokociach, od 0,0 do 1,0. Parametry


GL_FOG_START i GL_FOG_END ograniczaj zakres wartoci gbokoci uywanych do
oblicze mgy i zwykle wykorzystuje si je do precyzyjniejszego modelowania obszarw
zamglenia (na przykad przy przelocie przez chmury przerwy w chmurach nie powinny
by zamglone).

Powrt do programu przegldania terenu


Efekt lekkiej mgieki moe by doskonaym uzupenieniem programu przegldania terenu z
rozdziau 12. Na rysunku 16.5 widzimy fantastyczn popraw jakoci obrazu.
Osignlimy to dziki dodaniu poniszych trzech linii kodu:
glFogf(GL_FOG_DENSITY, 0 . 0 0 2 5 ) ;
glFogi(GL_FOG_MODE, GL_EXP);
glFogfv(GL_FOG_COLOR, fogcolor);

Rysunek 16.5.
Widok terenu z
zastosowaniem
lekkiej mgieki

W tym przypadku kolor mgy zosta zdefiniowany jako jednolity kolor RGB A (1,0, 1,0,
1,0, 1,0). Aby jeszcze bardziej poprawi jako obrazu (wyduajc czas rysowania),
moemy wywoa take
glHint(GL_FOG_HINT, GL_NICEST);

To wywoanie powoduje, e mga jest obliczana dla kadego wierzchoka, a nie dla kadego
wielokta. Niestety, w przypadku wikszoci scen oznacza to stukrotny wzrost oblicze!

Przejdmy teraz do listingu 16.4, czyli zmodyfikowanej funkcji RepaintWindow.


526_______________________Cz III Tematy zaawansowane i efekty specjalne

Listing 16.4. FOGSCENE. C: Zmodyfikowana funkcja RepaintWindow z programu przegldarki terenu,


_________tym razem korzystajca z funkcji glFog_____________________________

/*
* 'RepaintWindowO ' - Odrysowuje obszar roboczy okna sceny.
*/
void
RepaintWindowfRECT *rect) /* We - Obszar roboczy okna */
{
int i;
int x, y; /* Pooenie terenu
( x , y) */ int last_type; /* Poprzedni
typ terenu */ int *type; /* Biecy
typ terenu */ GLfloat *height, /*
Bieca wysoko terenu */ ( * n ) [ 3 ] ; /*
Bieca normalna terenu */ static GLfloat
sky_top[4][ 3 ] = { /* Wsprzdne nieba
*/
{ -TERRAIN_EDGE, TERRAIN_SIZE * 0 . 8 , -TERRAIN_EDGE }, {
TERRAIN_EDGE, TERRAIN_SIZE * 0 . 8 , -TERRAIN_EDGE }, {
TERRAIN_EDGE, TERRAIN_SIZE * 0 . 8 , TERRAIN_EDGE }, ( -
TERRAIN_EDGE, TERRAIN_SIZE * 0 . 8 , TERRAIN_EDGE }
};
static GLfloat sky_bottom[4][ 3 ] =
{
{ -TERRAIN_EDGE, 0 . 0 , -TERRAIN_EDGE },
{ TERRAIN_EDGE, 0 . 0 , -TERRAIN_EDGE },
{ TERRAIN_EDGE, 0 . 0 , TERRAIN_EDGE },
( -TERRAIN_EDGE, 0 . 0 , TERRAIN_EDGE }
>;
static GLfloat sunpos[4] = { 0 . 0 , 1 . 0 , 0 . 0 , 0.0 };
static GLfloat suncolor[4] = { 6 4 . 0 , 6 4 . 0 , 6 4 . 0 , 1.0 };
static GLfloat sunambient[ 4 ] = { 0.001, 0.001, 0.001,
1.0 };
static GLfloat fogcolor[4] = { 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 };

/*
* Wyzerowanie widoku i wyczyszczenie okna na jasny bkit
*/
glViewport( O , O, rect->right, rect-
>bottom); glClearColor(0.5, 0.5, 1.0,
1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_FOG);
glFogf(GL_FOG_DENSITY, 0.0025);
glFogi(GL_FOG_MODE, GL_EXP);
glFogfv(GL_FOG_COLOR, fogcolor);

if (Moving ||
Drawing) { /*
* Bez tekstur podczas rysowania lub lotu; jest za w o l n e . . .
* Rysowanie tylnego bufora dla pynnej animacji
*/
Rozdzia 16. * Efekty specjalne: przezroczysto l mga ____________________ 527

glDisable (GL_TEXTURE_2D) ;
glDrawBuf f er (GL_BACK) ;
else

Wczenie tekstur, gdy przestaniemy rysowa lub lata W


ten sposb tworzymy scen, ktr mona wydrukowa lub
zachowa w pliku.
Poniewa to trwa duej, rysujemy w przednim buforze, aby
uytkownik widzia przebieg rysowania...

glEnable (GL_TEXTURE_2D) ;
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) ;
glDrawBuf f er (GL_FRONT) ;

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;

/*
* Przygotowanie przeksztacenia widoku dla biecego
* punktu obserwacji
*/
glMatrixMode (GL_PROJECTION) ;
glLoadldentity () ;
gluPerspective(45.0, (float) rect->right / ( float) rect->bottom,
0 . 1 , 1000.0);

glMatrixMode (GL_MODELVIEW) ;
glPushMatrix() ;
glRotatef (Roli, 0.0, 0.0, 1 . 0 ) ;
glRotatef (Pitch, -1.0, 0.0, 0 . 0 ) ;
glRotatef (Heading, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glTranslatef (-PositionfO] ,
-Position [1 ] ,
-Position[2] ) ; glScalef (TERRAIN_SCALE,
TERRAIN_SCALE, TERRAIN_SCALE) ;

if ( ! (Moving l | Drawing) ) {
/*
* Rysowanie nieba. . .
*/
glDisable (GL_LIGHTING) ;
glCallList (SkyTexture) ;
glBegin(GL_QUAD_STRIP) ; for (i
= 0; i < 4; i ++) {
glTexCoord2f ( (float) i, 0 . 0 ) ;
glvertex3fv(sky_bottom[i] ) ;
glTexCoord2f ( (float)i, 0 . 8 ) ;
g!Vertex3fv(sky_top[i] ) ;
528______________________Cz III Tematy zaawansowane i efekty specjalne

glTexCoord2f( 4 . 0 , 0 . 0 ) ;
glVertex3fv(sky_bottom[0]);
glTexCoord2f( 4 . 0 , 0 . 8 ) ;
glVertex3fv(sky_top[0]);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( 0 . 5 , 1.0);
glVertex3f( 0 . 0 , TERRAIN_SIZE, 0 . 0 ) ;
for (i = 0; i < 4; i ++)
{
glTexCoord2f((float)i, 0 . 8 ) ;
glVertex3fv(sky_top[i]); };
glTexCoord2f( 4 . 0 , 0 . 8 ) ;
glVertex3fv(sky_top[0]);
glEnd(); };
/*
* Przygotowanie owietlenia...
*/
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

glEnable(GL_LIGHTO);
glLightfv(GL_LIGHTO, GL_POSITION, sunpos);
glLightfv(GL_LIGHTO, GL_DIFFUSE, suncolor);
glLightfv(GL_LIGHTO, GL_AMBIENT, sunambient);

if (Moving || Drawing)
glEnable(GL_COLOR_MATERIAL);
else
glDisable(GL_COLOR_MATERIAL);

/*
* Teraz teren...
*/
type = TerrainType[ 0 ] ;
height = TerrainHeight[ 0 ] ;
n = TerrainNormal[ 0 ] ;
for (y = 0; y < (TERRAIN_SIZE - 1); y ++)
{
last_type = -1;

for (x = 0; x < TERRAIN_SIZE; x ++, type ++, height ++, n ++) {


if (last_type != *type)
{ /*
* Jeli zmienia si typ terenu, zakocz istniejcy pasek
* i wyzeruj parametry tekstury/koloru
*/
Rozdzia 16. Efekty specjalne: przezroczysto i mga_____________________529

if (last_type != - 1 )
glEnd() ;
switch (*type)
{
case IDC_WATER :
if (Moving l l Drawing)
glColor3f( 0 . 0 , 0.0, 0 . 5 ) ;
else
glCallList(WaterTexture);
break; case IDC_GRASS :
if (Moving || Drawing)
glColorSf(0.0, 0.5,
0 . 0 ) ; else
glCallList(GrassTexture);
break; case IDC_ROCKS :
if (Moving || Drawing)
glColor3f(0.25, 0.25,
0.25); else
glCallList(RocksTexture);
break; case IDC_TREES :
if (Moving l| Drawing)
glColorSf( 0 . 0 , 0.25, 0 . 0 ) ;
else
glCallList(TreesTexture);
break; case IDC_MOUNTAINS :
if (Moving || Drawing)
glColor3f(0.2, 0.1, 0 . 0 5 ) ;
else
glCallList(MountainsTexture); break;
};
glBegin(GL_QUAD_STRIP);
if (last_type != -1) {
/*
* Zaczniemy od poprEedniego miejsca, aby nie byo dziur V
glTexCoord2i(x * 2 - 2, y * 2 ) ;
glNormal3fv(n[-l]);
glVertex3f((GLfloat)(x - TERRAIN_EDGE - 1 ) ,
height[-l], (GLfloat)(y -
TERRAIN_EDGE));
glTexCoord2i(x * 2 - 2 , y * 2 + 2 ) ;
glNormal3fv(n[TERRAIN_SIZE - 1 ] ) ;
glVertex3f((GLfloat)(x - TERRAIN_EDGE - 1 ) ,
height[TERRAIN_SIZE - 1 ] ,
(GLfloat)(y - TERRAIN_EDGE + 1 ) ) ;
};
last_type = *type;
530_______________________Cz III Tematy zaawansowane i efekty specjalne

glTexCoord2i(x * 2, y * 2 ) ;
glNorma!3fv(n[0]);
glVertex3f((GLfloat)(x - TERRAIN_EDGE),
height[0],
(GLfloat)(y - TERRAIN_EDGE));
glTexCoord2i(x * 2, y * 2 + 2 ) ;
glNormal3fv(n[TERRAIN_SIZE]);
glVertex3f((GLfloat)(x - TERRAIN_EDGE),
height[TERRAIN_SIZE],
(GLfloat)(y - TERRRIN_EDGE + l));
};
glEnd(); };
glPopMatrix();

/*
* Gdy lecimy lub rysujemy, uywamy podwjnego buforowania.
* Jeli trzeba, przerzu bufory
*/
glFinish();
if (Moving || Drawing)
SwapBuffers(SceneDC);

Podsumowanie
czenie kolorw i mga stanowi uzupenienie biblioteki OpenGL bdc kolejnym na-
rzdziem sucym do zwikszania realizmu tworzonych scen. Dziki czeniu kolorw
uzyskujemy efekt przezroczystoci oraz popraw antyaliasingu punktw, linii i wielok-
tw. Stosujc mg moemy cieniowa sceny w zalenoci od gbokoci oraz tworzy
efekty atmosferyczne - gste mgy, chmury lub leciutkie poranne mgieki. Dziki nim
tworzone obrazy wygldaj na mniej precyzyjne, czyli - ironicznie - bardziej przypomi-
najce rzeczywisty wiat.

Podrcznik
gIBIendFunc
Przeznaczenie Ustawia funkcj czenia kolorw.
Plik nagwkowy <gl.h>
Skadnia void glBlendFunc(GLenum sfactor, GLenum dfactor);
Opis Ta funkcja ustala kolor rdowy i docelowy przy czeniu kolorw.
Aby wczy czenie kolorw, musisz wywoa funkcj
glEnable(GL_BLEND). czenie kolorw jest dostpne jedynie
Rozdzia 16. Efekty specjalne: przezroczysto i mga 531

w kontekstach rysowania RGBA. Domylne ustawienie czenia kolorw to


glBlendFunc(GL_ONE, GL_ZERO).
Parametry
sfactor GLenum: Funkcja czenia koloru rdowego.
dfactor GLenum: Funkcja czenia koloru docelowego.
Zwracana warto Brak.
Przykad Kod programu BLENDPOT.C na pytce CD-ROM.

glFog
Przeznaczenie Okrela parametry mgy.
Plik nagwkowy <gl.h>
Skadnia void glFogf(GLenum pname, GLfloat param); void
Opis glFogfv(GLenum pname, GLfloat *params); void
glFogi(GLenum pname, GLint param); void
Parametry glFogiv(GLenum pname, GLint *params);
pname Funkcja glFog ustala parametry mgy. Aby w scenie pojawia si mga,
musisz j wczy wywoaniem glEnable(GL_FOG).

GLenum: Ustawiany parametr. Dostpne parametry to:


GL_FOG_COLOR Kolor mgy; musi by tablic czterech elementw
reprezentujcych kolor RGBA.
GL_FOG_DENSITY Gsto mgy; liczba wiksza od 0,0. Gsto mgy
jest uywana jedynie w trybach mgy GL_EXP i GL_EXP2.
GL_FOG_END Najwiksza gboko, dla ktrej obliczana jest mga. Jest to
przetransformowana warto Z (gboko) z zakresu od 0.0 do 1.0.
GL_FOG_INDEX Indeks koloru mgy, uywany, gdy kontekst
renderowania OpenGL jest kontekstem korzystajcym z indeksu kolorw.
GL_FOG_MODE Typ mgy; okrela formu uywan do renderowania
efektu mgy (GL_LINEAR, GL_EXP lub GL_EXP2).
GL_FOG_START Najmniejsza gboko, dla ktrej obliczana jest mga.
Jest to przetransformowana warto Z (gboko) z zakresu od 0,0 do 1,0.
GLenum: Funkcja czenia koloru docelowego.
Brak.
dfactor
Kod programu FOGSCENE.C na pytce CD-ROM.
Zwracana warto
Przykad
Rozdzia 17.
Krzywe i powierzchnie:
co to jest NURBS?!!
W tym rozdziale:
Dowiesz si, jak... Uywane funkcje
* Uy odwzorowa do tworzenia * glMap, glEvalCoord
krzywych i powierzchni Bziera.
* Skorzysta z wbudowanych funkcji 4 glMapGrid, glEvalMesh
oblicze upraszczajcych odwzorowanie
powierzchni
* Tworzy powierzchnie NURBS * gluNewNurbsRenderer,
gluBeginSurface, gluNurbsSurface,
gluEndSurface, gluDeleteNurbsRenderer
* Tworzy krzywe wycinania * gluBeginTrim, gluPwlCurve,
gluEndTrim

W przypadku wikszoci aplikacji wykorzystujcych grafik 3D, przydatne staj si


gadkie krzywe i powierzchnie. Za pomoc technik opisywanych w innych rozdziaach tej
ksiki moesz dzieli takie powierzchnie na wiele mniejszych czworoktw lub
trjktw, oblicza normalne dla poszczeglnych wierzchokw oraz stosowa owietlenie
- tworzc co, co przypomina bardzo gadk i poyskliw powierzchni. Moesz take,
przy zastosowaniu czego wicej ni podstawowej algebry, tworzy kod obliczajcy
powierzchni na podstawie rwna, dajcych lepsze lub gorsze przyblienie gadkiej
powierzchni paskami czworoktw lub trjktw.
Przypumy jednak, e chcesz utworzy krzyw lub powierzchni, lecz nie masz do dy-
spozycji odpowiednich rwna. Zadanie znalezienia wielomianu drugiego lub trzeciego
stopnia wcale nie jest banalne, jeli mamy do dyspozycji jedynie gar punktw tworzcych
krzyw lub powierzchni. Czysto matematyczne podejcie jest bardzo czasochon-
534______________________Cz III Tematy zaawansowane i efekty specjalne

ne i podatne na bdy, nawet przy zastosowaniu komputera. A jeli uwaasz, e moesz


dokona takich oblicze w gowie", to od razu moesz o tym zapomnie.
Dostrzegajc tak potrzeb w grafice komputerowej, Pierre Bezier, projektant nadwozi
samochodw w firmie Renault w latach siedemdziesitych, stworzy zestaw modeli mate-
matycznych sucych do reprezentacji krzywych i powierzchni poprzez niewielki zestaw
punktw kontrolnych. Oprcz uproszczenia reprezentacji zakrzywionych powierzchni, te
modele znakomicie sprawdziy si przy interaktywnym projektowaniu ksztatw
krzywych i powierzchni.
Od tego momentu opracowano take inne rodzaje krzywych i powierzchni, a w zasadzie
cay sownik terminw zwizanych z generowanymi komputerowo powierzchniami.
Matematyka kryjca si za tymi magicznymi formuami nie jest bardziej skomplikowana
od operacji na macierzach opisywanych w rozdziale 7, a co wicej, opisuje tworzone
obiekty w sposb bardzo intuicyjny. Tak jak w rozdziale 7, sprbujemy opisa j w taki
sposb, aby mg maksymalnie wykorzysta te funkcje, nie zagbiajc si przy tym w
bardziej skomplikowane zagadnienia matematyczne.

Krzywe i powierzchnie
Krzywa posiada punkt pocztkowy, dugo oraz punkt kocowy. W rzeczywistoci jest
tylko lini wijc si w trjwymiarowej przestrzeni. Z drugiej strony, powierzchnia posiada
zarwno dugo, jak i szeroko, a w zwizku z tym posiada rwnie powierzchni.
Rozdzia ten zaczniemy wic od opisu sposobw rysowania gadkich trjwymiarowych
krzywych, po czym poznane pojcia rozszerzymy na trjwymiarowe powierzchnie. Zanim
jednak do tego przejdziemy, poznajmy przynajmniej podstawowe terminy i kryjc si za
nimi matematyk.

Reprezentacja parametryczna
Gdy mylisz o linii prostej, najczciej masz na uwadze synne rwnanie: Y =
mX + b
W tym rwnaniu m odpowiada pochyleniu linii, za b jest punktem przecicia linii z osi Y.
By moe przypominasz sobie matematyk ze szkoy redniej, gdzie uczye si take o
rwnaniach paraboli, hiperboli, krzywych wykadniczych, itd. We wszystkich tych
rwnaniach zmienna Y (lub X) bya wyraona jako funkcja wartoci na osi X (lub Y).
Innym sposobem reprezentacji rwnania krzywej lub prostej jest rwnanie parametryczne.
Rwnanie parametryczne wyraa zarwno wsprzdne X, jak i Y poprzez inn zmienn,
zmieniajc si w okrelonym zakresie wartoci. Na przykad w fizyce wsprzdne X, Y i
Z mog by niekiedy wyraone w funkcji czasu, gdzie czas moe by po-
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS7J! 535

dawany w sekundach. W poniszych formuach f(), g() i h() to rne funkcje, zmienne w
czasie (t):
X = f(t) Y =
g(t); Z = h(t);
Gdy definiujemy krzyw w OpenGL, definiujemy jej rwnanie parametryczne. Parame-
tryczn zmienn krzywej bdziemy nazywa u, za jej zakres wartoci bdziemy nazywa
dziedzin tej krzywej. Powierzchnie bd opisywane przy uyciu dwch parametrw: u i
v. Reprezentacj krzywej i powierzchni poprzez dziedziny u i v przedstawia rysunek 17.1.
Wane jest, aby pamita, e zmienne parametryczne (u i v) reprezentuj parametry
rwnania, a nie same wartoci wsprzdnych.

Rysunek
17.1. u =1.0
Parametryczna
reprezentacja
krzywych i
powierzchni
u = 0.0

u = 1.0
v=1.0
x = f(u,v)
y=M

Punkty kontrolne
Krzywe s reprezentowane przez pewn ilo punktw kontrolnych, wpywajcych na
ksztat krzywej. W przypadku krzywych Beziera, punkty pierwszy i ostatni s jedno-
czenie pierwszym i ostatnim punktem samej krzywej. Pozostae punkty kontrolne za-
chowuj si jak magnes, przycigajc" krzyw do siebie. Kilka przykadw krzywych, z
rnymi ilociami punktw kontrolnych, przedstawia rysunek 17.2.

Rysunek 17.2. P,
W jaki sposb punkty
kontrolne wpywaj p
na ksztat krzywych l

(o) (b) (c)

Klas krzywej okrelamy przez ilo punktw kontrolnych uywanych do opisu tej
krzywej. Stopie krzywej jest liczb o jeden mniejsz od klasy. Matematyczne zna-
536_______________________Cz III Tematy zaawansowane i efekty specjalne

czenie tych terminw wywodzi si z rwna parametrycznych dokadnie opisujcych


dane krzywe, gdzie klasa oznacza ilo wspczynnikw, za stopie odpowiada naj-
wyszemu wykadnikowi zmiennej parametrycznej. Jeli chcesz lepiej pozna matema-
tyczne podstawy wykorzystywania krzywych Beziera, zajrzyj do dodatku B.
Krzywa z rysunku 17.2b jest nazywan krzyw kwadratow, czyli drugiego stopnia, za
krzywa z rysunku 17.2c jest nazywana krzyw kubiczn, czyli trzeciego stopnia.
Teoretycznie, mona zdefiniowa krzyw dowolnego stopnia, jednak krzywe wyszych
rzdw maj tendencje do niekontrolowanych oscylacji i zmian w wyniku choby naj-
mniejszych zmian punktw kontrolnych.

Cigo
Jeli dwie krzywe umieszczone obok siebie maj wsplny punkt, razem tworz krzyw
skadajc si z kawakw. Cigo krzywej w miejscach pocze okrela gadkie jest
przejcie pomidzy poszczeglnymi kawakami. Cztery kategorie cigoci to brak cigoci
(CO), cigo szczepna (Cl), cigo styczna (C2) oraz krzywizna (C3).
Jak wida na rysunku 17.3, brak cigoci wystpuje wtedy, gdy dwa kawaki krzywej
nie stykaj si ze sob. Cigo szczepna jest zachowanie, gdy dwa kawaki krzywej
maj przynajmniej wsplny punkt pocztkowy. Cigo styczna wystpuje wtedy, gdy
krzywe we wsplnym punkcie posiadaj t sam styczn. Na koniec, krzywizna jest za-
chowana wtedy, gdy pochodne obu kawakw krzywej w punkcie zczenia s rwne
(czyli wystpuje gadkie przejcie z kawaka do kawaka krzywej).

Rysunek 17.3. ^_^ Styczna


Cigo kawakw
krzywej
C-Bralc ci goci C' -Cigo styczna
C -Gglo szczepna

C3-Krzywizna

Podczas tworzenia zoonych krzywych i powierzchni, skadajcych si z wielu kawakw,


zwykle bdziesz si stara zachowa cigo typu C2 lub C3. Jak pniej zobaczysz,
mona tak dobra pewne parametry generowania krzywych i powierzchni, aby osign
podane rezultaty.
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 537

Obliczenia
OpenGL posiada kilka funkcji bardzo uatwiajcych rysowanie krzywych i powierzchni
Beziera, przez okrelenie punktw kontrolnych oraz zakresu zmiennych parametry-
cznych u i v. Nastpnie, przez wywoanie odpowiedniej funkcji wyliczajcej, generowane s
punkty tworzce krzyw lub powierzchni. Zaczniemy od utworzenia dwuwymiarowej
krzywej Beziera, a nastpnie rozszerzymy j o trzeci wymiar w celu zbudowania
powierzchni Beziera.

Dwuwymiarowa krzywa
Najlepszym sposobem bdzie przedstawienie przykadu i opisanie go linia po linii. Listing
17.1 zawiera fragmenty kodu z programu BEZIER na pytce CD-ROM. Program okrela
cztery punkty kontrolne krzywej Beziera, a nastpnie za pomoc funkcji obliczajcej
rysuje kolejne punkty samej krzywej. Wynik dziaania tego programu zosta
przedstawiony na rysunku 17.4.

Rysunek 17.4.
Wynik dziaania
programu BEZIER

Listing 17.1. Fragment programu BEZIER rysujcego krzyw Beziera z czterema punktami kontrolnymi

II Ilo punktw kontrolnych krzywej


GLint nNumPoints = 4;
GLfloat ctrlPoints[4][ 3 ] = {( -4.0f, O . O f , O . O f ) , // Punkt
kocowy
{ -6.0f, 4.0f, O . O f } , // Punkt kontrolny
( 6.0f, -4.0f, O . O f } , // Punkt kontrolny
{ 4.0f, O.Of, O.Of } } ; // Punkt kocowy

// Ta funkcja suy do rozmieszczenia punktw kontrolnych krzywej void


DrawPoints (void)
int i;
538______________________Cz III Tematy zaawansowane i efekty specjalne

// Rysujemy wiksze punkty, aby byy lepiej widoczne


glPointSize( 5 . 0 f );
// Ptla dla wszystkich punktw kontrolnych w tym przykadzie
glBegin(GL_POINTS);
for(i = 0 ; i < nNumPoints; i++)
glVertex2fv(ctrlPoints[ i ] ); glEnd(); }
// Zmiana bryy widzenia i widoku.
// Wywoywane w momencie zmiany wymiaru okna
void ChangeSize(GLsizei w, GLsizei h)
<
// Zabezpieczenie przed dzieleniem przez O
i f ( h == 0) h =
1;
// Ustawienie widoku na wymiary okna
glviewport( O , O, w, h ) ;
glMatrixMode(GL_PROJECTION);
glLoadldentity();
gluOrtho2D(-10.0f, 10.Of, -10.Of, 10.O f ) ;

// Zerowanie macierzy widoku modelu


glMatrixMode(GL_MODELVIEW);
glLoadldentity(); }
// Wywoywane w celu narysowania sceny
void RenderScene(void)
{
//int i;
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT);

// Przygotowanie krzywej Beziera


// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMaplf(GL_MAP1_VERTEX_3, // Rodzaj generowanych danych
O.Of, V// Pocztek zakresu u
100.O f , /--^7 Koniec zakresu u
3, f //Odstp pomidzy danymi wierzchokw
nNumPoints, ''~--J II ilo punktw kontrolnych
SctrlPoints[ 0 ] [ 0 ] ); // tablica punktw kontrolnych

// Wczenie funkcji obliczajcej


glEnable(GL_MAP1_VERTEX_3);
Uycie amanej "czcej punkty"
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 100; i++) {
// Obliczenie krzywej dla danego punktu
glEvalCoordlf((GLfloat) i); } glEnd();
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!!___________________539

// Wyrysowanie punktw kontrolnych


DrawPoints();
// Zrzucenie polece graficznych
glFlushO;

Pierwszym elementem w listingu 17.1 jest definicja punktw kontrolnych naszej


krzywej:
// Ilo punktw kontrolnych krzywej
GLint nNumPoints = 4;

GLfloat ctrlPoints[4][ 3 ] = {{ -4.0f, O . O f , O . O f ) , // Punkt kocowy


( - 6 . O t , 4.0f, O . O f ) , // Punkt kontrolny
{ e . O f , -4.0f, O . O f } , // Punkt kontrolny
{ 4.0f, O.Of, O.Of } } ; // Punkt
kocowy

Dla iloci punktw kontrolnych oraz samej tablicy punktw kontrolnych stworzylimy
zmienne globalne. Aby poeksperymentowa, moesz je zmieni dodajc kolejne punkty
kontrolne lub po prostu modyfikujc pooenie punktw.
Funkcja DrawPoints() jest chyba oczywista. Wywoujemy j z kodu renderujcego w
celu wywietlenia punktw kontrolnych krzywej. Jest take bardzo uyteczna przy
eksperymentach z pooeniem punktw kontrolnych. Nasza standardowa funkcja Chan-
geSize() ustanawia dwuwymiarowy rzut rwnolegy o rozcigoci od -10 do 10 jednostek
w osiach x i y.
Na koniec, przechodzimy do kodu renderujcego. Funkcja RenderScene() wywouje na
pocztku funkcj glMaplf (po wyczyszczeniu ekranu) w celu stworzenia odwzorowania dla
naszej krzywej:
// Wywoywane w celu narysowania sceny
void RenderScene(void)
{
//int i;

// Wyczyszczenie okna biecym kolorem ta


glClear(GL_COLOR_BUFFER_BIT);

// Przygotowanie krzywej Beziera


// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMaplf(GL_MAP1_VERTEX_3, // Rodzaj generowanych danych
O.Of, // Pocztek zakresu u
100.O f , // Koniec zakresu u
3, // Odstp pomidzy danymi wierzchokw
nNumPoints, // ilo punktw kontrolnych
SctrlPoints[ 0 ] [ 0 ] ); // tablica punktw kontrolnych

Pierwszy parametr funkcji glMaplf, GL_MAP1_VERTEX_3, przygotowuje funkcj


obliczajc do generowania trjek wsprzdnych wierzchokw (x, y i z), w odrnieniu
od GL_MAP1_VERTEX_4, sucego do generowania trjek wsprzdnych oraz
skadowej alfa. Moesz take przygotowa funkcj obliczajc inne wartoci, takie jak
540_______________________Cz III Tematy zaawansowane i efekty specjalne

wsprzdne tekstury czy informacje o kolorze. Szczegy znajdziesz w sekcji po-


drcznika.

Dwa nastpne parametry okrelaj dolny i grny zakres parametru u dla tej krzywej.
Dolna warto okrela pocztkowy punkt krzywej, za grna warto okrela ostatni
punkt krzywej. Wszystkie wartoci pomidzy nimi odnosz si do punktw tworzonej
krzywej. W naszym przykadzie ustalilimy zakres od O do 100.

Czwarty parametr funkcji glMaplf okrela ilo zmiennoprzecinkowych wartoci po-


midzy wierzchokami w tablicy punktw kontrolnych. Kady wierzchoek skada si z
trzech zmiennoprzecinkowych wartoci (dla x, y i z), wic ten parametr moemy ustawi
na 3. Ta elastyczno umoliwia umieszczenie punktw kontrolnych w rnych
strukturach danych, pod warunkiem, e te struktury s rozmieszczone w regularnych
odstpach w pamici.

Ostatni parametr funkcji to wskanik do bufora zawierajcego punkty kontrolne uyte do


definiowania krzywej. W naszym przykadzie przekazujemy wskanik do pierwszego
elementu tablicy. Po utworzeniu odwzorowania krzywej moemy wczy funkcj
obliczajc dla tego odwzorowania. Osigamy to przez wczenie odpowiedniej zmiennej
stanu; oto wywoanie potrzebne do wczenia funkcji obliczajcej generujcej punkty
wzdu krzywej:
// Wczenie funkcji

glEnable(GL_MAP1_VRTEX3);

Funkcja glEvalCoordl f otrzymuje pojedynczy argument: warto parametryczn krzywej. Ta


funkcja oblicza wsprzdne punktu krzywej dla danej wartoci zmiennej parametrycznej
i wewntrznie wywouje funkcj glVertex dla tego punktu. Poprzez przejcie (w ptli)
przez dziedzin krzywej i wywoywanie funkcji glEvalCoord w celu utworzenia
wierzchokw, moemy narysowa krzyw za pomoc pojedynczej amanej:
// Uycie amanej "czcej punkty"
glBegin(GL_LINE_STRIP);
for(i = 0; i <= 100; i++) {
// Obliczenie krzywej dla danego punktu
glEvalCoordlf((GLfloat) i); } glEnd();

Na koniec, chcemy jeszcze wyrysowa punkty kontrolne:


// Wyrysowanie punktw kontrolnych
DrawPoints();

// Zrzucenie polece graficznych


glFlushO ;

Obliczanie krzywej
OpenGL moe jeszcze bardziej uproci cae zadanie. Moemy przygotowa siatk punktw
za pomoc funkcji glMapGrid, sucej do utworzenia rwnomiernej siatki punktw w
dziedzinie krzywej. Nastpnie moemy wywoa funkcj glEvalMesh w celu
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!!___________________541

poczenia kropek" przy uyciu podanego prymitywu (GLJLINE lub GL_POINTS).


Ponisze dwa wywoania:
// Uycie funkcji wyszego poziomu do odwzorowania siatki, //
a nastpnie obliczenia caoci
// Odwzorowanie siatki 100 punktw od O do 100
glMapGridlddOO, 0 . 0 , 100.0) ;
// Utworzenie siatki przy uyciu linii
glEvalMeshl(GL_LINE,O,100);

cakowicie zastpuj ten kod:


// Uycie amanej "czcej punkty"
glBegin(GL_LINE_STRIP);
for(i = 0; i <= 100; i++) {
// Obliczenie krzywej dla danego punktu
glEvalCoordlf((GLfloat) i); } glEnd();

Jak wida, jest to bardziej spjne i efektywne, jednak prawdziwe korzyci pynce z
tych wywoa objawiaj si raczej podczas tworzenia powierzchni, nie krzywych.

Powierzchnia trjwymiarowa
Tworzenie trjwymiarowej powierzchni Beziera przebiega podobnie do tworzenia dwu-
wymiarowej krzywej. Oprcz zdefiniowania punktw w dziedzinie u, musimy zdefiniowa
punkty take w dziedzinie v.
Listing 17.2 pochodzi z naszego nastpnego programu, BEZ3D, w ktrym wywietlamy
siatk przedstawiajc powierzchni Beziera. Pierwsz zmian w stosunku do poprze-
dniego przykadu jest zdefiniowanie trzech dodatkowych zestaww punktw kontrol-
nych powierzchni, wzdu dziedziny v. Aby powierzchnia nie bya skomplikowana,
poza wartoci Z pozostae wsprzdne punktw kontrolnych pozostaj takie same. W
ten sposb stworzylimy jednorodn powierzchni, tak jakbymy rozcignli" nasz
dwuwymiarow krzyw Beziera wzdu osi Z.

Listing 17.2. Kod z programu BEZ3D tworzcy powierzchni Beziera__________________

// Ilo punktw kontrolnych krzywej


GLint nNumPoints = 3;
GLfloat ctrlPoints[3][3][3]= {{ { -4.0f, O.Of, 4 . 0 f ) ,
{ -2.0f, 4.0f, 4 . 0 f } , {
4.0f, O . O f , 4.0f } } ,
{{ -4.0f, O.Of, O . O f } ,
{ -2.0f, 4.0f, O . O f } , {
4.0f, O.Of, O.Of } } ,
({ -4.0f, O . O f , -4.0f},
{ -2.0f, 4.0f, - 4 . 0 f ) ,
{ 4 . 0 f , O . O f , -4.0f } } } ;
542 ________________Cz III Tematy zaawansowane i efekty specjalne

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
//int i;

// Wyczyszczenie okna biecym kolorem ta


glClear(GL_COLOR_BUFFER_BIT);
// Zachowanie macierzy widoku modelu
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Obrt siatki, aby byo j lepiej wida
glRotatef (45.0f, O.. Of, l.Of, O . O f ) ;
glRotatef(60.Ofr-A.Of, O . O f , O . O f ) ;
f.
II Przygotowanie krzywej Beziera
// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMap2f(GL_MAP2_VERTEX_3, // Rodzaj generowanych danych
O.Of, // Pocztek zakresu u
10.O f , // Koniec zakresu u
3, // Odstp pomidzy danymi wierzchokw
3, // Rozmiar w kierunku u (klasa)
O.Of, // Pocztek zakresu v
10.O f , // Koniec zakresu v
9, // Odstp pomidzy danymi wierzchokw
3, // Rozmiar w kierunku v (klasa)
&ctrlPoints[0] [ 0 ] [ 0 ] );// tablica punktw kontrolnych
// Wczenie funkcji obliczajcej
glEnable(GL_MAP2_VERTEX_3);
// Uycie funkcji wyszego poziomu do odwzorowania siatki, //
a nastpnie obliczenia caoci
// Odwzorowanie siatki 10 punktw od O do 10
glMapGrid2f(10,O.Of,10.Of,10, O.Of, 10.Of) ;
// Utworzenie siatki przy uyciu linii
glEvalMesh2(GL_LINE,0,10,0,10);
// Wyrysowanie punktw kontrolnych
DrawPoints ();
// Odtworzenie macierzy widoku modelu
glPopMatrix();
// Zrzucenie polece graficznych
glFlushO ;

Nasz kod renderowania take jest nieco inny. Oprcz obrcenia figury w celu uzyskania
lepszego widoku, zamiast funkcji glMap l f wywoujemy funkcj glMap2f. W ten sposb
okrelamy punkty w dziedzinach M i v, a nie tylko w dziedzinie u.
Rozdzia 17. * Krzywe i powierzchnie: co to jest NURBS?!! 543

// Przygotowanie krzywej Beziera


// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMap2f(GL_MAP2_VERTEX_3, // Rodzaj generowanych danych
O.Of, // Pocztek zakresu u
10.O f , // Koniec zakresu u
3, // Odstp pomidzy danymi wierzchokw
3, // Rozmiar w kierunku u ( k l a s a )
O.Of, // Pocztek zakresu v
10.O f , // Koniec zakresu v
9, // Odstp pomidzy danymi wierzchokw
3, // Rozmiar w kierunku v (klasa)
sctrlPoints[ 0 ] [ 0 ] [ 0 ] );// tablica punktw kontrolnych

W dalszym cigu musimy okrela pocztek i koniec dziedziny u; odlegoci pomidzy


punktami w dziedzinie u jest w dalszym cigu 3. Jednak tym razem musimy take
okreli pocztek i koniec dziedziny v. Odstp pomidzy punktami w dziedzinie v to 9,
gdy mamy trjwymiarow tablic punktw kontrolnych, w ktrej kady wiersz z dzie-
dziny u skada si z trzech punktw po trzy wartoci kady ( 3 x 3 = 9). Nastpnie infor-
mujemy funkcj glMap2f o iloci punktw w kierunku v okrelonych dla kadego
wiersza w kierunku u, a nastpnie przekazujemy wskanik do tablicy wszystkich punktw
kontrolnych.
Dwuwymiarowa funkcja obliczajca jest wczana podobnie jak funkcja jednowy-
miarowa, za funkcja glMapGrid2 jest wywoywana z iloci punktw kontrolnych w
kierunkach u i v:
glEnable(GL_MAP2_VERTEX_3);

// Uycie funkcji wyszego poziomu do odwzorowania siatki, //


a nastpnie obliczenia caoci
// Odwzorowanie siatki 10 punktw od O do 10
glMapGrid2f( 1 0 , O.Of,10.Of,10,O.Of,10.O f ) ;

Rysunek 17.5.
Wynik dziaania
programu BEZ3D

Po przygotowaniu funkcji obliczajcej, moemy wywoa dwuwymiarow (w sensie


dziedzin u i v) wersj funkcji glEvalMesh w celu utworzenia siatki punktw powierz-
544 Cz III Tematy zaawansowane i efekty specjalne

chni. Siatk tworzymy z linii, za zakres dziedzin u i v rozciga si od wartoci O do


wartoci 10.
// Utworzenie siatki przy uyciu linii
glEvalMesh2(GL_LINE,O,10,O,10);

Wynik dziaania tego programu zosta przedstawiony na rysunku 17.5.

Owietlenie i normalne
Kolejn cenn waciwoci funkcji obliczajcych jest automatyczne generowanie nor-
malnych. Przez prost zmian kodu:
// Utworzenie siatki przy uyciu linii
glEvalMesh2(GL_LINE,O,1 0 , 0 , 10);

na
// Utworzenie siatki przy uyciu linii
glEvalMesh2(GL_FILL,0,10,0,10) ;

a nastpnie wywoanie
glEnable(GL_A0TO_NORMAL);

w naszym kodzie inicjujcym, moemy atwo wygenerowa normalne do powierzchni


stworzonej za pomoc funkcji obliczajcej. Rysunek 17.6 przedstawia t sam powierz-
chni, co rysunek 17.5, z tym e wczono owietlenie i automatyczne generowanie nor-
malnych do powierzchni. Kod tego programu znajduje si w folderze BEZLIT na pytce
CD-ROM. Program stanowi jedynie nieznaczn modyfikacj programu BEZ3D.
Rysunek 17.6.
Wynik dziaania
programu BEZLIT
Rozdzia 17. * Krzywe i powierzchnie: co to jest NURBS?!!___________________545

NURBS
Funkcji obliczajcych powierzchnie Beziera moesz uywa do woli, jednak w przy-
padku bardziej zoonych krzywych bdziesz musia skada je z kawakw. W miar
dodawania kolejnych punktw kontrolnych coraz trudniej jest utworzy krzyw o po-
prawnej cigoci. Na szczcie, peniejsz kontrol mona osign uywajc funkcji
NURBS z biblioteki glu. NURBS to skrt sw non-uniform rational B-spline (nieje-
dnorodne wymierne krzywe B-sklejane). Matematycy ju wiedz, e chodzi po prostu o
bardziej uoglnion form krzywych i powierzchni ni te, ktre mog tworzy krzywe i
powierzchnie Beziera, a take kilka innych rodzajw krzywych. W przypadku funkcji
NURBS mona okrela wpyw punktw kontrolnych podanych funkcjom obliczajcym,
w celu otrzymania gadszych krzywych i powierzchni o wikszej liczbie punktw
kontrolnych.

Od krzywych Beziera do krzywych B-sklejanych


Krzywa Beziera jest zdefiniowana przez dwa punkty kocowe oraz dowoln liczb innych
punktw kontrolnych, wpywajcych na ksztat krzywej. Trzy krzywe Beziera z
rysunku 17.7 maj okrelone 3, 4 i 5 punktw kontrolnych. Krzywa jest styczna do linii
czcej punkty kocowe z nastpnymi punktami kontrolnymi. W przypadku krzywych o
trzech i czterech punktach kontrolnych, otrzymana krzywa Beziera jest bardzo gadka i
zwykle posiada cigo typu C3 (krzywizna). Jednak w przypadku wikszej iloci
punktw kontrolnych, krzywa zaczyna by coraz mniej gadka, gdy wygina" j coraz
wicej elementw.

Rysunek 17.7. ,;. P, \ P, \ P)


Cigo krzywych *. T ._
Beziera przy ''/"'*.
wzrocie iloci '/ ^**s,_
^^^ p
punktw kontrolnych L ^s^ "2
Trzy punkty kontrolne Cztery punkty kontrolne Pi punktw kontrolnych

Z drugiej strony, krzywe B-sklejane


(bikubiczne krzywe sklejane) wygldaj podobnie do krzywych Beziera, z tym e s
podzielone na segmenty. Ksztat kadego z segmentw zaley wycznie od pooenia
czterech najbliszych (w sensie kolejnoci) punktw kontrolnych, co daje krzyw zoon z
kawakw, z ktrych kady zachowuje charakterystyk podobn do krzywej Beziera o
czterech punktach kontrolnych. Oznacza to, e duga krzywa z wieloma punktami
kontrolnymi moe zachowa gadko, gdy poczenia pomidzy kawakami krzywej
zachowuj cigo typu C3. Oznacza to take, e krzywa nie musi przechodzi przez aden
ze swoich punktw kontrolnych.
546 Cz III Tematy zaawansowane i efekty specjalne

Wzy
Prawdziwa potga krzywych NURBS polega jednak na tym, e moesz okreli wpyw
czterech punktw kontrolnych na dany segment krzywej w celu osignicia podanej
gadkoci. Odbywa si to poprzez okrelenie sekwencji wartoci zwanych wzlami.
Dla kadego punktu kontrolnego s zdefiniowanie dwie wartoci wzw. Zakres wartoci
wzw odpowiada dziedzinom parametrw u oraz v i musi by niemalejcy, gdy wartoci
wzw okrelaj wpyw punktw kontrolnych przypadajcych na dany zakres w
przestrzeni u/v. Rysunek 17.8 przedstawia krzyw demonstrujc wpyw punktw
kontrolnych na krzyw posiadajc cztery jednostki w dziedzinie parametru M. Punkty w
rodkowej czci krzywej wyginaj j w wikszym stopniu, a na ksztat krzywej maj
wpyw jedynie punkty pomidzy O a 3.

Rysunek 17.8.
Wpyw
Wptyw punktw
kontrolnych wzdu
dziedziny
parametru u

2 3

Kluczowy jest fakt, e jedna z takich krzywych wpywu wystpuje dla kadego punktu w
dziedzinie parametrw u/v. Sekwencja wzw definiuje si wpywu punktw w tej
dziedzinie. Jeli warto wza si powtarza, punkty w pobliu tej parametrycznej
wartoci maj jeszcze wikszy wpyw. Powtarzanie wartoci wzw jest nazywane
multiplikacj wzw. Wysza multiplikacja wzw zmniejsza krzywizn krzywej lub
powierzchni w danym regionie.

Tworzenie powierzchni NURBS


Funkcje NURBS z biblioteki glu stanowi uyteczne narzdzie do tworzenia powierzchni.
Nie musisz jawnie wywoywa funkcji obliczajcych lub ustanawia odwzorowa bd
siatek. Aby wyrenderowa powierzchni NURBS, musisz najpierw stworzy obiekt
NURBS, do ktrego bdziesz si odwoywa za kadym razem przy wywoywaniu funkcji
zwizanych z powierzchniami NURBS w celu zmodyfikowania wygldu krzywej lub
powierzchni.
Funkcja gluNewNurbsRenderer tworzy renderera dla powierzchni NURBS. Do usuwania
utworzonego renderera suy funkcja gluDeleteNurbsRenderer. Uycie tych funkcji
demonstruje poniszy fragment kodu:
// Wskanik do obiektu NURBS
GLUnurbsObj *pNurb - NULL;
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!!___________________547

// Przygotowanie obiektu NURBS


pNurb = gluNewNurbsRenderer();

// Operacje na powierzchni NURBS.

// Usunicie obiektu NURBS, jeli zosta utworzony


if(pNurb)
gluDeleteNurbsRenderer(pNurb);

Waciwoci obiektw NURBS


Po stworzeniu renderera NURBS, moesz ustawia jego rnorodne waciwoci:
// Ustawienie tolerancji prbkowania gluNurbsPropertyfpNurb,
GLU_SAMPLING_TOLERANCE, 25.O f ) ;

// Wypenienie w celu otrzymania jednolitej powierzchni (jeli chcesz //


utworzy siatk wieloktw, uyj GLU_OUTLINE_POLYGON).
gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);

Zwykle bdziesz wywoywa te funkcje w procedurze przygotowujcej, a nie cay czas w


kodzie renderowania. W tym przykadzie parametr GLU_SAMPLING_TOLERANCE
okrela, jak szczegowa jest siatka definiujca powierzchni, za GLU_FILL informuje
OpenGL, aby wypeni powierzchni zamiast generowa siatk.

Definiowanie powierzchni
Definicja powierzchni jest przekazywana funkcji gluNurbsSurface jako tablice punktw
kontrolnych i sekwencji wzw. Jak wida, ta funkcja jest ujta pomidzy wywoania
gluBeginSurface oraz gluEndSurface:
// Renderuj powierzchni NURBS //
Pocztek definicji powierzchni
gluBeginSurface(pNurb);
// Obliczenia powierzchni
gluNurbsSurface(pNurb, // Wskanik do renderera NURBS
8, Knots, // Ilo wzw i tablica wzw w kierunku u.
8/ Knots, // Ilo wzw i tablica wzw w kierunku v.
4*3, // Odstp pomidzy punktami kontrolnymi
// kierunku u.
3. // Odstp pomidzy punktami kontrolnymi
// kierunku v.
sctrlPoints[ 0 ] [ 0 ] [ 0 ] , // Punkty kontrolne
4. 4, // klasa powierzchni u i v
GL_MAP2_VERTEX_3); // Rodzaj powierzchni
// Koniec definiowania powierzchni
gluEndSurface(pNurb);
548 Cz III Tematy zaawansowane i efekty specjalne

Moesz zastosowa wicej wywoa funkcji gluNurbsSurface w celu stworzenia wikszej


liczby powierzchni NURBS, lecz bd przy tym obowizywa waciwoci ustawione dla
renderera NURBS. Czsto wanie to jest podane - cho czasem zdarza si, e chcesz,
aby dwie powierzchnie (by moe poczone) miay rne rodzaje wypenienia (jedna
wypeniona, druga w postaci siatki).
Uywajc punktw kontrolnych i wartoci wzw pokazanych w nastpnym fragmencie
kodu, tworzymy pjdwierzchni NURBS przedstawion na rysunku 17.9. Ten program,
noszcy nazw NtTteBS, znajduje si na pytce CD-ROM doczonej do ksiki.

j
Rysunek 17.9.
Dziaanie programu
NURBS

// Siatka rozciga si na cztery jednostki od -6 do +6 wzdu osi xi y


// Ley na paszczynie Z v=
II u v ( x , y,z) V =
GLfloat ctrlPoints[4][4][3]= { { { -6.0f, -6.0f, O . O f } , // u = O, V =
{ -6.0f, -2.0f, O . O f } , // V =
- 2.0f, O . O f } ,
6.0f 6.0f, O.Of}:
,
// u = 1 v= O
-2.0f,-6.0f, O.Of}, v= l
-2.0f, -2.0f, v= 2
8.0f}, v= 3
-2.0f, 2.0f, 8.0f},
-2.0f, 6.0f, O . O f } } , v= O
v= l
{{ 2.0f, -6.0f, v= 2
O.Of }, // u v= 3
{ 2.0f, -2.0f, 8.0f }, //
{ 2.0f, 2.0f, 8.0f }, // v= O
{ 2.0f, 6.0f, O.Of } } , / / v= l
v= 2
{{ 6.0f, -6.0f, v= 3
O . O f}, // u
{ 6.0f, -2.0f,
O . O f}, //
{ 6.0f, 2.0f, O . O f } ,
//
{ 6.0f, 6.0f, O.Of}}};//
// Sekwencja wzw dla powierzchni
GLfloat Knots[8] = ( O . O f , O . O f , O . O f , O . O f , l . O f , l . O f , l . O f ,
l.Of};
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 549

Wycinanie
Wycinanie wie si z usuwaniem sekcji powierzchni NURBS. Zwykle stosuje sieje do
dosownego obcinania ostrych krawdzi tych powierzchni. Rwnie atwo mona take
wycina otwory w powierzchniach. Wynik dziaania programu NURBT zosta przedsta-
wiony na rysunku 17.10.

Rysunek 17.10.
Wynik dziaania
programu NURBT

Widzimy na nim t sam powierzchni, co w poprzednim przykadzie (bez narysowanych


punktw kontrolnych), z usunitym trjktnym obszarem. Ten program take znajduje si
na pytce CD-ROM.
Listing 17.3 zawiera kod dodany do przykadowego programu NURBS w celu wycicia
trjkta z rysowanej powierzchni. Pomidzy klamr wywoa gluBeginSufrace/gluEnd-
Surface zostao umieszczone wywoanie gluBeginTrim, po ktrym nastpuje definicja krzywej
wycinajcej (poprzez wywoanie gluPwlCurve), zakoczona wywoaniem gluEndTrim.

Listing 17.3. Modyfikacje programu NURBS w celu wycicia fragmentu powierzchni ____________

// Zewntrzne punkty wycinania, obejmujce ca powierzchni GLfloat


outsidePts [5] [2] - /* przeciwnie do ruchu wskazwek */
{{O.Of, O.Of), {l.Of, O.Of), ( l . O f , l . Of}, { O . O f , l.Of}, (O.Of,

// Wewntrzne punkty wycinania, tworzce t r j k t n y otwr w powierzchni GLfloat


insidePts [ 4] [2] = /* zgodnie z ruchem wskazwek */
{ { 0 . 2 5 f , 0 . 2 5 f ) , ( 0 . 5 f , 0 . 5 f ) , < 0. 75f , 0 . 2 5 f ) , { 0.25f,
0.25f}};

// Renderuj powierzchni NURBS. //


Pocztek definicji powierzchni
gluBeginSurface(pNurb);
Cz III Tematy zaawansowane i efekty specjalne

// Obliczenia powierzchni
gluNurbsSurface(pNurb, // Wskanik do renderera NURBS
8, Knots, // Ilo wzw i tablica wzw w kierunku u.
8, Knots, // Ilo wzw i tablica wzw w kierunku v.
4
* 3, // Odstp pomidzy punktami kontrolnymi
// kierunku u.
3
' , // Odstp pomidzy punktami kontrolnymi
// kierunku v.
sctrlPointst^KU [ 0 ] , // Punkty kontrolne
4
' 4/ >. // Klasa powierzchni u i v
GL_MAP2_VERTEX_3);)<' // Rodzaj powierzchni
f
/ 7 Obszar zewntrzny/ obejmujcy ca powierzchni
gluBeginTrim (pNurb) ;
gluPwlCurve (pNurb, 5, ioutsidePts [ 0 ] [ 0 ] , 2, GLU MAPI TRIM 2)
gluEndTrim (pNurb) ; ~ ~~ ~

// Wewntrzny trjktny obszar


gluBeginTrim (pNurb) ;
gluPwlCurve (pNurb, 4, SinsidePts [ 0 ] [ 0 ] , 2, GLU MAPI TRIM 2 ) -
gluEndTrim (pNurb) ; ~ - - '

// Koniec definiowania powierzchni


gluEndSurface (pNurb) ;

Wewntrz klamry gluBeginTrim/gluEndTrim moesz okreli dowoln ilo krzywych,


jeli tylko cznie tworz zamknit ptl. Moesz take uy funkcji gluNurbsCurve w
celu zdefiniowania regionu wycinania lub czci regionu wycinania. Te krzywe
wycinania musz by jednak wyraone jako krzywe o jednostkowych dziedzinach u i v.
Oznacza to, e caa dziedzina u/v rozciga si od wartoci 0,0 do l ,0.
Funkcja gluPwlCurve definiuje krzyw skadajc si z odcinkw amanej - czyli po
prostu kolejne punkty poczone odcinkami. W tym scenariuszu wewntrzna trjktna
krzywa wycinajca tworzy trjkt, lecz przy zastosowaniu wikszej iloci punktw
moesz utworzy przyblienie dowolnej potrzebnej krzywej.

Wycinanie krzywej powoduje usunicie obszaru powierzchni bdcej na prawo w sto-


sunku do kierunku krzywej. Tak wic w krzywych zgodnych z ruchem wskazwek zegara
zostanie wycite wntrze krzywej. Zwykle okrelana jest take zewntrzna krzywa
obcinania, obejmujca ca przestrze parametryczn NURBS. Dopiero potem definiuje si
mniejsze regiony wycinania, okrelone za pomoc zamknitych krzywych o kierunku
zgodnym z ruchem wskazwek zegara. T zaleno ilustruje rysunek 17.1 1.
Rysunek 17.11.
Wycinany jest obszar wewntrz krzywych uoonych
zgodnie z ruchem wskazwek zegara
Rozdziaf 17. * Krzywe i powierzchnie: co to jest NURBS?!!___________________551

Podsumowanie
Ten rozdzia z atwoci mg si sta najbardziej niezrozumiaym rozdziaem w ksice.
Jak jednak widzisz, koncepcje kryjce si za krzywymi i powierzchniami nie s a tak
trudne do zrozumienia. Jeli chcesz dokadniej pozna ich matematyczne podstawy, w
dodatku B znajdziesz wykaz odpowiedniej literatury.
Przykady z tego rozdziau stanowi dobry punkt wyjcia do eksperymentowania z po-
wierzchniami NURBS. Sprbuj dostosowa punkty kontrolne i sekwencje wzw w
celu uzyskania zawinitych lub pofadowanych powierzchni. Sprbuj take stworzy
powierzchnie drugiego, trzeciego i wyszych stopni. Na doczonej do ksiki pytki
CD-ROM znajdziesz dodatkowe przykady.
Uwaaj - jedn z najczstszych puapek jest prba stworzenia zoonych powierzchni
przy uyciu pojedynczych powierzchni NURBS. Przekonasz si, e wiksz elasty-
czno i moliwoci osigniesz wtedy, gdy skomponujesz zoon powierzchni z kilku
mniejszych i atwiejszych do opanowania powierzchni Beziera lub NURBS.

Podrcznik
glEyalCoord
Przeznaczenie Oblicza punkt jedno- lub dwuwymiarowej krzywej, za pomoc uprzednio
wybranej funkcji.
Plik nagwkowy <gl.h>
Skadnia void glEvalCoordld(GLdoub!e u);
void glEvalCoordlf(GLfloat u);
void glEvalCoord2d(GLdouble u, GLdouble v);
void glEvalCoord2f(GLfloat u, GLfloat v);
void glEvalCoordldv(const GLdouble *u);
void glEvaICoordlfv(const GLfloat *u);
void glEvalCoord2dv(const GLdouble *u);
void glEvalCoord2fv(const GLfloat *u);
Opis Ta funkcja uywa poprzednio wybranej (poprzez wywoanie glMap)
funkcji obliczajcej do stworzenia wierzchoka, koloru, normalnej oraz
wsprzdnych tekstury na podstawie wartoci parametrw u i v. Rodzaj
danych oraz wywoywanych funkcji jest okrelany przez wywoanie funkcji
glMap l orazglMap2.
552 Cz III Tematy zaawansowane i efekty specjalne

Parametry
w, v Te parametry okrelaj wartoci parametrw u i v, dla ktrych ma zosta
obliczony punkt krzywej.
Zwracana warto Brak.
Przykad Poniszylwd z przykadowego programu BEZIER odpowiada wywoaniu
funkcji glVertex3f za kadym razem, gdy jest wywoywana funkcja
glEvalCoordLfHF^ooenie wierzchokw jest obliczane z rwnania krzywej
dla Kolejnych wartoci z dziedziny krzywej, przekazywanych poprzez
zmienn i.
// Oycie amanej "czcej punkty"
glBegin(GL_LINE_STRIP);
for(i = 0; i <= 100; i++) {
// Obliczenie krzywej dla danego punktu
glEvalCoordlf((GLfloat) i ) ; } glEnd ();

glEvalMesh, glEvalPoint, glMapl, glMap2, glMapGrid


Patrz take

glEyalMesh
Przeznaczenie Oblicza punkt jedno- lub dwuwymiarowej siatki krzywej.
Plik nagwkowy <gl.h>
Skadnia void glEvalMeshl(GLenum mod, GLint ii, GLint i2);
void gIEvalMesh2(GLenum mod, GLint ii, GLint i2, GLint j l, GLint J2);
Opis Ta funkcja jest uywana razem z glMapGrid w celu utworzenia siatki
punktw powierzchni rwnomiernie rozoonych w dziedzinach u i v.
Funkcja glEvalMesh oblicza pooenie wierzchokw i tworzy punkty,
odcinki lub wypenione wielokty.
Parametry
mod GLenum: Okrela, czy siatka ma by tworzona z punktw (GL_POINT),
odcinkw (GL_LINE) czy wypenionych wieloktw w przypadku
powierzchni (GL_FILL).
11,12 GLint: Okrelaj pierwsz i ostatni warto cakowit w dziedzinie u.
JJJ2 GLint: Okrelaj pierwsz i ostatni warto cakowit w dziedzinie v.
Zwracana warto Brak.
Przykad Poniszy kod z przykadowego programu BEZIER tworzy odwzorowanie
siatki od O do 100 ze stoma podziaami. Wystpujce dalej wywoanie
glEvalMesh oblicza punkty siatki i rysuje odcinki pomidzy wszystkimi
punktami krzywej.
// Oycie funkcji wyszego poziomu do odwzorowania //
siatki, a nastpnie obliczenia caoci
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 553

// Odwzorowanie siatki 100 punktw od O do 100


glMapGridld(100,0 . 0 , 100.0);

// Utworzenie siatki przy uyciu linii


glEvalMeshl(GL_LINE,O,100);

Patrz take glBegin, glEvalCoord, glEvalPoint, glMapl, glMap2, glMapGrid

glEyalPoint
Przeznaczenie Plik Oblicza i generuje pojedynczy punkt siatki.
nagwkowy <gl.h>
Skadnia void glEvalPointl(GLint i);
void glEvalPoint2(GLint i, GLint j);
Opis Ta funkcja moe zosta uyta zamiast funkcji glEvalMesh w celu
obliczenia pojedynczego punktu krzywej lub powierzchni. W wyniku
Parametry i J oblicze powstaje pojedynczy prymityw, GL_POINTS. Pierwsza
odmiana funkcji (glEvalPointl) jest uywana w przypadku krzywych,
Zwracana warto za druga odmiana (glEvalPoint2) w przypadku powierzchni.
Przykad
GLint: Okrelaj warto parametrw u i v, dla ktrych ma zosta
obliczony punkt krzywej.
Brak.
Poniszy kod tworzy krzyw Beziera zoon z punktw, a nie z
segmentw linii. Jako komentarz pozostawiono niepotrzebne ju
wywoania, pozostae z poprzedniego przykadu, z opisu funkcji
glEvalCoord:
// Oycie amanej "czcej punkty"
glBegin(GL_LINE_STRIP);
for(i = 0; i o 100; i++) {
// Obliczenie krzywej dla danego punktu //
glEvalCoordlf((GLfloat) i ) ; glEvalPointl( i ) ; }
glEnd();

glEvalCoord, glEvalMesh, glMapl, glMap2, glMapGrid


Patrz take
giGetMap
Przeznaczenie Zwraca parametry funkcji obliczajcej.
Plik nagwkowy <gl.h>
Skadnia void glGetMapdv(GLenum target, GLenum query, GLdouble *v);
void gIGetMapfv(GLenum target, GLenum uery, GLfloat *v);
554 : III Tematy zaawansowane i efekty specjalne

void glGetMapiv(GLenum target, GLenum uery, GLint *v);


Opis Ta funkcja odczytuje ustawienia odwzorowania ustawione za pomoc
funkcji glMap. Opis rodzajw odwzorowa znajdziesz w opisie funkcji
glMapl i glMap2.
Parametry
target GLenum: Nazwa odwzorowania; zdefiniowane s nastpujce
odwzorowania:
COLOR_4, GL_MAP1 JNDEX,
GL_MAP1_NORMAL,
TEXTURE_COORD_1,
TEXTURE_COORD_2,
TEXTURE_COORD_3,
JEXTURE_COORD_4,
VERTEX_3, GL_MAP1_VERTEX_4,
COLOR_4, GL_MAP2_INDEX, GL_MAP2_NORMAL,
TEXTURE_COORD_1,
TEXTURE_COORD_2,
TEXTURE_COORD_3,
TEXTURE COORD 4,
GL_MAP1
GL_MAPl"
uery GL_MAP1~
GL_MAPl"
GL_MAPf
GL_MAP1
GL_MAP2"
GL_MAP2~
GL_MAP2~
GL_MAP2~
GL_MAP2~
GL_MAP2_VERTEX_3, GL_MAP2_VERTEX_4. Opis odwzorowa
znajdziesz w opisie funkcji glMap.
GLenum: Okrela parametr odwzorowania, ktry ma zosta zwrcony w
tablicy *v. Moe to by jedna z poniszych wartoci:
GL_COEFF: Zwraca tablic zawierajc punkty kontrolne dla
odwzorowania. Wsprzdne s zwracane wierszami. W odwzorowaniach
ID ilo zwracanych punktw kontrolnych odpowiada rzdowi krzywej, za
w odwzorowaniach 2D jest zwracanych rzd u razy rzd v punktw.
GL_ORDER: Zwraca rzd funkcji obliczajcej. W odwzorowaniach ID jest
to pojedyncza warto. W odwzorowaniach 2D s zwracane dwie wartoci -
tablica, w ktrej pierwszy element odpowiada rzdowi u, za drugi element -
rzdowi v.
GLJDOMAIN: Zwraca dziedzin parametrw odwzorowania. Dla funkcji
obliczajcych ID zwracana jest dolna i grna warto parametru u. W
odwzorowaniach 2D zwracana jest dolna i grna warto parametru u, za
po nich dolna i grna warto parametru v.
Wskanik do obszaru pamici, w ktrym zostan zoone zwracane
wartoci. Typ danych tego obszaru powinien odpowiada uytej funkcji
(double, float lub int).
Zwracana warto Brak.
Przykad Poniszy kod przedstawia ustawianie, a nastpnie (by moe w innej
funkcji) odczytywanie parametrw odwzorowania. W komentarzach
opisano zawarto bufora.
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 555

glMap2f(GL_MAP2_VERTEX_3, // Rodzaj generowanych danych


O . O f , // Dolny zakres u 10.O f , // Grny zakres u 3, //
Odlego miedzy punktami w danych 3, // Rozmiar w
kierunku u (rzd) O . O f , // Dolny zakres v 10.O f , //
Grny zakres v 9, // Odlego miedzy punktami w danych
3, // Rozmiar w kierunku v (rzd)
sctrlPoints[ 0 ] [ 0 ] [ 0 ] ); // tablica punktw kontrolnych

float parametricRange[ 4 ] ;

glGetMapfv(GL_MAP2_VERTEX_3,GL_DOMAIN,parametricRange);

/* Teraz parametricRange[ 0 ] = 0 . 0 // Dolne u


parametricRange[ 1 ] = 10.0 // Grne u
parametricRange[ 2 ] = 0 . 0 // Dolne v
parametricRange[ 3 ] = 10.0 // Grne v
*/
Patrz take glEvalCoord, glMapl, glMap2

gIMap
Przeznaczenie Definiuje funkcj obliczajc ID lub 2D.
Plik nagwkowy <gl.h>
Skadnia void glMapld(GLenum target, GLdouble ul, GLdouble u2, GLint
ustride, GLint uorder, const GLdouble *points);
void glMaplf(GLenum target, GLfloat ul, GLfloat u2, GLint ustride,
GLint uorder, const GLfloat *points);
void glMap2d(GLenum target, GLdouble ul, GLdouble u2, GLint ustride,
GLint uorder, GLdouble vi, GLdouble v2, GLint vstride, GLint vorder,
const GLdouble *points);
void glMap2f(GLenum target, GLfloat ul, GLfloat u2, GLint ustride,
GLint uorder, GLfloat vi, GLfloat v2, GLint vstride, GLint vorder, const
GLfloat *points);
Opis Ta funkcja definiuje funkcj obliczajc dla krzywych (ID) lub
powierzchni (2D). Funkcje glMaplx s uywane dla krzywych, za funkcje
glMap2x dla powierzchni. Funkcje obliczajce generuj wierzchoki i
zwizane z nimi informacje (patrz opis parametru target) dla parametrw
krzywych i powierzchni z dziedziny u i v.
556_______________________Cz III Tematy zaawansowane i efekty specjalne

Parametry
target GLenum: Okrela rodzaj wartoci generowanych przez funkcj
obliczajc. Dostpne wartoci to:
GL_MAP1_VERTEX_3 (lub GL_MAP2_VERTEX_3): Punktami
kontrolnymi s trjki wartoci reprezentujce wartoci wsprzdnych x, y i z.
Podczas obliczania siatki generowane s wewntrznie polecenia glVertex3.
GLJVIAP1JVERTEX_4 (lub GL_MAP2_VERTEX_4): Punktami
kontrolnymi s czwrki wartoci reprezentujce wartoci wsprzdnych x, y,
z i w. Podczas obliczania siatki generowane s wewntrznie polecenia
glVertex4.
GL_MAP1_INDEX (lub GL_MAP2_INDEX): Generowane punkty kontrolne
to pojedyncze wartoci zmiennoprzecinkowe okrelajce warto indeksu
koloru. Podczas obliczania siatki generowane s wewntrznie polecenia
gllndex. Uwaga: biecy indeks koloru nie jest zmieniany, inaczej ni w
przypadku bezporedniego wywoania polecenia gllndex.
GL_MAP1_COLOR_4 (lub GL_MAP2_COLOR_4): Generowane punkty
kontrolne to czwrki wartoci zmiennoprzecinkowych okrelajcych
skadowe czerwon, zielon, niebiesk oraz alfa koloru. Podczas obliczania
siatki generowane s wewntrznie polecenia glColor4. Uwaga: biecy kolor
nie jest zmieniany, inaczej ni w przypadku bezporedniego wywoania
polecenia glColor4.
GL_MAP1_NORMAL (lub GL_MAP2_NORMAL): Generowane punkty
kontrolne to trjki wartoci zmiennoprzecinkowych okrelajcych
wsprzdne x, y i z wektora normalnego. Podczas obliczania siatki
generowane s wewntrznie polecenia glNormal. Uwaga: bieca normalna
nie jest zmieniana, inaczej ni w przypadku bezporedniego wywoania
polecenia glNormal.
GL_MAP1_TEXTURE_COORD_1 (lub
GL_MAP2_TEXTURE_COORD_1): Generowane punkty kontrolne to
pojedyncze wartoci zmiennoprzecinkowe okrelajce wsprzdn s
tekstury. Podczas obliczania siatki generowane s wewntrznie polecenia
glTexCoordl. Uwaga: biece wsprzdne tekstury nie s zmieniane, inaczej
ni w przypadku bezporedniego wywoania polecenia glTexCoordl.
GL_MAP1_TEXTURE_COORD_2 (lub
GL_MAP2_TEXTURE_COORD_2): Generowane punkty kontrolne to pary
wartoci zmiennoprzecinkowych okrelajce wsprzdne s i t tekstury.
Podczas obliczania siatki generowane s wewntrznie polecenia
glTexCoord2. Uwaga: biece wsprzdne tekstury nie s zmieniane,
inaczej ni w przypadku bezporedniego wywoania polecenia glTexCoord.
GL_MAP1_TEXTURE_COORD_3 (lub
GL_MAP2_TEXTURE_COORD_3): Generowane punkty kontrolne to trjki
wartoci zmiennoprzecinkowych okrelajce wsprzdne s, t i r
Rozdzia 17. * Krzywe i powierzchnie: co to jest NURBS?!! 557

tekstury. Podczas obliczania siatki generowane s wewntrznie polecenia


glTexCoord3. Uwaga: biece wsprzdne tekstury nie s zmieniane,
inaczej ni w przypadku bezporedniego wywoania polecenia glTexCoord.
GL_MAP1_TEXTURE_COORD_4 (lub
GL_MAP2_TEXTURE_COORD_4): Generowane punkty kontrolne to
czwrki wartoci zmiennoprzecinkowych okrelajce wsprzdne s, t, r i q
tekstury. Podczas obliczania siatki generowane s wewntrznie polecenia
glTexCoord4. Uwaga: biece wsprzdne tekstury nie s zmieniane,
inaczej ni w przypadku bezporedniego wywoania polecenia glTexCoord.
Okrelaj liniowe odwzorowanie parametru u dziedziny.
Okrelaj liniowe odwzorowanie parametru v dziedziny. Stosowane
ul, u2 jedynie w odwzorowaniach 2D.
vl,v2 Okrelaj ilo zmiennych float lub double pomidzy kolejnymi punktami
ustride, vstride kontrolnymi w strukturze danych wskazywanej przez *points. Wsprzdne
uorder, vorder kadego punktu kontrolnego zajmuj okrelone miejsca w pamici, za te
parametry umoliwiaj zastosowanie dowolnych odstpw pomidzy
*points poszczeglnymi elementami.
Okrelaj ilo punktw kontrolnych w kierunku u i v.
Wskanik do obszaru pamici zawierajcego punkty kontrolne. Moe to by
dwu- lub trjwymiarowa tablica dowolnych struktur danych.

Zwracana warto Brak.


Przykad Poniszy fragment kodu pochodzi z programu BEZ3D. Ustanawia
odwzorowanie dla powierzchni Beziera drugiego stopnia.
// Ilo punktw kontrolnych krzywej GLint
nNumPoints = 3;

GLfloat ctrlPoints[3][ 3 ] [ 3 ] = [{ { -4.0f, O . O f , 4 . 0 f ) ,


{ -2.0f, 4 . 0f , 4 . 0 f } ,
{ 4.0f, O . O f , 4.0f
}},

{{ -4.0f, O . O f ,
O . O f } , { -2.0f,
4.0f, O . O f } , {
4.0f, O . O f , O . Of } },

{{ -4.0f, O . O f , -
4 . 0 f ) , { -2.0f, 4 . 0 f,
- 4 . 0 f } , { 4 . 0 f,
O . O f , -4.0f } } } ;

// Przygotowanie krzywej Beziera


// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMap2f(GL_MAP2_VERTEX_3, // Rodzaj generowanych danych
O.Of, // Pocztek zakresu u 10.O f ,
// Koniec zakresu u
558 Cz III Tematy zaawansowane i efekty specjalne

3, // Odstp pomidzy danymi wierzchokw


3, // Rozmiar w kierunku u (klasa) O . O f ,
// Pocztek zakresu v 10.O f , // Koniec
zakresu v 9, // Odstp pomidzy danymi
wierzchokw 3, // Rozmiar w kierunku v
( k l a s a ) // tablica punktw kontrolnych
&ctrlPoints[0][ 0 ] [ 0 ] );
glBegin, glColor, glEnable, glEvalCoord, glEvalMesh, glEvalPoint,
Patrz take glMapGrid, glNormal, glTexCoord, glVertex

glMapGrid
Przeznaczenie Definiuje siatk odwzorowania krzywej lub powierzchni.
Plik nagwkowy
Skadnia void glMapGrid l d(GLint un, GLdouble ul, GLdouble u2); void
glMapGridlf(GLint un, GLfloat ul, GLfloat u2);
void glMapGrid2d(GLint un, GLdouble ul, GLdouble u2, GLint vn,
GLdouble vi, GLdouble v2);
void glMapGrid2f(GLint un, GLfloat ul, GLfloat u2, GLint vn, GLfloat
vi, GLfloat v2);
Opis Ta funkcja ustanawia siatk odwzorowania ID lub 2D. Odwzorowanie jest
uywane przez funkcje glMap i glEvalMesh do obliczenia siatki
wsprzdnych krzywej lub powierzchni.
Parametry
un, vn GLint: Okrelaj ilo podziaw siatki w kierunku u i v. Okrelaj
ul, u2 dolny i grny zakres wartoci dziedziny w kierunku u. Okrelaj dolny
vl,v2 i grny zakres wartoci dziedziny w kierunku v. Brak.
Zwracana warto Poniszy fragment kodu pochodzi z programu BEZ3D. Ustanawia
odwzorowanie dla powierzchni Beziera drugiego stopnia, a nastpnie
Przykad oblicza punkty tej powierzchni.
// Przygotowanie krzywej Beziera
// Trzeba to zrobi tylko raz, wic powinnimy to
// uczyni w funkcji przygotowujcej kontekst.
glMap2f(GL_MAP2_VERTEX_3, // Rodzaj generowanych danych
O.Of, // Pocztek zakresu u 1 0 . O f ,
// Koniec zakresu u 3, // Odstp pomidzy
danymi wierzchokw 3, // Rozmiar w kierunku
u (klasa) O . O f , // Pocztek zakresu v
10.O f , // Koniec zakresu v 9, // Odstp
pomidzy danymi wierzchokw 3, // Rozmiar w
kierunku v (klasa) // tablica punktw
kontrolnych
Rozdzia 17. Krzywe i powierzchnie; co to jest NURBS711 559

&ctrlPoints[0][ 0 ] [ 0 ] ); //
Wczenie funkcji obliczajcej
glEnable(GL_MAP2_VERTEX_3);
// Uycie funkcji wyszego poziomu do odwzorowania
// siatki, a nastpnie obliczenia caoci
// Odwzorowanie siatki 10 punktw od O do 10
glMapGrid2f(10,O.Of,lO.Of,1 0 , 0 . 0 f , 1 0 . 0 f ) ;

// Utworzenie siatki przy uyciu linii


glEvalMesh2(GL_LINE,O,10,0,10);

Patrz take glEvalCoord, glEvalMesh, glEvalPoint, glMapl, glMap2

gluBeginCurye
Przeznaczenie Plik
Rozpoczyna definicj krzywej NURBS.
nagwkowy
<glu.h>
Skadnia Opis
void gluBeginCurve(GLUnurbsObj *nObj);
Parametry Ta funkcja, wraz z funkcj gluEndCurve, jest uywana do okrelenia
pocztku i koca definicji krzywej NURBS.
nObj
Zwracana warto
GLUnurbsObj: Okrela obiekt NURBS. Brak.
Przykad
Poniszy fragment kodu pochodzi z programu NURBC na pytce CD-
ROM. Demonstruje zastosowanie tej funkcji w celu okrelenia pocztku
definicji krzywej NURBS.
// Renderuj krzyw NURBS
// Pocztek definicji krzywej
gluBeginCurve(pNurb);
// Obliczanie krzywej
gluNurbsCurve(pNurb,
8, Knots,
3.
SctrlPoints[0][ 0 ] ,
4. GL_MAP1_VERTEX_3)
;

// Koniec definiowania krzywej


gluEndCurve(pNurb) ;
Patrz take gluEndCurve
560 Cz III Tematy zaawansowane i efekty
specjalne
Rozpoczyna definicj powierzchni
gluBeginSurface NURBS. <glu.h>
void gluBeginSurface(GLUnurbsObj *nObj);
Przeznaczenie Ta funkcja, wraz z funkcj gluEndSurface, jest uywana do
Plik okrelenia pocztku i koca definicji powierzchni NURBS.
nagwkowy
Parametry
Skadnia GLUnurbsObj: Okrela obiekt
nObj
Zwracana warto NURBS. Brak.
Przykad Poniszy fragment kodu pochodzi z programu NURBS na pytce CD-
ROM. Demonstruje zastosowanie tej funkcji w celu okrelenia pocztku
definicji powierzchni NURBS.
// Renderuj powierzchni NURBS //
Pocztek definicji powierzchni
gluBeginSurface(pNurb);

// Obliczenia powierzchni
gluNurbsSurface(pNurb,
8, Knots,
8, Knots,
4*3,
3.
&ctrlPoints[0][ 0 ] [ 0 ] ,
4. 4,
GL_MAP2_VERTEX_3);

// Koniec definiowania powierzchni


gluEndSurface(pNurb);

Patrz take gluEndSurface

gluBeginTrim
Przeznaczenie Rozpoczyna definicj zamknitej krzywej wycinajcej obszar
powierzchni NURBS.
Plik <glu.h>
nagwkowy void gluBeginTrim(GLUnurbsObj *nObj);
Skadnia Ta funkcja, wraz z funkcjgluEndTrim, jest uywana do okrelenia
pocztku i koca definicji krzywej wycinajcej. Krzywa wycinajca jest
krzyw zamknit lub zestawem poczonych krzywych, zdefiniowanych za
pomoc funkcji gluNurbsCurye lub gluPwlCurve. Funkcje gluBeginTrim i
gluEndTrim musz wystpowa wewntrz pary wywoa
gluBeginSurface/gluEndSurface. Gdy stosujesz wycinanie, kierunek
krzywej okrela, ktra cz powierzchni zostanie wycita. Obszar
powierzchni na lewo od krzywej (patrzc w kierunku tej krzywej)
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 561

pozostaje niewycity. Tak wic krzywe o kierunku zgodnym z ruchem


wskazwek zegara powoduj wycicie wewntrznego obszaru otoczonego
krzyw, podczas gdy krzywe o kierunku przeciwnym do ruchu wskazwek
zegara powoduj wycicie obszaru na zewntrz zamknitej krzywej.
Parametry
nObj GLUnurbsObj: Okrela obiekt NURBS.
Zwracana Brak.
warto Poniszy fragment kodu pochodzi z programu NURBT na pytce CD-
ROM i przedstawia dwie krzywe wycinania suce do wycicia
trjktnego obszaru z powierzchni stworzonej w programie NURBS.
Zewntrzna krzywa wycinania obejmuje ca powierzchni. Krzywa
wewntrzna ma w rzeczywistoci ksztat trjkta i wanie taki obszar
wycina z powierzchni.
// Renderuj powierzchni NURBS //
Pocztek definicji powierzchni
gluBeginSurface(pNurb);
// Obliczenia powierzchni
gluNurbsSurface(pNurb,
8, Knots,
8, Knots,
4 * 3,
3.
ictrlPoints[0][ 0 ] [ 0 ] ,
4. 4,
GL_MAP2_VERTEX_3);

// Obszar zewntrzny, obejmujcy ca powierzchni


gluBeginTrim (pNurb);
gluPwlCurve (pNurb, 5, soutsidePts[ 0 ] [ 0 ] ,
2, GLU_MAP1_TRIM_2);
gluEndTrim (pNurb);
// Wewntrzny trjktny obszar
gluBeginTrim (pNurb);
gluPwlCurve (pNurb, 4, iinsidePts[ 0 ] [ 0 ] ,
2, GLU_MAP1_TRIM_2);
gluEndTrim (pNurb);

// Koniec definiowania powierzchni


gluEndSurface(pNurb);
Patrz take gluEndTrim

gluDeleteNurbsRenderer
Przeznaczenie Niszczy obiekt NURBS.
Plik <glu.h>
562 Cz III Tematy zaawansowane i efekty specjalne

Skadnia void gluDeleteNurbsRenderer(GLUnurbsObj *nObj);


Opis Ta funkcja usuwa wskazany obiekt NURBS i zwalania wszelk zwizan
z nim pami.
Parametry
nObj GLUnurbsObj: Okrela obiekt NURBS przeznaczony do usunicia.
Zwracana warto Brak.
Przykad Poniszy fragment kodu pochodzi z programu NURBS na pytce CD-
ROM. Przedstawia usuwanie obiektu NURBS w momencie niszczenia
gwnego okna aplikacji. Zwr uwag, e na pocztku programu
wskanik zosta zainicjowany wartoci NULL, wic jeli nie powiodo
si jego utworzenie, nie bdzie usuwany.
// Okno jest niszczone, wic przeprowadzamy porzdki case
WM_DESTROY:
// Odoenie biecego kontekstu renderowania
// i usunicie go
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
// Usunicie obiektu NURBS, jeli zosta utworzony
if(pNurb)
gluDeleteNurbsRenderer(pNurb);
if(hPalette ! NULL)
DeleteObject(hPalette);

// Poinformowanie aplikacji o zakoczeniu dziaania


PostQuitMessage( 0 ) ;
break;

Patrz take gluNewNurbsRenderer

gluEndCurye
Przeznaczenie Plik Koczy definicj krzywej NURBS.
nagwkowy <glu.h>
Skadnia Opis void gluEndCurve(GLUnurbsObj *nObj);
Ta funkcja, wraz z funkcj gluBeginCurve, jest uywana do okrelenia
Parametry pocztku i koca definicji krzywej NURBS.
nObj
Zwracana warto GLUnurbsObj: Okrela obiekt NURBS.
Przykad Patrz Brak.
take Spjrz na przykad w opisie funkcji gluBeginCurve.
gluBeginCurve
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS7H 563

gluEndSurface
Przeznaczenie Koczy definicj powierzchni NURBS.
Plik <glu.h>
nagwkowy void gluEndSurface(GLUnurbsObj *nObj);
Skadni Ta funkcja, wraz z funkcj gluBeginSurface, jest uywana do okrelenia
a Opis pocztku i koca definicji powierzchni NURBS.

Parametry GLUnurbsObj: Okrela obiekt NURBS.


nObj Brak.
Zwracana Spjrz na przykad w opisie funkcji gluBeginSurface.
warto gluBeginSurface

gluEndfrim
Przeznaczenie Koczy definicj krzywej wycinajcej NURBS.
Pik <glu.h>
nagwkowy void gluEndTrim(GLUnurbsObj *nObj);
Skadnia Opis Ta funkcja, wraz z funkcj gluBeginTrim, jest uywana do okrelenia
pocztku i koca definicji krzywej wycinajcej NURBS. Wicej informacji
Parametry na temat krzywych wycinajcych znajdziesz w opisie funkcji
nObj gluBeginTrim.
Zwracana
warto GLUnurbsObj: Okrela obiekt NURBS.
Przykad Patrz Brak.
take Spjrz na przykad w opisie funkcji gluBeginTrim.
gluBeginTrim

gluGetNurbsProperty
Przeznaczenie Zwraca waciwo NURBS.
Plik <glu.h>
nagwkowy void gIuGetNurbsProperty(GLUnurbsObj *nObj, GLenum property,
GLloat *value);
Skadnia
Ta funkcja suy do odczytania waciwoci NURBS okrelonej dla
danego obiektu NURBS. Informacje dotyczce poszczeglnych
waciwoci znajdziesz w opisie funkcji gluNurbsProperty.
564 Cz III t Tematy zaawansowane i efekty specjalne

Parametry
nObj GLUnurbsObj: Okrela obiekt NURBS.
property GLenum: Odczytywana waciwo NURBS. Dostpne waciwoci to:
Zwracana warto GLU_SAMPLING_TOLERANCE, GLU_DISPLAY_MODE,
GLU_CULLING, GLU_AUTO_LOAD_MATRIX,
Przykad GLU_PARAMETRIC_TOLLERANCE, GLU_SAMPLING_METHOD,
GLU_U_STEP oraz GLU_V_STEP. Szczegy na temat tych parametrw
znajdziesz w opisie funkcji gluNurbsProperty.
Brak.
Poniszy przykad przedstawia sposb ustawienia waciwoci NURBS
GLU_SAMPLING_TOLERANCE na 25. W dalszej czci programu (by
moe ju w innej funkcji) wywoywana jest funkcja gluGetNurbsProperty w
celu odczytania tolerancji prbkowania.
gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 2 5 . Of};

GLfloat fTolerance;

gluGetNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE,
SfTolerance);

Patrz take gluNewNurbsRenderer, gluNurbsProperty

gluLoadSamplingMatrices
Przeznaczenie aduje macierze prbkowania i obcinania NURBS.
Plik nagwkowy <glu.h>
Skadnia void gluLoadSamplingMatrices(GLUnurbsObj *nObj, const GLfloat
modelMatrix[16], const GLfloat projMatrix[16], const GLint viewport[4]);
Ta funkcja jest uywana do ponownego przeliczenia macierzy prbkowania
Opis i obcinania dla powierzchni NURBS. Macierz prbkowania jest uywana
przy wyznaczaniu stopnia podziau powierzchni na wielokty, tak aby bya
zachowana tolerancja prbkowania. Macierz obcinania jest uywana do
wyznaczenia, czy przed renderowaniem powinny zosta wycite
niewidoczne powierzchnie. Zwykle nie trzeba wywoywa tej funkcji,
chyba e zostanie wyczona waciwo GLU_AUTO_LOAD_MATRIX.
Najczciej wycza si j przy pracy w trybach selekcji i informacji
zwrotnej.
Parametry
nObj GLUnurbsObj: Okrela obiekt NURBS.
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 565

modelMatrix GLfloat[16]: Okrela macierz widoku modelu.


projMatrix GLfloat[16]: Okrela macierz rzutowania.
viewport GLint[4]: Okrela widok.
Zwracana warto Brak.
Przykad Poniszy kod moe zosta uyty do rcznego przygotowania i
wykorzystnia macierzy prbkowania i obcinania.
GLfloat fModelView[16], fProjection[1 6 ] , fViewport[ 4 ] ;

pNurb = glNewNurbsRenderer(.

// Pobranie informacji o macierzy i widoku


glGetFloatv(GL_MODELVIEW_MATRIX, fModelView);
glGetFloatv(GL_PROJECTION_MATRIX, fProjection);
glGet!ntegerv(GL_VIEWPORT, fYiewport);

// Rczne zaadowanie macierzy


gluLoadSamplingMatrices(pNurb, fModelView, fProjection,
fViewport);
Patrz take gluNewNurbsRenderer, gluNurbsProperty

gluNewNurbsRenderer
Przeznaczenie Tworzy nowy obiekt NURBS.
Plik nagwkowy <glu.h>
Skadnia GLUnurbsObj * gluNewNurbsRenderer(void);
Ta funkcja tworzy obiekt renderowania NURBS. Ten obiekt jest
Opis
wykorzystywany do sterowania zachowaniem i charakterystykami krzywych
Zwracana warto i powierzchni NURBS. Wszystkie funkcje suce do modyfikacji
Przykad waciwoci NURBS wymagaj podania wskanika do tego obiektu. Po
zakoczeniu renderowania krzywych lub powierzchni musisz usun obiekt
NURBS wywoujc funkcj gluDeleteNurbsRenderer.
Wskanik do nowego obiektu NURBS. Ten obiekt bdzie
wykorzystywany podczas wywoywania funkcji sterujcych i
renderujcych.
Poniszy kod demonstruje tworzenie obiektu NURBS:
// Przygotowanie obiektu NURBS

// Zaczynamy od stworzenia go
pNurb = gluNewNurbsRenderer( ) ;
566 Cz III Tematy zaawansowane l efekty specjalne

// Ustawienie waciwoci NURBS


gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 25.O f ) ;
gluNurbsProperty(pNurb, GLU_DISPLAY_MODE,
(GLfloat)GLU_FILL);

.. inne waciwoci

Patrz take gluDeleteNurbsRenderer

gluNurbsCallback
Przeznaczenie Definiuje funkcj zwrotn dla NURBS.
Plik nagwkowy <glu.h>
Skadnia void gluNurbsCallback(GLUnurbsObj *nObj, GLenum which, void

Opis Ta funkcja zgasza funkcj zwrotn dla NURBS. Jedynym obsugiwanym


Parametry
zdarzeniem jest GL_ERROR. Gdy wystpi bd, wywoywana jest
zgoszona funkcja z argumentem typu GLenum, zawierajcym kod jednego
nObj which z 37 bdw, zdefiniowanych jako stae od GLU_NURBS_ERROR1 do
GLU_NURBS_ERROR37. Do odczytania acucha opisu bdu suy
funkcja gluErrorString. Kody bdw wraz z opisem zebrano w tabeli 17.1.
fn
Zwracana warto
GLUnurbsObj: Okrela obiekt NURBS.
Przykad
GLenum: Okrela zdarzenie majce powodowa wywoanie funkcji
zwrotnej. Dozwolona jest jedynie warto GLU_ERROR.
void *(): Adres zgaszanej funkcji zwrotnej. Brak.
Poniszy kod stanowi przykad procedury obsugi bdw NURBS.
Pokazany jest take kod instalujcy t procedur obsugi. Mona go
znale w przykadowym programie NURBS.
// Funkcja zwrotna bdw NURBS
void CALLBACK NurbsErrorHandler (GLenum nErrorCode)
{
char cMessage [ 6 4 ] ;
// Wydzielenie opisu bdu
strcpy (cMessage, "Wystpi bd NURBS: " ) ;
strcat (cMessage, gluErrorString (nErrorCode) ) ;
// Wywietlenie caego komunikatu Me s s
ageBox ( NULL , cMe s s ag , NULL , MB_OK | MB
ICONEKCLAMATION) ;
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 567

// Przygotowanie obiektu NURBS


pNurb = gluNewNurbsRenderer();
// Instalowanie procedury obsugi bdw NURBS
gluNurbsCallback(pNurb, GLU_ERROR,
NurbsErrorHandler);

gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE,
25. O f ) ;
. . . inne waciwoci

Patrz take gluErrorString

Tabela 17.1.
Kody bdw NURBS

Kod bdu Definicja


GLU_NURBS_ERROR1 Brak obsugi kolejnoci splajnw.
GLU_NURBS_ERROR Zbyt mao wzw.
2
GLU_NURBS_ERROR3 Poprawny zakres wzw jest pusty.
GLU_NURBS_ERROR W sekwencji wzw wystpi wze mniejszy ni poprzedni.
4GLU_NURBS_ERROR Multiplikacja wzw wiksza ni rzd splajna.
5GLU_NURBS_ERROR endcurve() musi wystpowa po bgncurve().
6GLU_NURBS_ERROR bgncurve() musi poprzedza endcurve().
7GLU_NURBS_ERROR Brak lub nadmiar danych geometrii.
8GLU_NURBS_ERROR Nie mona narysowa krzywych pwl.
9GLU_NURBS_ERROR Brak lub nadmiar danych dziedziny.
1GLU_NURBS_ERROR1
0 Brak lub nadmiar danych dziedziny.
1GLU_NURBS_ERROR endtrimO musi poprzedza endsurface().
1GLU_NURBS_ERROR1
2 bgnsurface() musi poprzedza endsurface().
3
GLU_NURBS_ERROR Jako krzyw wycinania podano krzyw niewaciwego typu.
14
GLU_NURBS_ERROR1 bgnsurface() musi poprzedza bgntrim().
5
GLU_NURBS_ERROR endtrim() musi wystpowa po bgntrim().
16
GLU_NURBS_ERROR1 bgntrim() musi poprzedza endtrim().
7
GLU_NURBS_ERROR 1 Brak lub bdna definicja krzywej wycinania.
8GLU_NURBS_ERROR bgntrim() musi poprzedza pwlcurve().
19
GLU_NURBS_ERROR Dwukrotne odwoanie do krzywej pwl.
20
GLU_NURBS_ERROR2 Wymieszane krzywe pwl i nurbs.
1
568 Cz III * Tematy zaawansowane i efekty specjalne

Tabela 17.1.
Kody bdw NURBS - cig dalszy

Kod bdu Definicja

GLU_NURBS_ERROR22 Niewaciwe uycie typu danych wycinania.


GLU_NURBS_ERROR23 Dwukrotne odwoanie do krzywej nurbs.
GLU_NURBS_ERROR24 Wymieszane krzywe nurbs i pwl.
GLU_NURBS_ERROR25 Dwukrotne odwoanie do powierzchni nurbs.
GLU_NURBS_ERROR26 Nieistniejca waciwo.
GLU_NURBS_ERROR27 endsurface() musi wystpowa po bgnsurface().
GLU_NURBS_ERROR28 Przecinajce si lub uoone w niezgodnych kierunkach krzywe
wycinania.
GLU_NURBS_ERROR29 Przecinajce si krzywe wycinania.
GLU_NURBS_ERROR30 NIEUYWANE.
GLU_NURBS_ERROR31 Niepoczone krzywe wycinania.
GLU_NURBS_ERROR32 Nieznany bd wza.
GLU_NURBS_ERROR33 Natrafiono na ujemn liczb wierzchokw.
GLU_NURBS_ERROR34 Ujemny odstp pomidzy elementami tablicy z punktami
kontrolnymi.
GLU_NURBS_ERROR35 Deskryptor nieznanego typu.
GLU_NURBS_ERROR36 Puste odwoanie do punktu kontrolnego.
GLU_NURBS_ERROR37 Zduplikowany punkt krzywej pwl.

gluNurbsCurye
Przeznaczenie Definiuje ksztat krzywej
Plik nagwkowy NURBS. <glu.h>
Skadnia void gluNurbsCurve(GLUnurbsObj *nObj, GLint nknots,
GLfloat *knots, GLint stride, GLfloat *ctlarray, GLint order,
GLenum type);
Opis
Ta funkcja suy do definiowania ksztatu krzywej NURBS.
Definicja krzywej musi wystpowa pomidzy wywoaniami
gluBeginCurve i gluEndCurve.
Parametry
nObj
GLUnurbsObj*: Wskanik do obiektu NURBS (utworzonego
w wyniku wywoania funkcji gluNewNurbsRenderer).
nknots
GLint: Ilo wzw w tablicy *knots. Odpowiada iloci
punktw kontrolnych plus rzd krzywej.
knots
GLfloat*: Tablica wartoci wzw, uoonych w kolejnoci niemalejcej.
Rozdzia 17. * Krzywe i powierzchnie: co to jest NURBS?!! 569

strlde GLint: Odstp, wyraony jako ilo wartoci zmiennoprzecinkowych


ctlArray pojedynczej precyzji (float), pomidzy kolejnymi wartociami punktw
order kontrolnych w tablicy.
type GLfloat*: Wskanik do tablicy struktur danych zawierajcych punkty
kontrolne dla powierzchni NURBS.
GLint: Rzd krzywej NURBS. Rzd jest o jeden wikszy od stopnia
krzywej.
GLenum: Typ krzywej. Moe nim by jeden z poniszych typw:
GL_MAP1_VERTEX_3, GL_MAP1_VERTEX_4, GL_MAP1_INDEX,
GL_MAP1_COLOR_4, GL_MAP1_NORMAL,
GL_MAP 1_TEXTURE_COORD_1,
GL_MAP1_TEXTURE_COORD_2,
GL_MAP1_TEXTURE_COORD_3,
GL_MAP 1_TEXTURE_COORD_4.
Zwracana warto Brak.
Przykad Patrz Spjrz na przykad przy opisie funkcji gluBeginCurve.
take gluBeginCurve, gluEndCurve, gluNurbsSurface

gluNurbsProperty
Przeznaczenie Ustawia waciwo NURBS.
Plik nagwkowy <glu.h>
Skadnia void gluNurbsProperty(GLUnurbsObj *nObj, GLenum property, GLfloat
value);
Opis Ta funkcja suy do ustawiania waciwoci obiektu NURBS. Dostpne s
nastpujce waciwoci:
GLU_SAMPLING_TOLERANCE: Okrela maksymaln dugo w
pikselach, ktra ma zosta uyta podczas stosowania metody
prbkowania GLU_PATH_LENGTH. Domylna warto to 50,0.
GLU_DISPLAYJMODE: Okrela sposb renderowania powierzchni
NURBS. Parametrem moe by GLU_FILL, powodujcy uycie
cieniowanych wieloktw, GLU_OUTLINE_POLYGON, powodujcy
rysowanie jedynie konturw wieloktw (ju po podziale powierzchni na
wielokty skadowe) oraz GLU_OUTLINE_PATCH, umoliwiajcy
rysowanie wycznie konturw zdefiniowanych przez uytkownika cieek i
krzywych wycinania. Domyln wartoci jest GLU_FILL.
GLU_CULLING: Warto parametru jest interpretowana jako warto
logiczna, okrelajca, czy krzywa NURBS ma by odrzucona, jeli jej
punkty kontrolne le poza widokiem.
GLU_PARAMETRIC_TOLERANCE: Ustawia maksymalny odstp
pikseli uywany, gdy metod prbkowania jest
570______________________Cz III Tematy zaawansowane i efekty specjalne

GLU_PARAMETRIC_ERROR. Domyln wartoci jest 0,5. Ta


waciwo pojawia si dopiero w GLU w wersji 1.1.
GLU_SAMPLING_METHOD: Okrela sposb podziau powierzchni
NURBS na wielokty. Ta waciwo pojawia si dopiero w GLU w wersji
1.1. Dostpne s ponisze waciwoci:
GLU_PATH_LENGTH okrela, e podczas renderowania
powierzchni, dugoci bokw (w pikselach) wieloktw podziau
powierzchni nie bd wiksze ni warto parametru
GLU_SAMPLING_TOLERANCE.
GLU_PARAMETRIC_ERROR okrela, e powierzchnia bdzie
renderowana przy uyciu parametru
GLU_PARAMETRIC_TOLERANCE, wyznaczaj cego maksymalny
dystans, w pikselach, pomidzy wieloktami podziau a przyblianymi
przez nie powierzchniami.
GLU_DOMAIN_DISTANCE okrela, we wsprzdnych
parametrycznych, jak wiele punktw prbkowania na jednostk
dugoci wystpuje w kierunkach u i v. Domyln wartoci jest
GLU_PATH_LENGTH.
GLU_U_STEP: Ustala ilo punktw prbkowania na jednostk dugoci w
kierunku u, we wsprzdnych parametrycznych. Ta warto jest uywana,
gdy metod prbkowania jest GLU_DOMAIN_DISTANCE. Domylna
warto tego parametru to 100. Ta waciwo pojawia si dopiero w GLU w
wersji 1.1.
GLU_V_STEP: Ustala ilo punktw prbkowania na jednostk dugoci w
kierunku v, we wsprzdnych parametrycznych. Ta warto jest uywana,
gdy metod prbkowania jest GLU_DOMAIN_DISTANCE. Domylna
warto tego parametru 100. Ta waciwo pojawia si dopiero w GLU w
wersji 1.1.
GLU_AUTO_LOAD_MATRIX: Warto parametru jest interpretowana jako
warto logiczna. Gdy zostanie ustawiona na GLJTRUE, powoduje, e kod
NURBS aduje z serwera OpenGL macierz widoku modelu, macierz
rzutowania oraz widok w celu obliczenia macierzy prbkowania i obcinania
dla kadej krzywej NURBS. Macierze prbkowania i obcinania s potrzebne
do wyznaczenia podziau powierzchni NURBS na segmenty linii oraz
wielokty, jak rwnie do obcicia tych fragmentw powierzchni NURBS,
ktre le poza widokiem. Jeli parametr zostanie ustawiony na warto
GL_FALSE, uytkownik powinien sam dostarczy macierze i widok dla
renderera NURBS w celu uycia ich do obliczenia macierzy prbkowania i
obcinania. Mona to osign uywajc funkcji gluLoadSamplingMatrices.
Domyln wartoci parametru jest GL_TRUE. Sama zmiana tego parametru
nie wpywa na prbkowanie i obcinanie powierzchni, chyba e zostanie
wywoana funkcja gluLoadSamplingMatrices.
Rozdzia 17. Krzywe i powierzchnie: co to jest NURBS?!! 571

Parametry
nObj GLUnurbsObj*: Wskanik do obiektu NURBS (utworzonego w wyniku
wywoania funkcji gluNewNurbsRenderer), ktrego waciwoci maj
zosta zmodyfikowane.
property GLenum: Modyfikowana lub ustawiana waciwo NURBS. Moe ni
by jedna z poniszych waciwoci:
value
GLU_SAMPLING_TOLERANCE, GLU_DISPLAY_MODE,
Zwracana GLU_CULLING, GLU_AUTO_LOAD_MATRIX,
warto GLU_PARAMETRIC_TOLERANCE, GLU_SAMPLING_METHOD,
GLU_U_STEP oraz GLU_V_STEP.
Przykad
GLfloat: Warto przypisywana ustawianej waciwoci.
Patrz take
Brak.
Poniszy kod z programu NURBS przygotowuje tryb wywietlania
powierzchni jako siatki krawdzi:
gluNurbsProperty (pNurb, GLU_DISPLAY_MODE,
GLU_OUTLINE_POLYGON) ;

gluGetNurbsProperry, gluGetString, gluLoadSamplingMatrices,


gluNewNurbsRenderer

gluNurbsSurface
Przeznaczenie Definiuje ksztat powierzchni NURBS.
Plik <glu.h>
nagwkowy void gluNurbsSurface(GLUnurbsObj *nObj, GLint uknotCount, GLfloat
*uknot, GLint vknotCount, GLfloat *vknot, GLint ustride, GLint vstride,
Skadnia GLfloat *ctlarray, GLint uorder, GLint vorder, GLenum type);
Ta funkcja suy do definiowania ksztatu powierzchni NURBS. Definicja
powierzchni musi wystpowa pomidzy wywoaniami gluBeginSurface i
gluEndSurface. Ksztat powierzchni jest obliczany przed jakimkolwiek
wycinaniem. Powierzchnia NURBS moe zosta wycita przez uycie
funkcji gluBeginTrim/gluEndTrim w poczeniu z funkcjami gluNurbsCurve
i/lub gluPwlCurve.
Parametry
nObj GLUnurbsObj*: Wskanik do obiektu NURBS (utworzonego w wyniku
wywoania funkcji gluNewNurbsRenderer).
uknotCount GLint: Ilo wzw w parametrycznym kierunku u.
u knot GLfloat*: Tablica wartoci wzw, reprezentujcych wzy w kierunku u.
Wartoci w tablicy musz by uoone w kierunku niemalejcym.
Rozmiar tablicy jest okrelony parametrem uknotCount.
572 Cz III * Tematy zaawansowane i efekty specjalne

vknotCount GLint: Ilo wzw w parametrycznym kierunku v.


vknot GLfloat*: Tablica wartoci wzw, reprezentujcych wzy w kierunku v.
Wartoci w tablicy musz by uoone w kierunku niemalejcym. Rozmiar
tablicy jest okrelony parametrem vknotCount.
uStride GLint: Odstp, wyraony jako ilo wartoci zmiennoprzecinkowych
pojedynczej precyzji (float), pomidzy kolejnymi wartociami punktw
kontrolnych kierunku u w tablicy.
vStride GLint: Odstp, wyraony jako ilo wartoci zmiennoprzecinkowych
pojedynczej precyzji (float), pomidzy kolejnymi wartociami punktw
kontrolnych kierunku v w tablicy.
ctlArray GLfloat*: Wskanik do tablicy struktur danych zawierajcych punkty
kontrolne dla powierzchni NURBS. Odstpy pomidzy poszczeglnymi
punktami kontrolnymi dla kierunkw u i v s przekazywane jako parametry
uStride i vStride.
uorder GLint: Rzd krzywej NURBS w kierunku u. Rzd jest o jeden wikszy od
stopnia, wic powierzchnia kubiczna w kierunku u posiada u stopnia
czwartego.
vorder GLint: Rzd krzywej NURBS w kierunku v. Rzd jest o jeden wikszy od
stopnia, wic powierzchnia kubiczna w kierunku v posiada v stopnia
czwartego.
type GLenum: Typ powierzchni. Moe nim by jeden z poniszych typw:
GL_MAP2_VERTEX_3, GL_MAP2_VERTEX_4, GL_MAP2_INDEX,
GL_MAP2_COLOR_4, GL_MAP2_NORMAL,
GL_MAP2_TEXTURE_COORD_1, GL_MAP2_TEXTURE_COORD_2,
GL_MAP2_TEXTURE_COORD_3, GL_MAP2_TEXTURE_COORD_4.
Brak.
Spjrz na przykad przy opisie funkcji gluBeginSurface.
Zwracana warto
gluBeginSurface, gluBeginTrim, gluNewNurbsRenderer, gluNurbsCurve,
Przykad Patrz gluPwlCurve
take

gluPwICurye
Przeznaczenie Okrela zoon z kawakw krzyw wycinania NURBS.
Plik nagwkowy <glu.h>
Skadnia void gluPwICurye (GLUnurbsObj *nObj, GLint count, GLfloat *array,
GLint stride, GLenum type);
Opis Ta funkcja definiuje zoon z kawakw krzyw wycinania dla
powierzchni NURBS. Punkty w tablicy s okrelone w parametrycznych
Rozdzia 17. * Krzywe i powierzchnie: co to jest NURBS?!! 573

wsprzdnych w przestrzeni u i v. Ta przestrze stanowi jednostkowy


kwadrat, o boku rwnym dokadnie jednej jednostce. Krzywe wycinania
tworzone w kierunku zgodnym z ruchem wskazwek zegara powoduj
wycicie otaczanego obszaru; krzywe tworzone w kierunku przeciwnym do
ruchu wskazwek zegara powoduj wycicie regionu zewntrznego. Zwykle
region obcinania definiuje si przez zdefiniowanie krzywej obcinania
obejmujcej ca powierzchni i wycinajcej wszystko poza ni. Nastpnie
tworzy si mniejsze krzywe, uoone zgodnie z ruchem wskazwek zegara,
wycinajce otwory w powierzchni. Krzywe wycinania mog by zoone z
kawakw krzywych. To oznacza, e funkcj gluPwlCurve lub
gluNurbsCurve mona wywoywa wicej razy, w celu zdefiniowania
regionu wycinania o dowolnym ksztacie, pod warunkiem, e krzywa
wycinania zostanie domknita i obejmie zamknity region w przestrzeni u/v.
GLUnurbsObj*: Wskanik do obiektu NURBS (utworzonego w wyniku wywoania
Parametry funkcji gluNewNurbsRenderer).
nObj GLint: Okrela ilo punktw krzywej przekazywanych w tablicy *array. GLfloat*:
Tablica punktw granicznych krzywej.
count
GLint: Odstp (w wartociach typu float) pomidzy punktami krzywej w tablicy.
array
GLenum: Okrela typ krzywej. Moe nim by GLU_MAP1_TRIM_2, uywany, gdy
stride krzywa wycinania jest wyraona we wsprzdnych u i v; lub GLU_MAP1_TRIM_3,
uywany, gdy do okrelenia krzywej wycinania stosuje si dodatkow wsprzdn w
type (skalowania).
Zwracana warto Brak.
Przykad Poniszy przykad z programu NURBT przedstawia powierzchni
NURBS wycinan przez obszar opisany krzyw w ksztacie trjkta. Caa
powierzchnia ujta jest w du krzyw wycinania, obcinajc cay obszar
poza powierzchni. Drugi, mniejszy obszar wycinania to wanie trjktny
otwr wycity w powierzchni.
// Zewntrzne punkty wycinania, obejmujce ca powierzchni GLfloat
outsidePts[ 5 ] [ 2 ] = /* przeciwnie do ruchu wskazwek */ { { O . O f ,
O . O f ), {l.Of, O . O f } , {l.Of, l . O f } , {O.Of, l . O f } , (O.Of,
O.Of}};
// Wewntrzne punkty wycinania, tworzce trjktny otwr w powierzchni
GLfloat insidePts[ 4 ] [ 2 ] = /* zgodnie z ruchem wskazwek */ {(0.25f,
0.25f}, {0.5f, 0 . 5 f } , {0.75f, 0.25f}, { 0.25f, 0 . 2 5 f } } ;

// Renderuj powierzchni NURBS //


Pocztek definicji powierzchni
gluBeginSurface(pNurb);
574______________________Cz III Tematy zaawansowane i efekty specjalne

// Obliczenia powierzchni
gluNurbsSurface(pNurb, // Wskanik do renderera NURBS
8, Knots, // Ilo wzw i tablica wzw w kierunku u.
8, Knots, // Ilo wzw i tablica wzw w kierunku v.
4 * 3 , // Odstp pomidzy punktami kontrolnymi
// kierunku u.
3. // Odstp pomidzy punktami kontrolnymi
// kierunku v.
&ctrlPoints[0][ 0 ] [ 0 ] , // Punkty kontrolne
4. 4, // klasa powierzchni u i v
GL_MAP2_VERTEX_3); // Rodzaj powierzchni
// Obszar zewntrzny, obejmujcy ca powierzchni
gluBeginTrim (pNurb);
gluPwlCurve (pNurb, 5, SoutsidePts[ 0 ] [ 0 ] , 2, GLU_MAP1_TRIM_2);
gluEndTrim (pNurb);

// Wewntrzny trjktny obszar


gluBeginTrim (pNurb);
gluPwlCurve (pNurb, 4, SinsidePts[ 0 ] [ 0 ] , 2, GLU_MAP1_TRIM_2);
gluEndTrim (pNurb);

// Koniec definiowania powierzchni


gluEndSurface(pNurb);

Patrz take gluBeginTrim, gluEndTrim, gluNurbsCurve


Rozdzia 18.
Podzia wieloktw
W tym rozdziale:

Dowiesz si, jak...______________________Uywane funkcje_______


4 Uy biblioteki GLU do rysowania skomplikowanych * gluBegin/gluEnd
wieloktw
* Uy biblioteki GLU do rysowania skomplikowanych * gluNextContour
powierzchni

Biblioteka OpenGL Utility (glu32.1ib) zawiera stabilny i wydajny interfejs podziau


wieloktw, dziki ktremu mona atwo renderowa zoone wielokty i powierz-
chnie. Podzia wieloktw polega na tworzeniu dowolnego wielokta z mniejszych, naj-
czciej trjktnych fragmentw, podobnie jak przy tworzeniu mozaiki.

Z trjktw skadany jest dowolny podany ksztat, za procedura podziau wieloktw


jest przygotowana take do tworzenia rzadko spotykanych ksztatw, na przykad
zawierajcych otwory.

Zoone wielokty
Co sprawia, e wielokt staje si zoony? C, w OpenGL zoony wielokt to taki,
ktry albo nie jest wypuky (posiada wcicia), albo posiada otwory. Na rysunku 18.1
przedstawiono kilka prostych oraz kilka zoonych wieloktw, ktre od czasu do czasu
zdarzy ci si renderowa.

Za pomoc prymitywu GL_POLYGON mona tworzy jedynie proste, wypuke wielokty.


Wielokt jest wypuky wtedy, gdy adna z poprowadzonych przez niego linii nie
przecina jego krawdzi wicej ni dwukrotnie. Tak wic, jeli jakakolwiek linia prze-
prowadzona przez wielokt przechodzi przez pust przestrze poza wieloktem, taki
wielokt jest wklsy lub zoony.
S76______________________Cz III Tematy zaawansowane i efekty specjalne

Rysunek 18.1. Wielokty proste Wielokty zoone


Wielokty proste
i zoone

Wklse wielokty to wielokty niewypuke, ktre nie posiadaj otworw w swoim


wntrzu. Wieloktem wklsym jest wielokt w prawym grnym rogu rysunku 18.1, nie jest
wklsy natomiast wielokt z prawego dolnego rogu, gdy zawiera w sobie otwr.

Wielokty zoone posiadaj otwory lub zakrzywienia. Prawy dolny wielokt z rysunku
18.1 jest wanie wieloktem zoonym.

Rysowanie wieloktw wklsych


Rysowanie wklsych wieloktw za pomoc biblioteki glu nie jest trudne. Pierwsza
rzecz, jak musimy zrobi, to stworzenie obiektu triangulatora:
GLUtriangulatorobj *tess;
tess = gluNewTess();

Struktura GLUtriangulatorobj zawiera informacje o stanie, uywane przez triangulatora


przy renderowaniu wielokta.

Nastpnie moemy wywoa sekwencj instrukcji gluBeginPolygon, gluTessVertex


oraz gluEndPolygon w celu wyrenderowania wielokta:
GLdouble vertices[100] [ 3 ] ;
gluBeginPolygon(tess) ;
gluTessVertes( t e s s , vertices[0], NULL);
gluTessVertes(tess, v e r t i c e s [ l ] , N U L L ) ;
gluTessVertes(tess, vertices[ 9 9 ] , N U L L ) ;
gluEndPolygon( t e s s ) ;

Po wywoaniu funkcji gluEndPolygon, triangulator przystpuje do pracy i tworzy seri


trjktw, paskw oraz wachlarzy trjktw. Poniewa ten proces moe trwa do dugo,
dobrym pomysem jest umieszczenie podzielonych wieloktw na licie wywietlania w
celu poprawy wydajnoci wywietlania (patrz rozdzia 10).
Rozdzia 18. Podzia wieloktw 577

Rysowanie wieloktw zoonych


Rysowanie wieloktw zoonych jest nieco bardziej skomplikowane ni rysowanie
wieloktw wklsych, jednak nie jest tak trudne, jak mogoby si wydawa. Wielokty
zoone mog zawiera otwory i wykrzywienia powierzchni, w zwizku z czym mamy do
dyspozycji funkcj gluNextContour, suc do okrelania rodzaju definiowanej
cieki wierzchokw.

Typy cieek wybierane funkcj gluNextContour zostay zebrane w tabeli 18.1.

Tabela 18.1.
Typy cieek funkcji glhNextContour

Typ cieki Opis


GLU_EXTERIOR cieka wyznacza zewntrzne krawdzie wielokta. cieka wyznacza
GLUJNTERIOR wewntrzne krawdzie wielokta. Nie wiesz, co wyznacza cieka;
GLU_UNKNOWN biblioteka sprbuje sama to wykry.
GLU_CCW To powinno by uywane tylko raz, w celu wskazania, e cieki przeciwne do
ruchu wskazwek zegara s ciekami zewntrznymi, za cieki zgodne z
ruchem wskazwek zegara s ciekami wewntrznymi.
GLU CW To powinno by uywane tylko raz, w celu wskazania, e cieki przeciwne do
ruchu wskazwek zegara s ciekami wewntrznymi, za cieki zgodne z
ruchem wskazwek zegara s ciekami zewntrznymi.

W przykadzie pokazanym na rysunku 18.2 definiujemy zewntrzn ciek dla konturu


litery, za ciek wewntrzn dla trjktnego otworu w jej rodku (rysunek 18.3).

Rysunek 18.2.
Litera A jako
\vielokat zoony
578 Cz III Tematy zaawansowane i efekty specjalne

Rysunek 18.3. cieka zewntrzna


cieki wierzchokw ~ dsika wewntrzna
dla litery A

Aby narysowa liter A, funkcj gluNextContour wywoujemy tylko raz, przed okreleniem
wewntrznych punktw. Przykad z listingu 18.1, LETTER.C, do rysowania wirujcej litery
A uywa poniszego kodu:
tess = gluNewTess();
gluTessCallback(tess, GLU_BEGIN, glBegin);
gluTessCallbackttess, GLU_VERTEX, glVertex3dv);
gluTessCallback(tess, GLU_END, glEnd);
gluBeginPolygon(tess),
gluTessVertex(tess, outside[ 0 ] , outside[ 0 ] )
gluTessVertex(tess, outside[ 1 ] , outside[ 1 ]
gluTessVertex(tess, outside[ 2 ] , )
gluTessVertex(tess, outside[ 3 ] , outside[ 2 ] )
gluTessVertex(tess, outside[ 4 ] , outside[ 3 ] )
gluTessVertex(tess, outside[ 5 ] , outside[ 4 ]
gluTessVertex(tess, outside[ 6 ] )
, outside[ 5 ] )
gluNextContour(tess, GLU_INTERIOR) ;
gluTessVertex(tess, inside[0], inside[0]>;
gluTessVertex (tess, inside[l], inside[l]);
gluTessVertex (tess, inside[2], inside[2]);
gluEndPolygon(tess) ; gluDeleteTess (tess) ;

Listing 18.1. LETTER.C: Podzia wielokta w celu utworzenia litery A _______


/*
* "letter.c" - Testowy program demonstrujcy uycie
* triangulatora z biblioteki GLO.
*/
include <GL/glaux.h>

Te definicje zostay wprowadzone w celu zapewnienia zgodnoci


pomidzy MS Windows a reszt wiata.
CALLBACK i APIENTRY to modyfikatory funkcji w MS Windows.

#ifndef WIN32
# define CALLBACK
# define APIENTRY
endif /* IWIN32 */
GLfloat rotation = 0 . 0 ;

'reshape_scene()' - Zmiana rozmiaru s c e n y . . .


Rozdzia 18. Podzia wieloktw _________________________________ 579

void CALLBACK
reshape_scene (GLsizei width, /* We - Szeroko okna w pikselach */
GLsizei height) /* We - Wysoko okna w pikselach */ { /*
* Wyzerowanie biecego widoku i przeksztacenia perspektywicznego.
*/
glviewport ( O , O, width, height);
glMatrixMode (GL_PROJECTION) ;
glLoadldentity ( ) ;
gluPerspective(22.5, (float) width / (float)height, 0 . 1 , 1000.0);
glMatrixMode (GL_MODELVIEW) ;

/*
* ' draw_scene ( ) ' - Rysuje scen zawierajca, liter "A"
*/
V0id CALLBACK
draw_scene (void)
{
GLUtriangulatorObj *tess;
static GLdouble outside [ 7 ] [ 3 ] =
{
{ 0 . 0 , 1 . 0 , 0.0 },
{ -0.5, -1.0, 0.0 },
{ -0.4, -1.0, 0.0 },
{ -0.2, -0.1, 0.0 },
{ 0 . 2 , -0.1, 0.0 },
{ 0 . 4 , -1.0, 0.0 ),
{ 0 . 5 , -1.0,
0.0 } >;
static GLdouble i n s i d e [ 3 ] [ 3 ] -{
{ 0 . 0 , 0 . 6 , 0.0 },
{ -0.1, 0.1, 0.0 },
{ 0 . 1 , 0.1, 0.0
} };
static float red_light[4] = { 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 };
static float red_pos[4] = { 1 . 0 , 0 . 0 , 0 . 0 , 0 . 0 }; static
float blue_light [ 4 ] = { 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 }; static
float blue_pos[4] - { - 1 . 0 , 0 . 0 , 0 . 0 , 0 . 0 } ;

/*
* Wczenie buforw i owietlenia
*/
glEnable (GL_DEPTH_TEST) ;
glDisable (GL_LIGHTING) ;
glEnable (GL_LIGHTO) ; glEnable
(GL_LIGHT1) ;
glShadeModel (GL SMOOTH) ;
580 Cz III Tematy zaawansowane i efekty
specjalne

Wyczyszczenie bufora koloru i gbokoci.

glClearColor( 0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

W scenie umiecilimy dwa wiata. Pierwsze z nich jest czerwone i


zostao umieszczone u gry z prawej strony, za obserwatorem. Drugie
jest niebieskie i znajduje si u dou po lewej stronie, przed
obserwatorem.

glLightfv(GL_LIGHTO, GL_DIFFUSE, red_light);


glLightfv(GL_LIGHTO, GL_POSITION, red_pos);

glLightfv(GL_LIGHTl, GL_DIFFUSE, blue_light);


glLightfv(GL_LIGHTl, GL_POSITION, blue_pos);

glEnable(GL_COLOR_MATERIAL) ; .

glPushMatrix();
glTranslatef( 0 . 0 , 0 . 0 , -1 5 . 0);
glRotatef(-rotation, 0 . 0 , 1 . 0 , 0 . 0 ) ;
glColor3f( 0 . 0 , 1 . 0, 0 . 0 ) ;
glNormal3f( 0 . 0 , 0 . 0 , 1 . 0 ) ;
tess = gluNewTess ();
gluTessCallback(tess, GLU_BEGIN, glBegin);
gluTessCallback(tess, GLU_VERTEX, glVertex3dv),
gluTessCallback(tess, GLU_END, glEnd);
gluBeginPolygon(tess)
gluTessVertex(tess, outside[ 0 ] , outside[ 0 ]
gluTessVertex( t e s s, outside[ 1 ] , )
gluTessVertex(tess, outside[ 2 ] , outside[ 1 ]
gluTessVertex(tess, outside[ 3 ] , )
gluTessVertex (tess, outside[ 4 ] , outside[ 2 ]
gluTessVertex(tess, outside[ 5 ] , )
gluTessVertex(tess, outside[ 6 ] outside[ 3 ]
, ) outside
gluNextContour(tess, GLU_INTERIOR);
gluTessVertex( t e s s ,
gluTessVertex(tess inside[0],
gluTessVertex(tess inside[0]);
gluEndPolygon( t e s s ) ; inside[l], i n s i d e f l ] ) ;
gluDeleteTess(tess) ; inside[2], i n s i d e [ 2 ] ) ;

glPopMatrix();
auxSwapBuffers();

1
rotate_objects()' - W wolnych chwilach obrt s c e n y . . .
Rozdzia 18. Podzia wieloktw ________________________________ 581

V0id CALLBACK
rotate_objects (void)
{
rotation +=> 2 . 0 ; if
(rotation >= 3 6 0 . 0 )
rotation -= 3 6 0 . 0 ;
draw scen ( ) ;

/*
* 'mainO' - Inicjowanie okna i wywietlanie sceny do momentu
* wcinicia klawisza 'Esc'.
V
void
main (void)
{
aux!nitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH) ;
auxlnitwindow("wielokt w ksztacie litery - G L U " ) ;

auxReshapeFunc (reshape_scene) ;
auxIdleFunc (rotate_objects) ;
auxMainLoop (draw_scene) ;

/*
* Koniec pliku " l e t t e r . c " .
*/

Funkcje zwrotne
Biblioteka glu definiuje kilka funkcji zwrotnych, ktre mog zosta wykorzystane do
osignicia pewnych efektw specjalnych. Funkcja gluTessCallback umoliwia zmian
tych funkcji na wasne. Wymaga podania trzech argumentw:
void gluTessCallback(GLUtriangulatorObj *tobj, GLenum which, void ( * f n ) ( ) ) ;

Argument which okrela definiowan funkcj zwrotn i musi by jedn z wartoci ze-
branych w tabeli 18.2.

Tabela 18.2.
Funkcje zwrotne triangulatora

Argument which Opis


GLU_BEGIN Funkcja jest wywoywana w momencie rozpoczcia budowania prymitywu
GLJTRIANGLES, GL_TRIANGLE_STRIP lub GL_TRIANGLE_FAN.
Funkcja musi przyjmowa pojedynczy parametr GLenum okrelajcy
tworzony prymityw, i zwykle jest wywoywana w momencie wywoania
funkcji glBegin.
582______________________Cz III Tematy zaawansowane i efekty specjalne

Tabela 18.2.
Funkcje zwrotne triangulatora - cig dalszy

Argument whlch Opis


GLU_EDGE_FLAG Funkcja jest wywoywana przy kadym wierzchoku
wielokta i musi
przyjmowa pojedynczy argument typu GLboolean,
okrelajcy, czy
wierzchoek jest wierzchokiem oryginalnym (GLJTRUE)
czy
wygenerowanym w celu podziau (GL_FALSE).
GLU_VERTEX Funkcja jest wywoywana przed kadym wysaniem kolejnego
wierzchoka
funkcj glVertex3dv. Funkcja otrzymuje kopi trzeciego
argumentu funkcji
gluTessVertex.
GLU_END Funkcja jest wywoywana na zakoczenie rysowania prymitywu,
zwykle
funkcj glEnd. Nie posiada argumentw.
GLU_ERROR Funkcja jest wywoywana w momencie wystpienia bdu. Musi
przyjmowa
pojedynczy argument typu GLenum.

Zwykle bdziesz uywa gwnie funkcji zwrotnych GLU_BEGIN, GLU_END,


GLU_VERTEX oraz GLU_ERROR. Funkcje zwrotne GLU_BEGIN, GLU_END oraz
GLU_VERTEX s wywoywane w momencie wywoania, odpowiednio, funkcji glBegin,
glEnd oraz glVertex3dv. Prosta funkcja wywietlajca bdy zgoszone przez triangulatora
zostaa przedstawiona na listingu 18.2.

Listing 18.2. Prosta procedura obsugi bdw triangulatora__________________________

void
tess_error_callback(GLenum error)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(NULL, gluErrorString(error), "Bd GLU", MB_OK |
MB_ICONEXCLAMATION);

Podsumowanie
Triangulator wieloktw w OpenGL moe zosta uyty w celu renderowania rnoro-
dnych zoonych wieloktw, ktrych nie da si narysowa przy uyciu prymitywu
OpenGL GL_POLYGON. Podzia wieloktw ma jednak swj cen, dobrze jest wic
umieszcza podzielone wielokty na listach wywietlania, w celu poprawy wydajnoci
rysowania.

Mechanizm zwrotny daje pewn kontrol nad wygenerowanymi wynikami, nie wpywa
jednak na uywany algorytm podziau. Z tego powodu funkcje zwrotne s uywane
do rzadko.
Rozdzia 18. Podzia wieloktw_________________________________583

Podrcznik
gluBeginPolygon_____________________
Przeznaczenie Rozpoczyna podzia zoonego wielokta.
Plik nagwkowy <glu.h>
Skadnia void gluBeginPoIygon(GLUtrianguIatorObj *tObj);
Opis Ta funkcja rozpoczyna podzia zoonego wielokta.
Parametry
tObj GLUtriangulatorObj*: Wskanik do obiektu triangulatora, uywanego
przy podziale wielokta.
Zwracana warto Brak.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluEndPolygon, gluNextContour, gluTessVertex

gluDeleteTess_______________________
Przeznaczenie Usuwa obiekt triangulatora.
Plik nagwkowy <glu.h>
Skadnia void gluDeleteTess(GLUtriangulatorObj *tObj);
Opis Funkcja gluDeleteTess zwalnia pami zwizan z obiektem
triangulatora.
Parametry
tObj GLUtriangulatorObj*: Wskanik do obiektu triangulatora
przeznaczonego do usunicia.
Zwracana warto Brak.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluNewTess

gluEndPolygon
Przeznaczenie Koczy podzia zoonego wielokta i renderuje go.
Plik nagwkowy <glu.h>
Skadnia void gluEndPolygon(GLUtriangulatorObj *tObj);
584______________________Cz III Tematy zaawansowane i efekty specjalne

Opis Ta funkcja koczy podzia zoonego wielokta i renderuje go.


Parametry
tObj GLUtriangulatorObj*: Wskanik do obiektu triangulatora, uywanego
przy podziale wielokta.
Zwracana wartoBrak.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluBeginPolygon, gluNextContour, gluTessVertex

gluNewTess________________________
Przeznaczenie Tworzy obiekt triangulatora.
Plik nagwkowy <glu.h>
Skadnia GLUtriangulatorObj *gluNewTess(void);
Opis Funkcja gluDeleteTess tworzy obiekt triangulatora.
Parametry Brak.
Zwracana warto GLUtriangulatorObj *: Nowy obiekt triangulatora.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluDeleteTess

gluNextContour______________________
Przeznaczenie Rozpoczyna nowy kontur lub otwr w zoonym wielokcie.
Plik nagwkowy <glu.h>
Skadnia void gluNextContour(GLUtriangulatorObj *tObj, GLenum type);
Opis Ta funkcja rozpoczyna nowy kontur lub otwr w zoonym wielokcie.
Parametry
tObj GLUtriangulatorObj*: Wskanik do obiektu triangulatora, uywanego
przy podziale wielokta.
type GLenum: Typ konturu. Dostpne typy zostay zebrane w tabeli 18.1
w treci rozdziau.
Zwracana wartoBrak.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluBeginPolygon, gluEndPolygon, gluTessVertex
Rozdzia 18. * Podzia wieloktw 585

gluTessCallback
Przeznaczenie Okrela funkcj zwrotn podziau wielokta.
Plik nagwkowy <glu.h>
Skadnia void gluTessCallback(GLUtriangulatorObj *tObj, GLenum which, void
(*fn)0);
Opis Ta funkcja okrela funkcje zwrotne podziau wielokta, wywoywane na
rnych etapach podziau. Funkcje zwrotne nie wpywaj na sposb
dziaania triangulatora ani na jego wydajno. Umoliwiaj raczej
uzupenienie generowanych wierzchokw o dodatkowe informacje, takie jak
kolor czy wsprzdne tekstury.
Parametry
tObj GLUtriangulatorObj*: Wskanik do obiektu triangulatora, uywanego
przy podziale wielokta.
which GLenum: Definiowana funkcja zwrotna. Dostpne funkcje zwrotne
zostay zebrane w tabeli 18.2 w treci rozdziau.

fn Zwracana void (*)(): Wywoywana funkcja.


warto Brak.

gluTessVertex
Przeznaczenie Dodaje wierzchoek do biecej cieki
wielokta.
Skadnia
Plik nagwkowy <glu.h>
void gluTessVertex(GLUtriangulatorObj *tObj, GLdouble v[3], void *data);
Opis
Ta funkcja dodaje wierzchoek do biecej cieki podziau wielokta. Argument
data jest przekazywany w funkcji zwrotnej GL_VERTEX.
Parametry GLUtriangulatorObj*: Wskanik do obiektu triangulatora, uywanego przy podziale
tObj wielokta.
GLdouble[3]: Wierzchoek 3D.
v data void *: Wskanik do danych, ktre maj zosta przekazane w funkcji zwrotnej
GL_VERTEX.
Zwracana warto Brak.
Przykad Przykadowy program LETTER.C na pytce CD-ROM.
Patrz take gluBeginPolygon, gluEndPolygon, gluNextContour
Rozdzia 19.
Grafika interaktywna
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje


* Przypisywa nazwy selekcji OpenGL * gllnitNames/glPushName/glPopName
prymitywom lub grupom prymityww
* Uywa selekcji do wyznaczenia * glSelectBuffer/glRenderMode
obiektw wskazywanych myszk
* Korzysta ze sprzenia zwrotnego * glFeedbackBuffer/gluPickMatrix
w celu otrzymania informacji
o narysowanych obiektach

Dotychczas uczye si tworzy za pomoc OpenGL wymyln grafik w aplikacjach,


ktre nie robiy nic poza generowaniem scen. Jednak wiele aplikacji graficznych (g-
wnie gier) wymaga wikszej interakcji ze scen. Oprcz menu i okien dialogowych,
musisz zapewni jaki sposb komunikowania si uytkownika z obiektami w scenie. W
systemie Windows zwykle odbywa si to za pomoc myszki.
Selekcja, bardzo uyteczny element OpenGL, umoliwia kliknicie myszk w pewne
miejsce okna i wyznaczenie obiektu, w obrbie ktrego nastpio to kliknicie. Fakt
selekcji konkretnego obiektu sceny jest nazywany wybraniem. Przy uyciu mechanizmu
selekcji OpenGL moesz okreli bry widzenia i wyznaczy, ktre obiekty si w niej
znajduj. Wydajna funkcja narzdziowa tworzy specjaln matryc, opart wycznie na
wsprzdnych ekranu i rozmiarach w pikselach; za pomoc tej matrycy mona stworzy
ma bry widzenia w miejscu kursora myszy. Nastpnie moesz uy selekcji do
sprawdzenia, jakie obiekty nale do tej bryy widzenia.
Sprzenie zwrotne pozwala na uzyskanie od OpenGL informacji o tym, w jaki sposb
wierzchoki s przeksztacane i owietlane, przed narysowaniem ich w buforze ramki.
Moesz uy tych informacji do przesyania rezultatw renderowania przez sie, ryso-
wania sceny za pomoc plotera czy te czenia obiektw OpenGL z grafik GDI.
Sprzenie zwrotne nie suy tym samym celom co selekcja, lecz sam tryb dziaania jest
588_______________________Cz III Tematy zaawansowane i efekty specjalne

bardzo podobny, co umoliwia wspprac obu mechanizmw. W dalszej czci rozdziau


znajdziesz przykad ilustrujcy takie wspdziaanie.

Selekcja
Selekcja jest w rzeczywistoci trybem renderowania, w ktrym adne piksele nie s ko-
piowane do bufora ramki. Zamiast tego prymitywy s rysowane w bryle widzenia (tak jak
normalnie pojawiyby si w buforze ramki) w wyniku czego tworz rekordy trafie" w
buforze selekcji.

Bufor selekcji naley przygotowa wczeniej, a take nazwa prymitywy lub grupy pry-
mityww (twoich obiektw) tak, aby mona je byo zidentyfikowa w buforze selekcji.
Nastpnie przetwarza si bufor selekcji w celu wyznaczenia, ktre obiekty przecinaj
bry widzenia. Ma to marginalne znaczenie dopty, dopki nie zmodyfikujesz bryy
widzenia przed przejciem do rysowania, w celu wyznaczenia, ktre obiekty znajduj si
w okrelonym obszarze sceny. W popularnym rozwizaniu okrela si bry widzenia
odpowiadajc wskanikowi myszy, a nastpnie sprawdza, ktry z nazwanych obiektw
jest wskazywany przez mysz (zawarty w tej bryle widzenia).

Nazywanie prymityww
Moesz nada nazw kademu prymitywowi skadajcemu si na scen, lecz rzadko jest to
uyteczne. O wiele czciej bdziesz nadawa nazwy grupom prymityww, czyli
obiektom lub czciom obiektw w scenie. Nazwy obiektw, podobnie jak nazwy list
wywietlania, nie s niczym innym jak cyfrowymi identyfikatorami w postaci liczb ca-
kowitych bez znaku.

Lista nazw jest przechowywana na stosie nazw. Po zainicjowaniu stosu nazw moesz
odkada nazwy na stos lub zastpowa nazw wystpujc na szczycie stosu. Gdy podczas
selekcji nastpi trafienie, wszystkie nazwy ze stosu nazw s kopiowane do bufora selekcji.
Tak wic pojedyncze trafienie moe zwrci wicej ni jedn nazw.

W naszym pierwszym przykadzie postaramy si zachowa maksymaln prostot.


Utworzymy uproszczony (i nie w skali) model czci ukadu planetarnego. Gdy uytko-
wnik kliknie lewym przyciskiem myszy, wywietlimy komunikat opisujcy planet, na
ktrej nastpio kliknicie. Listing 19.1 przedstawia fragment kodu renderowania z tego
przykadowego programu, PLANETS.C. Na pocztku kodu zostay zdefiniowane nazwy
dla obiektw Soca, Merkurego, Wenus, Ziemi i Marsa.

Listing 19.1. Nadawanie nazw (identyfikatorw) planetom w programie PLANETS______________

tdefine SUN l
tfdefine MERCURY 2
#define VENUS 3
#define EARTH 4
Idefine MARS 5
Rozdzia 19. * Grafika interaktywna 589

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glMatrixMode(GL_MODELVIEW); glPushMatrix();
// Przeksztacenie caej sceny do ukadu obserwatora
glTranslatef( O . O f , O . O f , -300.O f ) ;
// Inicjowanie stosu nazw
gllnitNames();
glPushName( 0 ) ;

// Ustawienie koloru materiau na ty //


Soce
glRGB(255, 255, 0);
glLoadName(SUN);
auxSolidSphere(15.Of);
// Rysowanie Merkurego
glRGB(128,0,0) ;
glPushMatrix () ;
glTranslatef( 2 4 . Of, O . O f , O . O f ) ;
glLoadName(MERCURY);
auxSolidSphere(2.Of);
glPopMatrix();

// Rysowanie Wenus glPushMatrix();


glRGB(128,128,255);
glTranslatef( 6 0 . Of, O . O f , O . O f ) ;
glLoadName(VENUS);
auxSolidSphere(4.Of); glPopMatrix();

... Pozostae planety

II Odtworzenie stanu macierzy


glPopMatrix(); // Macierz widoku modelu
// Zrzucenie polece graficznych
glFlushO ;

W programie PLANETS funkcja gllnitNames inicjuje i czyci stos nazw, za funkcja


glPushName odkada na stos identyfikator O, w celu wypenienia stosu przynajmniej jedn
nazw. W przypadku Soca i poszczeglnych planet wywoujemy funkcje glLoadName w
celu nazwania obiektu lub obiektw, ktre maj zosta narysowane. Te nazwy, w postaci
liczb cakowitych bez znaku, nie s odkadane na stos nazw, lecz zastpuj
590_______________________Cz III Tematy zaawansowane i efekty specjalne

biec nazw na szczycie stosu. Pniej omwimy zagadnienie utrzymywania stosu


nazw. Na razie po prostu zastpujemy nazw na szczycie stosu za kadym razem, gdy
przystpujemy do rysowania obiektu (Soca i poszczeglnych planet).

Praca w trybie selekcji


Jak ju wspomniano, OpenGL moe pracowa w trzech rnych trybach renderowania.
Domylnym trybem jest GLJRENDER, w ktrym wszystkie operacje graficzne poja-
wiaj si na ekranie. Aby uy selekcji, musimy zmieni tryb renderowania na tryb se-
lekcji, wywoujc funkcj:
glRenderMode(GL_SELECTION);

Gdy chcemy ponownie rysowa na ekranie, wywoujemy funkcj


glRenderMode(GL_RENDER) ;

ustawiajc OpenGL ponownie w tryb rysowania. Trzecim trybem renderowania jest


GL_FEEDBECK, ktry zostanie omwiony w dalszej czci rozdziau.

Kod nadajcy nazwy z listingu 19.1 nie przynosi adnego efektu do momentu prze-
czenia si do trybu selekcji. Najczciej bdziesz uywa tych samych funkcji do ren-
derowania w obu trybach, GL_RENDER i GL_SELECTION, tak jak robimy to w tym
programie.

Listing 19.2 przedstawia kod wykonywany w momencie kliknicia lewym przyciskiem


myszy. Procedura obsugi odczytuje wsprzdne wskanika myszy z parametru IParam i
przekazuje je funkcji ProcessSelection, przetwarzajcej w tym programie kliknicia
myszk.

Listing 19.2. Kod obsugujcy kliknicie lewym przyciskiem myszy_______________________

case WM_LBUTTONDOWN:
{
int xPos = LOWORD(IParam); // Pozioma wsprzdne kursora
int yPos = HIWORD(IParam); // Pionowa wsprzdne kursora
// Renderowanie w trybie selekcji i wywietlenie rezultatu
ProcessSelection(xPos, yPos) ;

Bufor selekcji
Podczas renderowania bufor selekcji jest wypeniany rekordami trafie. Rekord trafienia jest
generowany za kadym razem, gdy renderowany prymityw lub grupa prymityww
przecina bry widzenia. W normalnych warunkach byyby to wszystkie prymitywy, jakie
pojawiyby si na ekranie.
Rozdzia 19. Grafika interaktywna 591

Bufor selekcji to tablica liczb cakowitych bez znaku, za kady rekord selekcji zajmuje
przynajmniej cztery elementy tablicy. Pierwsza pozycja tablicy zawiera ilo nazw na
stosie nazw w momencie wystpienia trafienia. W przypadku programu PLANETS (listing
19.1) bdzie to zawsze 1. Nastpne dwie pozycje zawieraj minimaln i maksymaln
wsprzdn Z wszystkich wierzchokw zawartych w bryle widzenia od ostatniego
rekordu trafienia. Ta warto, z zakresu <0, 1>, jest skalowana do wartoci liczb
cakowitych bez znaku (232 - 1) w celu przechowania w buforze selekcji. Ten wzr,
przedstawiony na rysunku 19.1, powtarza si dla wszystkich rekordw trafie w buforze
selekcji.

Rysunek
19.1. Bufor selekcji [0] w Ilo nazw na stosie nazw w momencie
Format rekordu
trafienia = n,
trafienia w buforze
selekcji [ l ] ^- Minimalna warto z [2] ^-
Maksymalna warto z [n0+2] -^-Dno
stosu nazw

Nastpny rekord trafienia -^[n,+3] -^-Ilo nazw na stosie nazw w momencie


trafienia = n, [n.+4] -^-
Minimalna warto z

Z formatu bufora selekcji nie wynika adna informacja o iloci rekordw trafie, jakie
trzeba przeanalizowa. Dzieje si tak, poniewa bufor selekcji w rzeczywistoci nie jest
wypeniany a do momentu powrotu do trybu GL_RENDER. Gdy przeczysz si do
tego trybu funkcj glRenderMode, warto zwracana przez t funkcj odpowiada iloci
rekordw trafie skopiowanych do bufora.

Listing 19.3 przedstawia funkcj przetwarzajc wywoywan w momencie kliknicia


lewym przyciskiem myszy. W przedstawionym kodzie widzimy sposb alokowania i
tworzenia bufora selekcji funkcj glSelectBuffer. Ta funkcja wymaga podania dwch
argumentw: rozmiaru bufora oraz wskanika do tego bufora.

Listing 19.3. Funkcja przetwarzajca kliknicia myszk_____________________________

// Przetwarzanie selekcji, wywoywane w momencie kliknicia


// myszk w miejscu o wsprzdnych (xPos, yPos)
tdefine BUFFER_LENGTH 64
void ProcessSelectionlint xPos, int yPos)
{
// Miejsce na bufor selekcji
GLuint selectBuff[BUFFER_LENGTH];

// Licznik trafie i miejsce na widok


GLint hits, viewport[4];

// Przygotowanie bufora selekcji


glSelectBuffer(BOFFER_LENGTH, selectBuff);
592_______________________Cz III Tematy zaawansowane i efekty specjalne

// Pobranie widoku
glGetIntegerv(GL_VIEWPORT, viewport);

// Przejcie do macierzy rzutowania i zachowanie j e j


glMatrixMode(GL_PROJECTION); glPushMatrix();

// Zmiana trybu renderowania


glRenderMode(GL_SELECT);

// Ustanowienie nowej bryy widzenia jako jednostkowej kostki


// dookoa punktu wskanika myszy (xPos, y P o s ) , rozcigajcej si
// na dwa piksele w poziomie i w pionie.
// Poniewa OpenGL mierzy wsprzdne okna od dou, za Windows od
// gry,musimy to uwzgldni odejmujc wsprzdn y od gry okna.
// Daje to efekt odwrcenia ukadu wsprzdnych (y zaczyna si
// u gry).
glLoadldentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2 , 2 , viewport);

// Zastosowanie macierzy perspektywy


gluPerspective( 4 5 . Of, fAspect, 1 . 0 , 4 2 5 . 0 ) ;

// Wyrysowanie sceny
RenderScene();
// Zliczenie trafie
hits = glRenderMode(GL_RENDER);

// Jeli wystpio pojedyncze trafienie, wywietlenie informacji


if(hits == 1)
ProcessPiant(selectBuff[ 3 ] );

// Odtworzenie macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glPopMatrix();

// Powrt do widoku modelu w celu normalnego renderowania


glMatrixMode(GL_MODELVIEW);

Wybieranie
Wybieranie nastpuje wtedy, gdy podczas selekcji wykorzystujesz pooenie myszy do
utworzenia i uycia zmodyfikowanej bryy obcinania. Po utworzeniu mniejszej bryy
widzenia umieszczonej w scenie na miejscu wskanika myszy, trafienia bd generowane
jedynie przez te obiekty, ktre przecinaj t bry widzenia. Sprawdzajc zawarto
bufora selekcji, moesz wic sprawdzi, na ktrych obiektach nastpio kliknicie
myszk.

Podczas tworzenia macierzy opisujcej now bry widzenia bardzo przydaje si funkcja
gluPickMatrix:
Rozdzia 19. Grafika interaktywna_______________________________593

void gluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble


^height,
GLint viewport[ 4 ] );

Parametry x i y to rodek danej bryy widzenia we wsprzdnych okna. Wyraona jest


w nich pozycja myszy, za brya widzenia zostanie wyrodkowana dokadnie w tym
miejscu. Parametry width i height okrelaj szeroko i wysoko bryy widzenia w pi-
kselach okna. W przypadku klikni w pobliu obiektu uyj wikszych wartoci, w przy-
padku klikni bezporednio na obiektach uyj mniejszych wartoci. Tablica viewport
zawiera wsprzdne okna dla aktualnie zdefiniowanego widoku. Mona je atwo od-
czyta wywoujc
glGetIntegerv(GL_VIEWPORT, viewport);

Aby uy funkcji gluPickMatrix, powiniene najpierw zachowa biecy stan macierzy


rzutowania (czyli zachowa biec bry widzenia). Nastpnie wywoaj funkcj glLoad-
Identity w celu stworzenia jednostkowej bryy widzenia. Na koniec, musisz zastosowa
rzutowanie perspektywiczne, jakie zastosowae w oryginalnej scenie, gdy w prze-
ciwnym razie nie otrzymasz waciwego odwzorowania. Oto jak robimy to w programie
PLANETS (z listingu 19.3):
// Przejcie do macierzy rzutowania i zachowanie jej
glMatrixMode(GL_PROJECTION); glPushMatrix();

// Zmiana trybu renderowania


glRenderMode(GL_SELECT);

// Ustanowienie nowej bryy widzenia jako jednostkowej kostki //


dookoa punktu wskanika myszy (xPos, yPos), rozcigajcej si // na
dwa piksele w poziomie i w pionie. glLoadldentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2 , 2 , viewport);

// Zastosowanie macierzy perspektywy


gluPerspective(45.0f, fAspect, 1 . 0 , 4 2 5 . 0 ) ;
// Wyrysowanie sceny
RenderScene();
// Zliczenie trafie
hits = glRenderMode(GL_RENDER);

W tym segmencie, najpierw zachowujemy stan bryy widzenia. Nastpnie przechodzimy


do trybu selekcji, modyfikujemy bry widzenia tak, aby obejmowaa jedynie obszar pod
wskanikiem myszy, a nastpnie odrysowujemy scen wywoujc funkcj RenderScene.
Po wyrenderowaniu sceny ponownie wywoujemy funkcj glRenderMode w celu
przeczenia OpenGL do normalnego trybu rysowania, a jednoczenie otrzymujemy
ilo wygenerowanych rekordw trafie.
W nastpnym segmencie, jeli wystpio trafienie (w tym przykadzie moe wystpi
albo jedno trafienie, albo wcale), do naszej funkcji ProcessPlanet przekazujemy element
bufora selekcji zawierajcy nazw (identyfikator) trafionej planety. Na koniec odtwa-
594______________________Cz III Tematy zaawansowane i efekty specjalne

rzamy macierz rzutowania (czyli przywracamy star bry widzenia) i przeczamy si na


uywanie macierzy widoku modelu, normalnie bdcej domyln macierz.
// Jeli wystpio pojedyncze t r a f i e n i e , wywietlenie informacji
i f ( h i t s == 1)
ProcessPiant(selectBuff[3]);

// Odtworzenie macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glPopMatrix();

// Powrt do widoku modelu w celu normalnego renderowania


glMatrixMode(GL_MODELVIEW);

Funkcja ProcessPlanet po prostu wywietla okno komunikatu informujce, na ktrej planecie


nastpio kliknicie. Nie bdziemy przytacza tego kodu, gdy jest oczywisty i nie zawiera
nic oprcz zwykej instrukcji switch wybierajcej teksty dla okna komunikatu.

Wynik dziaania programu PLANETS zosta pokazany na rysunku 19.2, na ktrym wi-
dzimy efekt kliknicia na drug planet od Soca.

Rysunek 19.2.
Dziaanie programu PLANETSpo
klikniciu na panet

Wybr hierarchiczny
W programie PLANETS
nie odkadalimy nazw na
stos, lecz jedynie
zastpowalimy znajdujc
si na nim nazw. Ta
pojedyncza nazwa ze stosu
bya jedyn nazw zwra-
can w buforze selekcji. Po
umieszczeniu wikszej iloci
nazw na stosie nazw moglibymy otrzyma kilka nazw w buforze. Jest to uyteczne w
sytuacjach, gdy potrzebujemy dalszych informacji, na przykad, gdy chcemy by
poinformowani, e zostaa trafiona okrelona ruba, w okrelonym kole, w okrelonym
samochodzie w scenie itd.

W celu zademonstrowania kilku nazw zwracanych na stosie selekcji, pozostaniemy przy


temacie astronomicznym z poprzedniego przykadu. Rysunek 19.3 przedstawia (przy
pewnej dozie wyobrani)dwie planety: wiksz z pojedynczym ksiycem oraz mniejsz,
czerwon planet z dwoma ksiycami.
Rozdzia 19. Grafika Interaktywna 595

Rysunek 19.3.
Dwie planety z ksiycami

Zamiast identyfikowa
jedynie planet lub ksiyc,
na ktrych nastpio
kliknicie, bdziemy
identyfikowa take planet
zwizan z danym
ksiycem. Kod z listingu
19.4 przedstawia nowy kod
renderowania naszej sceny.
Oprcz nazw planet
odkadamy na stos take
nazwy ksiycw, przez co
bdzie on zawiera zarwno
nazw planety, jak i wybranego ksiyca.

Listing 19.4. Kod renderowania z programu MOONS___________________________ __

define EARTH l
#define MARS 2
define MOON1 3
#define MOON2 4
// Wywoywane w celu narysowania sceny
void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glMatrixMode(GL_MODELVIEW); glPushMatrix();

// Przeksztacenie caej sceny do ukadu obserwatora


glTranslatef( O . O f , O.Of, -300.O f ) ;
// Inicjowanie stosu nazw
gllnitNamesO ; glPushNarne (0)
;

// Rysowanie Ziemi
glPushMatrix();
glRGB(0,0,255) ;
glTranslatef(-100.Of,O . O f , O . O f ) ;
glLoadName(EARTH);
auxSolidSphere(30.Of);
596 _______________________ Cz III Tematy zaawansowane i efekty specjalne

// Rysowanie Ksiyca glTranslatef


(45. Of, O.Of, O . O f ) ;
glRGB(220,220,220) ; glPushName
(MOON1) ; auxSolidSphere (5.0f ) ;
glPopName ( ) ; glPopMatrix ( ) ;

// Rysowanie Marsa
glRGB(255,0,0) ;
glPushMatrix () ;
glTranslatef (100. Of, O.Of, O . O f ) ;
glLoadName(MARS) ;
auxSolidSphere (20 . Of ) ;

// Rysowanie pierwszego ksiyca


glTranslatef (-40. Of, 40. Of,
O . O f ) ; glRGB(220,220,220) ;
glPushName (MOON1) ; auxSolidSphere(5.0f)
; glPopName ( ) ;

// Rysowanie drugiego ksiyca


glTranslatef ( O . O f , -80. Of,
O . O f ) ; glPushName (MOON2) ;
auxSolidSphere(5.0f ) ; glPopName ( ) ;
glPopMatrix () ;

// Odtworzenie stanu macierzy glPopMatrix


() ; // Macierz widoku modelu

// Zrzucenie polece graficznych


glFlushO ;

Tym razem w funkcji ProcessSelection take wywoujemy funkcj ProcessPlanet, lecz w


tym przypadku przekazujemy jej cay bufor selekcji:
// Jeli wystpio pojedyncze trafienie, wywietlenie informacji
iflhits == 1)
ProcessPlanet (selectBuf f) ;

Listing 19.5 przedstawia funkcj ProcessPlanet, ktra w tym przykadzie jest bardziej
rozbudowana. W tym przypadku dolna nazwa na stosie nazw zawsze bdzie nazw planety,
gdy zostaa odoona na stos jako pierwsza. Jeli nastpi kliknicie na ksiyc, on take
znajdzie si na stosie nazw. Ta funkcja wywietla nazw wybranej planety, a jeli zosta
trafiony ksiyc, ta informacja rwnie jest wywietlana. Przykad dziaania programu
zosta przedstawiony na rysunku 19.4.
Rozdzia 19. Grafika interaktywna 597

Rysunek
19.4.
Przykad dziaania
programu MOONS

Listing 19.5. Kod przetwarzajcy bufor selekcji w przykadowym programie MOONS

// Przetwarzanie bufora selekcji w celu wyznaczenia


// obiektu planety/ksiyca, na ktry kliknito void
ProcessPlanet(GLuint *pSelectBuff)
int id,count; char
CMessage[ 6 4 ] ;

// Ilo nazw na stosie nazw


count = pSelectBuff [ 0 ] ;

// Dno stosu nazw id =


pSelectBuff[ 3 ] ;

// Sprawdzenie, czy kliknito na Ziemi lub na Marsa


switch(id)
case EARTH:
strcpy(CMessage,"Kliknle na Z i e m i . " ) ;

// Jeli na stosie nazw wystpuje inna nazwa,


// musia zosta trafiony ksiyc, if(count ==
2)
strcat(CMessage,"\nKonkretnie na Ksiyc.
break;
case MARS:
strcpy(CMessage,"Klikne na M a r s a . " ) ;
598______________________Cz III Tematy zaawansowane i efekty specjalne

// Wiemy, e stos nazw ma tylko dwa elementy. //


Znajduje si na nim nazwa trafionego ksiyca
if(count == 2)
if(pselectfiuff[ 4 ] == MOON1)
strcat(cMessage,"\nKonkretnie na ksiyc nr 1 . " ) ;
else
strcat(cMessage,"\nKonkretnie na ksiyc nr 2 . " ) ;
break;

// Jeli nic nie zostao trafione, nie powinno nas tu by!


default:
strcpy(cMessage,"Bd - Na nic nie klikne!");
break;

// Wywietlenie komunikatu o trafionej planecie i ewentualnie


ksiycu
MessageBox(NULL,cMessage,"Komunikat selekcji",MB_OK); }

Sprzenie zwrotne
Sprzenie zwrotne (ang. feedbacK), podobnie jak selekcja, jest trybem renderowania, w
ktrym nic nie jest rysowane na ekranie. Zamiast tego, do bufora sprzenia zwroten-go
wpisywane s informacje na temat sposobu renderowania sceny. Te informacje obejmuj
wsprzdne okna przetransformowanych wierzchokw, kolory wierzchokw ju po
owietleniu, a take dane tekstury.
Przejcie do trybu sprzenia zwrotnego odbywa si podobnie jak przejcie do trybu se-
lekcji, poprzez wywoanie funkcji glRenderMode z parametrem GLJFEEDBACK. W
celu wypenienia bufora sprzenia zwrotnego i powrotu do normalnego trybu renderowania
musisz wywoa funkcj glRenderMode(GL_RENDER).

Bufor sprzenia zwrotnego


Bufor sprzenia zwrotnego jest tablic wartoci zmiennoprzecinkowych, tworzon za
pomoc funkcji glFeedbackBuffer:
void glFeedbackBuffer(GLsizei, GLenum type, GLfloat * b u f f e r ) ;

Ta funkcja otrzymuje rozmiar bufora, typ i ilo potrzebnych informacji rysunkowych


oraz wskanik do bufora.
Dostpne wartoci dla typu danych zostay zebrane w tabeli 19.1. Rodzaj danych okrela
ilo danych umieszczanych w buforze dla kadego wierzchoka. Dane koloru (C) s
reprezentowane przez pojedyncz warto w trybie indeksu koloru lub przez cztery
wartoci w trybie RGBA.
Rozdzia 19. Grafika interaktywna 599
Tabela 19.1.
Typy danych w buforze sprzenia zwrotnego

Typ Wsprzdne Dane Dane tekstury czna ilo


wierzchoka koloru wartoci
GL_2D ", y - - 2
GL_3D x, y, z - - 3
GL_3D_COLOR x, y, z C - 3+C
GLJD_COLOR_TEXTURE x, y, z C 4 7+C
GL_4D_COLOR_TEXTURE x, y, z, w C 4 8+C

Dane sprzenia zwrotnego


Bufor sprzenia zwrotnego zawiera list elementw, po ktrych nastpuj dane wierz-
chokw i ewentualnie koloru i tekstury. Moesz przetwarza te elementy (tabela 19.2) w
celu wyznaczenia rodzajw prymityww, ktre miayby zosta wyrenderowane.

Tabela 19.2.
Elementy bufora sprzenia zwrotnego

Element Prymityw
GL_POINT_TOKEN Punkty
GL_LINE_TOKEN Linie
GL_LINE_RESET_TOKEN Segment linii po wyzerowaniu wzorca linii
GL_POLYGON_TOKEN Wielokt
GL_BITMAP_TOKEN Bitmapa
GL_DRAW_PIXEL_TOKEN Narysowany prostokt piksela
GL_COPYJ?IXEL_TOKEN Skopiowany prostokt piksela
GL_PASS_THROUGH_TOKEN Znacznik zdefiniowany przez uytkownika

Po elementach punkt, bitmapa i piksel wystpuj dane pojedynczego wierzchoka oraz


ewentualnie dane koloru i tekstury. Zaley to od rodzaju danych z tabeli 19.1, wskazanych
w wywoaniu funkcji glFeedbackBuffer. W przypadku linii zwracane s dwa zestawy
danych wierzchokw, za bezporednio po elemencie wielokta wystpuje warto
okrelajca ilo wierzchokw wielokta. Po znaczniku definiowanym przez uytkownika
(GL_PASS_THROUGH_TOKEN) wystpuje pojedyncza warto zmiennoprzecin-kowa
zdefiniowana przez uytkownika. Rysunek 19.5 przedstawia przykad zawartoci bufora
sprzenia zwrotnego po wybraniu danych typu GL_3D.
600 Cz III Tematy zaawansowane i efekty specjalne

Rysunek 19.5.
Przykad zawartoci Bufor sprzenia zwrotnego - GL POINTJOKEN
bufora sprzenia [I] - Wsprzdna x
zwrotnego [2] -Wsprzdnay
[3] -Wsprzdna;
[4] - GL_PASS_THROUGH_TOKEN
[5] - Warto zdefiniowana przez uytkownika
[6] GL_POLYGON_TOKEN
[7] Ilo wierzchokw wielokta
[8] - Wsprzdna x pierwszego wierzchoka
[9] Wsprzdna y pierwszego wierzchoka
[10] - Wsprzdna z pierwszego wierzchoka
[II] - Wsprzdna x drugiego wierzchoka

[n] - Wsprzdna z ostatniego wierzchoka

Znaczniki uytkownika
Podczas wykonywania kodu renderowania, bufor sprzenia zwrotnego jest wypeniany
elementami i danymi wierzchokw dla kadego podanego prymitywu. Podobnie jak w
trybie selekcji, moesz zaznacza poszczeglne prymitywy nadajc im nazwy. W trybie
sprzenia zwrotnego moesz take ustawia znaczniki pomidzy prymitywami. Suy
do tego funkcja glPassThrough:
void glPassThrough(GLfloat token);

Ta funkcja umieszcza element GL_PASS_THROUGH_TOKEN w buforze selekcji, a


bezporednio po nim warto podan przy wywoywaniu funkcji. Przypomina to nieco
nadawanie nazw prymitywom w trybie selekcji. Jest to jedyny sposb oznaczania obie-
ktw w buforze sprzenia zwrotnego.

Przykad
Doskonaym wykorzystaniem sprzenia zwrotnego jest uzyskiwanie informacji o wsp-
rzdnych okna dotyczcych renderowanych obiektw. Otrzymane informacje moesz
wykorzysta w celu umieszczenia kontrolek w pobliu obiektw lub w celu zintegrowania
grafiki GDI z obiektami w oknie.

Aby zademonstrowa sprzenie zwrotne, uyjemy take selekcji w celu wyznaczenia, na


ktry z dwch obiektw na ekranie nastpio kliknicie. Nastpnie przejdziemy do trybu
sprzenia zwrotnego i ponownie wyrenderujemy scen w celu uzyskania informacji o
wierzchokach we wsprzdnych okna. Uywajc tych danych wyznaczymy
Rozdzia 19. Grafika interaktywna_______________________________601

minimaln i maksymaln warto wsprzdnej obiektu, ktre wykorzystamy do nary-


sowania prostokta selekcji obiektu. W wyniku otrzymamy sposb graficznej selekcji
jednego lub obu obiektw.

Nadawanie obiektom etykiet


na potrzeby sprzenia zwrotnego
Na listingu 19.6 zosta przedstawiony kod renderujcy z naszego przykadowego pro-
gramu SELECT. Nie myl go z demonstracj trybu selekcji! Cho w tym fragmencie
wykorzystujemy tryb selekcji do wybrania obiektu w oknie, jednak naszym celem jest
uzyskanie informacji o obiekcie - poprzez sprzenie zwrotne - wystarczajcych do na-
rysowania za pomoc funkcji GDI prostokta otaczajcego obiekt na ekranie. Zwr
uwag na uycie funkcji glPassThrough - w celu nadania etykiet obiektom w buforze
sprzenia zwrotnego - tu po wywoaniach funkcji glLoadName, nadajcej etykiety
obiektom w buforze selekcji.

Listing 19.6. Kod renderujcy z przykadowego programu SELECT_____________________

#define CUBE l
#define SPHERE 2

// Wywoywane w celu narysowania sceny


void RenderScene(void)
{
// Wyczyszczenie okna biecym kolorem ta
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Zachowanie stanu macierzy i wykonanie obrotu


glMatrixMode(GL_MODELVIEW); glPushMatrix();

// Przeksztacenie caej sceny do ukadu obserwatora


glTranslatef(-80.Of, O . O f , -300.O f ) ;
// Inicjowanie stosu nazw
gllnitNames(); glPushName( 0 ) ;

// Ustawienie koloru materiau na ty //


Kostka
glRGB(255, 255, 0 ) ;
glLoadName(CUBE);
glPassThrough((GLfloat)CUBE);
auxSolidCube(75.Of);

// Rysowanie kuli
g!RGB(128,0,0) ;
glTranslatef(130.Of, O . O f , O . O f ) ;
glLoadName(SPHERE);
glPassThrough((GLfloat)SPHERE);
auxSolidSphere( 5 0 . O f ) ;
602 Cz III Tematy zaawansowane i efekty specjalne

// Odtworzenie stanu macierzy


glPopMatrix(); // Macierz widoku modelu
// Zrzucenie polece graficznych
glFlushf) ;

Krok : wybranie obiektu


Rysunek 19.6 przedstawia wynik dziaania kodu renderujcego, wywietlajcego kostk i
kul. Gdy uytkownik kliknie na jednen z obiektw, jest wywoywana funkcja Pro-
cessSelection (listing 19.7). Ten kod jest bardzo podobny do kodu selekcji z poprzednich
dwch przykadw.
Rysunek
19.6.
Wynik dziaania
programu SELECT
po klikniciu na

Listing 19.7. Przetwarzanie selekcji w programie SELECT

/l Przetwarzanie selekcji, wywoywane w momencie kliknicia


// myszk w miejscu o wsprzdnych (xPos, yPos)
#define BUFFER_LENGTH 64
void ProcessSelection(int xPos, int yPos)
{
// Miejsce na bufor selekcji
GLuint selectBuff[BUFFER_LENGTH];

// Licznik trafie i miejsce na widok


GLint hits, viewport[ 4 ] ;
// Przygotowanie bufora selekcji
glSelectBuffer(BUFFER_LENGTH, selectBuff);

// Pobranie widoku
glGet!ntegerv(GL_VIEWPORT, viewport);
// Przejcie do macierzy rzutowania i zachowanie jej
glMatrixMode(GL_PROJECTION); glPushMatrix();
Rozdzia 19. Grafika interaktywna_______________________________603

// Zmiana trybu renderowania


glRenderMode(GL_SELECT);
// Ustanowienie nowej bryy widzenia jako jednostkowej kostki
// dookoa punktu wskanika myszy (xPos, y P o s ) , rozcigajcej si
// na dwa piksele w poziomie i w pionie.
// Poniewa OpenGL mierzy wsprzdne okna od dou, za Windows od
// gry,musimy to uwzgldni odejmujc wsprzdn y od gry okna.
// Daje to efekt odwrcenia ukadu wsprzdnych (y zaczyna si
// u gry).
glLoadldentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2 , 2 , viewport);
// Zastosowanie macierzy perspektywy
gluPerspective( 6 0 . 0 f , fAspect, 1 . 0 , 4 2 5 . 0 ) ;
// Wyrysowanie sceny
RenderScene();
// Zliczenie trafie
hits = glRenderMode(GL_RENDER);

// Odtworzenie macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glPopMatrix();

// Powrt do widoku modelu w celu normalnego renderowania


glMatrixMode(GL_MODELVIEW);

// Jeli wystpio pojedyncze trafienie, wywietlenie informacji


if(hits == 1)
MakeSelection(selectBuff[ 3 ] );

Krok 2: pobieranie informacji o


narysowanych obiektach
Gdy wyznaczylimy ju, na ktry obiekt nastpio kliknicie, moemy przygotowa bufor
sprzenia zwrotnego i ponownie wyrenderowa scen w tym trybie. Listing 19.8
przedstawia kod przygotowujcy tryb sprzenia zwrotnego i wywoujcy funkcj Ren-
derScene w celu ponownego wyrysowania sceny. Tym razem jednak, za pomoc funkcji
glPassThrough, w buforze sprzenia zwrotnego zostan umieszczone znaczniki
poszczeglnych obiektw.

Listing 19.8. adowanie i przetwarzanie bufora sprzenia zwrotnego_____________________

// Przejcie do trybu sprzenia zwrotnego i wyrysowanie


// prostokta dookoa obiektu
#define FEED_BOFF_SIZE 4096
void MakeSelection(int nChoice)
{
// Miejsce na bufor sprzenia zwrotnego
GLfloat feedBackBuff[FEED_BUFF_SIZE];

// Miejsce na liczniki itd. int


size,i,j,count;
604 _______________________ Cz III Tematy zaawansowane i efekty specjalne

// Minimalne i maksymalne wartoci x i y dla wsprz. 2D


// wierzchokw
float nMaxX,nMaxY,nMinX,nMinY;

// Pocztkowe minimalne i maksymalne wartoci


nMaxX = nMaxY = - 9 9 9 9 9 9 . Of; nMinK = nMinY =
9 9 9 9 9 9 . Of;

// Przygotowanie bufora sprzenia zwrotnego


glFeedbackBuffer (FEED_BUFF_SIZE,GL_2D, f eedBackBuf f ) ;
// Przejcie do trybu sprzenia zwrotnego
glRenderMode (GL_FEEDBACK) ;

// Wyrysowanie sceny
RenderScene ( ) ;

// Wyjcie z trybu sprzenia zwrotnego


size = glRenderMode (GL_RENDER) ;

// Przetwarzanie bufora sprzenia zwrotnego // w


celu wyznaczenia min. i maks. wsprzdnych //
ekranowych ( x , y) obiektu i = 0;
whilefi < FEED_BUFF_SIZE) {
// Wyszukanie odpowiedniego znacznika if ( f
eedBackBuf f [ i ] == GL_PASS_THROUGH_TOKEN) if
(feedBackBuff [i+1] == (GLfloat)nChoice) {
i+= 2;
// Praca w ptli a do natrafienia na nastpny element
while (feedBackBuff [ i ] != GL_PASS_THROUGH_TOKEN) {
// Po prostu wielokty
if (feedBackBuff [ i ] == GL_POLYGON_TOKEN) {
// Pominicie wszystkich wartoci dla wielokta
count = (int) feedBackBuff [++i] ; // Ilo
// wierzchokw
i++;
// Ptla dla kadego wierzchoka
for (j = 0; j < count; j + + )
{
// Minimalna i maksymalna wsprzdna X if
(feedBackBuff [ i ] > nMaxX) nMaxX =
feedBackBuff [ i ] ;
if (feedBackBuff [ i ] < nMinX)
nMinX = feedBackBuff [ i ] ;

// Minimalna i maksymalna wsprzdna Y if


(feedBackBuff [ i ] > nMaxY) nMaxY =
feedBackBuff [ i ] ;
Rozdzia 19. Grafika interaktywna _______________________________ 605

if (feedBackBuff [ i ] < nMinY)


nMinY = feedBackBuff [ i ] ;

else
i++; // Przejcie do nastpnego indeksu

break;

// Narysowanie prostokta selekcji


HighLight ( (int) floor (nMinX+0. 5) , (int) f loor (nMinY+0 . 5) ,
(int) floor (nMaxX+0.5) , (int) f loor (nMaxY+0 . 5) ) ;

Po wypenieniu bufora sprzenia zwrotnego, wyszukujemy element GL_PASS_


THROUGHJTOKEN. Gdy go znajdziemy, pobieramy nastpn warto w celu spraw-
dzenia, czy wanie tego obiektu szukamy. Jeli tak, jedyne, co pozostao, to przejcie
przez wszystkie wielokty tego obiektu i wyznaczenie minimalnych i maksymalnych
wsprzdnych ekranowych x i y. Funkcja HighLight wykorzystuje funkcj Win32
DrawFocusRect w celu wyrysowania prostokta dookoa obiektu, na ktry nastpio
kliknicie. Ta funkcja uywa trybu rysowania XOR, wic jej kolejne wywoanie powoduje
usuniecie prostokta selekcji. Dziki temu moesz zaznaczy obiekt klikajc na niego i
usun zaznaczenie klikajc ponownie.

Podsumowanie
Selekcja i sprzenie zwrotne to dwa bardzo uyteczne elementy OpenGL, umoliwiajce
interakcj uytkownika ze scen. Selekcja i wybr s uywane przy identyfikacji obiektu
lub regionu sceny we wsprzdnych OpenGL, a nie we wsprzdnych okna. Sprzenie
zwrotne zwraca cenne informacje dotyczce pooenia rysowanych prymityww we
wsprzdnych okna. Moesz uy tych informacji w celu zintegrowania grafiki OpenGL z
grafik GDI w Windows.

Podrcznik
glFeedbackBuffer
Przeznaczenie Przygotowuje bufor sprzenia zwrotnego.
Plik nagwkowy <gl.h>
606 Cz III Tematy zaawansowane i efekty specjalne

Skadnia void glFeedbackbuffer(GLsizei size, GLenum type, GLfloat *buffer);


Opis Ta funkcja przygotowuje bufor sprzenia zwrotnego dla danych
wskazanego typu. Sprzenie zwrotne jest trybem renderowania; zamiast
renderowa do bufora ramki, w trybie sprzenia zwrotnego OpenGL
umieszcza dane wierzchokw we wskazanym buforze. Umieszczane bloki
danych mog zawiera wsprzdne ekranowe x, y, z oraz w wierzchokw,
a take dane koloru i tekstury. Rodzaj informacji umieszczanych w buforze
zaley od parametru type.
Parametry

stze GLsizei: Maksymalna ilo pozycji zaalokowanych w buforze *buffer. Jeli


type blok zapisywanych do bufora danych przekroczy objto bufora, zostanie
zapisana jedynie ta cz danych, ktra zmieci si w buforze.
GLenum: Okrela rodzaj danych o wierzchokach, umieszczanych w buforze
sprzenia zwrotnego. Dla kadego wierzchoka, w buforze umieszczany
jest osobny blok danych. Dla kadego z poniszych typw, blok danych
zawiera element wyznaczajcy rodzaj prymitywu, po ktrym nastpuj dane
wierzchokw. Dane wierzchokw mog zawiera:
GL_2D: par wsprzdnych x i y.
GLJ3D: trjk wsprzdnych x, y i z.
GL_3D_COLOR: wsprzdne x, y i z oraz dane koloru (jedna warto
dla trybu indeksu koloru, cztery wartoci dla trybu RGBA).
GL_3D_COLOR_TEXTURE: wsprzdne x, y i z oraz dane koloru (jedna
lub cztery wartoci), a take cztery wsprzdne tekstury.
GL_4D_COLOR_TEXTURE: wsprzdne x, y, z i w oraz dane koloru
(jedna lub cztery wartoci), a take cztery wsprzdne tekstury.
buffer GLfloat*: Wskanik do bufora sprzenia zwrotnego.

Zwracana warto Brak.


Przykad Poniszy kod z programu SELECT inicjuje bufor sprzenia zwrotnego
funkcjglFeedbackBuffer, przecza si do trybu sprzenia zwrotnego,
renderuje scen, po czym wypenia bufor przeczajc si ponownie do
standardowego trybu renderowania.
#define FEED BUFF SIZE 8192

// Miejsce na bufor sprzenia zwrotnego


GLfloat feedBackBuff[FEED_BUFF SIZE];

// Przygotowanie bufora sprzenia zwrotnego


glFeedbackBuffer(FEED_B0FF_SIZE,GL_2D, feedBackBuff};
Rozdzia 19. Grafika interaktywna_______________________________607

// Przejcie do trybu sprzenia zwrotnego


glRenderMode(GL_FEEDBACK);
// Wyrysowanie sceny
RenderScene O;
// Wyjcie z trybu sprzenia zwrotnego size
= glRenderMode(GL_RENDER);
Patrz take glPassThrough, glRenderMode, glSelectBuffer

gllnitNames_______________________
Przeznaczenie Przygotowuje bufor sprzenia zwrotnego.
Plik nagwkowy <gl.h>
Skadnia void glInitNames(void);
Opis Stos nazw jest uywany w celu umoliwienia rysowania prymityww lub
grup prymityww o nazwach nadanych podczas renderowania w trybie
selekcji. Za kadym razem gdy prymitywowi zostaje nadana nazwa, jest
ona odkadana na stos nazw funkcjglPushName lub zastpuje aktualn
nazw na szczycie stosu, za pomoc funkcji glLoadName. Funkcja
gllnitNames zeruje stos nazw, usuwajc z niego wszystkie wystpujce
nazwy.
Zwracana warto Brak.
Przykad Poniszy kod pochodzi z programu PLANETS. Inicjuje stos nazw
i umieszcza na nim pojedyncz warto.
// Inicjowanie stosu nazw
gllnitNames O;
glPushName( 0 ) ;
Patrz take gllnitNames, glPushName, glRenderMode, glSelectBuffer

glLoadName________________________
Przeznaczenie Umieszcza nazw na szczycie stosu nazw.
Plik nagwkowy <gl.h>
Skadnia void glLoadName(GLuint name);
Opis Ta funkcja umieszcza podan nazw na szczycie stosu nazw. Stos nazw
jest uywany do nazywania prymityww lub grup prymityww podczas
renderowania w trybie selekcji. Podana nazwa zastpuje aktualn nazw
na szczycie stosu.
608 Cz III * Tematy zaawansowane i efekty specjalne

Parametry
name GLuint: Nazwa, ktra ma zosta umieszczona na szczycie stosu nazw.
Nazwy selekcji s liczbami cakowitymi bez znaku.
Zwracana warto Brak.
Przykad Poniszy kod z programu PLANETS przedstawia adowanie nazwy na
Patrz take stos nazw, tu przed przystpieniem do renderowania obiektu.
// Ustawienie koloru materiau na ty //
Soce
glRGB(255, 255, 0);
glLoadName( S U N ) ;
auxSolidSphere( 1 5 . Of);
gllnitNames, glPushName, glRenderMode, glSelectBuffer

gIPassThrough
Przeznaczenie Umieszcza znacznik w buforze sprzenia zwrotnego.
Plik nagwkowy
Skadnia Opis void glPassThrough(GLfloat token);
Gdy OpenGL zostanie przeczony do trybu sprzenia zwrotnego, w
buforze ramki nie s rysowane adne piksele. Zamiast tego w buforze
sprzenia zwrotnego jest umieszczana informacja o rysowanych
prymitywach. Ta funkcja umoliwia umieszczenie w buforze elementu
GL_PASS_THROUGH_TOKEN, a zaraz po nim wskazanej
zmiennoprzecinkowej wartoci. Funkcja jest wywoywana w kodzie
renderujcym i poza trybem sprzenia zwrotnego nie wywouje adnego
efektu.
Parametry
token GLfloat: Warto, ktra ma zosta umieszczona w buforze sprzenia
zwrotnego bezporednio po elemencie GL_PASS_THROUGH_TOKEN.
Zwracana warto Brak.
Przykad Poniszy kod z programu SELECT demonstruje czne uycie funkcji
gIPassThrough i glLoadName w celu zidentyfikowania obiektu. W ten
sposb obiekt jest zaznaczany zarwno w buforze selekcji, jak i w
buforze sprzenia zwrotnego.
// Ustawienie koloru materiau na ty //
Kostka
glRGB(255, 255, 0) ;
glLoadName(CUBE);
gIPassThrough((GLfloat)CUBE);
auxSolidCube(75.0f);

Patrz take glFeedbackBuffer, glRenderMode


Rozdzia 19. Grafika interaktywna 609

gIPopName
Przeznaczenie Zdejmuje (usuwa) nazw ze szczytu stosu nazw.
Plik
nagwkowy void glPopName(void);
Skadnia Opis Stos nazw jest uywany podczas selekcji w celu identyfikacji rysowanych
obiektw. Ta funkcja powoduje usunicie nazwy ze szczytu stosu nazw.
Zwracana Biec wysoko stosu nazw mona odczyta wywoujc funkcj glGet z
warto parametrem GL_NAME_STACK_DEPTH.
Przykad Brak.
Poniszy kod z programu MOONS umieszcza na stosie nazw nazw planety
oraz nazwy jej ksiycw. Ten kod ilustruje zwaszcza zdejmowanie ze stosu
nazwy pierwszego ksiyca przed umieszczeniem na nim nazwy nastpnego
ksiyca.
// Rysowanie Marsa
glRGB(255,0,0) ;
glPushMatrix ( ) ;
glTranslatef ( l O O . O f , O . O f , O . O f ) ;
glLoadName (MARS) ;
auxSolidSphere (20. Of) ;
// Rysowanie pierwszego ksiyca
glTranslatef (-40. Of, 40. Of, O . O f ) ;
glRGB(220,220,220) ; glPushName (MOON1) ;
auxSolidSphere (5.0f ) ; gIPopName ( ) ;
// Rysowanie drugiego ksiyca
glTranslatef ( O . O f , -80. Of, O . O f ) ;
glPushName (MOON2) ; auxSolidSphere (5 .
Of ) ; gIPopName ( ) ; glPopMatrix ( ) ;
gllnitNames, glLoadName, glRenderMode, glSelectBuffer, glPushName

glPushName
Patrz take

Przeznaczenie Odkada nazw na szczyt stosu nazw.


Plik
nagwkowy void glPushName(GLuint name);
Skadnia Opis Stos nazw jest uywany do nazywania prymityww lub grup prymityww
podczas renderowania w trybie selekcji.
Ta funkcja odkada podan nazw na szczyt stosu nazw, w celu
zidentyfikowania nastpnych prymityww rysowanych poleceniami
graficznymi. Biec wysoko stosu nazw mona odczyta wywoujc
610 Cz III Tematy zaawansowane i efekty specjalne

funkcj glGet z parametrem GL_NAME_STACK_DEPTH, za wysoko


maksymaln- wywoujc t funkcj z parametrem
GL_MAX_NAME_STACK_DEPTH. Maksymalna wysoko stosu nazw
zaley od implementacji, jednak wszystkie implementacje musz obsugiwa
stos o wysokoci co najmniej 64 pozycji.
Parametry

name GLuint: Nazwa, ktra ma zosta odoona na szczyt stosu nazw. Nazwy
selekcji s liczbami cakowitymi bez znaku.
Zwracana warto Brak.
Przykad Poniszy kod z programu MOONS umieszcza na stosie nazw nazw planety
oraz nazwy jej ksiycw. Ten kod ilustruje zwaszcza odkadanie na stos
nazw ksiycw, po odoeniu na niego nazwy planety. Nazwa pierwszego
ksiyca jest zdejmowana ze stosu przed umieszczeniem na nim nazwy
nastpnego ksiyca.
// Rysowanie Marsa
glRGB(255,0,0) ;
glPushMatrix() ;
glTranslatef(lOO.Of, O.Of, O . O f ) ;
glLoadName(MARS);
auxSolidSphere(20. Of) ;
// Rysowanie pierwszego ksiyca
glTranslatef(-40.Of, 40.Of,
O . O f ) ; glRGB(220,220,220) ;
glPushName(MOON1) ;
auxSolidSphere(5.0f) ; glPopName();
// Rysowanie drugiego ksiyca
glTranslatef( O . O f , -80.Of, O . O f ) ;
glPushName(MOON2);
auxSolidSphere(5.0f) ; glPopName();
glPopMatrix();
gllnitNames, glLoadName, glRenderMode, glSelectBuffer, glPopName
Patrz take

glRenderMode
Przeznaczenie Przecza OpenGL w jeden z trzech trybw renderowania.
Plik nagwkowy <gl.h>
Skadnia Opis GLint glRenderMode(GLenum mod);
OpenGL dziaa w jednym z trzech trybw renderowania:
GL_RENDER: Tryb rysowania (domylny). Efekt wywoania funkcji
rysunkowych umieszczany jest w buforze ramki.
GL_SELECT: Tryb selekcji. W tym trybie w buforze ramki nie s
dokonywane adne zmiany. Zamiast tego do bufora selekcji zapisywane
Rozdzia 19. Grafika interaktywna 611

s rekordy trafie, odpowiadajce tym prymitywom, ktre po


narysowaniu przecinaj bry widzenia. Bufor selekcji musi by
wczeniej zaalokowany i przygotowany za pomoc funkcji
glSelectBuffer.
GL_FEEDBACK: Tryb sprzenia zwrotnego. W tym trybie w buforze
ramki nie s dokonywane adne zmiany. Zamiast tego do bufora sprzenia
zwrotnego s zapisywane informacje dotyczce wierzchokw, ktre
zostayby narysowane w oknie. Bufor sprzenia zwrotnego musi by
wczeniej zaalokowany i przygotowany za pomoc funkcji
glFeedbackBuffer.
Parametry
mod GLenum: Okrela tryb rasteryzacji. Moe to by tryb GL_RENDER,
GL_SELECT lub GL_FEEDBACK. Domylnym trybem jest
GL_RENDER.
Zwracana warto Zwracana warto zaley od trybu rasteryzacji, jaki zosta ostatnio
wybrany:
GL_RENDER: Zero.
GL_SELECT: Ilo rekordw trafie zapisanych do bufora selekcji.
GL_FEEDBACK: Ilo wartoci zapisanych do bufora sprzenia
zwrotnego. Zwr uwag, e ta liczba nie oznacza iloci skopiowanych
wierzchokw.
Przykad Poniszy kod przedstawia sposb wywoania funkcji glRenderMode w celu
przejcia do trybu selekcji w programie PLANETS. Ta funkcja jest
wywoywana ponownie z argumentem GL_RENDERER w celu powrotu do
trybu rysowania oraz skopiowania rekordw trafie do bufora selekcji.
// Przetwarzanie selekcji, wywoywane w momencie
// kliknicia myszk w miejsce o wsprzdnych ( x P o s , yPos)
define BUFFER_LENGTH 64
void ProcessSelection(int xPos, int yPos)
{
// Miejsce na bufor selekcji
GLuint selectBuff[BUFFER_LENGTH];

// Licznik trafie i miejsce na widok


GLint hits, viewport[ 4 ] ;
// Przygotowanie bufora selekcji
glSelectBuffer(BUFFER_LENGTH, selectBuff);
// Pobranie widoku
glGet!ntegerv(GL_VIEWPORT, viewport);

// Przejcie do macierzy rzutowania i zachowanie jej


glMatrixMode(GL_PROJECTION); glPushMatrix();
// Zmiana trybu renderowania
glRenderMode(GL SELECT);
612______________________Cz III Tematy zaawansowane i efekty specjalne

// Ustanowienie nowej bryy widzenia jako


// jednostkowej kostki dookoa punktu wskanika //
myszy (xPos, y P o s ) , rozcigajcej si // na dwa
piksele w poziomie i w pionie. glLoadldentity();
gluPickMatrix(xPos, viewport[3] - yPos,
2 , 2 , viewport);

// Zastosowanie macierzy perspektywy


gluPerspective( 6 0 . Of, fAspect, 1 . 0 , 4 2 5 . 0 ) ;
// Wyrysowanie sceny
RenderScene();
// Zliczenie trafie
hits = glRenderMode(GL_RENDER);

// Odtworzenie macierzy rzutowania


glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Powrt do widoku modelu w celu
// normalnego renderowania
glMatrixMode(GL_MODELVIEW);
// Jeli wystpio pojedyncze trafienie, //
wywietlenie informacji iflhits == 1)
MakeSelection(selectBuff[ 3 ] };
}
Patrz take glFeedbackBuffer, gllnitNames, glLoadName, glPassThrough,
glSelectBuffer, glPushName

gISelectBuffer
Przeznaczenie Ustawia bufor uywany w trybie selekcji.
Plik nagwkowy <gl.h>
Skadnia void glSelectBuffer(GLsizei size, GLuint *buffer);
Opis Gdy OpenGL dziaa w trybie selekcji (GL_SELECT), polecenia
rysunkowe nie powoduj rysowania pikseli w buforze ramki. Zamiast tego
generuj rekordy trafie, ktre s umieszczane w buforze selekcji,
przygotowanym przez t funkcj. Kady rekord trafienia skada si z
nastpujcych danych:
Iloci nazw na stosie nazw w momencie wystpienia trafienia.
Minimalnej i maksymalnej wartoci Z wszystkich wierzchokw
prymityww przecinajcych bry widzenia. Te wsprzdne s
skalowane do rozmiaru liczby cakowitej bez znaku (232 - 1).
Zawartoci stosu nazw w momencie trafienia, poczynajc od najgbiej
pooonego elementu.
Rozdzia 19. Grafika interaktywna 613

Parametry
size GLsize: Rozmiar bufora wskazywanego przez *buffer.
buffer GLuint*: Wskanik do zaalokowanego obszaru pamici. Brak.
Zwracana warto Poniszy kod przedstawia tworzenie bufora selekcji w programie
PLANETS.
Przykad
// Przetwarzanie selekcji, wywoywane w momencie kliknicia
// myszk w miejscu o wsprzdnych ( x P o s , yPos)
tdefine BUFFER_LENGTH 64
void ProcessSelection(int xPos, int yPos)
{
// Miejsce na bufor selekcji
GLuint selectBuff[BUFFER LENGTH];

// Przygotowanie bufora selekcji


glSelectBuffer(BUFFER_LENGTH, selectBuff);
Patrz take glFeedbackBuffer, gllnitNames, glLoadName, glPushName,
glRenderMode

gluPickMatrix
Przeznaczenie Definiuje obszar selekcji, ktry moe zosta uyty w celu wyznaczenia
wyboru dokonanego przez uytkownika.
Plik nagwkowy <glu.h>
Skadnia void gluPickMatrix(GLdouble x, GLdouble y, GLdouble width,
GLdouble height, GLint viewport[4]);
Opis Ta funkcja tworzy macierz, ktra na podstawie wsprzdnychekranu
definiuje mniejsz bry widzenia w oparciu o wsprzdne ekranu,
przeznaczon do wyboru obiektw. Uywajc w tej funkcji wsprzdnych
myszy w trybie selekcji, moesz wyznaczy, ktre obiekty s wskazywane
myszk. Tworzona macierz jest mnoona przez biec macierz rzutowania.
Zwykle powiniene wic wywoa funkcj glLoadldentity przed
wywoaniem tej funkcji, nastpnie przemnoy j przez macierz
perspektywy uytej do stworzenia oryginalnej bryy widzenia. Jeli uywasz
funkcji gluPickMatrix w celu wybrania powierzchni NURBS, przed
zastosowaniem tej funkcji musisz wyczy waciwo NURBS GLU
AUTO LOAD MATRIX.

Parametry

GLdouble: rodek regionu wybierania we wsprzdnych okna.


width, height GLdouble: Szeroko i wysoko danego obszaru wybierania w
pikselach.
614 Cz III Tematy zaawansowane i efekty specjalne

viewport GLint[4]: Biecy widok. Moesz odczyta parametry biecego widoku za


pomoc funkcji glGet!ntegerv z parametrem GL_VIEWPORT.
Zwracana warto Brak.
Przykad Poniszy kod pochodzi z przykadowego programu PLANETS. Uywa tej
funkcji do utworzenia nowej bryy widzenia pokrywajcej obszar okna o
wymiarach jedynie 2 x 2 piksele, wyrodkowanego w miejscu kliknicia
myszk. Ta brya jest uywana do wybrania obiektu znajdujcego si
bezporednio pod wskanikiem myszy.
// Licznik trafie i miejsce na widok GLint
hits, viewport[ 4 ] ;
// Przygotowanie bufora selekcji
glSelectBuffer(BUFFER_LENGTH, selectBuff);
// Pobranie widoku
glGetIntegerv(GL_VIEWPORT, viewport);
// Przejcie do macierzy rzutowania i zachowanie jej
glMatrixMode(GL_PROJECTION); glPushMatrix();

// Zmiana trybu renderowania


glRenderMode(GL_SELECT);
// Ustanowienie nowej bryy widzenia jako jednostkowej //
kostki dookoa punktu wskanika myszy (xPos, yPos), //
rozcigajcej si na dwa piksele w poziomie // i w pionie.
glLoadldentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2 , 2 , viewport);

// Zastosowanie macierzy perspektywy


gluPerspective(45.0f, fAspect, 1 . 0 , 425.0);

// Wyrysowanie sceny
RenderScene ();
// Zliczenie trafie
hits = glRenderMode(GL_RENDER);

// Jeli wystpio pojedyncze trafienie, //


wywietlenie informacji iffhits == 1)
ProcessPlanet(selectBuff[ 3 ] );
// Odtworzenie macierzy rzutowania
glMatrixMode(GL_PROJECTION);
glPopMatrix();

// Powrt do widoku modelu w celu //


normalnego renderowania
glMatrixMode(GL_MODELVIEW);
glGet, glLoadldentity, glMultMatrix, glRenderMode, gluPerspective

Patrz take
Rozdzia 20.
OpenGL w Sieci: VRML
OpenGL ma wiele zastosowa. W tym rozdziale omwimy jedno z nich, ktre stao si
ostatnio bardzo popularne: rzeczywisto wirtualn.

OpenGL doskonale nadaje si do penienia wielu funkcji zwizanych z modelowaniem i


grafik, stanowi take technologi dobrze przygotowan do celw rzeczywistoci wir-
tualnej. Te komputerowo generowane wiaty", w ktrych mona zanurzy wiele zmysw
uytkownika, zawieraj trjwymiarowe sceny, cznie z dwikami, a czasem nawet
reakcj zwrotn poprzez siowniki. Niektre produkty oferuj technologi tak za-
awansowan, e obejmuje rkawice z siownikami, trjwymiarowe gogle oraz oprogra-
mowanie w stylu trjwymiarowej gry komputerowej, umoliwiajcej poruszanie si we
wszystkich kierunkach cyfrowego wiata.

Internet, bdc o wiele dojrzalsz technologi ni rzeczywisto wirtualna, ostatnio staje


si coraz bardziej popularnym polem dziaania dla entuzjastw komputerw - nie
wspominajc oczywicie o profesjonalnych, naukowych i militarnych uytkownikach, dla
ktrych by pierwotnie przeznaczony. Obecnie niewiele ju chyba osb nie syszao
terminu cyberprzestrze - oznaczajcego osobny wiat komputerw w sieci, w ktrym
mona odwiedza wiele miejsc i spotyka wiele osb - za chyba kademu uytko-
wnikowi komputera zdarzyo si wdrowa po tej sieci i wyszukiwa dostpne w niej
informacje.

W tym rozdziale omwimy pokrtce implementacj rzeczywistoci wirtualnej w Inter-


necie, ktrej pocztki wywodz si wanie z OpenGL. Zakadamy przy tym, e posiadasz
ju pewn znajomo zagadnie Internetu, sieci WWW (czyli World Wide Web lub po
prostu Sieci) oraz przegldarek WWW, takich jak Internet Explorer czy Netscape
Navigator.

Na styku dwch wiatw


Niezbyt dugo trwao, zanim kto dostrzeg cise powizania pomidzy cyberprzestrze-ni
a rzeczywistoci wirtualn. W cyberprzestrzeni moesz podrowa po wiecie,
616 Cz III Tematy zaawansowane i efekty specjalne

odwiedzajc rne miejsca (strony WWW) i zbierajc rne rodzaje informacji. Byoby
wic sensowne, gdyby mona to byo robi w jakim wizualnym rodowisku, a nie tylko
poprzez seri trudnych do przebrnicia tekstowych opisw.

Graficzna nawigacja w Internecie pierwszy raz pojawia si, gdy Tim Berners-Lee z
CERN (europejskie centrum fizyki nuklearnej) w Genewie opracowa zestaw protokow
umoliwiajcych atwe zakodowanie poczenia pomidzy rnymi plikami zawartymi w
archiwach FTP. Te poczenia wizay ze sob dokumenty z innymi dokumentami o
powizanej treci, umoliwiajc przechodzenie z dokumentu do dokumentu, i to nawet w
innej kartotece, w innym komputerze czy na innym kontynencie. W tych protokoach
zostay wykorzystane nazwy URL (Universal Resource Locator), identyfikujce pooenie
dokumentw i stanowice podstaw sieci WWW.

Wkrtce po tym, Marc Andersen (ktry pniej zaoy Netscape Communications Cor-
poration) stworzy przegldark Sieci, ktra moga czy rne rodzaje plikw, cznie z
tekstem i grafik, w pojedyncz prezentacj. T przegldark by NCSA Mosaic, ktry
mg reprezentowa powizania pomidzy dokumentami, a take wykorzystywa
specjalny jzyk definiujcy format dokumentw z osadzonymi obrazkami i rnymi
rodzajami tekstu. Od tego momentu Internet nie by ju taki jak przedtem. W cigu nie-
caego roku, Internet z wycznej domeny profesjonalistw przeksztaci si w dostpny
dla kadego wirtualny wiat, umoliwiajcy dotarcie do kadego miejsca po kilku kli-
kniciach myszk.

Dwuwymiarowa nawigacja
Rysunek 20.1.
Typowa strona
WWW z czami
hipertekstowymi

Strony WWW to najczciej dokumenty tekstowe stworzone w specjalnym jzyku na-


zywanym HTML (HyperText Markup Language). W dokumentach HTML mona osadza
inne dokumenty, grafik, rwnie wideo i dwik, a take hipertekstowe cza do innych
dokumentw i serwerw WWW. Rysunek 20. l przedstawia typow stron g-
Rozdzia 20. OpenGL w Sieci: VRML_______________________________617

wn WWW; pokazana strona naley do Silicon Graphics i w duym stopniu wypeniona


jest grafik. Po klikniciu na przycisk obok interesujcego ci tematu lub na aktywny"
obszar wikszego obrazka, zostaniesz przeniesiony na inn stron, zawierajc kolejne
informacje oraz nowy zestaw kategorii i cz do innych stron.

VRML
Graficzna, cho wci dwuwymiarowa metoda nawigacji po Sieci w cigu kilku lat staa si
niezwykle popularna. Taka nawigacja" po cyberprzestrzeni jest bardzo efektywna i
wygodna, pod warunkiem, e przeszukiwane informacje mog by przedstawione w
postaci dokumentw. Jednak wiat nie jest bibliotek, za moliwo przedstawienia
wszystkiego jako dwuwymiarowego obrazu jest w znacznym stopniu ograniczona.

W 1994 roku Mark Pesce i Tony Parisi stworzyli nowy typ dokumentu i przegldarki
WWW, ktra umoliwiaa poruszanie si po trjwymiarowych dokumentach. Na dzie
w. Walentego 1994 roku powsta pierwszy trjwymiarowy serwer WWW. Serwer umo-
liwia poruszanie si w przestrzeni 3D i klikanie na obiekty, stanowice cza do innych
scen 3D lub zwykych stron HTML.

Trjwymiarowe sceny byy opisane za pomoc nowego jzyka skryptw, VRML (Vir-tual
Reality Markup Language lub Yirtual Reality Modeling Language). Silicon Graphics
(SGI), wiatowy lider w technologii grafiki komputerowej, zdecydowa si na
publiczne udostpnienie swojego jzyka opisu sceny Open Inventor, ktry sta si pod-
staw dla VRML w wersji l .0.

Sowo na temat Open Irwentora


Open Irwentor to interfejs modelowania 3D o znacznie
wyszym poziomie ni samo API OpenGL. Open lnventor to
biblioteka klas C++ stanowica nadbudow OpenGL.
Programici i narzdzia programistyczne uywaj tej biblioteki
przy tworzeniu zoonych scen 3D oraz obiektw, ktre byyby
zbyt skomplikowane, aby tworzy je rcznie, przy uyciu
samego OpenGL. Obiekty Open lnventora (w sensie C++)
posiadaj cech zwan trwaoci, ktra umoliwia
zapisywanie i pniejsze odczytywanie ich z dysku. SGI
udostpnio programistom VRML darmowy kod rdowy, ktry
jest uywany do przetwarzania skryptw opisu scen,
uywanego przez Open lnventor do przechowywania w binarnej
postaci scen i obiektw 3D, na informacje przydatne podczas
rende-rowania obiektw sceny. Open lnventor zostanie opisany
bardziej szczegowo w dalszej czci rozdziau.

Po udostpnieniu przez SGI darmowego kodu rdowego, od kwietnia 1995 VRML


sta si ulubiecem popularnej prasy Internetowej. Na rynku pojawiy si przegldarki
VRML rnych producentw, dla wszystkich popularnych platform cznie z komputerami
osobistymi. Obecnie istniejca technologia pozwala uytkownikom na co wicej ni tylko
wybieranie polecenie z menu. Obecnie mona spacerowa przez wirtualn bibliotek,
muzeum czy nawet sklep oraz wybiera i oglda interesujce nas obiekty.
618 ____ Cz III Tematy zaawansowane i efekty specjalne

WebSpace
Oczywicie, to Silicon Graphics bya pierwsz firm, ktra stworzya w peni zgodn,
komercyjnie dostpn przegldark VRML. Przegldarka nosia nazw WebSpace i sta-
nowia standard, z ktrym porwnywane byy wszystkie inne przegldarki VRML.
WebSpace zostaa zaprojektowana do dziaania na wasnych stacjach roboczych SGI,
jednak niezalena firma, Template Graphics Software, otrzymaa pozwolenie na opraco-
wanie wersji programu dla Microsoft Windows i innych platform. Wszystkie wersje tej
przegldarki w peni obsuguj standard VRML 1.0 i do renderowania scen wykorzystuj
OpenGL.
Instalacja
WebSpace moe zosta zainstalowana jako pomocnicza aplikacja wikszoci przegldarek
WWW. Aby uzyska informacje na temat sposobu instalacji, zajrzyj do pliku
README swojej przegldarki. WebSpace aduje plik VRML z rozszerzeniem .wrl, a
take pliki scen Open Inventora z rozszerzeniem .iv. Dodatkowo, najnowsza wersja
WebSpace z Template Graphics automatycznie aduje pliki .wrl skompresowane jako
gzip, w popularnym w Internecie formacie kompresji. Dziki temu mamy do czynienia ze
znacznie mniejszymi plikami, ktre mona o wiele szybciej cign.

WebSpace na pytce CD-ROM


Kopia przegldarki WebSpace dla Microsoft Windows jest
dostpna take na doczonej do ksiki pytce CD-ROM, w
kartotece \TGS\ WebSpace. Oprogramowanie i przykadowe
sceny zostay doczone dziki uprzejmoci firm Silicon
Graphics Inc. i Template Graphics Software. Te pliki s
dostpne jako Shareware. Jeli chcesz ich uy do czego
wicej ni do zabawy, powiniene zarejestrowa swoj
kopi. Informacje na temat uzyskania licencji znajdziesz w
pliku README.

Tryb spacerowy
Przegldarka WebSpace moe dziaa w dwch trybach. Pierwszym z nich jest tryb spa-
cerowy (Walk Yiewer), ktry pozwala na poruszanie si po prezentowanym modelu, takim jak
muzeum czy model architektoniczny. Drugim trybem jest tryb ogldania (Examiner
Yiewer), uywany do ogldania obiektw w WebSpace, takich jak samolot, narzdzie czy
element umeblowania. Wkrtce poznasz oba tryby w dziaaniu.
Rysunek 20.2 przedstawia przegldark WebSpace podczas przegldania przykadowej
sceny VRML w trybie spacerowym. Ten tryb jest uywany do poruszania si w trjwy-
miarowej scenie. Moe ni by nieskomplikowany trjwymiarowy teren, architektoniczny
widok budynku, dom towarowy czy nawet obszar maego miasta.
Rozdzia 20. OpenGL w Sieci: VRML 619

Rysunek
20.2.
Przegldarka
WebSpace
dziaajca \v trybie

Szczegowe instrukcje na temat uycia programu


Ten rozdzia stanowi wprowadzenie do VRML i rzeczywistoci
wirtualnej w Internecie. Programu WebSpace uywamy jako
punktu wyjcia przy demonstrowaniu podstawowych koncepcji
nawigacji po trjwymiarowych scenach. Szczegowe informacje
na temat uywania przegldarki WebSpace znajdziesz w pliku
README i plikach pomocy doczonej do programu.

Niektre obiekty w scenie mog by poczone z innymi stronami lub dokumentami


HTML, podobnie jak w zwykej stronie WWW. Kontrolki w dolnej czci okna nosz
wspln nazw deski rozdzielczej; s uywane do nawigowania w obrbie sceny.
Czworoktny przycisk po lewej stronie to przycisk wyszukiwania; pomaga w szybkim
przejciu do wskazanego punktu sceny. Aby go uy, kliknij na niego przechodzc do
trybu wyszukiwania, a nastpnie kliknij w dowolne miejsce sceny. Nawigator pynnie
przejdzie we wskazane miejsce, bez koniecznoci uycia jakiegokolwiek innego na-
rzdzia do nawigacji.
Przycisk po prawej stronie suy do przesuwania widoku sceny w poziomie i w pionie.
Widok jest przesuwany jedynie w osiach x i y (w poziomie i w pionie). Kierunek wi-
dzenia nie jest pochylany w adn stron.
Wreszcie, na rodku deski rozdzielczej znajduje si joystick - uywany do poruszania si
do przodu i do tyu w scenie, obracania si w lewo i w prawo, a take pochylania
gowy" w d i podnoszenia w gr. Po prostu kliknij na joystick i przecignij go
620 Cz III Tematy zaawansowane i efekty specjalne

w gr lub w d, aby przej do przodu lub do tyu albo w lewo lub w prawo, aby obrci
si w wybranym kierunku.

Nawigacja w trzech wymiarach


Trjwymiarowy interfejs przegldarki WebSpace pozostawia
wiele do yczenia. Dziaa podobnie jak interfejs symulatora
lotu lub gry zrcznociowej i z pewnoci mona by go
uzupeni o wiele przydatnych moliwoci. Moesz oczekiwa,
e w najbliszych latach takie interfejsy zostan znacznie
usprawnione, gdy tylko pojawi si wiksza liczba
przegldarek.

Po prawej stronie joysticka znajduje si czerwona gaka, suca do pochylania gowy w


d lub podnoszenia jej w gr. Kliknij na ni i przecignij myszk w gr, aby
podnie gow, lub w d, aby spojrze w kierunku podogi. Na rysunku 20.3 uyto tej
gaki w celu spojrzenia w kierunku podogi.

Rysunek 20.3.
Dziki uyciu gaki
najoysticku moemy
spojrze w kierunku
podogi

Tryb ogldania
Tryb ogldania, jak sama nazwa wskazuje, umoliwia blisze przyjrzenie si obiektom.
Rysunek 20.4 przedstawia przegldark WebSpace podczas ogldania modelu komputera.
Wyobra sobie, e wdrujesz po wirtualnym muzeum w trybie spacerowym, a nastpnie
klikasz na may obrazek komputera. Gdy przegldarka przeczy si w tryb ogldania,
moesz przyjrze si komputerowi bliej. Oprcz tego, moesz mie do dyspozycji inne
hipertekstowe cza prowadzce do opisu komputera, gier komputerowych itd.
Rozdzia 20. OpenGL w Sieci: VRML 621

Rysunek 20.4.
Tryb ogldania

Jak wida, deska rozdzielcza w trybie ogldania wyglda podobnie jak w trybie space-
rowym, z tym e joystick zosta zastpiony trackballem i pokrtem. Pokrto umoliwia
zblianie si do obiektu lub oddalanie od niego. Kliknij na pokrto i przecignij je w
gr, aby oddali si od obiektu, lub w d, aby si przybliy. Rysunek 20.5 przedstawia
model komputera z wikszej odlegoci.

Rysunek 20.5.
Model komputera w
trybie ogldania,
widziany z nieco
wikszej odlegoci
622_______________________Cz III Tematy zaawansowane i efekty specjalne

Za pomoc trackballa moesz obraca obiekt w rnych kierunkach. Kliknij w dowolne


miejsce trackballa i przecignij myszk obracajc obiekt. Jeli podczas przecigania
zwolnisz przycisk myszy, obiekt w dalszym cigu bdzie si obraca.

Open liwentor i VRML


Aby zrozumie powizania pomidzy Open Inventorem a VRML, powiniene zdoby
nieco wicej informacji na temat Open Inventora. Ta obiektowo zorientowana biblioteka
oraz zestaw narzdzi jest zaimplementowana przy uyciu OpenGL. Biblioteka pro-
gramowa prawie zawsze wykorzystywana jest z C++, lecz istniej take elementy
umoliwiajce poczenie jej z C. Takie obiektowo zorientowane podejcie zapewnia
duo wyszy stopie kontroli nad kompozycj obiektw i sceny.

Gdy do tworzenia sceny lub obiektu jest uywany OpenGL, kada funkcja i polecenie
wywiera natychmiastowy wpyw na bufor ramki. Dopki nie uywasz podwjnego
buforowania, wynik kadej instrukcji jest od razu widoczny na ekranie. Nazywa si to
renderowaniem w trybie natychmiastowym.

Z kolei Open Inventor operuje w tzw. trybie wstrzymywanym. W tym trybie, uywane
polecenia i funkcje su do utworzenia bazy danych sceny. Dopiero potem baza danych
obiektw i materiaw jest renderowana w caoci i tworzy scen na ekranie. Du
zalet tego trybu jest to, e bardzo atwo mona programowo manipulowa poszczeglnymi
obiektami sceny. Co wicej, mona ustanowi powizania pomidzy obiektami, co
umoliwia manipulowanie jednym obiektem poprzez manipulowanie innym obiektem
(na przykad elementami przekadni w modelach mechanicznych). Dziki obiektom
biblioteki Open Inventor mona atwo obraca obiekty, animowa je i wykonywa inne
operacje. Informacja o modyfikacji obiektu jest umieszczana w bazie danych, bez
koniecznoci stosowania adnego dodatkowego kodu.

Specyfikacja VRML 1.0 jest oparta wycznie na formacie wymiany dla trjwymiaro-
wych" plikw Open Inventora. Ten format plikw, stanowicy po prostu ustandaryzo-
wany opis ukadu obiektw w scenie, umoliwia projektantom 3D atw modyfikacj
obiektw i scen za pomoc rnych narzdzi opartych na bibliotece Open Inventor.
Dziki nim mona atwo stworzy i zapisa do pojedynczego pliku zarwno indywi-
dualne obiekty, jak i cae sceny wypenione obiektami.

Podsumowanie
WebSpace nie jest jedynym sposobem odwiedzenia cyberprzestrzeni w trzech wymiarach.
Wielu innych producentw (cznie z Microsoftem) przystpio do wspzawodnictwa
tworzc wasne wersje przegldarek VRML. Unikatowa cecha WebSpace to zgodno
prawie z wszystkimi przegldarkami WWW i operowanie na plikach VRML oraz Open-
Inventora, i to skompresowanych lub nie.
Rozdzia 20. OpenGL w Sieci: VRML_______________________________623

W momencie, gdy ksika trafia do druku, wrd firm programistycznych toczy si


wojna o to, kto ma ustala standardy dla VRML w wersji 2.0. W tej nowej wersji maj
si znale nowe funkcje przeznaczone dla animacji i rozszerze multimedialnych w
scenach przeznaczonych do ogldania przez Internet.
Czy rzeczywisto wirtualna dostpna przez Internet to tylko przemijajca moda czy te
pocztek rewolucji? Tylko czas to pokae, mona jednak ufa sprawdzonemu stwier-
dzeniu, e apetyt ronie w miar jedzenia. Gdy sieci komputerowe bd dziaa z wiksz
szybkoci i stabilnoci, za w komputerach pojawi si lepszy sprzt graficzny, moesz
by pewien, e w naszych systemach zadomowi si take rzeczywisto wirtualna, ktra
coraz lepiej, coraz szybciej i coraz bardziej szczegowo bdzie odzwierciedla
rzeczywisty wiat.
OpenGL i...
W czwartej i ostatniej czci tej ksiki zajmiemy si kilkoma oglnymi zagadnieniami programowania
zwizanymi z uywaniem OpenGL. Dwa rozdziay zostay przeznaczone dla programistw C++ uywajcych
dwch najpopularniejszych bibliotek klas C++ w Windows: MFC i OWL. Nie opucimy take w potrzebie
programistw korzystajcych z jzykw 4GL i innych wizualnych" narzdzi, takich ja Visual Basic. W rozdziale
23. zaprezentujemy tworzenie kontrolek OCX OpenGL, ktre mog by wykorzystane praktycznie w kadym
32-bitowym rodowisku programowania dla Windows.
Ponadto, adna ksika o Windows i OpenGL nie moe si obej bez opisu zagadnie dotyczcych
wspdziaania OpenGL z innymi graficznymi interfejsami API. Oprcz GDI, nale do nich take architektura
DirectK oraz 3DDDI.
Rozdzia 21.
OpenGL i MFC
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje

Ustawi styl okna MFC, aby speniao wymagania PreCreateWindow


OpenGL
Stworzy i przygotowa kontekst renderowania OnCreate
Usun kontekst renderowania na zakoczenie OnDestroy
dziaania programu
Rozmieci kod rzutowania i widoku OnSize
Rozmieci kod renderowania OnDraw
Zabezpieczy si przed migotaniem okna pomidzy OnEraseBkgnd
renderowaniami
Rozmieci kod zarzdzajcy palet OnQueryNewPalette,
OnPaletteChanged

Obecnie coraz wiksza liczba programistw przy tworzeniu aplikacji dla Windows ko-
rzysta z C++. Jak dotd w treci ksiki prezentowalimy jedynie kod napisany w C. Na
szczcie, wikszo programistw C++ doskonale daje sobie rad z analiz programw
napisanych w C. Niestety, nie jest to ju tak powszechne w odwrotnej sytuacji (wielu
programistw C ma kopoty ze zrozumieniem kodu C++). Nie twierdzimy, e C++ jest
znacznie trudniejszy w opanowaniu, lecz gdy sigasz po ksik na temat grafiki kom-
puterowej z zamiarem opanowania wanie tego tematu, raczej nie chcesz przy okazji
uczy si nowej skadni jzyka.

Cho wikszo przykadw w ksice mona skompilowa zarwno za pomoc kom-


pilatora C, jak i C++, wikszo programistw C++ tworzcych aplikacje dla Windows
nie pisze kodu w C. Zamiast niego najczciej uywaj komercyjnych pakietw progra-
mistycznych lub wasnych bibliotek klas C++. Rnica polega na tym, e wikszo
628________________________________________Cz IV OpenGL i...

aplikacji C++ nie zawiera procedur takich jak przedstawione w tej ksice ani tych in-
strukcji case z pieka rodem", obsugujcych komunikaty przekazywane do okien.
Celem tego rozdziau jest pomoc programicie C++ w wykorzystaniu jednej z popularnych
bibliotek klas C++ jako punktu wyjcia dla wasnych aplikacji C++. Bibliotek klas
opisywan w tym rozdziale jest MFC (Microsoft Foundation Classes). Przykady i zrzuty
okien wystpujce w tym rozdziale zostay przygotowane przy uyciu Microsoft Yisual
C++ 5.0. Inne kompilatory i pakiety wykorzystujce MFC powinny dziaa podobnie.

Uwaga:
Jeli uywasz OWL (Object Windows Library Borlanda), przejd
do rozdziau 22.

Piszc ten rozdzia, zakadalimy, e ju sam potrafisz zrobi pewne rzeczy:


* Umiesz wykorzysta Yisual C++ i MFC do tworzenia aplikacji dla Windows NT i
Windows 95.
* Opanowae materia z czwartego rozdziau tej ksiki, opisujcy OpenGL dla
Windows oraz uycie kontekstw renderowania.
* Rozumiesz zagadnienia zwizane z obsug palety, opisywane w rozdziale 8.

Wydzielenie kodu zwizanego z OpenGL


W przypadku kadej aplikacji dobrym pomysem jest uczynienie kodu rdowego na
tyle modularnym, na ile to jest moliwe. Wydzielajc funkcjonalne fragmenty kodu,
mona duo atwiej konserwowa i ponownie wykorzystywa poszczeglne procedury.
Przez oddzielenie czystego" kodu OpenGL w osobnym module, moesz efektywnie
zastpowa ten modu specyficznym kodem, zachowujc przy tym funkcjonalno
reszty aplikacji. Dziki temu, stosunkowo atwo byo przekonwertowa przedstawiony w
tym rozdziale przykad w C na program w C++, wykorzystujcy bibliotek MFC.
Zaczniemy od zadeklarowania trzech funkcji w pliku rdowym C, glcode.c. Plik
glcode.h zawiera deklaracje tych funkcji i jest wczany do pliku implementacji naszej
klasy, wyprowadzonej z klasy CYiew, w celu umoliwienia dostpu do funkcji.
// glcode.h
// Deklaracje dla zewntrznego moduu OpenGL. Te funkcje s
// zaimplementowane w pliku glcode.c i s wywoywane z wntrza
// funkcji skadowych klasy wyprowadzonej z CView.
#ifndef _GLCODE_
define _GLCODE_

extern "C" {
Rozdzia 21. OpenGL i MFC____________________________________629

void GLSetupRC(void *pData);


void GLRenderScene(void *pData); void
GLResize(GLsizei h, GLsizei w ) ; }

Funkcja GLSetupRC zawiera cay kod zwizany z inicjowaniem kontekstu renderowania.


Zawarty w niej kod moe by bardzo prosty, przygotowujcy jedynie kolor czyszczenia ta,
lub do skomplikowany, okrelajcy warunki owietlenia. Funkcja GLRenderScene bdzie
wywoywana z wntrza metody OnDraw naszej klasy widoku (wyprowadzonej z CYiew)
w celu wyrysowania sceny. Na koniec, funkcja GLResize bdzie wywoywana z procedury
obsugi komunikatu WM _SIZE (metody OnSize), z przekazan now szerokoci i
wysokoci obszaru roboczego okna. Moesz w niej zawrze wymagane obliczenia
zwizane z ustanowieniem nowego widoku i bryy widzenia.
Zwr uwag, e funkcje GLSetupRC i GLRenderScene otrzymuj wskaniki typu
void. Dziki temu do funkcji renderujcej moesz przekazywa dane dowolnego typu,
bez koniecznoci pniejszych zmian interfejsu. Cho moglibymy z pliku glcode.c
uczyni plik C++, atwiej jest skopiowa istniejcy kod C z dowolnego rda i wstawi go
do programu MFC. Yisual C++ po prostu skompiluje ten plik jako plik C i poczy go z
reszt aplikacji.
W tym miejscu nie bdziemy prezentowa zawartoci pliku glcode.c, gdy ten plik jest
do dugi, a jeli koniecznie chcesz si z nim zapozna, moesz go skopiowa z pytki
CD-ROM. Ponadto, ten sam plik zostanie wykorzystany w przykadzie dla OWL w na-
stpnym rozdziale.

Zaczynamy od AppWizarda
Wiele aplikacji napisanych w C++ zaczyna istnienie od AppWizarda. Architektur do-
kumentu-widoku mona porwnywa z architektur modelu-widoku w innych obie-
ktowo zorientowanych rodowiskach programistycznych. Nawet w przypadku szybkich,
prbnych aplikacji lub eksperymentalnych projektw, AppWizard moe w nieca minut
utworzy aplikacj SDI (z pojedynczym dokumentem), MDI (z wieloma dokumentami)
lub opart na oknie dialogowym. Tak wic sensownie bdzie uy wanie AppWizarda w
celu stworzenia szkieletu aplikacji SDI MFC, w ktrej pniej wykorzystamy take
OpenGL. Aby stworzy prost scen OpenGL, dodamy funkcje i zmienne do klasy wi-
doku, wyprowadzonej z CYiew. Podobnych metod bdziesz mg uy w celu dodania
elementw OpenGL do kadej klasy wyprowadzonej z CWnd.

Budowanie szkieletu
Zaczniemy od zbudowania szkieletu aplikacji SDI za pomoc AppWizarda, pomijajc
opcje zwizane z dostpem do baz danych i funkcjonalnoci OLE. Rysunek 21.1
przedstawia oryginaln szkieletow aplikacj SDI stworzon przez AppWizarda.
630 Cz IV OpenGL i
Rysunek 21.1.
Oryginalna
szkieletowa
aplikacja SDI
stworzona przez
AppWizarda

By moe zechcesz take wyczy opcj wydruku (Print) i podgldu wydruku (Print
Preview). Sceny OpenGL mog by renderowane w kontekcie urzdzenia drukarki tylko
wtedy, gdy drukarka jest drukark kolorow obsugujc co najmniej cztery lub wicej
bitplanw koloru (16 lub wicej kolorw). Drukowanie na monochromatycznej drukarce
laserowej lub mozaikowej take jest moliwe, lecz do kopotliwe. Przykad kodu
sucego do drukowania scen przy uyciu nowych elementw OpenGL w wersji l. l
znajdziesz w uzupeniajcym przykadzie GLPRTNT, na pytce CD-ROM, w folderze
\OPENGL11 \SAMPLES\GLPRINT.

Dodawanie bibliotek
Zanim zaczniemy dodawa do szkieletu aplikacji jakikolwiek kod OpenGL, musimy
doda do projektu biblioteki OpenGL. W tym celu wybierz w menu polecenie Project/
Settings. Rysunek 21.2 przedstawia miejsce, gdzie powiniene dopisa nazwy bibliotek
OpenGL. By moe dodasz do projektu take inne biblioteki, w zalenoci od potrzeb
swojej aplikacji. Na rysunku zostay przedstawione jedynie pliki wymagane dla aplikacji
OpenGL.
Oprcz tego bdziesz musia doda do projektu pliki nagwkowe OpenGL. Najlepiej
umieci je w pliku stdafx.h (a potem mona ju o nich zapomnie). Dopisz po prostu
dwie ponisze linie wczajce pliki nagwkowe, ktre zostan dopisane take do pre-
kompilowanego pliku nagwkowego:
tinclude <gl\gl.h> // Biblioteka OpenGL
tinclude <gl\glu.h> // Biblioteka GLU OpenGL
Rozdzia 21. OpenGL i MFC 631

Rysunek 21.2.
Dodawanie bibliotek
OpenGL do projektu
VisualC++

Przygotowanie klasy widoku dla OpenGL


Gdy uyjesz architektury dokument-widok przygotowanej przez AppWizarda dla aplikacji
SDI, otrzymasz klas wyprowadzon z CYiew, odpowiedzialn za prezentacj
wynikw dziaania twojej aplikacji. W naszym przykadzie ta klasa nosi nazw CMfcgl-
Yiew. Jest zadeklarowana w pliku mfcglYiew.h, za zaimplementowana w pliku mfcgl-
Yiew.cpp.
Najwaniejszym wymaganiem co do okien, ktre maj by uywane przez OpenGL,
jest zastosowanie stylw okna WS_CLIPCHILDREN oraz WS_CLIPSIBLINGS. Mo-
emy je atwo doda wewntrz wirtualnej funkcji skadowej PreCreateWindow naszej
klasy okna (ta funkcja jest domylnie wstawiana do pliku mfcglYiew.cpp). Dziki tej
funkcji moemy modyfikowa struktur CREATESTRUCT tu przed utworzeniem
okna. Jedno z pl tej struktury zawiera style okna uywane przy jego tworzeniu. Moemy
po prostu ustawi dodatkowe bity stylu wykonujc logiczn operacj OR, na przykad
tak:
BOOL CMfcglView::PreCreateWindow(CREATESTROCT& es)

// Dodaje style okna wymagane przez OpenGL


C S . style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS l CSJDWNDC);

return CView::PreCreateWindow( e s ) ;

Zwr uwag, e ustawiamy take styl CS_OWNDC, dziki ktremu okno moe posiada
prywatny kontekst urzdzenia. Cho nie jest to rygorystycznie wymagane, powoduje
szybsze i wydajniejsze dziaanie programu. Niektre wskaniki do kontekstw urzdze
632 Cz IV OpenGL i...

zwracane przez MFC s tymczasowe i nie mog by przechowywane do pniejszego


uycia. W naszym przypadku lepiej jest pobra taki wskanik i przechowa.
W klasie CMfcglYiew przygotujemy take miejsce na kontekst urzdzenia oraz kontekst
renderowania:
public:
HGLRC m_hRC; // Kontekst renderowania
HDC m hDC; // Kontekst urzdzenia

Format pikseli i kontekst renderowania


Teraz, gdy mamy ju okno z ustawionymi stylami wymaganymi przez OpenGL, musimy
ustawi format pikseli OpenGL. Poniewa do utworzenia formatu pikseli wymagany jest
kontekst urzdzenia, musimy to zrobi ju po utworzeniu okna. Moemy uy
ClassWizarda w celu dodania procedury obsugi komunikatu WM_CREATE, wysyanego
do tego okna. Rysunek 21.3 przedstawia okno dialogowe ClassWizarda, zawierajcego
pozycj take dla komunikatu WM_DESTROY.
Rysunek 21.3.
Dodawanie pozycji
mapy komunikatw
dla komunikatw
WM_CREATE i
WM DESTROY
IOJ4PP ABOUT
10 APP_EX1T WM CTLCOLOR WM
ID~EDIT COPY DEADCHAR WM
IDlEDIT~CUT ID DELETEITEM
EDIT PASIE ID WM_DESTHOY
EDIT UNDO WM DESTROYCUPBOARD

OnDestioy
OnDiao.
PieOeaeWindow

Ustawienie formatu pikseli wewntrz procedury obsugi komunikatu WM_CREATE jest


stosunkowo proste. Listing 21.1 przedstawia nasz procedur obsugi komunikatu za-
wierajc kod przygotowujcy format pikseli dla kontekstu urzdzenia.

Listing 21.1. Procedura obsugi komunikatu WM CREATE, w ktrej przygotowujemy format pikseli____

int CMfcglView::OnCreate(LPCREATESTRUCT IpCreateStruct) {


if (CView::OnCreate( I p C r e a te S tr u c t) == -1)
return -1;
int nPixelFormat; // Indeks formatu pikseli
m hDC = : : G e t D C ( m hWnd); // Pobranie kontekstu
// urzdzenia
Rozdzia 21. OpenGL i MFC____________________________________633

static PIKELFORMATDESCRIPTOR pfd = {


sizeof(PIKELFORMATDESCRIPTOR), // Rozmiar tej struktury
l, // Wersja struktury
PFD_DRAW__TO_WINDOW | // Rysowanie w oknie (nie na
// bitmapie) PFD_SUPPORT_OPENGL
| // Obsuga wywoa OpenGL w tym
// oknie
PFD_DOUBLEBUFFER, // Tryb podwjnego buforowania
PFD_TYPE_RGBA, // Tryb kolorw RGBA
24, // Chcemy 24-bitowego koloru
0,0,0,0,0,0, // Nieuywane przy wybieraniu trybu
0,0, // Nieuywane przy wybieraniu trybu
0,0,0,0,0, // Nieuywane przy wybieraniu trybu
32, // Rozmiar bufora gbokoci
O, // Nieuywane przy wybieraniu trybu
O, // Nieuywane przy wybieraniu trybu
PFD_MAIN_PLANE, // Rysowanie na gwnym planie
O, // Nieuywane przy wybieraniu trybu
0 , 0 , 0 }; // Nieuywane przy wybieraniu trybu

// Wybranie formatu pikseli najbardziej zblionego do wskazanego


// w pfd
nPixelFormat = ChoosePixelFormat(m_hDC, Spfd);

// Ustawienie formatu pikseli dla kontekstu urzdzenia


VERIFY(SetPixelFormat(m_hDC, nPixelFormat, spfd));

// Utworzenie kontekstu renderowania


m_hRC = wglCreateContext(m_hDC);

// Uczynienie kontekstu renderowania biecym, przeprowadzenie //


inicjowanie, a nastpnie odoenie kontekstu
VERIFY(wglMakeCurrent(m_hDC,m_hRC)); GLSetupRC(m_hDC);
wglMakeCurrent(NULL, NULL) ;

// W razie potrzeby utworzenie palety


InitializePalette();

SetTimer(101,175,NULL); // 8 razy na sekund...

return 0;

Zwr uwag, e kontekst urzdzenia i kontekst renderowania przechowujemy w zmiennych


skadowych klasy, m_hDC i m_hRC. Natychmiast po stworzeniu kontekstu renderowania
czynimy go biecym i wywoujemy zewntrzn funkcj GLSetupRC. Ta funkcja
zainicjuje wymagany kontekst renderowania, po czym moemy go odoy. Dziki
temu moemy uywa kilku kontekstw renderowania, na wypadek gdybymy chcieli
zastosowa OpenGL w kilku oknach. (Nie robimy tego w naszym przykadzie, ale jeli
wykorzystasz go jako punkt wyjcia dla wasnego programu, nie bdziesz ju musia
przebudowywa caego kodu).
634________________________________________Cz IV OpenGL i...

Usuwanie kontekstu renderowania


Powinnimy pj krok dalej i zanim o tym zapomnimy, doda kod czyszczcy i usu-
wajcy kontekst renderowania. Wykorzystamy do tego procedur obsugi komunikatu
WM_DESTROY, take pokazan na rysunku 21.3. Przy okazji zwolnimy kontekst
urzdzenia pobrany tu po utworzeniu okna.
// Okno jest niszczone, wiec robimy porzdki
void CMfcglView::OnDestroy()
{
// Usuwanie timera
KillTimer( 1 0 1 ) ;

// Usunicie kontekstu renderowania...


wglDeleteContext(m_hRC);
// . . . i kontekstu urzdzenia
::ReleaseDC(m_hWnd,m_hDC);
CView::OnDestroy();

Obsuga zmiany rozmiaru okna


Gdy zmienia si rozmiar okna, otrzymuje ono komunikat WM_SIZE. Za pomoc
ClassWizarda dodamy procedur obsugi tego komunikatu i z jej wntrza wywoamy
zewntrzn funkcj GLResize, przekazujc jej nowe wymiary obszaru roboczego okna.
Przed wywoaniem tej funkcji musimy uczyni kontekst renderowania biecym, gdy w
przeciwnym razie wywoania funkcji OpenGL w funkcji GLResize nie przynios
efektu. Oto kod procedury obsugi:
void CMfcglView::OnSize(UINT nType, int ex, int cy) {
CView::OnSize(nType, ex, cy);

VERIFY(wglMakeCurrent(m_hDC,m_hRC));
GLResize( e x , cy);
VERIFY(wglMakeCurrent(NULL,NULL));

Renderowanie sceny
Teraz moemy doda kod odpowiedzialny za renderowanie sceny w OpenGL. Metoda
OnDraw klasy widoku jest wywoywana za kadym razem, gdy okno otrzymuje komunikat
WM_PAINT. Wewntrz tej metody wybieramy kontekst renderowania jako biecy i
wywoujemy funkcj GLRenderScene, zawierajc jedynie wywoania funkcji OpenGL.
Poniewa wczeniej zadalimy trybu z podwjnym buforowaniem, zaraz po tym
wywoujemy funkcj SwapBuffers i odkadamy kontekst renderowania.
Rozdzia 21. OpenGL i MFC____________________________________635

// Wywoywane, gdy okno otrzymuje komunikat WM_PAINT, renderuje scen


void CMfcglYiew::OnDraw(CDC* pDC)
{
// Uczynienie kontekstu renderowania biecym
wglMakeCurrent(m_hDC,m_hRC);

// Wywoanie zewntrznego kodu OpenGL


GLRenderScene(NULL);
// Wywietlenie sceny w oknie
SwapBuffers(m_hDC);
// Odoenie kontekstu renderowania
wglMakeCurrent(m_hDC,NULL);

Unikanie niepotrzebnego czyszczenia okna


Za kadym razem, gdy okno zmienia rozmiar lub jest uniewaniane, MFC czyci to
okna przed odrysowaniem. Poniewa naszym kolorem ta OpenGL jest czer, to wyma-
zywanie (ktre powoduje wymalowanie okna na biao) powoduje migotanie za kadym
razem, gdy jest wywoywana funkcja OnDraw.

Aby zapobiec migotaniu, przesonimy domyln procedur obsugi komunikatu WM_ERA-


SEBACKGROUND. Zwykle okno jest wymazywane przed odmalowaniem po zmianie
rozmiaru. Jeli ta funkcja zwrci warto FALSE, okno nie bdzie odmalowywane i nie
wystpi migotanie. Zwykle ta funkcja zwraca warto funkcji CView::OnEraseBkgn-
d(pDC), odpowiadajcej za wymazywanie ta, ale moemy po prostu zwrci warto
FALSE.
// Przesonite w celu uniemoliwienia wymazywania ta przy
// kadym odmalowywaniu okna
BOOL CMfcglView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;

Obsuga palety
Ostatnie poprawki dotyczce naszego przykadu MFC zwizane s z obsug palety, co
wie si ze stworzeniem i zrealizowaniem palety RGB dla urzdze korzystajcych z
palety (kart 256-kolorowych). Zamiast przechowywa uchwyt palety, tak jak w rozdziale
8, stworzymy obiekt MFC typu CPalette. Dla listingu 21.2, w pliku mfcglYiew.h
deklarujemy egzemplarz obiektu klasy CPalette:
CPalette m_GLPalette; // Paleta logiczna

a nastpnie rcznie dodajemy do klasy CMfcglYiew metod inicjujc palet. Jej kod
jest niemal identyczny z kodem funkcji GetOpenGLPalette zaprezentowanej w rozdziale 8,
z tym e zamiast zwracania uchwytu palety konstruowany jest obiekt klasy CPalette.
636________________________________________Cz IV OpenGL i...

Listing 21.2. Tworzenie i inicjowanie obiektu CPalette_____________________________

// Inicjowanie obiektu CPalette


void CMfcglView::InitializePalette( v o i d )
(
PIXELFORMATDESCRIPTOR pfd; // Deskryptor formatu pikseli LOGPALETTE
*pPal; // Wskanik do obszaru pamici dla palety
// logicznej
int nPixelFormat; // Indeks formatu pikseli
int nColors; // Ilo pozycji palety
int i; // Licznik
BYTE RedRange,GreenRange,BlueRange;
// Zakres dla kadej pozycji koloru ( 7 , 7 //
i 3)
// Pobranie indeksu formatu pikseli oraz deskryptora formatu
// pikseli
nPixelFormat = GetPixelFormat(m_hDC);
DescribePixelFormat(m_hDC, nPixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), spfd);

// Czy ten format pikseli wymaga palety? Jeli nie, po prostu nie //
twrz palety i zwr warto NULL if(!(pfd.dwFlags &
PFD_NEED_PALETTE)) return;

// Ilo pozycji w palecie. 8 bitw oznacza 256 pozycji


nColors = l pfd.cColorBits;

// Zaalokowanie pamici na struktur logicznej palety


// i wszystkie j e j pozycje
pPal = {LOGPALETTE*Jmalloc(sizeof(LOGPALETTE)
+nColors*sizeof(PALETTEENTRY));

// Wypenienie nagwka palety


pPal->palVersion = 0x300; // Windows 3 . 0
pPal->palNumEntries = nColors; // rozmiar tabeli

// Budowanie maski wszystkich jedynek. Tworzy liczb


// reprezentowan przez x dolnych bitw ustawionych, gdzie x =
// pfd.cRedBits, pfd.cGreenBits,oraz pfd.cBlueBits.
RedRange = (l pfd.cRedBits) - 1 ;
GreenRange = (l pfd.cGreenBits) - 1;
BlueRange = (l pfd.cBlueBits) -1;

// Przejcie przez wszystkie pozycje palety


ford = 0; i < nColors; i++)
{
// Wypenienie 8-bitowych odpowiednikw dla kadego komponentu
pPal->palPalEntry[ i ] .peRed = (i pfd.cRedShift) & RedRange;
pPal->palPalEntry[ i ] .peRed = (unsigned char)(
(double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);

pPal->palPalEntry[ i ] .peGreen = (i pfd.cGreenShift) s


^GreenRange;
pPal->palPalEntry[ i ] .peGreen = (unsigned char)(
(double)pPal->palPalEntry[ i ] .peGreen * 255.0 /
^GreenRange) ;
pPal->palPalEntry[i].peBlue = (i pfd.cBlueShift) &
^BlueRange;
Rozdzia 21. OpenGL i MFC ____________________________________ 637

pPal->palPalEntry [ i ] .peBlue = (unsigned char) (


(double)pPal->palPalEntry [ i ] .peBlue * 255.0 / BlueRange);

pPal->palPalEntry [ i ] .peFlags = (unsigned char) NULL; }


// Utworzenie palety m_GLPalette .
CreatePalette (pPal ) ;

// Wybranie i zrealizowanie palety dla biecego kontekstu //


urzdzenia
SelectPalette (m_hDC, (HPALETTE)m_GLPalette, FALSE) ;
RealizePalette (m_hDC) ;

// Zwolnienie pamici uytej przez struktur palety logicznej


free(pPal) ;

Po uyciu ClassWizarda w celu dodania odpowiednich funkcji obsugujcych komunikaty


WM_QUERNEWPALETTE oraz WM_PALETTECHANGED, nasz kod odpowiadajcy
za realizacj palety wyglda tak, jak na listingu 21.3.

Listing 21.3. Kod realizujcy palet dla klasy widoku

BOOL CMfcglView: :OnQueryNewPalette ( ) {


//Jeli paleta zostaa utworzona.
i f ( (HPALETTE)m_GLPalette)
{
int nRet;

// Wybranie palety w biecym kontekcie urzdzenia


SelectPalette (m_hDC, (HPALETTE)m_GLPalette, FALSE);
// Odwzorowanie pozycji biecej palety na palet systemow. //
Zwracan wartoci jest ilo zmodyfikowanych pozycji // palety.
nRet = RealizePalette (m_hDC) ;
// Przemalowanie, ktre wymusza nowe odwzorowanie palety //
w biecym oknie InvalidateRect (NULL, FALSE) ;
return nRet;
}
return CView: :OnQueryNewPalette ( ) ;

void CMfcglView: :OnPaletteChanged (CWnd* pFocusWnd) {


if ( ( (HPALETTE)m_GLPalette ! = N U L L ) && (pFocusWnd ! = t h i s ) ) {
// Wybranie palety w kontekcie urzdzenia
SelectPalette (m hDC, (HPALETTE)m GLPalette, FALSE) ;
638__________________________________________Cz IV OpenGL I . . .

// Odwzorowanie pozycji w palet systemow


RealizePalette(m_hDC);
// Przemapowanie biecych kolorw do nowo zrealizowanej //
palety
UpdateColors(m_hDC);
return;

CView::OnPaletteChanged(pFocusWnd) ; }

Kod realizujcy palet bardzo przypomina kod z rozdziau 8. Tutaj jednak Windows nie
przekazuje tych komunikatw bezporednio do klasy widoku, lecz do klasy CMainFrame
aplikacji. Dzieje si tak, poniewa Windows wysya komunikaty o zmianie palety
jedynie do gwnego okna aplikacji; gwne okno odpowiada za rozesanie tych komu-
nikatw do odpowiednich okien potomnych.

Ponownie wic uyjemy ClassWizarda w celu dodania dwch procedur obsugi komu-
nikatw palety do klasy CMainFrame. W tych procedurach po prostu wyznaczamy aktywny
widok i posyamy mu niezmienione komunikaty palety, pozwalajc widokowi na ich
samodzielne obsuenie. Te procedury obsugi zostay przedstawione na listingu 21.4.

Listing 21.4. Kod klasy CMainFrame przesyajcy komunikaty palety do okna widoku ___________

// Przekierowanie komunikatu do okna widoku


void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd)

CView* pYiew = GetActiveView();


if (pView)
// Metoda OnPaletteChanged nie jest publiczna, wic wysyamy
// komunikat
pView->SendMessage(WM_PALETTECHANGED,
(WPARAM)(pFocusWnd->GetSafeHwnd()),
(LPARAM)O);

// Przekierowanie komunikatu do okna widoku


BOOL CMainFrame::OnQueryNewPalette()
{
CView* pView = GetActiveView{);
if (pView)
{
// Metoda OnQueryNewPalette nie jest publiczna, wiec wysyamy //
komunikat
return pView->SendMessage(WM_QUERYNEWPALETTE,
(WPARAM) O, (LPARAM) 0) ; } return FALSE;
Rozdzia 21. OpenGL i MFC____________________________________639

Oprcz tego dodalimy do klasy widoku procedur obsugi komunikatw WM_TIMER


oraz utworzylimy timer, dziki ktremu moemy animowa scen (rysunek 21.4). Funkcja
timera po prostu uniewania obszar roboczy okna, wymuszajc jego odmalowanie. W
module glcode.c funkcja renderujca przy kadym odrysowywaniu okna inkrementuje kt
obrotu, tworzc w ten sposb efekt animacji. Cay kod jest dostpny na pytce CD-ROM,
jako program MFCGL.

Rysunek 21.4.
Kocowa animowana
scena tworzona przez
program MFCGL

Podsumo
wanie
W tym
rozdziale
omwili
my
zagadnieni
a zwizane
z
uywanie
m OpenGL w aplikacjach opartych na MFC, pokazujc, gdzie naley ustawi style okna
wymagane przez OpenGL, gdzie i kiedy ustawi format pikseli, a take jak stworzy
kontekst renderowa-nia. Przykadowy program ilustruje take, kiedy naley uczyni
kontekst renderowania biecym oraz jak w razie potrzeby zrealizowa palet za pomoc
klasy MFC CPalette.

Przykadow aplikacj zaprezentowan w tym rozdziale bdziesz mg wykorzysta jako


punkt wyjcia dla wasnych programw OpenGL. Oprcz tego, szkielet aplikacji -wraz z
caym kodem OpenGL w module glcode.c - moe posuy do zamiany innych
przykadw C/OpenGL na programy MFC. Inne przykadowe programy MFC korzystajce
z OpenGL znajdziesz na pytce CD-ROM.
Rozdzia 22.
OpenGL i OWL
W tym rozdziale:

Dowiesz si, jak... Uywane funkcje

Ustawi styl okna OWL, aby speniao wymagania OpenGL EvCreate


Stworzy i przygotowa kontekst renderowania EvCreate
Usun kontekst renderowania na zakoczenie dziaania EvDestroy
programu
Rozmieci kod rzutowania i widoku EvSize
Rozmieci kod renderowania EvPaint
Zabezpieczy si przed migotaniem okna pomidzy EvEraseBkgnd
renderowaniami
Rozmieci kod zarzdzajcy palet EvQueryNewPalette,
EvPaletteChanged

Obecnie coraz wiksza liczba programistw przy tworzeniu aplikacji dla Windows ko-
rzysta z C++. Dotychczas w treci ksiki prezentowalimy jedynie kod napisany w C. Na
szczcie, wikszo programistw C++ doskonale daje sobie rad z analiz programw
napisanych w C. Niestety, nie jest to ju tak powszechne w odwrotnej sytuacji (wielu
programistw C ma kopoty ze zrozumieniem kodu C++). Nie twierdzimy, e C++ jest
znacznie trudniejszy w opanowaniu, lecz gdy sigasz po ksik na temat grafiki
komputerowej z zamiarem opanowania wanie tego tematu, raczej nie chcesz przy
okazji uczy si nowej skadni jzyka.

Cho wikszo przykadw w ksice mona skompilowa zarwno za pomoc kom-


pilatora C, jak i C++, wikszo programistw C++ tworzcych aplikacje dla Windows
nie pisze kodu w C. Zamiast niego najczciej uywaj komercyjnych pakietw progra-
mistycznych lub wasnych bibliotek klas C++. Rnica polega na tym, e wikszo
aplikacji C++ nie zawiera procedur takich jak przedstawione w tej ksice ani tych in-
strukcji case z pieka rodem", obsugujcych komunikaty przekazywane do okien.
642________________________________________Cz IV OpenGL i...

Celem tego rozdziau jest pomoc programicie C++ w wykorzystaniu jednej z popu-
larnych bibliotek klas C++ jako punktu wyjcia dla wasnych aplikacji C++. Bibliotek
klas opisywan w tym rozdziale jest OWL (Object Windows Library) Borlanda. Przykady
i zrzuty okien wystpujce w tym rozdziale zostay przygotowane przy uyciu Borland
C++5.0.

Uwaga
Jeli uywasz MFC (Microsoft Foundation Classes), wr do
rozdziau 21

Piszc ten rozdzia, zakadalimy, e ju sam potrafisz zrobi pewne rzeczy:


* Umiesz wykorzysta Borland C++ i OWL do tworzenia aplikacji dla Windows NT i
Windows 95.
* Opanowae materia z czwartego rozdziau tej ksiki, opisujcy OpenGL dla
Windows oraz uycie kontekstw renderowania.
* Rozumiesz zagadnienia zwizane z obsug palety, opisywane w rozdziale 8.

Wydzielenie kodu zwizanego z OpenGL


W przypadku kadej aplikacji dobrym pomysem jest uczynienie kodu rdowego na
tyle modularnym, na ile to jest moliwe. Wydzielajc funkcjonalne fragmenty kodu,
mona o wiele atwiej konserwowa i ponownie wykorzystywa poszczeglne procedury.
Przez oddzielenie czystego" kodu OpenGL w osobnym module, moesz efektywnie
zastpowa ten modu specyficznym kodem, zachowujc przy tym funkcjonalno reszty
aplikacji. Dziki temu stosunkowo atwo byo przekonwertowa przedstawiony w tym
rozdziale przykad w C na program w C++, wykorzystujcy bibliotek OWL.

Zaczniemy od zadeklarowania trzech funkcji w pliku rdowym C, glcode.c. Plik


glcode.h zawiera deklaracje tych funkcji i jest wczany do pliku implementacji naszej
klasy, wyprowadzonej z klasy TWindowYiew, w celu umoliwienia dostpu do funkcji.
// glcode.h
// Deklaracje dla zewntrznego moduu OpenGL. Te funkcje s
// zaimplementowane w pliku glcode.c i wywoywane z wntrza
// funkcji skadowych klasy wyprowadzonej z TWindowYiew.
tifndef _GLCODE_
#define _GLCODE_

extern " C " {

void GLSetupRC(void *pData);


void GLRenderScene(void *pData); void
GLResize(GLsizei h, GLsizei w ) ; }

Funkcja GLSetupRC zawiera cay kod zwizany z inicjowaniem kontekstu renderowa-nia.


Zawarty w niej kod moe by bardzo prosty, przygotowujcy jedynie kolor czy-
Rozdzia 22. OpenGL i OWL____________________________________643

szczeni ta, lub do skomplikowany, okrelajcy warunki owietlenia. Funkcja GLRen-


derScene bdzie wywoywana z wntrza metody OnDraw naszej klasy widoku
(wyprowadzonej z TWindowYiew) w celu wyrysowania sceny. Na koniec, funkcja GL-
Resize bdzie wywoywana z procedury obsugi komunikatu WM_SIZE, z przekazan
now szerokoci i wysokoci obszaru roboczego okna. Moesz w niej zawrze wymagane
obliczenia zwizane z ustanowieniem nowego widoku i bryy widzenia.

Zwr uwag, e funkcje GLSetupRC i GLRenderScene otrzymuj wskaniki typu


void. Dziki temu do funkcji renderujcej moesz przekazywa dane dowolnego typu,
bez koniecznoci pniejszych zmian interfejsu. Cho moglibymy z pliku glcode.c
uczyni plik C++, atwiej jest skopiowa istniejcy kod C z dowolnego rda i wstawi go
do programu OWL. Borland C++ po prostu skompiluje ten plik jako plik C i poczy go z
reszt aplikacji.

W tym miejscu nie bdziemy prezentowa zawartoci pliku glcode.c, gdy ten plik jest
do dugi, a jeli koniecznie chcesz si z nim zapozna, moesz go skopiowa z pytki
CD-ROM. Ponadto ten sam plik zosta wykorzystany w przykadzie dla MFC w poprzednim
rozdziale.

Zaczynamy od AppExperta
Wiele aplikacji napisanych w C++ zaczyna istnienie od AppExperta. Architektur doku-
mentu-widoku mona porwnywa z architektur modelu-widoku w innych obiektowo
zorientowanych rodowiskach programistycznych. Nawet w przypadku szybkich, pr-
bnych aplikacji lub eksperymentalnych projektw, AppExpert moe w nieca minut
stworzy aplikacj SDI (z pojedynczym dokumentem), MDI (z wieloma dokumentami) lub
opart na oknie dialogowym. Tak wic sensownie bdzie uy wanie AppExperta w celu
stworzenia szkieletu aplikacji SDI OWL, w ktrej pniej wykorzystamy take OpenGL.
Aby stworzy prost scen OpenGL, dodamy funkcje i zmienne do klasy widoku,
wyprowadzonej z TWindowYiew. Podobnych metod bdziesz mg uy w celu dodania
elementw OpenGL do kadej klasy wyprowadzonej z TWindow.

Budowanie szkieletu
Zaczniemy od zbudowania szkieletu aplikacji SDI za pomoc AppExperta, pomijajc
opcje zwizane z funkcjonalnoci OLE, przeciganiem i upuszczaniem itd. Rysunek
22.1 przedstawia pierwszy dialog AppExperta przy tworzeniu szkieletu aplikacji OWL.

By moe zechcesz take wyczy opcj wydruku i podgldu wydruku (Print and Print
Preview). Sceny OpenGL mog by renderowane w kontekcie urzdzenia drukarki
tylko wtedy, gdy drukarka jest drukark kolorow obsugujc co najmniej cztery lub
wicej bitplanw koloru (16 lub wicej kolorw). Drukowanie na monochromatycznej
drukarce laserowej lub mozaikowej take jest moliwe, lecz do kopotliwe. Przykad
kodu sucego do drukowania scen przy uyciu nowych elementw OpenGL w wersji
644 Cz IV OpenGL I...

l. l znajdziesz w uzupeniajcym przykadzie GLPRINT, na pytce CD-ROM, w folderze


\OPENGL11 \SAMPLES\GLPRINT.

Rysunek 22.1.
Pocztek tworzenia
nowej aplikacji SDI
za pomoc
AppExperta

Moesz pozostawi opcje aplikacji w ich domylnym stanie lub te wyczy paski na-
rzdzi, pasek stanu itd. Dodatkowo musisz pamita, aby w oknie MainWindow Basic
Options wczy style okna wymagane przez OpenGL (Clip Children i Clip Siblings). Na
koniec, wybierz kategori SDI Client i wska, e gwne okno ma by wyprowadzone z
klasy TWindowWiev, tak jak pokazano na rysunku 22.2.

Rysunek 22.2.
Wskazywanie, e
okno klienta ma by
wyprowadzone z
klasy TWindowYiew

Po wygenerowaniu kodu i zbudowaniu szkieletowej aplikacji, otrzymasz program po-


kazany na rysunku 22.3.
Rozdzia 22. OpenGL i OWL 645

Rysunek 22.3.
Szkieletowa aplikacja
SDI wygenerowana
przez AppExperta

Dodawanie nagwkw
Zanim zaczniemy dodawa do szkieletu aplikacji jakikolwiek kod OpenGL, musimy doda
do projektu nagwki OpenGL. Najlepiej umieci je w pliku owlglapp.h. Dopisz po prostu
dwie ponisze linie wczajce pliki nagwkowe:
tfinclude <gl\gl.h> // Biblioteka OpenGL
include <gl\glu.h> // Biblioteka GLU OpenGL

Zgodnie z ogln zasad, Borland automatycznie linkuje programy z bibliotek importow


zawierajc wszystkie funkcje API Win32. Czasem te biblioteki nie s zsynchronizowane
z najnowsz wersj systemu operacyjnego, a wtedy musisz stworzy wasne biblioteki
importowe i poczy z nimi program. (Zajrzyj do dyskusji na temat Borland C++ we
wprowadzeniu do ksiki).

Dodawanie procedur obsugi komunikatw


Tworzenie szkieletowej aplikacji dla OpenGL w OWL zakoczymy dodaniem procedur
obsugi dla przynajmniej pierwszych piciu komunikatw okienkowych zebranych w tabeli
22.1. Pi pierwszych komunikatw z tabeli powinno by obsugiwanych w kadej
szanujcej si aplikacji OpenGL dla Windows. Komunikaty palety s wymagane jedynie
wtedy, gdy w programie jest zawarty kod obsugi palety i przewidujesz, e aplikacja bdzie
uywana w trybach 256-kolorowych. Komunikat WM_TIMER jest opcjonalny, jednak
jest przydatny, gdy chcesz stworzy prost animacj. W naszym przykadzie w dalszej
czci rozdziau wykorzystujemy komunikat WMJTIMER wanie do celw animacji.
646 Cz IV OpenGL i...

Tabela 22.1.
Podstawowe komunikaty obsugiwane w aplikacjach OpenGL

Komunikat Przeznaczenie procedury obsugi

WM_CREATE Tworzenie okna. Ustala wymagane style okna i tworzy kontekst


renderowania.
WM_DESTROY Zrobienie porzdkw przez usunicie kontekstu renderowania.
WM_ERASEBKGND Poinformowanie GDI, aby nie wymazywao ta przed odwieeniem
zawartoci okna.
WM_PAINT Odrysowanie zawartoci okna. W tej procedurze jest wywoywany kod
renderowania OpenGL.
WM_SIZE Wywoanie kodu modyfikujcego informacje o widoku OpenGL.
WM_QUERYNEWPALETTE Ewentualna realizacja palety aplikacji.
WM_PALETTECHANGED Ewentualna reakcja na zmian palety.
WM TIMER Regularne wywoywanie funkcji, na przykad do celw animacji.

Okno AppExperta, w ktrym dodajemy procedury obsugi tych komunikatw, zostao


przedstawione na rysunku 22.4.

Rysunek 22.4.
Dodawanie procedur
obsugi komunikatw
za pomoc
ClassExperta.

Wypenianie szkieletu aplikacji


W tym momencie mamy ju kompletn szkieletow aplikacj, ze zdefiniowanymi pro-
cedurami obsugi komunikatw przeznaczonymi do inicjowanie i destrukcji okna, ryso-
wania, zmiany rozmiaru i obsugi palety. Do tego szkieletu dodamy kod umoliwiajcy
OpenGL rysowanie w oknie. Osigamy to przez wywoanie funkcji Win32 specyfi-
Rozdzia 22. OpenGL i OWL____________________________________647

cznych dla OpenGL, a nastpnie wywoanie naszego kodu OpenGL w odpowiednich


funkcjach z moduu glcode.c.

Przygotowanie klasy widoku dla OpenGL


AppExpert generuje klas TOwlglWindowYiew, wyprowadzon bezporednio z klasy
TWindowYiew. Ta klasa jest odpowiedzialna za obszar roboczy okna aplikacji. W na-
szym przykadzie ta klasa jest zadeklarowana w pliku owlglwnv.h, za zaimplemento-
wana w pliku owlglwnv.cpp.
Najpierw wypenimy kod procedury obsugi komunikatu WM_CREATE. Jak ju wspo-
mniano, OpenGL wymaga przede wszystkim, aby tworzone okno miao ustawione style
WS_CLIPCHILDREN i WS_CLIPSIBLINGS. Poniewa ustawilimy te style podczas
tworzenia szkieletu aplikacji za pomoc AppExperta, nie musimy ju nic w tym kie-
runku robi. Gdyby jednak musia ustawi je w programie, moesz wykorzysta do tego
wanie procedur obsugi komunikatu WM_CREATE, na przykad tak:
BOOL TOwlglWindowView::EvCreateWindow(CREATESTRUCT& es) {
int result;
// Dodaje style okna wymagane przez OpenGL
e s . style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);
result = TWindowView::EvCreate( e s ) ;

Zwr uwag, e ustawiamy take styl CS_OWNDC, dziki ktremu okno moe po-
siada prywatny kontekst urzdzenia. Cho nie jest to rygorystycznie wymagane, powoduje
szybsze i wydajniejsze dziaanie programu. Niektre wskaniki do kontekstw
urzdze zwracane przez OWL s tymczasowe i nie mog by przechowywane do
pniejszego uycia (podobnie jak w MFC). W naszym przypadku lepiej jest pobra
taki wskanik i przechowa go.
W klasie TOwlglWindowYiew (w pliku nagwkowym owlglwnv.h) przygotujemy take
miejsce na kontekst urzdzenia, kontekst renderowania oraz palet
public:
HGLRC m_hRC; // Kontekst renderowania
HDC m_hDC = NULL; // Kontekst urzdzenia
TPalette *m_pPalette; // Paleta 3-3-2

Format pikseli i kontekst renderowania


W pozostaej czci procedury obsugi komunikatu WM_CREATE ustawimy format pikseli
i stworzymy kontekst renderowania dla okna. Poniewa do utworzenia formatu pikseli
wymagany jest kontekst urzdzenia, musimy to zrobi ju po utworzeniu okna.
Ustawianie formatu pikseli w tej funkcji przebiega w taki sam sposb, jak w kadym z
przykadowych programw C w tej ksice poczwszy od rozdziau 4 (jak pamitasz,
648_______________________________________Cz IV OpenGL i...

a do trzeciego rozdziau posugiwalimy si bibliotek AUX). Listing 21.1 przedstawia


ukoczon procedur obsugi komunikatu zawierajc take kod przygotowujcy format
pikseli dla kontekstu urzdzenia.

Listing 21.1. Procedura obsugi komunikatu WM_CREATE, \v ktrej przygotowujemy format pikseli____

int TOwlglWindowView::EvCreate(CREATESTRUCT fars createStruct) {


int result;
createStruct.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
=>CS_OWNDC) ;

result - TWindowView::EvCreate(createStruct);

// Select pixel format/rendering context


Static PIKELFORMATDESCRIPTOR pfd = {
sizeof(PIKELFORMATDESCRIPTOR), // Rozmiar tej struktury
l, // Wersja struktury
PFD_DRAW_TO_WINDOW | // Rysowanie w oknie (nie na
// bitmapie)
PFD_SUPPORT_OPENGL ] // Obsuga wywoa OpenGL w tym oknie
PFD_DOUBLEBUFFER, // Tryb podwjnego buforowania
PFD_TYPE_RGBA, // Tryb kolorw RGBA
24, // Chcemy 24-bitowego koloru
0,0,0,0,0,0, // Nieuywane przy wybieraniu trybu
0,0, // Nieuywane przy wybieraniu trybu
0,0,0,0,0, // Nieuywane przy wybieraniu trybu
32, // Rozmiar bufora gbokoci
O, // Nieuywane przy wybieraniu trybu
O, // Nieuywane przy wybieraniu trybu
PFD_MAIN_PLANE, // Rysowanie na gwnym planie
O, // Nieuywane przy wybieraniu trybu
0 , 0 , 0 }; // Nieuywane przy wybieraniu trybu
// Pobranie kontekstu urzdzenia
m_hDC = ::GetDC(this->GetHandle());
// Wybranie formatu pikseli najbardziej zblionego do wskazanego w pfd
int nPixelFormat = ChoosePixelFormat(m_hDC, Spfd);
// Ustawienie formatu pikseli dla kontekstu urzdzenia
SetPixelFormat(m_hDC, nPixelFormat, ipfd);
// Utworzenie palety 3-3-2
SetupPalette(m_hDC);
// Utworzenie kontekstu renderowania
m_hRC = wglCreateContext(m_hDC);

// Uczynienie kontekstu renderowania biecym, przeprowadzenie //


inicjowanie
wglMakeCurrent(m_hDC,m_hRC);
GLSetupRC(m_hDC);
SetTimer(200,101,NULL); // 5 razy na sekund

return result;
Rozdzia 22. OpenGL i OWL____________________________________649

Natychmiast po utworzeniu kontekstu renderowania czynimy go biecym i wywoujemy


zewntrzn funkcj GLSetupRC. Ta funkcja zainicjuje wymagany kontekst renderowania,
po czym moemy go odoy. Dziki temu moemy uywa kilku kontekstw
renderowania, na wypadek gdybymy chcieli zastosowa OpenGL w kilku oknach. (Nie
robimy tego w naszym przykadzie, ale jeli wykorzystasz go jako punkt wyjcia dla
wasnego programu, nie bdziesz ju musia przebudowywa caego kodu).

Usuwanie kontekstu renderowania


Powinnimy pj krok dalej i zanim o tym zapomnimy, doda kod czyszczcy i usu-
wajcy kontekst renderowania. Wykorzystamy do tego procedur obsugi komunikatu
WM_DESTROY, pokazan na listingu 22.2.

Listing 22.2. Procedura obsugi komunikatu WM_DESTROY, usuwajca kontekst renderowania______


// Okno jest niszczone, wic robimy porzdki
void TOwlglWindowView::EvDestroy()
{
// Usuwanie timera
KillTimer(101);
// Usunicie kontekstu renderowania...
wglMakeCurrent(NULL,NULL);
wglDeleteContext(m_hRC);
// . . . i kontekstu urzdzenia
::ReleaseDC(this->GetHandle() ,m_hDC);
TWindowYiew::EvDestroy();

Obsuga zmiany rozmiaru okna


Gdy zmienia si rozmiar okna, otrzymuje ono komunikat WM_SIZE. Za pomoc Class-
Experta dodamy procedur obsugi tego komunikatu i z jej wntrza wywoamy zewntrzn
funkcj GLResize, przekazujc jej nowe wymiary obszaru roboczego okna. Przed
wywoaniem tej funkcji musimy uczyni kontekst renderowania biecym, gdy w prze-
ciwnym razie wywoania funkcji OpenGL w funkcji GLResize nie przynios efektu.
Oto kod procedury obsugi (listing 22.3):

Listing 22.3. Procedura obsugi komunikatu WM_PAINT, aktualizujca wymiary okna roboczego___

void TOwlglWindowView::EvSize(uint sizeType, TSizei size) {


TWindowView::EvSize(sizeType, s ize);
wglMakeCurrent(m_hDC,m_hRC);
GLResize(size.ex, size.cy);
wglMakeCurrent(m_hDC,NULL);
650 Cz IV OpenGL i...

Renderowanie sceny
Teraz moemy doda kod odpowiedzialny za renderowanie sceny w OpenGL. Metoda
EvPaint klasy widoku jest wywoywana za kadym razem, gdy okno otrzymuje komunikat
WM_PAINT. Wewntrz tej metody wybieramy kontekst renderowania jako biecy i
wywoujemy funkcj GLRenderScene, zawierajc jedynie wywoania funkcji
OpenGL. Kod tej metody zosta przedstawiony na listingu 22.4. Poniewa wczeniej
zadalimy trybu z podwjnym buforowaniem, zaraz po tym wywoujemy funkcj
SwapBuffers. Oprcz tego, w obsudze komunikatu WM_PAINT naley zatwierdzi
obszar roboczy okna informujc Windows o zakoczeniu rysowania. Jeli tego nie uczy-
nimy, Windows bdzie bez przerwy posya do okna kolejne komunikaty WM_PAINT.

Listing 22.4. Procedura obsugi komunikatu WM_PAINT____________________________

void TOwlglWindowView::EvPaint()
{
// Uczynienie kontekstu renderowania biecym
wglMakeCurrent(m_hDC,m_hRC);

// Wywoanie zewntrznego kodu OpenGL


GLRenderScene(NULL);
wglMakeCurrent(NULL,m_hRC);

// Wywietlenie sceny w oknie


SwapBuffers(m_hDC);

// Zatwierdzenie okna
Validate();

Unikanie niepotrzebnego czyszczenia okna


Za kadym razem, gdy okno zmienia rozmiar lub jest uniewaniane, Windows czyci to
okna przed odrysowaniem. Poniewa naszym kolorem ta OpenGL jest czer, to wy-
mazywanie (ktre powoduje wymalowanie okna na biao) powoduje migotanie za kadym
razem, gdy jest wywoywana funkcja EvPaint.
Aby zapobiec migotaniu, przesonimy domyln procedur obsugi komunikatu WM_
ERASEBACKGROUND. Zwykle okno jest wymazywane przed odmalowaniem po
zmianie rozmiaru. Jeli ta funkcja zwrci warto FALSE, okno nie bdzie odmalowywane
i nie wystpi migotanie. Zwykle ta funkcja zwraca warto funkcji TWindow-
View::EvEraseBkgnd(dc), odpowiadajcej za wymazywanie ta, ale moemy po prostu
zwrci warto FALSE (listing 22.5).
Rozdzia 22. OpenGL i OWL____________________________________651

Listing 22.5. Zabezpieczenie okna przed niepotrzebnym wymazywaniem____________________

// Obsuga komunikatu WM_ERASEBACKGROUND bool


TOwlglWindowView::EvEraseBkgnd(HDC dc) (
return FALSE;

Niech si krci
Cho oczywicie nie jest to wymogiem, w przykadzie w tym rozdziale uywamy timera w
celu uniewaniania obszaru roboczego okna co 200 milisekund (czyli wymuszamy
odrysowanie zawartoci okna przez kod OpenGL). Kod w module glcode.c przy kadym
wywoaniu obraca nasze obiekty. Dziki temu powstaje efekt pynnej animacji
obiektw - w tym przypadku trzech trjwymiarowych liter. Zaimplementowanie timera jest
proste: naley ustawi timer w funkcji EvCreate(), doda procedur obsugi komunikatu
WM_TIMER, a na zakoczenie programu usun timer w funkcji EvDestroy. Stanowi
to standardow praktyk programowania w Windows, za odpowiedni kod zosta
przedstawiony na listingu 22.6.
Wynik dziaania programu w obecnej postaci zosta przedstawiony na rysunku 22.5.
Rysunek 22.5.
Animowane litery
w programie
OWLGL

Listing 22.6. Kod tworzcy, obsugujcy i niszczcy timer wykorzystywany do animacji_____

int TOwlglWindowYiew::EvCreate(CREATESTRUCT fars createStruct)

SetTimer( 2 0 0 , 101,NULL); // 5 r a z y na sekund


652__________________________________________Cz IV OpenGL i.

// Obsuga komunikatu WM_TIMER


void TOwlglWindowView::EvTimer(uint timerld)
{
TWindowView::EvTimer(timerld);

// Wymuszenie odrysowania okna


Invalidate(); }
// Okno jest niszczone, wic robimy porzdki
void TOwlglWindowView::EvDestroy()
{
// Usuwanie timera
KillTimer( 1 0 1 ) ;

Obsuga palety
Ostatnie poprawki do naszego przykadu OWL dotycz obsugi palety, co wie si z
utworzeniem i zrealizowaniem palety RGB dla urzdze korzystajcych z palety (kart
256-kolorowych). Zamiast przechowywa uchwyt palety, tak jak w rozdziale 8, stwo-
rzymy obiekt OWL typu TPalette. W pliku owlglwnf.h deklarujemy wskanik do obiektu
klasy TPalette:
TPalette *m_pPalette; // Paleta logiczna

a nastpnie rcznie dodajemy do klasy TOwlglWindowYiew metod inicjujc palet. Jej


kod, przedstawiony na listingu 22.7, jest niemal identyczny z kodem funkcji Get-
OpenGLPalette, zaprezentowanej w rozdziale 8, z tym e zamiast zwracania uchwytu
palety konstruowany jest obiekt klasy TPalette.

Listing 22.7. Tworzenie i inicjowanie obiektu CPalette_____________________________

// W razie potrzeby utworzenie palety


void TOwlglWindowYiew::SetupPalette(HDC hDC)
{
PIKELFORMATDESCRIPTOR pfd; // Deskryptor formatu pikseli
LOGPALETTE *pPal; // Wskanik do obszaru pamici dla palety
// logicznej
int nPixelFormat; // Indeks formatu pikseli
int nColors; // Ilo pozycji palety
int i; // Licznik
BYTE RedRange,GreenRange,BlueRange;
// Zakres dla kadej pozycji koloru ( 7 , 7 //
i 3)
// Pobranie indeksu formatu pikseli oraz deskryptora formatu //
pikseli
Rozdzia 22. OpenGL i OWI____________________________________653

nPixelFormat = GetPixelFormat(hDC);
DescribePixelFormat(hDC, nPixelFormat,
sizeof(PIKELFORMATDESCRIPTOR), Spfd);

// Czy ten format pikseli wymaga palety? Jeli nie, po prostu nie //
twrz palety i wr
if(!(pfd.dwFlags & PFD_NEED_PALETTE))
return;

// Ilo pozycji w palecie. 8 bitw oznacza 256 pozycji


nColors = l pfd.cColorBits;
// Zaalokowanie pamici na struktur logicznej palety // i
wszystkie jej pozycje
pPal = (LOGPALETTE*)malloc(sizeof(LOGPftLETTE)
+nColors*sizeof(PALETTEENTRY));
// Wypenienie nagwka palety pPal->palVersion =
0x300; // Windows 3 . 0 pPal->palNumEntries =
nColors; // rozmiar tabeli
// Budowanie maski wszystkich jedynek. Tworzy liczb
// reprezentowan przez x dolnych bitw ustawionych, gdzie
// x = pfd.cRedBits, pfd.cGreenBits oraz pfd.cBlueBits.
RedRange = (l pfd.cRedBits) -1;
GreenRange = (l pfd.cGreenBits) - 1;
BlueRange = (l pfd.cBlueBits) -1;
// Przejcie przez wszystkie pozycje palety
for(i = 0 ; i < nColors; i++)
{
// Wypenienie 8-bitowych odpowiednikw dla kadego komponentu
pPal->palPalEntry[ i ] .peRed = (i pfd.cRedShift) & RedRange;
pPal->palPalEntry[i].peRed = (unsigned char)(
(double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
pPal->palPalEntry[ i ] .peGreen = (i pfd.cGreenShift) &
GreenRange; pPal-
>palPalEntry[ i ] .peGreen = (unsigned char)(
(double)pPal->palPalEntry[ i ] .peGreen * 255.0 /
^GreenRange) ;
pPal->palPalEntry[i].peBlue = (i pfd.cBlueShift) &
^BlueRange;
pPal->palPalEntry[ i ] .peBlue = (unsigned char)(
(double)pPal->palPalEntry[ i ] .peBlue * 255.0 / BlueRange);
pPal->palPalEntry[ i ] .peFlags = (unsigned char) NULL;
}
// Utworzenie palety
m_pPalette = new TPalette(pPal);

// Wybranie i zrealizowanie palety dla biecego kontekstu //


urzdzenia
if (SelectPalette(hDC,m_pPalette->GetHandle() ,FALSE) <== NULL)
::MessageBox(NULL,"Nie powid si wybr p a l e t y " , "Bd",MB
OK);
654________________________________________Cz IV OpenGL i.

if(RealizePalette(hDC) == NULL)
::MessageBox(NULL,"Nie powiodo si zrealizowanie palety",
"Bd",MB_OK);
// Zwolnienie pamici uytej przez struktur palety logicznej
free(pPal);

Nie zapomnij o wywoaniu tej funkcji w procedurze obsugi komunikatu WM_CREATE.


Powiniene to zrobi przed utworzeniem kontekstu renderowania:
// Ustawienie formatu pikseli dla kontekstu urzdzenia
SetPixelFormat(m_hDC, nPixelFormat, &pfd);
// Utworzenie palety 3-3-2
SetupPalette(m_hDC);
// Utworzenie kontekstu renderowania
m_hRC = wglCreateContext(m_hDC);

Po uyciu ClassExperta w celu dodania odpowiednich funkcji obsugujcych komunikaty


WM_QUERNEWPALETTE oraz WM_PALETTECHANGED, nasz kod odpowiadajcy
za realizacj palety wyglda tak, jak na listingu 22.8.

Listing 22.8. Kod realizujcy palet dla klasy -widoku______________________________


// Obsuguje komunikat WM_QUERYNEWPALETTE bool
TOwlglWindowView::EvQueryNewPalette()
bool result;

// Jeli paleta zostaa utworzona


if(m_pPalette != NULL)
int nRet;

// Wybranie palety w biecym kontekcie urzdzenia


if(SelectPalette(m_hDC, m_pPalette->GetHandle(),FALSE) ==
ONULL)
::MessageBox(NULL,"Nie mona wybra palety"," B d " , MB_OK);

// Odwzorowanie pozycji biecej palety na palet systemow. //


Zwracan wartoci jest ilo zmodyfikowanych pozycji // palety.
nRet = RealizePalette(m_hDC);
// Przemalowanie, ktre wymusza nowe odwzorowanie palety
// w biecym oknie Invalidate();
return nRet;

// Wywoanie domylnej funkcji result =


TWindowView::EvQueryNewPalette(); return result;
}
Rozdzia 22. * OpenGL i OWI____________________________________655

void TOwlglWindowView::EvPaletteChanged(HWND hWndPalChg) {


// Tylko, gdy paleta zostaa utworzona lub nie jest to
// okno, ktre j utworzyo
if((m_pPalette != NULL) ss (hWndPalChg != this->HWindow))
{
// Wybranie palety w kontekcie urzdzenia
::SelectPalette(m_hDC,m_pPalette->GetHandle(),FALSE);

// Odwzorowanie pozycji w palet systemow


::RealizePalette(m_hDC);

// Przemapowanie biecych kolorw do nowo zrealizowanej //


palety
::UpdateColors(m_hDC); return;
}
// Wywoanie domylnej funkcji
TWindowYiew::EvPaletteChanged(hWndPalChg);

Kod realizujcy palet bardzo przypomina kod z rozdziau 8. Tutaj jednak Windows nie
przekazuje tych komunikatw bezporednio do klasy widoku, lecz do klasy TDecora-
tedFrame aplikacji (w naszym przykadzie SDIDecFrame). Dzieje si tak, poniewa
Windows wysya komunikaty o zmianie palety jedynie do gwnego okna aplikacji;
gwne okno odpowiada za rozesanie tych komunikatw do odpowiednich okien po-
tomnych.
Ponownie wic uyjemy ClassExperta w celu dodania dwch procedur obsugi komuni-
katw palety do klasy SDIDecFrame. W tych procedurach po prostu wyznaczamy potomny
widok TWindowYiew i posyamy mu niezmienione komunikaty palety, pozwalajc wi-
dokowi na ich samodzielne obsuenie. Te procedury obsugi zostay przedstawione na
listingu 22.9.

Listing 22.9. Kod klasy SDIDecFrame przesyajcy komunikaty palety do okna widoku___________

// Przekierowanie komunikatu WM_QUERYNEWPALETTE do okna widoku


bool TSDIDecFrame::EvQueryNewPalette()
{
bool result;
TWindow *pGLWindow;

// Pobranie potomnego okna SDI


pGLWindow = GetClientWindow();
// Wysanie komunikatu
if(pGLWindow)
pGLWindow->SendMessage(WMJ2UERYNEWPALETTE, O, 0) ;

return TRUE;
656________________________________________Cz IV OpenGL l

// Przekierowanie komunikatu WM_PALETTECHANGES do okna widoku


void TSDIDecFrame::EvPaletteChanged(THandle hWndPalChg)
(
TWindow *pGLWindow;

// Pobranie potomnego okna SDI


pGLWindow = GetClientWindow();

// Wysanie komunikatu
if(pGLWindow)
pGLWindow->SendMessage(WM_PALETTECHANGED, (UINT)hWndPalChg,
( O I N T ) 0);

Podsumowanie
W tym rozdziale omwilimy zagadnienia zwizane z uyciem OpenGL w aplikacjach
opartych na OWL, pokazujc, gdzie naley ustawi style okna wymagane przez OpenGL,
gdzie i kiedy ustawi format pikseli, a take jak utworzy kontekst renderowania.
Przykadowy program ilustruje take, kiedy naley uczyni kontekst renderowania bie-
cym oraz jak w razie potrzeby zrealizowa palet za pomoc klasy OWL TPalette.
Przykadow aplikacj zaprezentowan w tym rozdziale bdziesz mg wykorzysta jako
punkt wyjcia dla wasnych programw OpenGL. Oprcz tego, szkielet aplikacji - wraz z
caym kodem OpenGL w module glcode.c - moe posuy do zamiany innych przy-
kadw C/OpenGL na programy OWL. Inne przykadowe programy OWL korzystajce z
OpenGL znajdziesz na pytce CD-ROM.
658_______________________________________Cz IV OpenGL i...

argumenty, typ zwracanej wartoci oraz plik DLL-a, w ktrym zawarta jest dana
funkcja.

Z uywaniem OpenGL w jednym ze wspomnianych rodowisk wi si jednak dwie


niedogodnoci. Po pierwsze, korzystanie z funkcji OpenGL jest niesychanie mudne! W
kadym ze rodowisk musi zosta zdefiniowana i zaimportowana kada uywana
funkcja OpenGL. Oprcz tego, jej argumenty i zwracane wartoci musz zosta odwzo-
rowane na lokalne typy danych uywanego rodowiska. Co wicej, nie tylko funkcje
musz zosta zdefiniowane, ale take wszystkie zmienne stanu oraz znaczniki (GL_AC-
CUM, GL_LOAD itd.) z plikw nagwkowych. Co gorsza, trzeba to zrobi osobno w
kadym rodowisku, w ktrym chcesz korzysta z OpenGL!

Kolejn niedogodnoci jest wymaganie OpenGL, aby tworzone okna miay ustawione
style WS_CLIPCHILDREN oraz WS_CLIPSIBLINGS. W niektrych ze rodowisk
bardzo trudno jest dobra si do jakichkolwiek niskopoziomowych stylw okna, chyba e
gdzie dostpne jest okno dialogowe z odpowiednimi opcjami. W najgorszym przypadku
trzeba wyeksportowa z Windows funkcj CreateWindow i wywoa j z wntrza
swojego programu.

Jeli nie przeraa ci perspektywa brnicia przez te niedogodnoci w celu uycia OpenGL
powiedzmy, w Yisual Basicu, by moe powiniene po prostu napisa DLL-a w C, ktry
zawieraby cay kod zwizany z renderowaniem OpenGL, a nastpnie wywoywa go z
wntrza procedur Basica. To rozwizanie, mimo e najlepsze pod wzgldem wydajnoci,
nie ma jednak zastosowania dla programistw nie obeznanych z C/C++.

Jeli jednak kupie t ksik, aby nauczy si programowa przy uyciu OpenGL i do tej
pory dawae sobie rad z analiz przykadw i definicji funkcji, wci jeszcze jest dla
ciebie nadzieja!

Magia obiektw
Termin obiektowo zorientowany jest chyba, podobnie jak termin klient/serwer, jednym z
najczciej naduywanych i bdnie uywanych sloganw lat 90-tych. Chcielibymy unikn
powanych rozwaa na ten temat, naley jednak wspomnie o jednej z najwaniejszych
technologii umoliwiajcych wielokrotne wykorzystanie tego samego kodu.

T technologi jest OLE (Object Linking and Embedding) lub - co waniejsze dla tego
rozdziau - OCX (OLE Gustom Control). Gdy Microsoft opracowa Yisual Basic i umoliwi
tworzenie wasnych kontrolek poprzez VBX, w cigu dosownie jednej nocy powstaa
nowa ga przemysu. Powstay nowe firmy, przynoszce fortuny, zajmujce si
dostarczaniem programistom Yisual Basica nowych i interesujcych programowych
gadetw. Wkrtce powstay konkurencyjne rodowiska (PowerBuilder, Delphi i inne),
take umoliwiajce uycie kontrolek VBX w swoich aplikacjach. To jeszcze bardziej
podsycio zapa do tworzenia komponentw nadajcych si do wielokrotnego zasto-
sowania.
Rozdzia 23.
OpenGL w Visual Basic
S4GL
Poza rozdziaami 21 i 22, w caej ksice opisywalimy OpenGL API z punktu widzenia
programisty C. Jednak aden opis zagadnie zwizanych z programowaniem Windows
nie mgby by kompletny bez dyskusji na temat jzykw czwartej generacji (4GL) i
innych popularnych wizualnych rodowisk programowych. W tym rozdziale omwimy
pokrtce wymagania zwizane z uywaniem OpenGL w niektrych z takich rodowisk.
Oprcz tego, zademonstrujemy doczone do tej ksiki kontrolki OCX OpenGL, ktre
mog zosta uyte w dwch najpopularniejszych rodowiskach programowych Win32: w
Yisual Basic 6.0 Microsoftu oraz Delphi 2.0 Borlanda.

Piszc ten rozdzia, zakadalimy, e potrafisz si posugiwa wykorzystywanym przez


siebie rodowiskiem (Yisual Basic lub Delphi) oraz wiesz, jak uywa i wywoywa
metody kontrolek OCX. Jednak nawet jeli nie masz dowiadczenia z kontrolkami
OCX, przekonasz si, jak proste mog one by w uyciu.

Wymagany dostp niskiego poziomu


Z OpenGL moe skorzysta kady jzyk lub rodowisko programowania Windows, pod
warunkiem, e umoliwia niskopoziomowy dostp do Win32 API i innych bibliotek
zawartych w plikach DLL. Wikszo rodowisk i narzdzi na to pozwala, w celu umo-
liwienia integracji aplikacji z innymi bibliotekami oraz choby po to, aby programista
mg skorzysta z nowych elementw systemu operacyjnego, ktre jeszcze nie byy do-
stpne w momencie tworzenia danego narzdzia.

Cae API OpenGL mieci si w dwch plikach DLL: opengl32.dll oraz glu32.dll. Tak jak
wikszo API Win32 jest dostpnych bezporednio z bibliotek DLL, take w przypadku
bibliotek opengl32.dll, glu32.dll i innych moesz wywoywa ich funkcje bezporednio z
jzyka programowania wyszego poziomu. W kadym narzdziu i rodowisku jest to
jednak odmiennie zorganizowane. Zwykle musisz poda nazw funkcji, jej
660________________________________________Cz IV OpenGL i...

prostu umie kontrolk w formularzu i zacznij wywoywa jej metody, tak jakby byy
funkcjami i poleceniami OpenGL.
Kade polecenie nosi nazw tak jak w OpenGL API, lecz z odrzuconym przedrostkiem g/.
Gdy kontrolk nazwiesz g/, twj kod bdzie wyglda bardzo podobnie do kodu C uy-
wajcego OpenGL. Aby si o tym przekona, zajrzyj do przykadw dla VB i Delphi w
dalszej czci rozdziau.
Kontrolka odpala dwa zdarzenia, ktre moesz przechwyci w swojej aplikacji. Pierwszym
z nich jest SetupRC, wywoywane za pierwszym razem, gdy kontrolka prbuje odrysowa
swj obszar roboczy. W tym momencie format pikseli i kontekst renderowania zostay ju
utworzone i przygotowane. W swoim kodzie moesz przygotowa owietlenie, kolor ta itd.
Drugim zdarzeniem jest Render, wywoywane za kadym razem, gdy kontrolka ma zosta
odrysowana. Umieszczajc w tym miejscu swj kod renderowania, moesz efektywnie
wypeni obszar roboczy za pomoc OpenGL.
Podczas uywania kontrolki musisz mie na uwadze jeszcze par innych rzeczy:
* Poniewa mgby uy w swojej aplikacji wicej ni jednej kontrolki OpenGL,
kontrolka nie moe zakada, e kontekst renderowania zawsze jest dostpny dla
niej. W zwizku z tym zostay dostarczone dwie metody: MakeCurrent oraz
MakeNotCurrent. Wszystkie wywoania OpenGL musz by ujte pomidzy
wywoania tych dwch funkcji; dotyczy to take funkcji SetupRC i Render.
* Oprcz tego, jeli uczynisz kontekst renderowania biecym dla kontrolki, zawsze
moesz bezporednio wywoywa OpenGL API. Moesz to robi w celu
poprawienia wydajnoci lub w przypadku chci wykorzystania nowych funkcji w
nastpnych wersjach OpenGL, ktre nie zostay zawarte na licie metod kontrolki.
Do dyspozycji masz take kod rdowy kontrolki, wic jeli masz Yisual C++ i
spore zacicie, zawsze moesz sam zmodyfikowa kontrolk.
* Dla kontrolki jest tworzona paleta 3-3-2, realizowana za kadym razem, gdy jest
odpalane zdarzenie Render. Prby samodzielnego manipulowania palet mog
prowadzi do nieprzewidzianych rezultatw.
* Na koniec, okno kontrolki jest podwjnie buforowane, wic aby wywietli obraz,
zawsze musisz wywoa metod SwapBuffers.

Znaczniki OpenGL
Niemoliwe jest korzystanie z funkcji i polece OpenGL bez moliwoci dostpu do
wielu specjalnych znacznikw i zmiennych stanu. Kada z wartoci tych znacznikw jest
dostpna poprzez metod o nazwie odpowiadajcej nazwie danego znacznika. Nazwy tych
metod zawieraj jednak jedynie mae litery, gdy przy zachowaniu oryginalnych nazw
wystpoway problemy z prawdziwymi definicjami w plikach nagwkowych. Cho w
pewnych przypadkach sensowne byoby zaimplementowanie pewnych zmiennych stanu
jako waciwoci kontrolki, jednak nie zawsze byoby to moliwe. Dla zachowania
spjnoci zdecydowalimy si zastosowa metody dopasowane do OpenGL na tyle, na ile
to byo moliwe.
Rozdzia 23. OpenGL w Visual Basic i 4GL___________________________661

Cho wiele funkcji posiada kilka odmian, wszystkie zostay zaimplementowane jako
pojedyncza metoda. Oznacza to, e funkcje takie jak
void glVertex2fv(const GLfloat *v) ;

zostay zaimplementowane w postaci metody jako


Vertex2(float x, float y)

Dostpny jest plik pomocy (WaiteGL.hlp) zawierajcy spis wszystkich metod zdefinio-
wanych w kontrolce WaiteGL. Zostay one podzielone na trzy biblioteki OpenGL (gl, glu
i glaux) oraz definicje wszystkich staych. Aby skorzysta z pliku pomocy, odszukaj
potrzebn funkcj OpenGL, a nastpnie poszukaj opisu metody kontrolki WaiteGL dla tej
funkcji.
Przejdmy teraz do tworzenia programw korzystajcych z OpenGL w dwch najpopu-
larniejszych rodowiskach 4GL. W nastpnej sekcji omwimy zagadnienia zwizane z
Yisual Basicem. Jeli uywasz Delphi 2.0 (w wersji 32-bitowej), moesz przej od razu
do nastpnej sekcji.

Instalacja i uycie kontrolki WaiteGL


w Visual Basicu 6.0
Aby uy kontrolki WaiteGL, musisz j najpierw zarejestrowa w systemie operacyjnym
(Windows NT lub Windows 95). Skopiuj plik ,ocx do kartoteki systemowej i uruchom
dostarczony program ocxreg.exe. W linii polece tego programu podaj nazw pliku
,ocx oraz polecenie install (aby zarejestrowa kontrolk) lub uninstall (aby j
wyrejestrowa). Na przykad:
ocxreg.exe WaiteGL.ocx install

Program (wraz z kodem rdowym) znajdziesz na doczonej do ksiki pytce CD-


ROM, w kartotece tego rozdziau.

Instalowanie kontrolki
Po zarejestrowaniu kontrolki w systemie, musisz j zainstalowa w palecie narzdzi Yisual
Basica. W tym celu kliknij prawym przyciskiem myszy w obszarze palety
komponentw i z wywietlonego menu lokalnego wybierz opcj Components.... Z listy w
oknie dialogowym z rysunku 23.1 wybierz pozycj WaiteGL OLE Control module, po
czym kliknij na przycisk OK. Teraz bdziesz mg przecign kontrolk z palety na
formularz, a nastpnie dostosowa jej rozmiar.
662 Cz IV OpenGL i.

Rysunek 23.1.
Instalowanie
kontrolki WaiteGL
w Visual Basicu

Przykad w Visual Basicu


W naszej przykadowej aplikacji VB umiecimy kontrolk na formularzu i nadamy jej
nazw g/. W formularzu umiecimy take timer, odpalany co 200 milisekund. Spjrz na
rysunek 23.2. Zauwaysz, e kontrolka nie odrysowuje ani nie czyci swojego obszaru
roboczego. Dzieje si tak, poniewa kod rysunkowy musi zosta napisany w Basicu i
umieszczony w procedurze obsugi zdarzenia Render.
Rysunek 23.2.
Formularz VB z
kontrolka OCX

Jak ju wspominalimy, w naszym kodzie musimy obsuy dwa zdarzenia zgaszane


przez kontrolk. Stworzymy kod inicjujcy kontekst renderowania przez ustawienie po-
cztkowej bryy widzenia, wybranie koloru ta, a by moe rwnie koloru rysowania i
definicji owietlenia. Listing 23.1 zawiera kod sucy do przygotowania kontekstu ren-
derowania. Nasz kod po prostu ustawia kolor ta, kolor rysowania oraz bry widzenia.
Rozdzia 23. OpenGL w Visual Basic i 4GL___________________________663

Listing 23.1. Przygotowanie kontekstu renderowania w Yisual Basicu____________________

Private Sub gl_SetupRC()


Rem Uczy kontekst renderowania biecym
gl.MakeCurrent

Rem Ustawienie koloru ta na czarny


gl.ClearColor 0#, 0#, 0#, 1#

Rem ustanowienie bryy widzenia


gl.Loadldentity
gl.Ortho -100#, 100#, -100#, 100#, -100#, 100#
Rem Ustalenie koloru rysowania
REM Zrzucenie polece graficznych
Rem Odoenie kontekstu renderowania
gl.Color O, O, 255, 255
gl.Flush
gl.MakeNotCurrent
End Sub

Malowanie w oknie OpenGL


Kolejnym zdarzeniem, ktre musimy obsuy, jest zdarzenie Render. To zdarzenie jest
odpalane przez kontrolk za kadym razem, gdy trzeba odwiey jej obszar roboczy. W
tej funkcji umiecimy nasz kod odwoujcy si do metod kontrolki sucych do ry-
sowania. Listing 23.2 zawiera kod Yisual Basica rysujcy siatkowy imbryk do herbaty z
biblioteki AUX.

Listing 23.2. Kod Visual Basica rysujcy siatkowy imbryk do herbaty_____________________


Private Sub gl_Render()
Rem Uczy kontekst renderowania biecym
gl.MakeCurrent
Rem Wyczyszczenie ekranu i wyrysowanie imbryka z biblioteki AUX
gl.Clear (gl.glColorBufferBit)
gl.auxWireTeapot (55#)

Rem Zrzucenie polece graficznych


Rem Odoenie kontekstu renderowania
Rem Przerzucenie buforw
gl.Flush
gl.MakeNotCurrent
gl.SwapBuffers
End Sub

Zwr uwag, e najpierw kontekst renderowania jest wybierany jako kontekst biecy,
za po wywoaniu kodu rysunkowego jest odkadany. Nie jest to potrzebne, gdy posiadasz
tylko jedn kontrolk i kontekst renderowania, lecz zapewnia, e nie bd wymagane
pniejsze zmiany w kodzie, gdy zechcesz zastosowa dodatkow kontrolk
664 Cz IV OpenGL i...

WaiteGL. Po odoeniu kontekstu renderowania musisz wywoa metod SwapBuffers w


celu przywoania rysunku na ekran.

Troch ruchu
Przedstawiony powyej kod wystarczy do wywietlenia rysunku OpenGL. W tym przy-
kadzie jednak sprbujemy doda nieco animacji. W formularzu z rysunku 23.2 umiecimy
timer, odpalany co 200 milisekund. Za kadym tykniciem timera nasza funkcja uczyni
kontekst renderowania biecym dla kontrolki, obrci macierz widoku o 5, a
nastpnie odoy kontekst renderowania. Na koniec polecimy kontrolce, aby si od-
rysowaa, wywoujc bezporednio metod gl_Render. Spjrz na listing 23.3.

Listing 23.3. Funkcja timera obracajca bry widzenia o 5"__________________________


Private Sub Timerl_Timer()
Rem Uczy kontekst renderowania biecym
gl.MakeCurrent
Rem Obrt o 5 stopni
gl.Rotate 5#, 1#, 1#, 0.5
Rem Odoenie kontekstu renderowania Rem
i wymuszenie odmalowania
gl.MakeNotCurrent gl_Render
End Sub

Ukoczona aplikacja Yisual Basica zostaa przedstawiona na rysunku 23.3.


Rysunek 23.3.
Wynik dziaania
programu w VB
korzystajcego z
OpenGL
Rozdzia 23. * OpenGL w Visual Basic i 4GL 665

Wykorzystanie kontrolki OCX w


Delphi 2.0
Aby uy kontrolki WaiteGL, musisz j najpierw zarejestrowa w systemie operacyjnym
(Windows NT lub Windows 95). Skopiuj plik .ocx do kartoteki systemowej i uruchom
dostarczony program ocxreg.exe. W linii polece tego programu podaj nazw pliku
.ocx oraz polecenie install (aby zarejestrowa kontrolk) lub uninstall (aby j
wyrejestrowa). Na przykad:
ocxreg.exe WaiteGL.ocx install

Program (wraz z kodem rdowym) znajdziesz na doczonej do ksiki pytce CD-


ROM, w kartotece tego rozdziau.

Instalowanie kontrolki
Po zarejestrowaniu kontrolki w systemie, musisz j zainstalowa w palecie narzdzi
Delphi. W gwnym menu wybierz Component, a nastpnie polecenie Install. Kliknij na
przycisk OCX, po czym w oknie dialogowym z rysunku 23.4 pojawi si lista zarejestro-
wanych kontrolek OCX, ktre mog zosta zainstalowane.

Wybierz pozycj WaiteGL OLE Control module, po czym kliknij na przycisk OK. Spo-
woduje to dodanie naszej kontrolki do palety narzdzi. Po prostu przecignij kontrolk na
rodek formularza, a otrzymasz okno przeznaczone do rysowania za pomoc OpenGL.
Rysunek Import OLE Control

23.4.
Instalowanie VBSMSChailWizaid yD
kontrolki WaiteGL First Impression Library VD
Formua One Lfciary VCI
w Delphi WsualSoellet Litu

Przykad w Delphi
W przykadzie w Delphi zaczniemy od utworzenia nowego formularza i umieszczenia na
jego rodku kontrolki WiggleGL, tak aby zajmowaa wikszo powierzchni. Oprcz
666 Cz IV OpenGL i...

tego w formularzu umiecimy timer, ktry zostanie wykorzystany do prostej animacji.


Ukoczony formularz przedstawia rysunek 23.5. Zauwa, e kontrolk nie odrysowuje ani
nie czyci swojego obszaru roboczego. Dzieje si tak, poniewa kod rysunkowy musi
zosta napisany w Pascalu i umieszczony w procedurze obsugi zdarzenia Render.

Rysunek 23.5.
Formularz Delphi
z kontrolk OCX

Na rysunku 23.6 widzimy zakadk Events inspektora obiektw; jak wida, kontrolk
wywouje dwie unikatowe procedury obsugi: OnRender oraz OnSetupRC

Rysunek 23.6.
Zdarzenia dostpne ijgl: TWaileGLDrl
dla kontrolki
'
WaiteGL

Po dwukrotnym klikniciu na zdarzenie OnSetupRC zostanie stworzona funkcja glSe-


tupRC. Edytor zostanie otwarty umoliwiajc zdefiniowanie funkcji. Kod z listingu 23.4
przedstawia przygotowanie kontekstu renderowania, sprowadzajce si do wybrania
czarnego ta oraz rwnolegej bryy widzenia.

Listing 24.3. Kod Delphi wywoywany w odpowiedzi na zdarzenie SetupRC wywoane przez kontrolk

procedur TForml.glSetupRC(Sender: TObject);


begin
Rozdzia 23. OpenGL w Visual Basic i 4GL___________________________667

// Uczy kontekst renderowania biecym


gl.MakeCurrent();

// Ustalenie koloru ta i bryy widzenia


gl.ClearColor(0.0, 0.0, 0.0, 1 . 0 ) ;
gl.Loadldentity(); gl.0rtho(-100,100,-
100,100,-100,100);

// Zrzucenie polece graficznych i odoenie //


kontekstu renderowania gl.Flush();
gl.MakeNotCurrent(); end;

Malowanie w oknie OpenGL


Funkcja glRender jest tworzona w podobny sposb, przez dwukrotne kliknicie na zda-
rzenie OnSetupRC. W tej funkcji umiecimy nasz kod odwoujcy si do metod kon-
trolki sucych do rysowania. Listing 23.5 zawiera kod Delphi rysujcy siatkowy
imbryk do herbaty z biblioteki AUX. Zwr uwag, e najpierw kontekst renderowania
jest wybierany jako kontekst biecy, za po wywoaniu kodu rysunkowego jest odka-
dany. Nie jest to potrzebne, gdy posiadasz tylko jedn kontrolk i kontekst renderowania,
lecz zapewnia, e nie bd wymagane pniejsze zmiany w kodzie, gdy zechcesz
zastosowa dodatkow kontrolk WaiteGL. Po odoeniu kontekstu renderowania musisz
wywoa metod SwapBuffers w celu przywoania rysunku na ekran.

Listing 23.5. Kod Delphi rysujcy siatkowy imbryk do herbaty_________________________

procedur TForml.glRender(Sender: TObject);


begin
// Uczy kontekst renderowania biecym
gl.MakeCurrent();
// Wyczyszczenie ta i rysowanie imbryka
gl.Clear(gl.glColorBufferBit());
gl.Color(0, O, 255, 255);
gl.auxWireTeapot( 5 5 . 0 ) ;

// Zrzucenie polece graficznych i odoenie //


kontekstu renderowania // Przerzucenie buforw
gl.Flush (); gl.MakeNotCurrent (); gl.SwapBuffers () ;
end;

Troch ruchu
Przedstawiony powyej kod wystarczy do wywietlenia rysunku OpenGL. W tym przy-
kadzie jednak sprbujemy doda nieco animacji. W formularzu z rysunku 23.6 umie-
668 Cz IV OpenGL i...

cilimy timer odpalany co 200 milisekund. Za kadym tykniciem timera, nasza funkcja
uczyni kontekst renderowania biecym dla kontrolki, obrci macierz widoku o 5, a
nastpnie odoy kontekst renderowania. Na koniec polecimy kontrolce, aby si odry-
sowaa, wywoujc porednio funkcj Delphi Invalidate(). Poniewa w Delphi wszystkie
kontrolki OCX s oknami, wszelkie komunikaty lub polecenia wysyane do okien mog
by wysyane bezporednio do kontrolki. Spjrz na listing 23.6.

Listing 23.6. Funkcja timera obracajca bry widzenia o 5"__________________________

procedur TForml.TimerITimer(Sender: TObject); begin


// Uczy kontekst renderowania biecym
// Nieco obr scen
gl.MakeCurrent();
gl.Rotate( 5 . 0 , 0 . 0 , 1 . 0 , 0 . 5 ) ;
gl.MakeNotCurrent();

// Odmaluj kontrolk
gl.Invalidate();
end;

Ukoczona aplikacja Delphi zostaa przedstawiona na rysunku 23.7.

Rysunek 23.7.
Wynik dziaania
programu
stworzonego w
Delphi,
korzystajcego z
OpenGL

Par uwag na temat kodu rdowego


Kontrolka WaiteGL zostaa napisana w Yisual C++ 4.0 przy uyciu MFC w wersji 4.0. Ta
nowa wersja Yisuala znacznie uatwia tworzenie kontrolek CX i z pewnoci spowoduje,
e zalej nas niezliczone iloci wykorzystywalnych kontrolek OLE. Celem tego rozdziau
nie byo wprowadzenie do tworzenia kontrolek OCX. Chcielimy jedynie za-
Rozdzia 23. OpenGL w Visual Basic i 4GL___________________________669

prezentowa jedn z nich, uywajc OpenGL i umoliwiajc wywoywanie kodu


OpenGL z Yisual Basica, Delphi i innych rodowisk obsugujcych kontrolki OCX.

Oczywicie, na pytce CD-ROM, w folderze tego rozdziau, znajduje si peny kod r-


dowy kontrolki. Kod zosta wygenerowany przez kreatora Microsoft Control Wizard i
jest wypeniony komentarzami. Oprcz tego, metody i znaczniki zostay podzielone
pomidzy cztery pliki rdowe, w celu uatwienia analizy i modyfikacji kodu. Plik
ocxgl.cpp zawiera funkcje porednie dla funkcji biblioteki gl; podobnie, plik ocxglu.cpp
zawiera funkcje biblioteki glu. Plik ocxAux.cpp zawiera funkcje porednie dla funkcji
biblioteki AUX tworzcych siatkowe i jednolite obiekty, takie jak imbryk. Na koniec,
plik ocxflags.cpp zawiera rne definicje oraz funkcje dostpu suce do odczytywania
stanu znacznikw OpenGL.

Gwnym plikiem projektu jest plik WaitGLCtl.cpp, zawierajcy kod odpowiedzialny za


przygotowanie kontekstu renderowania oraz odpalanie zdarze przygotowania i ma-
lowania. Znajduj si w nim take wszystkie funkcje zwizane z przygotowaniem okna i
GDI. Dodatkowo, w tym pliku wystpuj funkcje pomocnicze bezporednio zwracajce
kontekst renderowania i kontekst urzdzenia, na wypadek gdyby potrzebowa ich w
swoim niskopoziomowym kodzie.

Zwr uwag, e kontrolka korzysta z biblioteki MFC w osobnym pliku DLL. Dla twojej
wygody, w podkartotece \REDIST zostay umieszczone redystrybuowalne pliki MFC.

Podsumowanie
W tym rozdziale omwilimy moliwoci i wyzwania kryjce si za uyciem OpenGL w
pewnych popularnych rodowiskach programowych. Cho w wikszoci tych rodowisk
moliwy jest bezporedni dostp do niskopoziomowych funkcji API, duo atwiej jest
jednak posuy si przygotowan przez nas kontrolka OCX. Wikszo przykadowych
programw z tej ksiki moe zosta atwo przerobionych tak, aby mona je byo
zaimplementowa w jzyku czwartej generacji (4GL) przy uyciu tej kontrolki. Oprcz
tego na pytce CD-ROM zostay zamieszczone uzupeniajce przykady.
Rozdzia 24.
Przyszo OpenGL w
Windows
Ta ksika nie jest wycznie o OpenGL - ona jest na temat OpenGL w systemie Mi-
crosoft Windows. Pozwolimy sobie w tym miejscu na omwienie biecej sytuacji
OpenGL oraz sprbujemy wysnu wnioski co do jego rozwoju i zastosowa w najbliszej
przyszoci.
OpenGL to w zaoeniu programowy interfejs dla sprztu 3D. Cho zarwno w Windows
NT, jak w Windows 95 dostpna jest oglna", czysto programowa implementacja tej
biblioteki, wynika to gwnie z faktu, e sprzt 3D dla komputerw osobistych jest jeszcze
w powijakach. Oczywicie, w przypadku OpenGL powinno si korzysta z takiego
sprztu, jeli tylko jest to moliwe.

W momencie powstawania tej ksiki rynek akceleratorw 3D jest jeszcze bardzo mody.
Ceny kart akceleratorw 3D zgodnych z OpenGL zaczynaj ostatnio spada, jednak
prawdziwym motorem wymuszajcym znaczny spadek cen s gry komputerowe prze-
znaczone do uruchamiania na komputerach osobistych. Gry komputerowe wymagaj
najszybszego dostpnego sprztu i najwydajniej napisanych programw. Komputery
osobiste z przynajmniej kilku powodw dobrze nadaj si na maszynki do grania. Przy
odpowiednim osprzcie, moesz gra na ekranie wysokiej jakoci monitora, ktry o par
klas przewysza ekran domowego odbiornika telewizyjnego. To wszystko uzupenia
dwik, nawet z syntez \vave-table, prawie nie rnicy si od brzmienia rzeczywistych
instrumentw. Oprcz joysticka z jednym lub dwoma przyciskami masz do dyspozycji
mysz i ca klawiatur, co otwiera zupenie nowe moliwoci w interakcji z gr. Dodaj
do tego ogromne pojemnoci choby zwykych pytek CD-ROM oraz moliwo
przechowywania (powiedzmy sobie szczerze: kopiowania) programw na dysku. Jeli
zoysz to wszystko razem, otrzymasz bardzo drogi, lecz niezwykle wydajny sprzt do
zabawy.

Oczywicie, niewiele osb przyznaje si, e kupuje komputer wycznie do grania (chyba
e chodzi o tzw. gry edukacyjne). Ale nie oszukujmy si - skoro masz ju w domu
potny komputer przeznaczony do pracy lub cznoci ze wiatem, nie zaszkodzi chyba,
e pozwolisz sobie na nieco rozrywki, prawda? Gdy Micorosft Windows opanoway
672__________________________________________Cz IV OpenGL i...

rynek na tyle, e powane" aplikacje stay si znacznie powszechniejsze dla tego sy-
stemu ni dla DOS-a, wiele osb zainstalowao ten system w swoich komputerach.
Mimo to, do mniej wicej roku temu, twrcy gier unikali Windows jak ognia, tworzc
gry prawie wycznie dla DOS-a.
Wszystkie powody ku temu mona uj w jednym sowie: wydajno. Windows znacznie
uatwiaj ycie twrcom aplikacji, gdy wszystkie polecenia graficzne wywouje si tak
samo bez wzgldu na sprzt zainstalowany w komputerze. Chcesz narysowa prostokt?
Po prostu wywoaj funkcj rysujc ten prostokt! Nie musisz konwertowa
wsprzdnych ekranowych na adres fizyczny w pamici ekranu ani martwi si, e nie
znasz szybkich algorytmw. Wszystko, co potrzebne do obsuenia karty graficznej, to
odpowiedni sterownik Windows, tumaczcy wywoania GDI na instrukcje sprztowe.
Niestety, w takim podejciu pomidzy instrukcjami graficznymi wywoywanymi przez
programist a sam kart graficzn wystpuje wiele porednich warstw kodu zwizanego z
tworzeniem obrazu na ekranie. Powoduje to powstawanie pewnego zjawiska, ktre nosi
nazw P-O-W-O-L-I. aden szanujcy si twrca gier nie mg pozwoli sobie na
tworzenie gier wideo dla Windows, wic przez duszy czas jedynymi przykadami pa-
sjonujcych gier dla Windows byy pasjans i saper.
Dostawcy sprztu starajcy si utrzyma na rynku komputerw wykorzystywanych gwnie
do prac biurowych i przetwarzania tekstw, zaczli tworzy karty graficzne oferujce
sprztow akceleracj wielu powszechnie uywanych polece rysunkowych Windows.
Rynek zalaa powd kart graficznych z akceleratorami 2D, przyspieszajcymi dziaanie
systemw Windows i sprawiajcymi, e gry dla Windows przestay by czym nierealnym.
Programistom ciko byo si oprze pokusie wykorzystania nowego, kolorowego
interfejsu, jake atrakcyjnego w porwnaniu ze zwykym tekstowym interfejsem DOS-a.
Powoli zaczy powstawa gry karciane, gry strategiczne, a nawet powstao kilka gier
wideo.
W tym momencie kady ju zdawa sobie spraw, e standardem jest system Windows,
jednak wikszo najlepszych gier (gwnie gier akcji i symulatorw pojazdw) wci
bya przeznaczona dla DOS-a. Programici po prostu nie mogli osign takiej iloci
klatek na sekund i prdkoci wywietlania, jakie mona byo osign w DOS-ie.
Pierwsz prb, jak Microsoft podj w celu wsparcia twrcw gier, byo WinG API. W
praktyce nowy interfejs nie zawiera wiele wicej ni kilka funkcji umoliwiajcych
bardzo szybkie przerzucanie bitmap. WinG stanowio znaczny postp, jednak byo to
wci za mao, aby znaczca ilo twrcw gier zwrcia si ku Windows.
Kamieniem milowym dla rynku gier okazao si powstanie systemu Windows 95.
Microsoft desperacko stara si ustanowi Windows 95 32-bitowym nastpc DOS-a dla
biurowych i domowych systemw. Tak si zoyo, e Windows NT byy wykorzystywane
gwnie do powaniejszych zada, wic Windows 95 znalazy sobie przytuln (i obszern)
nisz jako system do zastosowa domowych. Jednak nawet zanim stao si to oczywiste,
Microsoft chcia uczyni z Windows 95 podstawowy system do gier. W zwizku z tym
konieczna bya rozbudowa moliwoci multimedialnych tego systemu, i to w bardzo
duym stopniu.
Rozdzia 24. * Przyszo OpenGL w Windows___________________________673

Aby umoliwi twrcom gier bardziej bezporedni dostp do sprztu, Microsoft opracowa
zestaw interfejsw API, znanych teraz pod wspln nazw DirectX.
Nale do nich Direct Draw, przeznaczony do szybkiego przerzucania bitmap na ekran,
Direct Sound do szybkiej obsugi dwiku i MIDI, Direct Play do umoliwienia gry w
sieci oraz Direct Input do obsugi joysticka i innych urzdze wejciowych. Pomidzy
sprztem a aplikacj wystpuje jedynie bardzo cienka" warstwa porednia oprogra-
mowania, dziki czemu programista ma niespotykany dotd dostp do sprztu, zatem
gry mog zyska niespotykan dotd w Windows szybko.
Ostatnim komponentem dodanym do pakietu DirectX by DirectSD. Dzisiejsze gry wideo
nie s ju paskimi, dwuwymiarowymi scenkami. S wysoce zoonymi symulatorami
lotw lub trjwymiarowymi strzelaninami, penymi teksturowanych potworw, cian i
korytarzy. Direct3D jest cile zintegrowany z DirectDraw i kartami akceleratorw 3D.
Jeli jakie funkcje nie s obsugiwane przez sprzt, s emulowane programowo.
Dziki temu twrcy gier mog kodowa i testowa swoje aplikacje, a pniej
bezproblemowo korzysta z dodatkowych moliwoci oferowanych przez nowy sprzt.
Jak to wszystko ma si do OpenGL? Cakiem zwyczajnie: co jest dobre dla gier, jest
rwnie dobre dla OpenGL. Za rok czy dwa od momentu ukazania si tej ksiki, akce-
leratory 3D zapewne stan si standardowym wyposaeniem wikszoci komputerw
osobistych. Istnieje wiele historycznych przesanek, ktre mog utwierdzi nas w tym
przekonaniu. Na przykad, gdy pojawiy si napdy CD-ROM, nie mona w nich byo
odtwarza muzycznych pyt CD. Wkrtce jednak kto spostrzeg, e napd posiadajcy
tak moliwo z pewnoci bdzie si lepiej sprzedawa. Kt nie chciaby sucha
muzyki pracujc przy komputerze? Oczywicie, dzisiaj nie mona kupi nowego napdu
CD-ROM, w ktrym nie daoby si odtwarza muzycznych pytek CD.
To samo dziao si z pocztkowymi akceleratorami 2D dla Windows. Karty z akceleracj
szybko stay si bardzo tanie, oferujc sprztowe przyspieszenie operacji za bardzo
niewielk dodatkow cen. Na koniec, podobnie dzieje si w przypadku faksmodemw. Id
do sklepu i sprbuj kupi nowy modem, ktry rwnoczenie nie mgby dziaa jako faks.
Producenci ukadw scalonych zespolili funkcje obu urzdze w jednej kostce i dziki
masowej produkcji cena faksmodemu spada do ceny zwykego modemu.
Oczywicie, naley zakada e podobnie bdzie si dziao z kartami graficznymi z
akceleratorami 3D, a z czasem bdzie coraz lepiej. W 1995 roku Microsoft kupi firm
RenderMorphics, Ltd., twrc Reality Lab 3D API. Jest to wysokowydajna biblioteka
3D przeznaczona do tworzenia trjwymiarowej grafiki w czasie rzeczywistym na kom-
puterach osobistych. Reality Lab API jest szybsze ni OpenGL, lecz uzyskuje to ko-
sztem pewnej utraty jakoci tworzonej grafiki. Dodatkowo, w tej bibliotece nie s
dostpne wszystkie efekty specjalne i moliwoci dostpne w OpenGL. Jednak dla gier
komputerowych nie ma to wikszego znaczenia, gdy w tym przypadku szybko ma
(na razie!) o wiele wiksze znaczenie ni realizm grafiki.
W nastpnej wersji DirectX, Reality Labs API zostanie doczone do Direct3D. Di-
rect3D bdzie mogo pracowa w jednym z dwch trybw, w trybie wstrzymywanym,
bdcym oryginalnym trybem Reality Labs, oraz w trybie natychmiastowym, stanowicym
niskopoziomowy interfejs dostpu do sprztu akceleratora 3D. Relacje pomidzy
674________________________________________Cz IV OpenGL i...

trybem natychmiastowym a trybem wstrzymywanym s podobne do relacji pomidzy


OpenGL a Open Inventorem. Tryb wstrzymywany to interfejs wyszego poziomu upra-
szczajcy tworzenie scen i manipulowanie obiektami, zbudowany na bazie trybu naty-
chmiastowego.

Dobr wiadomoci dla programistw OpenGL jest to, e OpenGL bdzie mg korzysta
ze sterownikw Direct3D przyspieszajcych dziaanie DirectSD w trybie natych-
miastowym. Tak wic w przypadku kart graficznych z akceleratorem 3D zostanie
przyspieszone rwnie dziaanie aplikacji OpenGL. Gdy komputery stan si szybsze, a
poganiani przez konkurencj producenci kart 3D stworz szybsze modele, nadejdzie czas,
gdy na przecitnym komputerze osobistym bdzie mona oglda skomplikowane animacje
3D tworzone wycznie w OpenGL. Ten czas si zblia i programici (moe nawet Ty)
bd musieli bra pod uwag nie tylko szybko dziaania, ale te wizualn jako swoich
produktw.

OpenGL bdzie doskonaym narzdziem do tworzenia zapierajcych dech w piersiach


efektw i realistycznych animacji. Gdy szybkie 3D stanie si rzeczywistoci, twoja in-
westycja w OpenGL nie pjdzie na marne. W najbliszej przyszoci najprawdopodobniej
to DirectX API zapanuje w komputerach z systemem Windows. Jeli jednak chodzi o
tworzenie kodu przeznaczonego do dziaania na rnych platformach, OpenGL jest nie do
pobicia. Obecnie najszersze zastosowanie dla OpenGL mona znale w dziedzinie
przemysu rozrywkowego (efekty specjalne w kinie i w reklamach), modelowania
naukowego i edukacyjnego oraz w symulacji. Oprcz tego, wielu twrcw gier decyduje
si na uycie OpenGL przy tworzeniu plansz tytuowych, bitmap ta oraz tekstur, a nawet
do tworzenia komputerowo generowanych animacji (plikw .avi i .mpg).

Wnioski
Gdy stay si dostpne pierwsze akceleratory 2D, w rzeczywistoci tylko niewielka liczba
uytkownikw potrzebowaa dodatkowej szybkoci. Obecnie karta graficzna z akceleratorem
dla Windows jest standardowym wyposaeniem kadego komputera. W grach w dalszym
cigu rysowanie odbywa si bez pomocy akceleratora 3D, jednak og projektantw jest
gotowy do zaakceptowania akceleracji 3D, jak tylko stanie si ona powszechnie dostpna.

Moesz by pewien, e rozmiar, zoono i wymagania oprogramowania bd zawsze do


koca wykorzystyway moliwoci sprztu. Trudno sobie wyobrazi, e kiedy komputery z
kolorowym monitorem byy uwaane za niepotrzebne fanaberie. Kto pamita czasy,
kiedy 386 byy uwaane za w najwyszym stopniu zaawansowany procesor,
przeznaczony jedynie dla serwerw i naukowych stacji roboczych? To samo mwiono o
486, potem o Pentium, a teraz o Pentium Pro. Kady, kto ma wspczynnik inteligencji
powyej dwch, powinien dostrzec tu jaki wzorzec.

Wkrtce standardowe, przecitne karty graficzne bd zawieray zarwno akceleracj 3D, jak
i akceleracj 2D dla Windows. Tak jak komputery z kolorowym monitorem przestay by
uwaane za maszynki do grania, tak trjwymiarowe technologie wykorzystywane
Rozdzia 24. Przyszo OpenGL w Windows___________________________675

w grach bd zastosowane take w powaniejszych" dziedzinach. Rnica pomidzy


grafik trjwymiarow generowan wycznie programowo a grafik 3D obsugiwan
przez sprzt jest kolosalna, mniej wicej taka jak midzy wykorzystaniem goniczka
komputera do tworzenia muzyki a wykorzystaniem do tego karty Sound Blaster. Podobnie
jak karty dwikowe stay si tak popularne jak kolorowe monitory, rwnie karty
graficzne z akceleratorami 3D stan si standardowym wyposaeniem kadego kom-
putera, kupowanego w promocyjnej cenie w lokalnym supermarkecie.
Dodatek A
Poprawianie wydajnoci
OpenGL w Windows
Celem tej ksiki jest przedstawienie OpenGL z funkcjonalnego punktu widzenia. Jeli
przeczytae ca ksik, poznae OpenGL pod ktem wykorzystania jego funkcji i
polece. Poznae take kilka technik, takich jak tworzenie cieni, ktre nie s zwizane
bezporednio z konkretnymi funkcjami czy zestawami funkcji. Posiadajc te informacje
masz solidne podstawy do tworzenia aplikacji wymagajcych renderowania 3D.

Jednak grafika niejedno ma imi". Nawet jeli programujesz dopiero od tygodnia, z


pewnoci ju wiesz, e zamierzony cel mona osign na kilka sposobw. Strategie -
czy te najszersze, polegajce na wyborze narzdzi, czy te mniejsze, dotyczce stoso-
wanych algorytmw - mog si znacznie od siebie rni, lecz wci prowadz do
okrelonego celu. Twoim zadaniem, jako twrcy oprogramowania, jest dokonanie opty-
malnego wyboru w celu stworzenia jak najmniej kosztownego i najefektywniejszego
programu.

Teraz, gdy wiesz ju, jak programowa przy uyciu OpenGL, chcielibymy podsun ci
kilka rad i uwag uatwiajcych tworzenie jak najbardziej optymalnego kodu OpenGL. Te
rady i uwagi s oglnymi zaleceniami i mog zosta zastosowane w programach bez
wzgldu na platform, ktrej uywasz.

Listy wywietlania
* Uywaj list wywietlania za kadym razem, gdy ten sam obiekt ma by rende-
rowany wicej ni raz. Nawet w wycznie programowych implementacjach.
Listy wywietlania mog znacznie poprawi wydajno.
* Sprbuj osadzi kosztowne przeksztacenia macierzy i zmiany stanu w listach
wywietlania - szczeglnie podczas komponowania tekstur. Do takich prze-
ksztace nale funkcje Rotate, Translate oraz Scal.
* Niektre systemy i karty graficzne mog bezporednio korzysta z list wywie-
tlania OpenGL (na przykad poprzez uycie DMA), wic zastosowanie list
680________________________________________________Dodatki

wywietlania poprawia prdko komunikacji pomidzy procesorem a kart


graficzn. Jednak operacje takie jak glPushAttrib, glPopAttrib, glCallList oraz
glCallLists mog zwolni ten proces, gdy pewne fragmenty list wywietlania
nie mog by przekazywane kanaem DMA. Tak wic lepiej jest wywoywa
seri list wywietlania ni pojedyncz zagniedon list.

Operacje na macierzach
Uywaj wbudowanych funkcji (glRotate, glTranslate, glScale) zamiast samemu
komponowa i przemnaa wasne macierze. Wbudowane funkcje s wysoce
zoptymalizowane, szczeglnie jeli w systemie znajduje si odpowiedni sprzt.
Uywaj funkcji glLoadldentity do czyszczenia stosu macierzy zamiast adowa
wasn macierz, a to z powodw wymienionych powyej.
Zmienne stanu odkadaj i zdejmuj ze stosu (glPushAttrib/glPopAttrib) zamiast
odczytywa i ustawia je indywidualnie.

Operacje zwizane z owietleniem


Jeli nie potrzebujesz gadkiego cieniowania, uyj zamiast niego funkcji glSha-
deModel(GL_FLAT).
Okrela wasne jednostkowe wektory normalne zamiast zmusza OpenGL, aby
wyliczy je za ciebie.
Unikaj uywania funkcji glScale podczas dokonywania oblicze owietlenia.
Lepiej jest rcznie przeskalowa obiekt przed umieszczeniem go w scenie.
Jeli to moliwe, w celu zmiany waciwoci materiau zamiast funkcji glMa-
terial uywaj funkcji glColorMaterial. Uycie funkcji glMaterial jest praktyczne
tylko wtedy, gdy zmienia si jedynie pojedynczy zestaw waciwoci
materiau.

Konstruowanie obiektw
Gdziekolwiek jest to moliwe, uywaj prymitywu GLJTR.IANGLES. Czsto
krcej trwa narysowanie dwch lub wicej trjktw ni jednego czworokta
lub wielokta. Z kolei GL_QUADS jest szybszy od GL_POLYGON, bdc
przy tym rwnie szybkim lub szybszym ni GL_TRIANGLES w czysto pro-
gramowych implementacjach OpenGL.
Grupy podobnych prymityww umieszczaj wewntrz pojedynczej pary instrukcji
glBegin/glEnd.
Uywaj danych wierzchokw i innych polece w formie tablicowej, w celu
przekazania jak najwikszej iloci danych w jak najmniejszej iloci instrukcji.
Dodatek A. Poprawianie wydajnoci OpenGL w Windows ___________________ 681

* Podczas rysowania lub kopiowania obrazw, wycz rasteryzacj i operacje na


fragmentach; w przeciwnym wypadku OpenGL zastosuje tekstury do obrazw.
* Uywaj paskw prymityww (np. GL_QUAD_STRJPS) podczas podziau paskich
powierzchni; to radykalnie upraszcza obliczenia zwizane z podziaem.

Inne rady
Nie dodawaj programowi niepotrzebnej pracy, na przykad wci ustawiajc
ten sam kolor lub ustawiajc ten sam znacznik stanu.
Manualnie usuwaj niewidoczne czci sceny. Postaraj si nie rysowa obie-
ktw, o ktrych wiesz, e nie pojawi si w scenie (takich jak obiekty za tob).
Nie prbuj sprawdza widocznoci kadego obiektu, ale raczej tak dostosuj
struktur swojego programu, aby wyeliminowa oczywistych kandydatw (zajrzyj
do symulatora czogu w rozdziale 7).
W Windows jednym z waniejszych wskich garde jest przerzucanie buforw.
Gdy zmianie ulega jedynie niewielka cz sceny, uyj funkcji rozszerzenia
glAddSwapHintRectWIN.
W celu przyspieszenia renderowania zredukuj ilo szczegw sceny. Jeli po-
siadasz akcelerator sprztowy, w celu uzyskania lepszych efektw graficznych
moesz zwikszy ilo szczegw. Obecno akceleratora sprztowego moesz
sprawdzi za pomoc funkcji DescribePixelFormat. W wersji 1.1 i pniejszych
sprawd obecno znacznika PFD_GENERIC_ACCELERATED w polu
dwFlags struktury PIXELFORMATDESCRIPTOR.
Uywaj 16-bitowego bufora gbokoci, chyba e twoja aplikacja wymaga doda-
tkowej precyzji. W ten sposb nie tylko oszczdzisz pami, ale take bdziesz
mg skorzysta z wikszoci taszych akceleratorw, ktre nie obsuguj
32-bitowego bufora gbokoci.
Dodatek B
Dalsza lektura
W tym dodatku zamiecilimy list rde dalszych informacji dotyczcych programo-
wania OpenGL. Wrd podanych ksiek znajduj si zarwno pozycje zwizane bez-
porednio z OpenGL, jak i z programowaniem Windows w oglnoci, za kilka z nich
dotyczy zaawansowanych technik programowania grafiki 3D. Oprcz tego zamiecilimy
kilka ciekawych adresw stron internetowych wypenionych informacjami na temat
programowania OpenGL, przykadowymi programami oraz czami do innych zwizanych
z tym stron.

Ksiki na temat programowania Windows


Windows 95 Win32 Programming APl Bibie
Richard J. Simon, with Michael Conker and Brian Barnes
Waite Group Press

Windows 95 Common Controls & Messages


APl Bibie Richard J. Simon Waite Group Press

Windows 95 Multimedia & ODBC


APl Bibie Richard J. Simon Waite
Group Press

Programming Windows 95
Charles Petzold, Paul Yao
Microsoft Press
(polskie wydanie:Programowanie Windows 95 READ ME)
684_______________________________________________Dodatki

32-Bit Windows Programming


Ben Ezzell
SAMS

Ksiki i materiay na temat OpenGL


The OpenGL Programming Guid
Jackie Neider/OpenGL Architecture Review Board

OpenGL Reference Manual OpenGL


Architecture Review Board Addison-
Wesley

The Imentor Mentor


Josie Wemecke/Open Irwentor Architecture Group
Addison-Wesley

The Imentor Toolmaker


Josie Wernecke
Addison-Wesley Publishing Company

3D Graphics Programming with OpenGL


Clayton Walnum
QUE

Ksiki komputerowe na temat programowania grafiki (w


szczeglnoci 3D)
Computer Graphics: Principles and Practice Foley,
Van Dam, Feiner and Hughes Addison-Wesley

Serwery FTP i WWW zwizane z OpenGL


Firma________________URL___________________________
Silicon Graphics http://www.sgi.com/
Silicon Graphics http://sgigate.sgi.com/
Dodatek B. Dalsza lektura 685

Firma URL
Silicon Graphics/OpenGL WWW http://www.sgi.com/Technology/openGL/
Center
Template Graphics http://www.cts.com/~template/
Microsoft http://www.microsoft.com/ntworkstation/opengl.htm
Yiewpoint Datalabs http://www.viewpoint.com/
3D Accelerator Information http://www.cs.columbia.edu/~bm/3dcards/3d-cardsl.html
Mark Kilgard's home page http://reality.sgi.com/employees/mjk_asd/home.html
Silicon Graphics/Mark Kilgard http://www.sgi.com/Technology/openGL/glut3.html
Skadnice VRML
The VRML Repository http://www.sdsc.edu/vrmy
Paragraph International http://vrml.paragraph.com/
Silicon Graphics Vertex http://webspace.sgi.com/Repository/
International The http://www.vrml. com:80/models/vertex/
Geometry Center Ziff- http://www.geom.umn.edu/~daerorL/bin/legitlist.cgi
Davis ORC http://www.zdnet.com/zdi/vrml/
http://www.ocnus/models/models.html
Dodatek C
OpenGL wersja 1.1
W grudniu 1995 roku, podczas powstawania tej ksiki, grupa OpenGL Architecture
Review Board ratyfikowaa i zaaprobowaa now wersj, 1.1, specyfikacji OpenGL.
Wraz z wypuszczeniem Windows NT 4.0, Microsoft stanie si jednym z pierwszych,
jeli nie pierwszym, dostawc penej implementacji nowej specyfikacji OpenGL, prze-
znaczonej do komputerw osobistych. Oprcz zachowania zgodnoci z now specyfi-
kacj, Microsoft poprawi wydajno OpenGL oraz doda kilka nowych elementw i
moliwoci, midzy innymi moliwo umieszczania wywoa OpenGL w rozszerzonych
metaplikach, a take poprawion obsug wydruku.
Do najciekawszych elementw nowej specyfikacji OpenGL nale:
* Tablice wierzchokw, umoliwiajce szybsze przekazywanie pooenia wierz-
chokw, normalnych, kolorw oraz indeksw kolorw, wsprzdnych tekstur
oraz znacznikw krawdzi.
* Operacje logiczne na pikselach w trybie RGBA, a nie tylko w trybie indeksu
kolorw.
4 Wiele nowych i ulepszonych waciwoci zwizanych z teksturami^to jest pra-
wdopodobnie najwaniejszym dodatkiem zawartym w nowej specyfikacji).
Nowa wersja OpenGL dla Windows 95 ma si pojawi w kilka miesicy od ukazania si
Windows NT 4.0, czyli ju po wydaniu tej ksiki. Tak wic aby mc odpowiednio
przedstawi now specyfikacj i rozszerzenia dodane przez Microsoft, na pytce CD-
ROM zamiecilimy specjaln kartotek. Kartoteka \OpenGLll zawiera bardziej kom-
pletn dokumentacj na temat nowych elementw wersji 1.1, a take troch dodatko-
wych rzeczy dorzuconych przez Microsoft. Znajdziesz tam take kilka przykadowych
programw.
Dodatek D
Sownik
Alfa
Czwarta warto koloru dodana w celu umoliwienia okrelenia przezroczystoci koloru
obiektu. Warto alfa 0,0 oznacza cakowit przezroczysto, za warto l ,0 oznacza
zupeny brak przezroczystoci.

Antyaliasing
Metoda renderowania uywana do uzyskiwania gadkich linii i krzywych. Ta technika
urednia kolor pikseli przylegych do linii i daje wizualny efekt zagodzenia przejcia z
pikseli linii do pikseli otaczajcych lini, przez co linia wydaje si gadsza.

Aspekt ekranu
Stosunek szerokoci okna do jego wysokoci, szeroko okna w pikselach podzielona
przez wysoko okna w pikselach.

Biblioteka AUX
Niezalena biblioteka narzdziowa. Uyteczna przy popiesznym tworzeniu przenonych
programw OpenGL.

Bitplan
Tablica bitw odwzorowywanych bezporednio na piksele ekranu.

Brya widzenia
Obszar przestrzeni 3D, ktry mona obserwowa przez okna na ekranie. Obiekty i punkty
poza bry widzenia zostan obcite (nie bd widoczne).

Bufor
Obszar pamici uywany do przechowywania informacji o obrazie. Tymi informacjami
mog by kolor, gboko czy informacje o mieszaniu kolorw. Bufory dla czerwieni,
zieleni i bkitu nosz wspln nazw bufora koloru.
690______________________________________________Podatki

Culling
Eliminacja przedniej lub tylnej ciany prymitywu, w wyniku czego nie jest ona
rysowana.

Czworokt
Wielokt o dokadnie czterech bokach.

Dese
Wzorzec binarny uywany przy blokowaniu operacji w buforze ramki podczas rysowania
linii i wieloktw. Przypomina to uycie bitmapy maski, lecz w przypadku linii
uywane s jednowymiarowe desenie, za w przypadku wieloktw - dwuwymiarowe.

Krzywa Beziera
Krzywa, ktrej ksztat jest wyznaczany przez punkty kontrolne w pobliu krzywej, a nie
przez same punkty krzywej.

Krzywa parametryczna
Krzywa, ktrej ksztat jest wyznaczony przez jeden (w przypadku krzywej) lub dwa (w
przypadku powierzchni) parametry. Te parametry wystpuj w osobnych rwnaniach,
wyznaczajcych wsprzdne x, y i z punktw nalecych do krzywej.

Lista wywietlania
Skompilowana lista polece i funkcji OpenGL. Gdy zostanie wywoana, jest wykonywana
szybciej, ni trwaoby wywoywanie poszczeglnych polece i funkcji z listy.

Litera
Warto, a nie nazwa zmiennej. Oznacza acuch lub sta liczbow wpisan bezporednio
w kodzie rdowym.

Macierz
Dwuwymiarowa tablica liczb. Na macierzach mona wykonywa operacje matematy-
czne, za same macierze s wykorzystywane przy przeksztaceniach wierzchokw.

Macierz widoku modelu


Macierz OpenGL przeznaczona do transformacji prymityww ze wsprzdnych obiektu
do wsprzdnych obserwatora.

Mapowanie tekstury
Proces nakadania obrazu tekstury na powierzchni. Powierzchnia nie musi by przy
tym planarna (paska). Mapowanie tekstury czsto jest uywane w celu owinicia"
obrazu dookoa zakrzywionego obiektu lub w celu uzyskania powierzchni z deseniem, na
przykad drewna czy marmuru.
Dodatek D. Sownik________________________________________691

Normalizacja
Oznacza redukcj wektora normalnego do wektora jednostkowego, przy zachowaniu
oryginalnego kierunku. Normalna jednostkowa jest wektorem, ktrego dugo wynosi
dokadnie 1,0.

Normalna
Wektor kierunkowy wskazujcy prostopadle do paszczyzny lub powierzchni w danym
punkcie. Jeli uywasz normalnych, musisz okreli je dla kadego wierzchoka
prymitywu.

NURBS
Skrt od Non-Uniform Rational B-Spline (niejednorodna wymierna krzywa B-skleja-na).
Metoda parametrycznej reprezentacji krzywych i powierzchni.

Obcinanie
Eliminacja czci pojedynczego prymitywu lub grupy prymityww. Punkty, ktre miayby
zosta narysowane poza regionem lub bry obcinania, nie s rysowane. Bryla
obcinania to oglnie uywane okrelenie macierzy rzutowania.

Open Irwentor
Biblioteka klas C++ oraz zestaw narzdzi przeznaczone do tworzenia interaktywnych
aplikacji 3D. Open Inventor jest zbudowany na podstawie OpenGL.

Ostrosup widzenia
Brya widzenia w ksztacie ostrosupa uywana w rzucie perspektywicznym (blisze
obiekty s wiksze, dalsze s mniejsze).

Paleta
Zestaw kolorw dostpnych dla operacji rysunkowych. W przypadku 8-bitowych trybw
Windows paleta zawiera 256 kolorw, ktre musz wystarczy do wyrysowania
wszystkich pikseli na ekranie.

Perspektywa
Tryb rzutowania, w ktrym obiekty pooone dalej od obserwatora wydaj si mniejsze od
obiektw pooonych bliej.

Piksel
Nazwa pochodzi od zoenia sw picture element - element obrazu. Najmniejszy element
obrazu na ekranie komputera. Piksele s uoone w wiersze i kolumny ekranu i s im
przypisywane odpowiednie kolory skadajce si na cakowity obraz.

Podwjne buforowanie
Technika rysowania uywana w OpenGL. Obraz, ktry ma zosta wywietlony, tworzony
jest w pamici, a nastpnie przerzucany na ekran w pojedynczej operacji, w przeci-
wiestwie do tworzenia obrazu prymityw po prymitywie, bezporednio na ekranie.
692____________________________________________________Dodatki

Podwjne buforowanie jest szybk i pynn operacj odwieania ekranu i powinno by


wykorzystywane przy animacji.

Podzia wielokata
Proces podziau zoonego wielokata lub powierzchni analitycznej na siatk paskich
wieloktw wypukych. Moe zosta zastosowany take w celu rozbicia zoonej krzywej
na seri mniej zoonych odcinkw.

Prymityw
Paski wieloktny ksztat zdefiniowany w OpenGL. Wszystkie obiekty i sceny skadaj si
z rnorodnych kombinacji prymityww.

Przeksztacenie
Manipulacja ukadem wsprzdnych. Do przeksztace nale obroty, translacje (prze-
sunicia), skalowanie (w okrelonym kierunku lub rwnomiernie we wszystkich kie-
runkach) oraz podzia perspektywiczny.

Pasteryzacja
Zamiana prymityww we wsprzdnych obiektu na obraz w buforze ramki. Tzw. kana
renderowania to proces, w ktrym polecenia i instrukcje OpenGL zostaj zamienione w
piksele na ekranie.

Roztrzsanie
Metoda uywana do symulacji szerszego zakresu kolorw, ni jest sprztowo dostpny,
przez rozmieszczanie obok siebie odpowiednio pokolorowanych pikseli, tworzcych
wzory dajce wraenie przejcia midzy kolorami.

Rzut rwnolegy
Tryb rzutowania, w ktrym nie wystpuje perspektywa. W tym rzutowaniu rozmiary
wszystkich prymityww pozostaj niezmienne bez wzgldu na ich orientacj i odlego
od obserwatora.

Rzutowanie
Przeksztacenie linii, punktw i wieloktw ze wsprzdnych obserwatora do obcitych
wsprzdnych na ekranie.

Siatka
Reprezentacja jednolitych obiektw przez siatk linii zamiast wypenionych, cienio-
wanych wieloktw. Modele siatkowe zwykle s rysowane szybciej i mog suy do
przedstawienia zarwno przedniej, jak i tylnej ciany modelu rwnoczenie.

Splajn
Oglne okrelenie kadej krzywej utworzonej przez rozmieszczenie dookoa niej punktw
kontrolnych, wpywajcych na ksztat tej krzywej. Uoenie krzywej przypomina reakcj
elastycznego materiau na nacisk przyoony w rnych jego miejscach.
Dodatek D. Sownik________________________________________693

wiato otaczajce
wiato w scenie, ktre nie pochodzi z adnego konkretnego rda ani kierunku. wiato
otaczajce rwnomiernie iluminuje wszystkie obiekty ze wszystkich stron.

Teksel
Podobny do piksela (elementu obrazu), z tym e stanowi element tekstury (texture ele-
ment). Teksel reprezentuje kolor tekstury, jaki zostanie zastosowany w buforze ramki dla
pikseli reprezentujcych dany fragment wielokta z naoon tekstur.

Tekstura
Obraz (bitmapa) nakadany na powierzchni prymitywu.

Transcluencja
Stopie przezroczystoci obiektu. W OpenGL reprezentowany jest przez warto alfa z
zakresu od l ,0 (nieprzezroczysty) co 0,0 (cakowicie przezroczysty).

Tryb indeksu kolorw


Tryb koloru, w ktrym kolory sceny s wybierane z ustalonej liczby kolorw dost-
pnych w palecie. Kolory w scenie okrela si za pomoc indeksw pozycji palety.

Tryb natychmiastowy
Tryb renderowania grafiki, w ktrym funkcje i polecenia natychmiast wpywaj na stan
renderowania.

Ukad kartezjaski
Ukad wsprzdnych oparty na trzech skierowanych osiach, uoonych pod ktem pro-
stym do siebie. Wsprzdne w tym ukadzie oznaczane s literami x, y i z.

Widok
Obszar okna uywany do wywietlania obrazw OpenGL. Zwykle obejmuje cay obszar
roboczy okna Windows. Rozcignite lub skurczone widoki mog suy do tworzenia
powikszonego lub pomniejszonego obrazu w fizycznym oknie na ekranie.

Wielokt
Dwuwymiarowy ksztat z dowoln (lecz wiksz ni dwa) liczb wierzchokw.

Wielokty wypuke
Wielokty, ktre nie posiadaj wci" ani wgniece". Precyzyjnie: wielokt wypuky to
taki, w ktrym adna przechodzca przez niego linia nie przecina krawdzi wicej ni dwa
raz (raz wchodzi" i raz wychodzi").

Wierzchoek
Pojedynczy punkt w przestrzeni. Uywany przy definiowaniu wieloktw i linii, definiuje
take punkt, w ktrym cz si dwie krawdzie wielokta.
694________________________________________________Dodatki

Wsprzdne obserwatora
Ukad wsprzdnych oparty na pooeniu obserwatora. Oko obserwatora znajduje si na
osi z, a patrzy w kierunku ujemnych wartoci tej osi.

Wyciganie
Proces dodawania trzeciego wymiaru do paskiego obrazu lub ksztatu, na przykad za-
miana dwuwymiarowych czcionek na trjwymiarowe litery.
Skorowidz
.BMP 367 AUX_RETURN 83
3DDI 36 4GL AUX_RGBA 80
52, 657 8514 AUX_RIGHT 83
240 AUX_RIGHTBUTTON 84
AUX_SINGLE 80
AUX_SPACE 83
alpha blending 260 AUX_STENCIL 81
ambient 272, 273 AUX_UP 83 AUX_Z 83
animacja 74 AUX_z 83 aux!dleFunc()
animacja palety 259 74,79 auxInitDisp!ayMode()
ANSI 356 77, 80 aux!nitPosition() 61, 81
antyaliasing 260,498 aux!nitWindow() 62,81
API 35,51 auxKeyFunc() 82
aplikacja konsoli 59 auxMainLoop() 67, 83
AppExpert 643 auxMouseFunc() 84
AppWizard 629 auxReshapeFunc() 69, 85
ARB 37 auxSetOneColor() 85
Architecture Review Board 37 auxSolidBox() 86
aspect ratio 72 auxSo!idCone() 86, 87
automatyczne generowanie wsprzdnych auxSolidCylinder() 87
tekstury 401 AUX 33, 51, 52 auxSolidDodecahedron() 88
AUX_0 83 AUX_9 83 AUX_A auxSolid!cosahedron() 88
83 AUX_a 83 AUX_ACCUM 81 auxSolidOctahedron() 88
AUX_ALPHA 81 AUX_DEPTH auxSolidSphere() 89
81 AUX_DEPTH16 81 auxSolidTeapot() 89
AUX_DOUBLE 80 auxSolidTetrahedron() 90
AUX_DOWN 83 AUX_ESCAPE auxSolidTorus() 90
83 AUX_FIXED_332_PAL 81 auxSolidxxxx() 78
AUX_INDEX 80 AUX_LEFT 83 auxSwapBuffers() 77,91
AUX_LEFTBUTTON 84 auxWireBox() 91
AUX_MIDDLEBUTTON 84 auxWireCone() 91,92,208
AUX_MOUSEDOWN 84 AUX auxWireCylinder() 92
MOUSEUP 84 auxWireDodecahedron() 93
auxWire!cosahedron() 93
auxWireOctahedron() 94
auxWireSphere() 94
auxWireTeapot() 78
auxWireTeapot() 95
696 Dodatki
auxWireTetrahedron() 95 cprintf() 60 CreatePalette()
auxWireTorus() 95 254 CS_PARENTDC 108
auxWirexxxx() 78 cylindry 435 czcionki
bitmapowe 355 czworokty
B 174 czysto kodu 55
BeginPaint() 104 czyszczenie okna 62
Bezier 535 Bezier
545
biblioteka AUX 33,51,56 dane typu
biblioteka narzdziowa 52 double 54
bitmapa 175 float 54
BITMAPINFOHEADER 365, 367 GLbitfield 54
bitmapy 351 blending 505 bd GLboolean 54
GL_INVALID_ENUM 139 GLbyte 54
GL_INVALID_OPERATION 138, 139 GLclampd 54
GL_INVALID_VALUE 139 GLclampf 54
GL_NO_ERROR 138, 139 GLdouble 54
GL_OUT_OF_MEMORY 138, 139 GLenum 54
GL_STACK_OVERFLOW 139 GLfloat 54
GL_STACK_UNDERFLOW 139 GLint 54
GLU_INVALID_ENUM 139 GLshort 54
GLU_INVALID_VALUE 139 GLsizei 54
GLU_OUT_OF_MEMORY 138, 139 GLubyte 54
bdy 133 brya obcinania 49 brya GLuint 54
widzenia 50,217 bufor GLushort 54
akumulacji 494 long 54
gbokoci 479 short 54
koloru 64, 477 signed char 54
selekcji 590 unsigned char 54
sprzenia zwrotnego 598 unsigned long 54
stereo 478 szablonu 489 unsigned short 54
buforowanie 76, 77 bufory 60, DDI 38 DEC 37
473 definiowanie
bryy obcinania 72
tekstur 389
C 52 widoku 71 Delphi 657,665
C++ 52 DescribePixelFormat() 118, 476
CAD 36, 49 dese 176
CALLBACK 66 Device Driver Interface 38
CGA 239 diffuse 272,273
ChangeSizeO 69,114 DirectDraw 36 DirectX 36
chipset GLINT 40 dithering 242, 250 DLL 53
ChoosePixelFormat() 109,116, 476 domylny kolor rysowania 163
cigo krzywej 536 dopasowywanie kolorw 249
cienie 302 DOS 59 double 54
cieniowanie 43, 235, 246 drukowanie bitmap 372
cie 44 dyski 435
COLORREF 62
Skorowidz 697
ChangeSize() 69,114
ChoosePixelFormat()
efekty specjalne 459 109,116,476 cprintfO 60
EGA 240 CreatePalette() 254
ekran 44 DescribePixelFormat()
EndDoc() 373 118,476 EndDoc() 373
EndPageO 373 EndPage() 373 EndPaint()
EndPaint() 104 104 getch() 60
etykiety sprzenia zwrotnego GetPixelFormat() 122
601 glAccumO 495,499
glBeginO 149, 184,340
fala wietlna 236 glBitmapO 352
false 54 glBlendFunc() 507, 530
FL_FOG_HINT 525 glCallListO 343 glCallLists()
float 54 344 glClear() 64, 170
format pikseli 108 glClearColor() 62, 96, 500
fosfor 238 glClearDepth() 481,500
funkcja renderujca 66 glClear!ndex() 263, 501
funkcja glClearStencilO 489, 501
aux!dleFunc() 74, 79 glColorO 245, 263
aux!nitDisplayMode() glColorMask() 265
77, 80 aux!nitPosition() glColorMaterial() 279, 309
61, 81 aux!nitWindow() glCopyPixels() 366, 377
62, 81 auxKeyFunc() 82 glCullFaceO 185,310
auxMainLoop() 67, 83 glDeleteLists() 345
auxMouseFunc() 84 glDepthFuncO 502
auxReshapeFunc() 69, glDepthRange() 481, 503
85 auxSetOneColor() 85 glDisableO 153,160,461,468
auxSolidBox() 86 glDrawBuffer() 501
auxSolidCone() 86 gIDrawPixels() 359, 362, 378
auxSolidCube() 87 glEdgeFlagO 181, 186
auxSolidCylinder() 87 glEnable() 153, 160,461,468
auxSolidDodecahedron() glEndO 149, 188,340
88 glEndListO 340, 346
auxSolid!cosahedron() glEvalCoord() 540,551
88 auxSolidOctahedron() glEvalMesh() 541,552
88 auxSolidSphere() 89 glEvalPoint() 553
auxSolidTeapot() 89 glFeedbackBuffer() 598, 605
auxSolidTetrahedron() glFlush() 96 glFog() 531
90 auxSolidTorus() 90 glFrontFace()
auxSolidxxxx() 78 164,173,188,310
auxSwapBuffers() 77, 91 glFrustum() 218,225
auxWireBox() 91 glGenList() 346 glGet() 153
auxWireCone() 91 glGetBoolean() 462
auxWireCube() 92, 208 glGetErrorO 134, 138
auxWireCylinder() 92 glGetFloatO 153
auxWireDodecahedron() glGetLastErrorO 138
93 glGetLight() 312 glGetMapO
auxWire!cosahedron() 553 glGetMaterial() 311
93 auxWireOctahedron() glGetPolygonStipple() 189
94 auxWireSphere() 94
auxWireTeapot() 78,95
auxWireTetrahedron()
95 auxWireTorus() 95
auxWirexxxx() 78
BeginPaint() 104
698 Dodatki
funkcja glTexCoord() 394, 429
glGetStringO 136, 139 glTexEnv() 429 glTexGen()
glHintO 137, 140, 525 430 glTex!magelD() 389,431
gllndex() 265 gl!ndexMask() glTexImage2D() 391,432
266 gllnitNamesO 607 glTexParameter() 433
glIsDisabled() 462 glTextEnv() 392 glTranslateO
gllsEnabledO 462, 470 209,216,231 gluBeginCurve()
gllsListO 347 glLight() 559 gluBeginPolygon() 576,
300,314 glLightModelO 315 583 gluBeginSurfaceO 547,
glLineStippleO 160, 190 560 gluBeginTrimO 549,560
glLineWidthO 158, 191 gluCylinder() 437,451
glListBase() 348 gluDeleteNurbsRenderer()
glLoadEntityO 147 547, 561 gluDeleteQuadric()
glLoadldentityO 72, 212, 226 452 gluDeleteTessO 583
glLoadMatrix() 223,226 gluDiskO 438,452
glLoadName() 607 gluEndCurve() 562
glLogicOpO 267 glMap() gluEndPolygon() 576, 583
539, 555 glMapGridO 541, gluEndSurface() 547,563
558 glMaterialO 293,317 gluEndTrim() 549, 563
glMatrixMode() 147, 212, gluErrorStringO 135, 141
224, 227 glMultMatrix() 224, gluGetNurbsPropertyO 563
228 glNewList() 340, 349 gluGetStringO 136, 141
glNormalO 284,318 glOrtho() gluLoadSamplingMatrices()
69, 97, 147 gIPassThroughO 654 gluLookAt() 231
600, 608 glPixelMap() 362, gluNewContour() 584
379 glPixelStore() 362, 380 gluNewNurbsRenderer() 547,
glPixelTransfer() 360, 382 565 gluNewQuadric() 436,
glPixelZoom() 362,383 453 gluNewTess() 576, 584
glPointSize() 152, 193 gluNextContour() 577
glPolygonMode() 173,194 gluNurbsCallback() 566
glPolygonStipple() 195 gluNurbsCurve() 568
glPopAttrib() 301,470 gluNurbsProperty() 547, 569
glPopMatrix() 148,216,228 gluNurbsSurfaceO 547, 571
glPopNameO 609 gluOrtho2D() 232
glPushAttribO 301,462,470 gluPaitialDisk() 439, 453
glPushMatrix() 148, 216, 229 gluPerspective() 218,233
glPushNameO 609 gluPickMatrix() 593,613
glRasterPos() 353 gluPwlCurve() 549, 572
glReadPixels() 363, 384 gluQuadricCallback() 454
glRect() 66,98 gluQuadricDrawStyle() 436,
glRenderMode() 590,610 454 gluQuadricNormals() 436,
glRotate() 79, 148, 209, 216, 455 gluQuadricOrientation()
229 glScale() 210,230 436, 455 gluQuadricTexture()
glSelectBuffer() 612 glSet() 436,456 gluSphere() 439, 456
153 glShadeMode() 169 gluTessCallback() 581,585
glShadeModel() 268 gluTessVertex() 576, 585
glStencilFunc() 489 glVertex() 148, 196
glStencilMask() 489 glViewport() 69, 71, 97
glStencilOpO 489 RenderScene() 66, 115,
148,289 SetPixelFormat()
109, 122 SetTimerO 114
SetupRCO 277
Skorowidz 699
funkcja GL_BLUE_BIAS 383, 464
StretchBltO 373 SwapBuffersO GL_BLUE_SCALE 383,464
115, 123 wgICreateContext() 106, GL_BORDER_COLOR 434
124 wglDeleteContext() 106, 125 GLJ3YTE 344,379 GL_CCW
wglGetCurrentContext() 125 164, 189,310 GL_CLAMP 434
wglGetCurrentDCO 126 GL_CLEAR 268 GL_COEFF
wglGetProcAddress() 126 554 GL_COLOR 378
wglMakeCurrent() 106, 127 GL_COLOR_BUFFER_BIT 170,463
wglShareListsO 128 GL_COLOR_INDEX 359, 379, 432, 433
wglUseFontBitmaps() 129, 355 GL_COLOR_INDEXES 312
wglUseFontOutlinesO 130 GL_COLOR_MATERIAL 279, 309, 463, 464
WinMain() 111 WndProcO 111 GL_COLOR_MATERIAL_FACE 464
funkcje bufora szablonu 489 GL_COMPILE 341, 349
funkcje Wiggle 106 GL_COMPILE_AND_EXECUTE 341,349
funkcje zwrotne 581 GL_CONSTANT_ATTENUATION 313
GL_COPY 268 GL_COPY_INVERTED 268
GL_COPY_PIXEL_TOKEN 599
GDI 35, 102, 245 GL_CULL_FACE 172, 186, 310, 463, 464
getch() 60 GL_CULL_FACE_MODE 464
GetPixelFormat() 122 GL_CURRENTJBIT 463
GL 36 gl 52 gl.h 52 GL_CURRENT_POSITION_VALID 463
GL_2_BYTES 344 GL_2D 599, 606 GL_CW 164, 189 GL_DECAL 393,430
GL_3_BYTES 344 GL_3D 599,606 GL_DECR 491 GL_DEPTH 378
GL_3D_COLOR 599, 606 GL_DEPTH_BIAS 383,464
GL_3D_COLOR_TEXTURE 599, 606 GL_DEPTH_BUFFER 463
GL_4_BYTES 344 GL_DEPTH_BUFFER_BIT 170
GL_4D_COLOR_TEXTURE 599, 606 GL_DEPTH_COMPONENT 379
GL_ACCUM 494, 499 GL_DEPTH_SCALE 383,464
GL_ACCUM_BUFFER_BIT 463 GL_ADD GL_DEPTH_TEST 170, 461, 463
494,499 GL_ALPHA 379, 432, 433 GL_DEPTH_WRITEMASK 463
GL_ALPHA_BIAS 383,464 GLJDIFFUSE 309 GL_DITHER 250, 463
GL_ALPHA_LUMINANCE 432, 433 GL_DOMAIN 554 GL_DONT_CARE 141
GL_ALPHA_SCALE 383, 464 GL_DRAW_PIXEL_TOKEN 599
GL_ALPHA_TEST 463 GL_ALWAYS GL_DST_ALPHA 506 GL_DST_COLOR 506
480,503 GL_AMBIENT 309 GL_EDGE_FLAG 463 GL_EMISSION 309
GL_AMBIENT_AND_DIFFUSE 279, 309 GL_ENABLE_BIT 463 GL_EQUAL 480, 503
GL_AND 268 GL_AND_INVERTED 268 GL_EQUIW 268 GL_EVAL_BIT 463
GL_AND_REVERSE 268 GL_EXP 520 GL_EXP2 520
GL_AUTO_NORMAL 463 GL_BACK 173, GL_EXTENSIONS 136, 140
186, 195, 309, 478, 502 GL_EYE_LINEAR 431 GL_EYE_PLANE 431
GL_BACK_AND_FRONT 309 GL FALT 169
GLJBITMAP 360,379
GL_BITMAP_TOKEN 599 GL_BLEND
393, 430, 463, 505 GL_BLUE 379, 432, 433
700 Dodatki
GL_FASTEST 141 GL_LINE_TOKEN 599
GLJFEEDBACK 598,611 GL_LINE_WIDTH_GRANULARITY 158
GL_FILL 173, 195 GL_LINE_WIDTH_RANGE 158 GLJJNEAR
GL_FLAT 268 390, 520 GL_LINEAR_ATTENUATION 313
GL_FLOAT 344, 379 GL_LINEAR_MIPMAP_LINEAR 391,396
GL_FOG 463 GL_LINEAR_M1PMAP_NEAREST 391,396
GL_FOG_BIT 463 GL_LINES 155, 184 GL_LIST_BASE 464
GL_FOG_COLOR 531 GL_LIST_BIT 464 GL_LOAD 494, 499
GL_FOG_DENSITY 524, 531 GL_LOGIC_OP 267, 463 GL_LUMINANCE
GL_FOG_END 531 359, 379, 432, 433 GL_LUMINANCE_ALPHA
GL_FOG_HINT 140,463 379 GL_MAP_COLOR 380, 382, 464
GL_FOG_INDEX 531 GL_MAP_DEPTH 464 GL_MAP_STENCIL
GL_FOG_MODE 463,520,531 380, 382 GL_MAP1_COLOR_4 554, 556, 569
GL_FOG_START 531 GL_MAP1_INDEX 554, 556, 569
GL_FRONT 186, 195, 309, 478, 502 GL_MAP1_NORMAL 554, 556, 569
GL_FRONT_AND_BACK 195,478,502 GL_MAP1_TEXTURE_COORDJ 554, 556,
GL_FRONT_FACE 464 569 GL_MAP1_TEXTURE_COORD_2
GL_GEQUAL 480, 503 554, 556,
GL_GREATER 480, 503 569 GL_MAP1_TEXTURE_COORD_3
GL_GREEN 379,432,433 554,556,
GL_GREEN_BIAS 383,464 569 GL_MAP1_TEXTURE_COORD_4
GL_GREEN_SCALE 383, 464 554,556,
GL_HINT_BIT 463 569
GLJNCR 491 GL_MAP1_VERTEX_3 539,554,556,569
GL_INDEX_OFFSET 383, 464 GL_MAP1_VERTEX_4 539, 554, 556, 569
GL_INDEX_SHIFT 383,464 GL_MAPl_x 463
GLJNT 344, 379 GL_MAP2_COLOR_4 554, 556, 572
GL_INVALID_ENUM 135, 139 GL_MAP2JNDEX 554, 556, 572
GL_INVALID_OPERATION 138, 139 GL_MAP2_NORMAL 554, 556, 572
GL_INVALID_VALUE 139 GL_MAP2_TEXTURE_COORD_1 554, 556,
GLJNYERT 268, 491 572 GL_MAP2_TEXTURE_COORD_2
GLJCEEP 490 554, 556,
GL_LEFT_BACK 478, 502 572 GL_MAP2_TEXTURE_COORD_3
GL_LEFT_FRONT 478, 502 554, 556,
GL_LEQUAL 480, 503 572 GL_MAP2_TEXTURE_COORD_4
GL_LESS 479, 503 554, 556,
GL_LIGHT 313 572
GL_LIGHT_MODEL_AMBIENT 278,315 GL_MAP2_VERTEX_3 554, 556, 572
GL_LIGHT_MODEL_LOCAL_VIEWER GL_MAP2_VERTEX_4 554, 556, 572
316,464 GL_MAP2_x 463 GL_MATRIX_MODE 464
GL_L1GHT_MODEL_TWO_SIDE 315,464 GL_MAX_MODELVIEW_STACK_DEPTH
GL_LIGHTO 288 GL_LIGHTi 463 214
GL_LIGHTING 277, 463, 464 GL_MAX_NAME_STACK_DEPTH 610
GL_LIGHTING_BIT 301,464 GL_LIGHTx GL_MAX_PROJECTION_STACK_DEPTH
464 GL_LINE 173, 195 GL_LINE_BIT 464 214
GL_LINE_LOOP 156, 185 GL_MODELVIEW 212, 224, 227, 431
GL_L1NE_RESET_TOKEN 599 GL_MODULATE 393,430 GL MULT
GL_LINE_SMOOTH 463, 464 494,499
GL_LINE_SMOOTH_HINT 140, 463
GL_LINE_STIPPLE 160,190,463,464
GL_LINE_STRIP 156, 184
Skorowidz 701
GL_NAME_STACK_DEPTH 609 GL_POLYGON_SMOOTH_HINT 141,463
GL_NAND 268 GL_NEAREST 390 GL_POLYGON_STIPPLE 176, 195,463,464
GL_NEAREST_MIPMAP_LINEAR 391,396 GL_POLYGON_STIPPLE_BIT 464
GL_NEAREST_MIPMAP_NEAREST 391, 396 GL_POLYGON_TOKEN 599 GL_POSITION
GL_NEVER 479, 503 GL_NICEST 141,525 298,313 GL_PROJECTION 227 GL_Q 431
GL_NO_ERROR 135, 138, 139 GL_NOOP 268 GL_QUAD_STRIP 175, 185
GL_NOR 268 GL_QUADRATIC_ATTENUATION 313
GL_NORMALIZE 285,318,463,464 GL_QUADS 174, 185 GL_R 431
GL_NOTEQUAL 480, 503 GL_READ_BUFFER 464 GL_RED
GL_OBJECT_LINEAR 401,430,431 379,432,433 GL_RED_BIAS 383,464
GL_ONE 506,531 GL_RED_SCALE 383, 464
GL_ONE_MINUS_DST_ALPHA 506 GL_RENDER 590,610 GL_RENDERER
GL_ONE_MINUS_DST_COLOR 506 140,611 GL_REPEAT 394, 434
GL_ONE_MINUS_SRC_ALPHA 506 GL_REPLACE 490 GL_RETURN 494,
GL_OR 268 499 GL_RGB 359,379,432,433
GL_OR_INVERTED 268 GL_RGBA 379,432,433
GL_OR_REVERSE 268 GL_RIGHT_BACK 478, 502
GL_ORDER 554 GL_RIGHT_FRONT 478, 502 GL_S
GL_OUT_OF_MEMORY 135, 138, 139 401,431 GL_SCISSOR_BIT_BIT 464
GL_PACK_ALIGNMENT 381 GL_SCISSOR_TEST 463, 464
GL_PACK_LSB_FIRST 381 GL_SELECT 610 GL_SELECTION 590
GL_PACK_ROW_LENGTH 381 GL_SET 268 GL_SHADE_MODE 464
GL_PACK_SKIP_PIXELS 381 GL_SHININESS 292,312 GL_SHORT
GL_PACK_SKIP_ROWS 381 344, 379 GL_SMOOTH 169,268
GL_PACK_SWAP_BYTES 381 GL_SPECULAR 292, 309
GL_PASS_THROUGH_TOKEN 599, 608 GL_SPHERE_MAP 431
GL_PERSPECTIVE_CORRECTION_HINT GL_SPOT_CUTOFF 300,313
140, 463 GL_SPOT_DIRECTION 313
GL_PIXEL_MAP_A_TO_A 380 GL_SPOT_EXPONENT 300,313
GL_PIXEL_MAP_B_TO_B 380 GL_SRC_ALPHA 506
GL_PIXEL_MAP_G_TO_G 380 GL_SRC_ALPHA_SATURATE 506
GL_PIXEL_MAP_I_TO_A 380 GL_STACK_OVERFLOW 139,214
GL_PIXEL_MAP_I_TO_B 380 GLJSTACKJJNDERFLOW 139,214
GL_PIXEL_MAP_I_TO_G 380 GL_STENCIL 378
GL_PIXEL_MAP_I_TO_I 380 GL_STENCIL_BUFFER_BIT 464
GL_PIXEL_MAP_I_TO_R 380 GL_STENCILJNDEX 379
GL_PIXEL_MAP_R_TO_R 380 GL_STENCIL_TEST 463, 464 GL_T
GL_PIXEL_MAP_S_TO_S 380 401,431 GL_TEXTURE 227
GL_PIXEL_MODE_BIT 464 GL_TEXTURE_1D 434,463
GL_POINT 195 GL_POINT_BIT GL_TEXTURE_2D 432, 433, 434, 463
464 GL_TEXTURE_BIT 464
GL_POINT_SIZE_GRANULARITY 153, 193 GL_TEXTURE_ENV 430 GL
GL_POINT_SIZE_RANGE 153, 193 TEXTURE ENV COLOR 430
GL_POINT_SMOOTH 463, 464
GL_POINT_SMOOTH_HINT 141,463
GL_POINT_TOKEN 599 GL_POINTS 149, 184
GL_POLYGON 185,575 GL_POLYGON_B1T
464 GL_POLYGON_MODE 464
GL_POLYGON SMOOTH 463,464
702 Dodatki
GL_TEXTURE_ENV_MODE 430 glDeleteLists() 345
GL_TEXTURE_GEN 463 glDepthFuncO 502
GL_TEXTURE_GEN_MODE 430, glDepthRange() 481,503
464 GL_TEXTURE_GEN_Q 430 glDisableO 153,
GL_TEXTURE_GEN_R 430 160,461,468 GLdouble 54
GL_TEXTURE_GEN_S 430 glDrawBuffer() 501
GL_TEXTURE_GEN_T 430 glDrawPixels() 359, 362,
GL_TEXTURE_GEN_x 464 378 glEdgeFlagO 181, 186
GL_TEXTURE_MAX_FILTER glEnable()
434 GL_TEXTURE_MIN_FILTER 153,160,461,468 glEnd()
390,434 GL_TEXTURE_WRAP_S 149,188,340 glEndListO
394, 434 GL_TEXTURE_WRAP_T 340, 346 GLenum 54
434 GL_TRANSFORM_BIT 464 glEvalCoord() 540,551
GL_TRIANGLE_FAN glEvalMesh() 541,552
165,185,581 glEvalPoint() 553
GL_TRIANGLE_STRIP glFeedbackBuffer() 598,
164,185,581 GLJTRIANGLES 605 GLfloat 54 glFlush()
162,185,581 96 glFogO 520,531
GL_UNPACK_ALIGNEMNT 382, glFrontFaceO 164, 173,
379 GL_UNPACK_LSB_FIRST 188, 310 glFrustumO
381 218,225 glGenList() 346
GL_UNPACK_ROW_LENGTH glGet() 153 glGetBoolean()
362, 382 462 glGetErrorO 134, 138
GL_UNPACK_SKIP_PIXELS 362, glGetFloatO 153
382 GL_UNPACK_SKIP_ROWS glGetLastError() 138
363, 382 glGetLightO 312
GL_UNPACK_SWAP_BYTES 381 glGetMapO 553
GL_UNSIGNED_BYTE 344, 379 glGetMaterial() 311
GLJJNSIGNEDJNT 344, 379 glGetPolygonStippleO 189
GL_UNSIGNED_SHORT 344, 379 glGetStringO 136,139
GL_VENDOR 140 GL_VERSION glGetStringO 139 glHintO
140 GL_VIEWPORT_BIT 464 137, 140, 525 gllndex() 265
GL_XOR 268 GL_ZERO gl!ndexMask() 266
490,506,531 GL_ZOOM_X 464 gllnitNamesO 607 GLINT
GL_ZOOM_Y 464 glAccumO 40 GLint 54 glIsDisabled()
495,499 glaux.h 52 glaux.lib 52 462 glIsEnabled() 462, 470
glBegin() 149,184,430 GLbitfield glIsList() 347 glLight()
54 glBitmapO 352 glBlendFuncO 300,314 glLightModelO
507, 530 GLboolean 54 GLbyte 54 315 glLineStippleO 160,
glCallList() 343, 344 GLclampd 54 190 glLineWidth() 158, 191
GLclampf 54 glClear() 64, 170 glListBase() 348
glClearColorO 62, 96, 500 glLoadEntityO 147
glClearDepthO 481,500 glLoadIdentity()
glCleadndex() 263, 501 212,226,72 glLoadMatrix()
glClearStencilO 489, 501 glColorO 223, 226 glLoadName()
245, 263 glColorMaskO 265 607 glLogicOpO 267
glColorMaterial() 279, 309 glMapO 539, 555
glCopyPixels() 366, 377 glMapGridO 541, 558
glCullFaceO 185,310
Skorowidz 703
glMaterialO 293,317 GLU_ERROR 566, 567, 582
glMatrixMode() 147,212,224,227 GLU_EXTENSIONS 136 GLU_EXTERIOR
glMultMatrix() 224,228 577 GLU_FALSE 437 GLU_FILL 436, 454,
glNewList() 340, 349 569 GLU_FLAT 437, 455 GLU_INSIDE 455
glNormalO 284,318 GLU_INTERIOR 577 GLU_INVALID_ENUM
glOrthoO 69, 97, 147 139 GLU_INVALID_VALUE 139 GLU_LINE
glPassThrough() 600,608 436 GLU_LINE 454 GLU_MAP1_TRIM_2
glPixelMap() 362,379 573 GLU_MAP1_TRIM_3 573 GLU_NONE
glPixelStore() 362, 380 437,455 GLU_NURBS_ERRORx 566,567
glPixelTransfer() 360, 382 GLU_OUT_OF_MEMORY 135,138, 139
glPixelZoom() 362, 383 GLU_OUTLINE_PATCH 569
glPointSize() 152, 193 GLU_OUTLINE_POLYGON 569
glPolygonMode() 173, 194 GLU_OUTSIDE 455
glPolygonStipple() 195 GLU_PARAMETRIC_ERROR 570
glPopAttrib() 301,470 GLU_PARAMETRIC_TOLERANCE 564, 569
glPopMatrix() 148,216,228 GLU_PATH_LENGTH 569, 570 GLU_POINT
glPopName() 609 436, 454 GLU_SAMPLING_METHOD 564,
glPushAttribO 301,462,470 570 GLU_SAMPLING_TOLERANCE 564, 569
glPushMatrix() 148, 216, 229 GLU_SILHOUETTE 436, 454 GLU_SMOOTH
glPushNameO 609 437,455 GLUJTRUE 437 GLU_U_STEP 564,
glRasterPos() 353 570 GLUJJNKNOWN 577 GLU_V_STEP 564,
glReadPixels() 363, 384 570 GLU_VERTEX 582 glu32.dll 52
glRectO 66,98 gluBeginCurve() 559 gluBeginPoygonO 576,
glRenderMode() 590,610 583 gluBeginSurfaceO 547, 560 gluBeginTrimO
glRotate() 79, 148, 209, 216, 229 549,560 GLubyte 54 gIuCylinder() 437,451
glScale() 210,230 gluDeleteNurbsRenderer() 547, 561
g!SelectBuffer() 612 gluDeleteQuadric() 452 gluDeleteTessO 583
glSet() 153 gluDiskO 438, 452 gluEndCurve() 562
glShadeMode() 169 gluEndPolygonO 576, 583 gluEndSurface() 547,
glShadeModelO 268 563 gluEndTrim() 549, 563 gluErrorStringO
GLshort 54 135, 141 gluGetNurbsPropertyO 563
GLsizei 54 gluGetStringO 136, 141 GLuint 54
glStencilFunc() 489 gluLoadSamplingMatricesO 654
glStencilMask() 489 gluLookAt() 231
glStencilOpO 489
g!TexCoord() 394, 429
glTexEnv() 429
glTexGen() 430
glTex!magelD() 389,431
glTexImage2D() 391,432
glTexParameter() 433
glTextEnv() 392
glTranslateO 209,216,231
glu 52
glu.h 52
GLU_AUTO_LOAD_MATRIX 564, 570, 613
GLUJ3EGIN 581
GLU_CCW 577
GLU_CULLING 564, 569
GLU_CW 577
GLU_DISPLAY_MODE 564, 569
GLU_DOMAIN_DISTANCE 570
GLU_EDGE_FLAG 582
GLU END 582
704 Dodatki
gluNewContour() 584
gluNewNurbsRenderer()
547, 565 gluNewQuadric() jednolite obiekty 166
436, 453 gluNewTess() jzyk 4GL 52 jzyk
576,584 gluNextContour() GL 36
577 gluNurbsCallback() 566 K
gluNurbsCurve() 568
GLUnurbsObj 546 karta
gluNurbsPropertyO 547, 569 8514 240
gluNurbsSurfaceO 547, 571 EGA 240
gluOrtho2D() 232 Hercules 239
gluPartialDisk() 439, 453 VGA 240
gluPerspective() 218,233 kartezjaski ukad wsprzdnych
gluPickMatrix() 593,613 45 kierunek trjkta 163 kierunek
gluPwlCurve() 549,572 wieloktw 285 kierunkowe
gluQuadricCallback() 454 rdo wiata 299 klasa krzywej
gluQuadricDrawStyle() 436, 535 klawiatura 83 kolejka polece
454 gluQuadricNormals() 64 kolejka przeksztace 207
436, 455 GLUuadricObj kolor 43, 63, 235
436 gluQuadricOrientation() dopasowywanie 249
436, 455 paleta 249 komunikat
gluQuadricTexture() 436, WM_CLOSE 338
456 GLushort 54 WM_CREATE 107
gluSphereO 439, 456 WM_DESTROY 107
gluTessCallback() 581,585 WM_PAINT 104, 107,338
gluTessVertes() 576, 585 WM_PALETTECHANGED
GLUtriangulatorObj 576 116,253
glVertex() 148, 196 WM_QUERYNEWPALETTE
glViewport() 69,71,97 252
GLYPHMETR1CSFLOAT WM_QUERYPALETTE 116
131 gbia koloru 241 WM_SIZE 114
gboko mgy 524 grafika WMJTIMER 115,337
interaktywna 587 grafika konfigurowanie buforw 474
rastrowa 351 Graphics konstruowanie wieloktw 179
Device Interface 35 GUI 59 kontekst renderowania OpenGL
105 kontekst urzdzenia GDI 102
H kontrolki OCX 659 konwencje
HAL 39 nazw funkcji 55 kopiowanie
Hardware Abstraction Layer pixmap 366 kostka kolorw 243
39 krzywe 533 krzywe
HBRUSH 103 Beziera 535, 545
Hercules 239 cigo 536
HGLRC 106 dwuwymiarowe 537
hierarchia obiektw 594 klasa 535
HPALETTE 251 obliczenia 537
punkty kontrolne 535
l reprezentacja parametryczna
IBM 37 imbryk 534
78 inicjowanie stopie 535
67 Intel 37 wzy 546
Internet 615 kwadryki
IR1S GL 36, 37 435
Skorowidz 705
normalne jednostkowe 285
lampa 44 NURBS 54,533,545
linie 145
linie przerywane 160
listy wywietlania 340 obcinanie wsprzdnych 46
LOGPALETTE 251 obiekt GLUnurbsObj 546
long 54 GLUquadricObj 436
GLUtriangulatorObj 576 obrt 203, 209 obszar
obcinania 46, 49 obszar roboczy okna 46 OCX
adowanie macierzy 223 659 odbyski 291 odczytplikow.BMP 368
amane 156 amane odtwarzanie zmiennych stanu 462 odwzorowanie
zamknite 156 czenie GL_MAP1_COLOR_4 554, 556, 569
kolorw 509 GL_MAP1_INDEX 554,556,569
GL_MAP1_NORMAL 554, 556, 569
M GL_MAP1_TEXTURE_COORD_1 554,556,
macierze 206, 680 569
macierz GL_MAP1_TEXTURE_COORD_2 554,556,
GL_MODELVIEW 227 569
GL_PROJECTION 227 GL_MAP1_TEXTURE_COORD_3 554,556,
GL_TEXTURE 227 569
adowanie 223 rzutowania GL_MAP1_TEXTURE_COORD_4 554, 556,
216 stos macierzy 213 569
tosamociowa 211 widoku GL_MAP1_VERTEX_3 554,556,569
modelu 208 GL_MAP1_VERTEX_4 554,556,569
makro RGB 103,245 GL_MAP2_COLOR_4 554, 556, 572
mapowanie tekstur 387 GL_MAP2_INDEX 554, 556, 572
maszyna stanu OpenGL 461 GL_MAP2_NORMAL 554, 556, 572
materia 275 owietlenie GL_MAP2_TEXTURE_COORD_1 554, 556,
275 waciwoci 275, 572
279 GL_MAP2_TEXTURE_COORD_2 554, 556,
MFC 52, 627 572
mga 505, 520 GL_MAP2_TEXTURE_COORD_3 554, 556,
GL_FOG_COLOR 531 572
GL_FOG_DENSITY 531 GL_MAP2_TEXTURE_COORD_4 554, 556,
GL_FOG_END 531 572
GL_FOG_INDEX 531 GL_MAP2_VERTEX_3 554, 556, 572
GL_FOG_MODE 531 GL_MAP2_VERTEX_4 554, 556, 572
GL_FOG_START 531 okno widoku 46 oko 41
mipmapy 389, 394 Open Inventor 617
model 202 opengl32.dll 52 operacja
model cieniowania 246 GL_AND 268
model owietlenia 278 GL_AND_INVERTED 268
modelowanie obiektw 321 GL_AND_REVERSE 268
mysz 84 GL_CLEAR 268
GL_COPY 268
N GL_COPY_INVERTED 268
nakadanie tekstur 388 nazwy GL_EQUIW 268
funkcji 55 nazywanie
prymityww 588 niezaleno
od platformy 57 normalizacja
285 normalne 544
706 Dodatki
operacja glu.h 52
GLJNYERT 268 glu32.dll 52
GLJMAND 268 opengl32.dll 52
GL_NOOP 268 WINSRV.DLL 38 pliki
GL_NOR 268 nagwkowe 60 Pug and Play 659
GLJDR 268 paskie cieniowanie 248 paszczyzna
GL ORJNYERTED 268 44 paszczyzna xy 45 pynne
GL~OR_REVERSE 268 cieniowanie 246 podwjne
GL_SET 268 buforowanie 76, 77, 477 podzia
GL_XOR 268 wielokta 181,575 PO1NTFLOAT
oprnianie kolejki polece 64 131 pojedyncze buforowanie 60
osie ukadu wsprzdnych 45 poprawianie wydajnoci 340, 679
ostrosup widzenia 218 porwnywanie gbokoci 479
owietlenie 271 owietlenie powierzchnie 533, 541
materiau 275 otwarte API 57 normalne 544
OWL 52,641 owietlenie 544
pozycjonowanie okna 60
pozycyjne rdo wiata 299
PAINTSTRUCT 104 PRINTDLG 372 prostokt 66
paleta systemowa 251 prymityw
paleta 242,249 GL_LINE_LOOP 156, 185
3-3-2 255 GL_LINE_STRIP 156, 184
animacja 259 GLJJNES 155, 184
struktura 254 GL_POINTS 149, 184
tworzenie 253, 258 GL_POLYGON 185,575
usuwanie 258 PALETTEENTRY 254 pasek GL_QUAD_STRIP 175, 185
czworoktw 175 perspektywa 50, 218 pdzle GL_QUADS 174, 185
103 PFD_DOUBLE_BUFFER_DONT_CARE GL_TR1ANGLE_FAN 165,185,581
121, GL_TRIANGLE_STRIP 164, 185, 581
475 GLJRIANGLES 162, 185, 581
PFD_DOUBLEBUFFER 121,475 prymitywy 47, 145 przedrostki nazw
PFD_DRAW_TO_B1TMAP 121,475 funkcji 52 przeksztacenia 200
PFD_DRAW_TO_WINDOW 121,475 przeksztacenie modelu 202 przeksztacenie
PFD_GENERIC_FORMAT 121,476 okna 206 przeksztacenie punktu
PFD_MA1N_PLANE 122 obserwacji 202 przeksztacenie rzutowania
PFD_NEED_PALETTE 121,254,476 205 przerzucanie kolorw 478 przestrze
PFD_NEED_SYSTEM_PALETTE 121,476 trjwymiarowa 146 przesunicie 203,208
PFD_OVERLAY_PLANE 122 PFD_STEREO przezroczysto 505 przygotowanie modelu
121,475 PFD_STEREO_DONT_CARE 121,475 owietlenia 278 przygotowanie okna 108
PFD_SUPPORT_GDI 121, 475 przygotowanie waciwoci materiau 279
PFD_SUPPORT_OPENGL 121,475 przyrostki nazw zmiennych 54 punkt
PFD_TYPE_COLORINDEX 122,260,475 zbiegu 205 punkty 145 punkty kontrolne
PFD_TYPE_RGBA 122,475 535
PFD_UNDERLAY_PLANE 122
PKELFORMATDESCRIPTOR 109, 254, 474
pixmapy 359 plik .BMP 367
gl.h 52
glaux.h 52
glaux.lib 52
Skorowidz 707
SetTimerO 114
SetupRCO 277
ay tracing 35 sfery 435 SGI
Reality Labs 39 35 short 54
remapowanie kolorw 360 sie komputerowa 615 signed
renderowanie 66 char 54 Silicon Graphics 35
RenderSceneO 66, 115, 148,289 skalowanie pixmapy 362
reprezentacja parametryczna krzywych 534 skalowanie 68, 114,203,210
RGB 51, 103,245 specular 272, 273 sprzenie
RGBA 60, 239 zwrotne 587 staa AUX_0 83
rotacja 203 AUX_9 83
rozdzielczo ekranu 241 AUX_A 83
roztrzsanie 242, 250 AUX_a 83
rwnanie parametryczne 534 AUX_ACCUM 81
rysowanie bitmapy 351 AUX_ALPHA 81
cylindrw 437 AUX_DEPTH 81
czworokty 174 AUX_DEPTH16 81
domylny kolor 163 AUX_DOUBLE 80
dyskw 438 AUX_DOWN 83
jednolite obiekty 166 AUX_ESCAPE 83
kierunek trjkta 163 AUX_FIXED_332_PAL 81
konstruowanie wieloktw 179 AUX_1NDEX 80
linie 155 AUX_LEFT 83
linie przerywane 160 AUX_LEFTBUTTON 84
amane 156 AUX_MIDDLEBUTTON 84
amane zamknite 156 AUX_MOUSEDOWN 84
pasek czworoktw 175 AUX_MOUSEUP 84
pixmapy 359 AUX_RETURN 83
podzia wielokta 181 AUX_RGBA 80
prymityww 47 AUX_RIGHT 83
punkty 149 AUX_RIGHTBUTTON 84
sfer 439 AUX_SINGLE 80
stokw 438 AUX_SPACE 83
wiata punktowego 301 AUX_STENCIL 81
trjktw 162,261 AUX_UP 83
tryby wieloktw 173 AUX_Z 83
ustawienie koloru wieloktw 169 AUX_z 83
usuwanie niewidocznych powierzchni 171 COLORREF 62
wachlarz trjktw 165 false 54
wieloktw 289 FL_FOG_HINT 525
wieloktw wklsych 576 GL_2_BYTES 344
wieloktw zoonych 577 GL_2D 599, 606
wycinkw dysku 439 GL_3_BYTES 344
wypenianie wieloktw 175 GL_3D 599,606
znacznik krawdzi 181 rzutowanie GL_3D_COLOR 599, 606
perspektywiczne 205, 218 rzutowanie GL_3D_COLOR_TEXTURE 599, 606
rwnolege 205,217 rzutowanie GL_4_BYTES 344
216,322 rzuty 48 rzuty GL_4D_COLOR_TEXTURE 599, 606
perspektywiczne 50 GL_ACCUM_BUFFER_BIT 463
GL_ALPHA 379, 432, 433
GL_ALPHA_BIAS 383,464
selekcja 588
SetPixelFormat() 109, 122
708 Dodatki
stal GL_DOMAIN 554 GL_DONT_CARE 141
GL_ALPHA_LUMINANCE 432, 433 GL_DRAW_PIXEL_TOKEN 599
GL_ALPHA_SCALE 383,464 GL_DST_ALPHA 506 GL_DST_COLOR
GL_ALPHA_TEST 463 GL_ALWAYS 506 GL_EDGE_FLAG 463 GL_EMISS10N
480, 490, 503 GL_AMBIENT 309 309 GL_ENABLE_BIT 463 GL_EQUAL
GL_AMBIENT_AND_DIFFUSE 279, 309 480, 490, 503 GL_EQUIW 268
GL_AND 268 GL_AND_INVERTED 268 GL_EVAL_BIT 463 GL_EXP 520
GL_AND_REVERSE 268 GL_EXP2 520 GL_EXTENSIONS 136, 140
GL_AUTO_NORMAL 463 GL_BACK 173, GL_EYE_LINEAR 431 GL_EYE_PLANE
186, 195, 309, 478, 502 431 GL_FALT 169 GL_FASTEST 141
GL_BACK_AND_FRONT 309 GL_FEEDBACK 590, 598, 611 GL_FILL
GL_BITMAP 360,379 173, 195 GL_FLAT 268 GL_FLOAT 344,
GL_BITMAP_TOKEN 599 GL_BLEND 379 GL_FOG 463 GL_FOG_BIT 463
430, 463, 505 GL_BLUE 379,432,433 GL_FOG_COLOR 531 GL_FOG_DENSITY
GL_BLUE_BIAS 383,464 524,531 GL_FOG_END 531
GL_BLUE_SCALE 383, 464 GL_FOG_HINT 140,463 GL_FOG_INDEX
GL_BORDER_COLOR 434 GL_BYTE 344, 531 GL_FOG_MODE 463,520,531
379 GL_CCW 164,189,310 GL_CLAMP GL_FOG_START 531 GL_FRONT 186,
434 GL_CLEAR 268 GL_COEFF 554 195, 309, 478, 502
GL_COLOR 378 GL_FRONT_AND_BACK 195, 478, 502
GL_COLOR_BUFFER_BIT 170,463 GL_FRONT_FACE 464 GL_GEQUAL 480,
GL_COLOR_INDEX 359, 579, 432, 433 490, 503 GL_GREATER 480, 490, 503
GL_COLOR_INDEXES 312 GL_GREEN 379,432,433
GL_COLOR_MATER1AL 279 GL_GREEN_BIAS 383,464
GL_COLOR_MATERIAL 309, 463, 464 GL_GREEN_SCALE 383,464
GL_COLOR_MATERIAL_FACE 464 GL_HINT_BIT 463 GL_INDEX_OFFSET
GL_COMPILE 341,349 383, 464 GL_INDEX_SHIFT 383, 464
GL_COMPILE_AND_EXECUTE 341,349 GLJNT 344, 379 GL_INVAL1D_ENUM
GL_CONSTANT_ATTENUATION 313 135, 139 GL_INVALID_OPERATION 138,
GL_COPY 268 GL_COPY_INVERTED 268 139 GL_1NVALID_VALUE 139
GL_COPY_PIXEL_TOKEN 599 GLJNYERT 268 GL_LEFT_BACK 478,
GL_CULL_FACE 172,186,310,463,464 502 GL_LEFT_FRONT 478, 502
GL_CULL_FACE_MODE 464 GL_LEQUAL 480, 490, 503 GL_LESS
GL_CURRENT_BIT 463 479,490,503 GL_LIGHT 313
GL_CURRENT_POSITION_VALID 463 GL_LIGHT_MODEL_AMBIENT 278,315
GL_CW 164, 189 GL_DECAL 392,430 stal
GL_DEPTH 378 GL_DEPTH_BIAS 383,
464 GL_DEPTH_BUFFER 463
GL_DEPTH_BUFFER_BIT 170
GL_DEPTH_COMPONENT 379
GL_DEPTH_SCALE 383,464
GL_DEPTH_TEST 170,461,463
GL_DEPTH_WRITEMASK 463
GLJDIFFUSE 309 GL DITHER 250, 463
Skorowidz 709
GL_LIGHT_MODEL_LOCAL_VIEWER 316, GL_MAP2_TEXTURE_COORD_3 554, 556,
464 572 GL_MAP2_TEXTURE_COORD_4 554,
GL_LIGHT_MODEL_TWO_SIDE 315,464 556,
GL_LIGHTO 288 GL_LIGHTi 463 572
GL_LIGHTING 277, 463, 464 GL_MAP2_VERTEX_3 554, 556, 572
GL_LIGHTING_BIT 301,464 GL_LIGHTx GL_MAP2_VERTEX_4 554, 556, 572
464 GL_LINE 173, 195 GL_LINE_B1T 464 GL_MAP2_x 463 GL_MATRIX_MODE 464
GL_LINE_LOOP 156, 185 GL_MAX_MODELVIEW_STACK_DEPTH
GL_LINE_RESET_TOKEN 599 214
GL_LINE_SMOOTH 463,464 GL_MAX_NAME_STACK_DEPTH 610
GL_LINE_SMOOTH_HINT 140,463 GL_MAX_PROJECTION_STACK_DEPTH
GL_LINE_STIPPLE 160, 190, 463, 464 214
GL_LINE_STRIP 156, 184 GL_LINE_TOKEN GL_MODELVIEW 212,224,227,431
599 GL_LINE_WIDTH_GRANULARITY 158 GL_MODULATE 430
GL_LINE_WIDTH_RANGE 158 GL_LINEAR GL_NAME_STACK_DEPTH 609
390, 520 GL_LINEAR_ATTENUATION 313 GL_NAND 268 GL_NEAREST 390
GL_LINEAR_MIPMAP_LINEAR 391,396 GL_NEAREST_MIPMAP_LINEAR 391,396
GL_LINEAR_MIPMAP_NEAREST 391,396 GL_NEAREST_MIPMAP_NEAREST 391,
GL_LINES 155, 184 GL_LIST_BASE 464 396
GL_LIST_BIT 464 GL_LOGIC_OP 267, 463 GL_NEVER 479, 490, 503
GL_LUMINANCE 359, 379, 432, 433 GLJNICEST 141,525
GL_LUMINANCE_ALPHA 379 GL_NO_ERROR 135, 138, 139
GL_MAP_COLOR 380, 382, 464 GL_NOOP 268 GL_NOR 268
GL_MAP_DEPTH 464 GL_MAP_STENCIL GL_NORMALIZE 285,318,463,464
380, 382 GL_MAP1_COLOR_4 554, 556, 569 GL_NOTEQUAL 480, 490, 503
GL_MAP1_INDEX 554, 556, 569 GL_OBJECT_LINEAR 430
GL_MAP1_NORMAL 554,556,569 GL_OBJECT_PLANE 401,431
GL_MAP1_TEXTURE_COORD_1 554, 556, GL_ONE 506,531
569 GL_MAP1_TEXTURE_COORD_2 GL_ONE_MINUS_DST_ALPHA 506
554,556, GL_ONE_MINUS_DST_COLOR 506
569 GL_MAP1_TEXTURE_COORD_3 554, GL_ONE_MINUS_SRC_ALPHA 506
556, GL_OR 268
569 GL_MAP1_TEXTURE_COORD_4 554, GL_OR_INVERTED 268
556, GL_OR_REVERSE 268
569 GL_ORDER 554
GL_MAP1_VERTEX_3 539,554,556,569 GL_OUT_OF_MEMORY 135, 138, 139
GL_MAP1_VERTEX_4 539, 554, 556, 569 GL_PACK_ALIGNMENT 381
GL_MAPl_x 463 GL_PACK_LSB_FIRST 381
GL_MAP2_COLOR_4 554, 556, 572 GL_PACK_ROW_LENGTH 381
GL_MAP2_INDEX 554, 556, 572 GL_PACK_SKIP_PIXELS 381
GL_MAP2_NORMAL 554, 556, 572 GL_PACK_SKIP_ROWS 381
GL_MAP2_TEXTURE_COORD_1 554, 556, GL_PACK_SWAP_BYTES 381
572 GL_MAP2_TEXTURE_COORD_2 554, GL_PASS_THROUGH_TOKEN 599, 608
556, GL_PERSPECTIVE_CORRECTION_HINT
572 140,463
GL_PIXEL_MAP_A_TO_A 380
GL_PIXEL_MAP_B_TO_B 380
GL_PIXEL_MAP_G_TO_G 380
GL_PIXEL_MAP_I_TO_A 380 GL
PIXEL MAP I TO B 380
710 Dodatki
staa GL_SPOT_DIRECTION 313
GL_PIXEL_MAP_I_TO_G GL_SPOT_EXPONENT 300,313
380 GL_PIXEL_MAP_I_TO_I GL_SRC_ALPHA 506
380 GL_SRC_ALPHA_SATURATE 506
GL_PIXEL_MAP_1_TO_R GL_STACK_OVERFLOW 139,214
380 GL_STACK_UNDERFLOW 139,214
GL_PIXEL_MAP_R_TO_R GL_STENCIL 378
380 GL_STENCIL_BUFFER_BIT 464
GL_PIXEL_MAP_S_TO_S GL_STENC1L_INDEX 379
380 GL_PIXEL_MODE_BIT GL_STENCIL_TEST 463, 464 GL_T
464 GL_POINT 195 401,431 GL_TEXTURE 227
GL_POINT_BIT 464 GL_TEXTURE_1D 392, 434, 463
GL_POINT_SIZE_GRANULARITY GL_TEXTURE_2D 392, 432, 433, 434,
153,193 GL_POINT_SIZE_RANGE 463 GL_TEXTURE_BIT 464
153,193 GL_POINT_SMOOTH 463, GL_TEXTURE_ENV 392,430
464 GL_POINT_SMOOTH HINT GL_TEXTURE_ENV_COLOR 430
141,463 GL_POINT_TOKEN 599 GL_TEXTURE_ENV_MODE 392, 430
GL_POINTS 149, 184 GL_POLYGON GL_TEXTURE_GEN 463
185,575 GL_POLYGON_BIT 464 GL_TEXTURE_GEN_MODE 430, 464
GL_POLYGON_MODE 464 GL GL_TEXTURE_GEN_Q 430
POLYGON_SMOOTH 463, 464 GL_TEXTURE_GEN_R 430
GLJPOLYGON_SMOOTH_HINT GL_TEXTURE_GEN_S 430
141,463 GL_POLYGON_STIPPLE GL_TEXTURE_GEN_T 430
176, 195,463,464 GL_TEXTURE_GEN_x 464
GL_POLYGON_STIPPLE_BIT 464 GL_TEXTURE_MAX_FILTER 434
GL_POLYGON_TOKEN 599 GL_TEXTURE_MIN_FILTER 390,
GL_POSITION 298,313 434 GL_TEXTURE_WRAP_S 394,
GL_PROJECTION 227 GL_Q 431 434 GL_TEXTURE_WRAP_T 434
GL_QUAD_STRIP 175, 185 GL_TRANSFORM_BIT 464
GL_QUADRATIC_ATTENUATION GL_TRIANGLE_FAN 165, 185, 581
313 GL_QUADS 174, 185 GL_R 431 GL_TRIANGLE_STRIP 164,185,581
GL_READ_BUFFER 464 GLJTRIANGLES 162, 185, 581
GL_RED 379,432,433 GL_UNPACK_ALIGNEMNT 382, 379
GL_RED_BIAS 383,464 GL_UNPACK_LSB_FIRST 381
GL_RED SCAL GL_UNPACK_ROW_LENGTH 362,
383,464 GL_RENDER 382 GL_UNPACK_SKIP_PIXELS 362,
590,610 GL RENDERER 382 GL_UNPACK_SKIP_ROWS 363,
140,611 GL~REPEAT 382 GL_UNPACK_SWAP_BYTES 381
394, 434 GL_RGB GL_UNSIGNED_BYTE 344, 379
359,379,432,433 GLJJNSIGNEDJNT 344, 379
GL_RGBA 379, 432, 433 GL_UNSIGNED_SHORT 344, 379
GL RIGHT_BACK 478, GL_VENDOR 140 GL_VERSION 140
502 GL~RIGHT_FRONT GL_VIEWPORT_BIT 464 GL_XOR
478, 502 GL_S 401,431 268 GL_ZERO 506 GL_ZERO 531
GL_SCISSOR_BIT_BIT GL_ZOOM_X 464 GL_ZOOM_Y 464
464 GL_SCISSOR_TEST GLU_AUTO_LOAD_MATRIX
463, 464 GL_SELECT 564,570,613 GLU_BEGIN 581
610 GL_SELECTION 590 GLU_CCW 577 GLU CULLING 564,
GL_SET 268 569
GL_SHADE_MODE 464
GL_SHININESS 292,312
GL_SHORT 344, 379
GL_SMOOTH 169,268
GL_SPECULAR 292, 309
GL_SPHERE_MAP 431 GL
SPOT CUTOFF 300,313
Skorowidz 711
staa PFD_UNDERLAY_PLANE 122
GLU_CW 577 PIXELFORMATDESCRIPTOR 254
GLU_DISPLAY_MODE 564, 569 true 54
GLU_DOMAIN_DISTANCE 570 WGL_FONT_LINES 131
GLU_EDGE_FLAG 582 GLU_END 582 WGL_FONT_POLYGONS 131
GLU_ERROR 566, 567, 582 stan bufora gbokoci 465
GLU_EXTENSIONS 136 GLU_EXTERIOR 577 bufora szablonu 465
GLU_FALSE 437 GLU_FILL 436, 454, 569 owietlenia 465
GLU_FLAT 437, 455 GLUJNSIDE 455 pikseli 467
GLUJNTERIOR 577 GLU_INVALID_ENUM rysowania 464
139 GLU_INVALID_VALUE 139 GLU_LINE teksturowania 466
436,454 GLU_MAP1_TRIM_2 573 stereoskop 42 stopie krzywej
GLU_MAP1_TRIM_3 573 GLU_NONE 437, 535 stopie poryskliwoci
455 GLU_NURBS_ERRORx 566, 567 293 stos macierzy 213
GLU_OUT_OF_MEMORY 135, 138, 139 stosunek wsprzdnych 72
GLU_OUTLINE_PATCH 569 StretchBltO 373 struktura
GLU_OUTLINE_POLYGON 569 palety 254 struktura
GLU_OUTSIDE 455 BITMAPFILEHEADER 367
GLU_PARAMETRIC_ERROR 570 BITMAPINFOHEADER 365
GLU_PARAMETRIC_TOLERANCE 564, 569 GLYPHMETRICSFLOAT 131
GLU_PATH_LENGTH 569, 570 GLU_POINT LOGPALETTE 251
436, 454 GLU_SAMPLING_METHOD 564, 570 PAINTSTRUCT 104
GLU_SAMPLING_TOLERANCE 564, 569 PALETTEENTRY 254
GLU_SILHOUETTE 436,454 GLU_SMOOTH PIXELFORMATDESCRIPTOR 109,474
437,455 GLU_TRUE 437 GLU_U_STEP 564, POINTFLOAT 131
570 GLUJJNKNOWN 577 GLU_V_STEP 564, PRINTDLG 372
570 GLU_VERTEX 582 style okien 108 styl
PFD_DOUBLE_BUFFER_DONT_CARE 121, CS_PARENTDC 108
475 WS_CLIPCHILDREN 108
PFD_DOUBLEBUFFER 121,475 WS_CL1PSIBLINGS 108
PFD_DRAW_TO_BITMAP 121,465 WS_OWNDC 107 Super VGA 61
PFD_DRAW_TO_WINDOW 121,475 SwapBuffers() 115, 123 szybko
PFD_GENERIC_FORMAT 121 dziaania 336
PFD_MAIN_PLANE 122
PFD_NEED_PALETTE 121,254
PFD_NEED_SYSTEM_PALETTE 121 cieka
PFD_OVERLAY_PLANE 122 PFD_STEREO GLU_CCW 577 GLU_CW
121,475 PFD_STEREO_DONT_CARE 121,475 577 GLU_EXTERIOR 577
PFD_SUPPORT_GDI 121,475 GLUJNTERIOR 577
PFD_SUPPORT_OPENGL 121,475 GLUJJNKNOWN 577
PFD_TYPE_COLOR1NDEX 122, 260, 475 PFD wiato 44,236 wiata
TYPE_RGBA 122, 475 punktowe 298 wiato jako
czstka 237 wiato
kierunkowe 299 wiato
ambient 272, 273 diffuse
272, 273 odbysku 272,
273 otaczajce 272, 273
712 Dodatki
wiato HGLRC 106
rozproszone 272, HPALETTE 251
273 specular 272, typy danych 53
273
U
uchwyt palety 251 uchwyt
tablice odwzorowa kolorw 361 pdzla 103 udostpnianie
teksturowanie cylindrw 438 palety 251 ukad
teksturowanie dysku 439 wsprzdnych 44, 45
teksturowanie sfer 440 kartezjaski 45
tekstury 387 osie 45
test szybkoci 336 UNICODE 356 UNIX 56 unsigned
timer 114 char 54 unsigned long 54 unsigned
transformacje wsprzdnych 199 short 54 ustalanie gruboci linii 158
translacja 203 ustalanie koloru rysowania 245
trjkt 162,261 ustalanie rozmiaru punktu 152
trjwymiarowe wsprzdne ustawianie bryy obcinania 68
kartezjaskie 48 ustawianie widoku 68 ustawienie
TrueColor 259 koloru wieloktw 169 usuwanie
true 54 niewidocznych linii 43 usuwanie
tryb cieniowania 248 niewidocznych powierzchni 171
tryb graficzny 241 usuwanie palety 258 urednianie
tryb indeksu koloru 239, 259, 308 normalnych 294 uywanie rda
tryb konsoli 59 wiata 281
tryb renderowania
GL_FEEDBACK 590
GL_RENDER 590 VGA 45,61,240
GL_SELECTION 590 tryb Yisual Basic 52,657
RGBA 239 tryb wywietlania 60 VRML 617
tryb-RGBA 60 tryby wieloktw
173 trzeci wymiar 41, 78 W
tworzenie kontekstu renderowania wachlarz trjktw 165
106 tworzenie kwadryk 436 warto
tworzenie palety 253, 258 AUX_0 83
tworzenie powierzchni NURBS AUX_9 83
546 tworzenie wasnych AUX_A 83
przeksztace 224 typ danych AUX_a 83
GL_2D 599,606 AUX_ACCUM 81
GL_3D 599,606 AUX_ALPHA 81
GL_3D_COLOR 599, 606 AUX_DEPTH 81
GL_3D_COLOR_TEXTURE 599, AUX_DEPTH16 81
606 AUX_DOUBLE 80
GL_4D_COLOR_TEXTURE 599, AUX_DOWN 83
606 AUX_ESCAPE 83
GL_2_BYTES 344 AUX_FIXED_332_PAL 81
GL_3_BYTES 344 AUX_INDEX 80
GL_4_BYTES 344 AUX_LEFT 83
GL_BYTE 344 AUX_LEFTBUTTON 84
GL_FLOAT 344 AUX MIDDLEBUTTON 84
GLJNT 344
GL_SHORT 344
GL_UNSIGNED_BYTE 344
GL_UNSIGNED_INT 344
GL UNSIGNED SHORT 344
Skorowidz 713
warto GL_COLOR_INDEXES 312
AUX_MOUSEDOWN GL_COLOR_MATERIAL 279
84 AUX_MOUSEUP GL_COLOR_MATERIAL 309, 463,
84 AUX_RETURN 83 464
AUX_RGBA 80 GL_COLOR_MATERIAL_FACE
AUX_RIGHT 83 464 GL_COMPILE 341,349
AUX_RIGHTBUTTON GL_COMPILE_AND_EXECUTE
84 AUX_SINGLE 80 341,349
AUX_SPACE 83 GL_CONSTANT_ATTENUATION
AUX_STENCIL 81 313 GL_COPY 268
AUX_UP 83 AUX_Z GL_COPY_INVERTED 268
83 AUX_z 83 GL_COPY_PIXEL_TOKEN 599
COLORREF 62 false GL_CULL_FACE
54 172,186,310,463,464
FL_FOG_HINT 525 GL_2_BYTES GL_CULL_FACE_MODE 464
344 GL_2D 599, 606 GL_CURRENT_BIT 463
GL_3_BYTES 344 GL_3D 599, GL_CURRENT_POSITION_VALID
606 GL_3D_COLOR 599, 606 463 GL_CW 164, 189 GL_DECAL
GL_3D_COLOR_TEXTURE 599, 392, 430 GL_DEPTH 378
606 GL_4_BYTES 344 GL_DEPTH_BIAS 383,464
GL_4D_COLOR_TEXTURE 599, GL_DEPTH_BUFFER 463
606 GL_ACCUM_BUFFER_BIT GL_DEPTH_BUFFER_BIT 170
463 GL_ALPHA 379, 432, 433 GL_DEPTH_COMPONENT 379
GL_ALPHA_BIAS 383,464 GL_DEPTH_SCALE 383,464
GL_ALPHA_LUMINANCE 432, GL_DEPTH_TEST 170, 461, 463
433 GL_ALPHA_SCALE 383,464 GL_DEPTH_WRITEMASK 463
GL_ALPHA_TEST 463 GL_DIFFUSE 309 GL_DITHER
GL_ALWAYS 480, 490, 503 250, 463 GL_DOMAIN 554
GL_AMBIENT 309 GLJDONT_CARE 141
GL_AMBIENT_AND_DIFFUSE GL_DRAW_PIXEL_TOKEN 599
279, 309 GL_AND 268 GL_DST_ALPHA 506
GL_AND_INVERTED 268 GL_DST_COLOR 506
GL_AND_REVERSE 268 GL_EDGE_FLAG 463
GL_AUTO_NORMAL 463 GL_EMISSION 309
GL_BACK 173, 186, 195, 309, 478, GL_ENABLE_BIT 463 GL_EQUAL
502 GL_BACK_AND_FRONT 309 480, 490, 503 GL_EQUIW 268
GL_BITMAP 360,379 GL_EVAL_BIT 463 GL_EXP 520
GL_BITMAP_TOKEN 599 GL_EXP2 520 GL_EXTENSIONS
GL_BLEND 430, 463, 505 136, 140 GL_EYE_LINEAR 431
GL_BLUE 379,432,433 GL_EYE_PLANE 431 GL_FALT
GL_BLUEJ3IAS 383,464 169 GL_FASTEST 141
GL_BLUE_SCALE 383, 464 GL_FEEDBACK 590,598,611
GL_BORDER_COLOR 434 GL_FILL 173, 195 GL_FLAT 268
GL_BYTE 344,379 GL_CCW GL_FLOAT 344, 379 GL_FOG 463
164,189,310 GL_CLAMP 434 GL_FOG_BIT 463
GL_CLEAR 268 GL_COEFF 554 GL_FOG_COLOR 531
GL_COLOR 378 GL_FOG_DENSITY 524,531
GL_COLOR_BUFFER_BIT GL_FOG_END 531
170,463 GL COLOR_INDEX 359, GL_FOG_HINT 140,463
579, 432, 433
714 Dodatki

warto GL_LUMINANCE_ALPHA 379


GL_FOG_INDEX 531 GL_FOG_MODE GL_MAP_COLOR 380, 382, 464
463,520,531 GL_FOG_START 531 GL_MAP_DEPTH 464 GL_MAP_STENCIL
GL_FRONT 186, 195, 309, 478, 502 380, 382 GL_MAP1_COLOR_4 554,556,569
GL_FRONT_AND_BACK 195,478,502 GL_MAP1_INDEX 554,556,569
GL_FRONT_FACE 464 GL_GEQUAL GL_MAP1_NORMAL 554, 556, 569
480, 490, 503 GL_GREATER 480, 490, 503 GL_MAP1_TEXTURE_COORD_1 554, 556,
GL_GREEN 379, 432, 433 569 GL_MAP1_TEXTURE_COORD_2 554,
GL_GREEN_B1AS 383,464 556,
GL_GREEN_SCALE 383, 464 569 GL_MAP1_TEXTURE_COORD_3 554,
GL_H1NT_BIT 463 GL_INDEX_OFFSET 556,
383, 464 GL_INDEX_SHIFT 383,464 569 GL_MAP1_TEXTURE_COORD_4 554,
GLJNT 344, 379 GL_INVALID_ENUM 556,
135, 139 GL_INVALID_OPERATION 138, 569
139 GL_INVALID_VALUE 139 GL_MAP1_VERTEX_3 539,554,556,569
GLJNYERT 268 GL_LEFT_BACK 478, GL_MAP1_VERTEX_4 539,554,556,569
502 GL_LEFT_FRONT 478, 502 GL_MAPl_x 463
GL_LEQUAL 480, 490, 503 GLJJESS 479, GL_MAP2_COLOR_4 554, 556, 572
490, 503 GL_LIGHT 313 GL_MAP2_INDEX 554, 556, 572
GL_LIGHT_MODEL_AMBIENT 278,315 GL_MAP2_NORMAL 554, 556, 572
GL_LIGHT_MODEL_LOCAL_VIEWER 316, GL_MAP2_TEXTURE_COORD_1 554, 556,
464 572 GL_MAP2_TEXTURE_COORD_2 554,
GL_LIGHT_MODEL_TWO_SIDE 315,464 556,
GL_LIGHTO 288 GL_LIGHTi 463 572 GL_MAP2_TEXTURE_COORD_3 554,
GL_LIGHTING 277, 463, 464 556,
GL_LIGHTING_BIT 301, 464 GL_LIGHTx 464 572 GL_MAP2_TEXTURE_COORD_4 554,
GL_LINE 173, 195 556,
GL_L1NE_BIT 464 GL_LINE_LOOP 156, 185 572
GL_LINE_RESET_TOKEN 599 GL_LINE SMOOTH GL_MAP2_VERTEX_3 554, 556, 572
463,464 GL_LINE~SMOOTH_HINT 140,463 GL_MAP2_VERTEX_4 554, 556, 572
GL_LINE_STIPPLE 160,190,463,464 GL_LINE_STRIP GL_MAP2_x 463 GL_MATRIX_MODE 464
156, 184 GL_LINE_TOKEN 599 GL_MAX_MODELVIEW_STACK_DEPTH
GL_LINE_WIDTH_GRANULARITY 158 214
GL_LINE_W1DTH_RANGE 158 GL_MAX_NAME_STACK_DEPTH 610
GL_L1NEAR 390, 520 GL_MAX_PROJECTION_STACK_DEPTH
GL_LINEAR_ATTENUAT1ON 313 214
GL_LINEAR_MIPMAP_LINEAR 391,396 GL_MODELVIEW 212,224,227,431
GL_LINEAR_MIPMAP_NEAREST 391,396 GL_MODULATE 430
GL_LINES 155, 184 GL_LIST_BASE 464 GL_NAME_STACK_DEPTH 609
GL_LIST_BIT 464 GL_LOGIC_OP 267,463 GL_NAND 268 GL_NEAREST 390
GL_LUMINANCE 359, 379, 432, 433 GL_NEAREST_MIPMAP_LINEAR 391,396
GL_NEAREST_M1PMAP_NEAREST 391,
396
GL_NEVER 479, 490, 503
GL_NICEST 141,525
GL_NO_ERROR 135, 138, 139
GL_NOOP 268 GL_NOR 268
GL_NORMALIZE 285,318,463,464
GL_NOTEQUAL 480,490, 503 GL
OBJECT LIN AR 430
Skorowidz 715
warto GL_READ_BUFFER 464 GL_RED
GL_OBJECT_PLANE 401,431 379,432,433 GL__RED_BIAS 383,464
GL_ONE 506,531 GL_RED_SCALE 383,464 GL_RENDER
GL_ONE_MINUS_DST_ALPHA 506 590,610 GL_RENDERER 140,611
GL_ONE_MINUS_DST_COLOR 506 GL_REPEAT 394,434 GL_RGB 359, 379,
GL_ONE_MINUS_SRC_ALPHA 506 432, 433 GL_RGBA 379,432,433
GL_OR 268 GL_RIGHT_BACK 478, 502
GL_OR_INVERTED 268 GL_RIGHT_FRONT 478, 502 GL_S
GL_OR_REVERSE 268 401,431 GL_SCISSOR_BIT_BIT 464
GLJ3RDER 554 GL_SCISSOR_TEST 463, 464 GL_SELECT
GL_OUT_OF_MEMORY 135, 138, 139 610 GL_SELECTION 590 GL_SET 268
GL_PACK_ALIGNMENT 381 GL_SHADE_MODE 464 GL_SHININESS
GL_PACK_LSB_FIRST 381 292,312 GL_SHORT 344, 379
GL_PACK_ROW_LENGTH 381 GL^SMOOTH 169,268 GL_SPECULAR
GL_PACK_SKIP_PIXELS 381 292, 309 GL_SPHERE_MAP 431
GL_PACK_SKIP_ROWS 381 GL_SPOT_CUTOFF 300,313
GL_PACK_SWAP_BYTES 381 GL_SPOT_DIRECTION 313
GL_PASS_THROUGH_TOKEN 599, 608 GL_SPOT_EXPONENT 300,313
GL_PERSPECTIVE_CORRECTION_HINT GL_SRC_ALPHA 506
140,463 GL_SRC_ALPHA_SATURATE 506
GL_PIXEL_MAP_A_TO_A 380 GL_STACK_OVERFLOW 139,214
GL_PIXEL_MAP_B_TO_B 380 GL_STACK_UNDERFLOW 139,214
GL_PIXEL_MAP_G_TO_G 380 GL_STENCIL 378
GL_PIXEL_MAP_I_TO_A 380 GL_STENCIL_BUFFER_BIT 464
GL_PIXEL_MAP_I_TO_B 380 GL_STENCIL_INDEX 379
GL_PIXEL_MAP_I_TO_G 380 GL_STENCIL_TEST 463, 464 GL_T
GL_PIXEL_MAP_I_TO_I 380 401,431 GL_TEXTURE 227
GL_PIXEL_MAP_I_TO_R 380 GL_TEXTURE_1D 392,434,463
GL_PIXEL_MAP_R_TO_R 380 GL_TEXTURE_2D 392, 432, 433, 434, 463
GL_PIXEL_MAP_S_TO_S 380 GL_TEXTURE_BIT 464
GL_PIXEL_MODE_BIT 464 GL_TEXTURE_ENV 392, 430
GL_POINT 195 GL_POINT_BIT GL_TEXTURE_ENV_COLOR 430
464 GL_TEXTURE_ENV_MODE 392, 430
GL_POINT_SIZE_GRANULARITY 153, 193 GL_TEXTURE_GEN 463
GL_POINT_SIZE_RANGE 153, 193 GL_TEXTURE_GEN_MODE 430, 464
GL_POINT_SMOOTH 463, 464 GL_TEXTURE_GEN_Q 430
GL_POINT_SMOOTH_HINT 141,463 GL_TEXTURE_GEN_R 430
GL_POINT_TOKEN 599 GL_POINTS 149, GL_TEXTURE_GEN_S 430
184 GL_POLYGON 185,575 GL_TEXTURE_GEN_T 430
GL_POLYGON_BIT 464 GL_TEXTURE_GEN_x 464
GL_POLYGON_MODE 464 GL_TEXTURE_MAX_FILTER 434
GL_POLYGON_SMOOTH 463, 464 GL_TEXTURE_MIN_FILTER 390, 434
GL_POLYGON_SMOOTH_HINT 141,463 GL_TEXTURE_WRAP_S 394, 434
GL_POLYGON_STIPPLE 176, 195,463,464 GL_TEXTURE_WRAP_T 434 GL
GL_POLYGON_STIPPLE_BIT 464 TRANSFORM BIT 464
GL_POLYGON_TOKEN 599 GL_POSITION
298,313 GL_PROJECTION 227 GL_Q 431
GL_QUAD_STRIP 175, 185
GL_QUADRATIC_ATTENUATION 313
GL_QUADS 174, 185 GL R 431
716 Dodatki

warto GLU_SAMPLING_TOLERANCE 564, 569


GL_TRIANGLE_FAN 165, 185, 581 GLU_SILHOUETTE 436, 454
GL_TRIANGLE_STRIP 164,185,581 GLU_SMOOTH 437,455
GLJTRIANGLES 162,185,581 GLU_TRUE 437
GL_UNPACK_ALIGNEMNT 382, 379 GLU_U_STEP 564, 570
GL_UNPACK_LSB_FIRST 381 GLUJJNKNOWN 577
GL_UNPACK_ROW_LENGTH 362, 382 GLU_V_STEP 564, 570
GLJJNPACK_SKIP_PIXELS 362, 382 GLU_VERTEX 582
GL_UNPACK_SKIP_ROWS 363, 382 PFD_DOUBLE_BUFFER_DONT_CARE 121,
GL_UNPACK_SWAP_BYTES 381 475
GL_UNSIGNED_BYTE 344, 379 PFD_DOUBLEBUFFER 121,475
GLJJNSIGNEDJNT 344, 379 PFD_DRAW_TO_BITMAP 121,465
GL_UNSIGNED_SHORT 344, 379 PFD_DRAW_TO_WINDOW 121, 475
GL_VENDOR 140 GL_VERSION 140 PFD_GENERIC_FORMAT 121
GL_VIEWPORT_BIT 464 GL_XOR 268 PFD_MAIN_PLANE 122
GL_ZERO 506 GL_ZERO 531 PFD_NEED_PALETTE 121,254
GL_ZOOM_X 464 GL_ZOOM_Y 464 PFD_NEED_SYSTEM_PALETTE 121
GLU_AUTO_LOAD_MATRIX 564,570,613 PFD_OVERLAY_PLANE 122
GLU_BEGIN 581 GLU_CCW 577 PFD_STEREO 121,475
GLU_CULLING 564, 569 GLU_CW 577 PFD_STEREO_DONT_CARE 121,475
GLU_DISPLAY_MODE 564, 569 PFD_SUPPORT_GDI 121,475
GLU_DOMAIN_DISTANCE 570 PFD_SUPPORT_OPENGL 121,475
GLU_EDGE_FLAG 582 GLU_END 582 PFD_TYPE_COLORINDEX 122, 260, 475
GLU_ERROR 566, 567, 582 PFD_TYPE_RGBA 122,475
GLU_EXTENSIONS 136 GLU_EXTERIOR PFD_UNDERLAY_PLANE 122
577 GLU_FALSE 437 GLU_FILL 436, 454, 569 PKELFORMATDESCRIPTOR 254
GLU_FLAT 437, 455 GLUJNSIDE 455 WGL_FONT_LINES 131
GLUJNTERIOR 577 GLU_1NVALID_ENUM WGL_FONT_POLYGONS 131
139 GLU_1NVALID_VALUE 139 GLU_LINE warto TRUE 54 WebSpace 618
436, 454 GLU_MAP1_TRIM_2 573 wejcie/wyjcie 57 wektor
GLU_MAP1_TRIM_3 573 GLU_NONE 437, normalny 283 wzy krzywych 546
455 GLU_NURBS_ERRORx 566,567 WGL_FONT_LINES 131
GLU_OUT_OF_MEMORY 135, 138, 139 WGL_FONT_POLYGONS 131
GLU_OUTLINE_PATCH 569 wglCreateContext() 106, 124
GLU_OUTLINE_POLYGON 569 wglDeleteContext() 106, 125
GLU_OUTSIDE 455 wglGetCurrentContext() 125
GLU_PARAMETRIC_ERROR 570 wglGetCurrentDC() 126
GLU_PARAMETRIC_TOLERANCE 564, 569 wglGetProcAddress() 126
GLU_PATH_LENGTH 569, 570 GLU_POINT wglMakeCurrent() 106, 127
436, 454 GLU_SAMPLING METHOD 564, 570 wglShareListsO 128
wglUseFontBitmapsO 129,355
wglUseFontOutlines() 130 widok
46 wielokty 145 wielokty
paskie 180 wielokty zoone 575,
577 wierzchoki 48 wiggle 101
Win32 SDK 53 Win32 38
WindowsAPI 35 WinG 35
Skorowidz 717
WinMain() 111 WINSRV.DLL 38 waciwoci materiau 275 wczanie owietlenia 277 WM_CLOSE 338
WM_CREATE 107 WM_DESTROY 107 WM_PAINT 104, 107,338 WM_PALETTECHANGED 116, 253
WM_QUERYNEWPALETTE 252 WM_QUERYPALETTE 116 WM_SIZE 114 WMJTIMER 115,337
WndProc() 111 WS_CLIPCHILDREN 108 WS_CLIPSIBLINGS 108 WS_OWNDC 107 wsprzdne
obserwatora 201 wsprzdne okna 61 WWW 615 wybieranie 592
wybieranie kontekstu rendcrowania 106 wybr hierarchiczny 594 wybr koloru 243 wycinanie powierzchni
549 wydajno 340, 679 wykrawanie obszarw 362 wykrywanie bdw 133 wypenianie okna kolorem 62
wypenianie wieloktw 175 wywietlanie bitmap 375

zachowywanie zmiennych stanu 462


zapis pliku .BMP 370
zmienna stanu GL_ALPHA_BIAS 464
GL_ALPHA_SCALE 464
GL_ALPHA_TEST 463
GL_AUTO_NORMAL 463
GL_BLEND 463
GL_BLUE_BIAS 464
GL_BLUE_SCALE 464
GL_COLOR_MATERIAL 463, 464
GL_COLOR_MATERIAL_FACE 464
GL_CULL_FACE 463, 464
GL_CULL_FACE_MODE 464
GL_CURRENT_POSITION_VALID 463
GL_DEPTH_BIAS 464
GL_DEPTH_BUFFER 463
GL_DEPTH_SCALE 464
GL_DEPTH_TEST 463
GL DEPTH WRITEMASK 463
GL_DITHER 463 GL_EDGE_FLAG 463 GL_FOG 463
GL_FOG_HINT 463 GL_FOG_MODE 463 GL_FRONT_FACE 464 GL_GREEN_BIAS 464 GL_GREEN_SCALE 464
GL_INDEX_OFFSET 464 GL INDEX_SHIFT 464 GL~LIGHT_MODEL_LOCAL_VIEWER 464 GL_LIGHT_MODEL_TWO_SIDE 464
GLJLIGHTi 463
GL_LIGHTING 463,464
GL_LIGHTx 464
GL_LINE_SMOOTH 463, 464
GL_LINE_SMOOTH_HINT 463
GL_LINE_STIPPLE 463, 464
GL_LIST_BASE 464
GL_LOGIC_OP 463
GL_MAP_COLOR 464
GL_MAP_DEPTH 464
GL_MAPl_x 463
GL_MAP2_x 463
GL_MATRIX_MODE 464
GL_NORMALIZE 463, 464
GL_PERSPECTIVE_CORRECTION_HINT 463
GL_POINT_SMOOTH 463, 464
GL_POINT_SMOOTH_HINT 463
GL_POLYGON_MODE 464
GL_POLYGON_SMOOTH 463, 464
GL_POLYGON_SMOOTH_HINT 463
GL_POLYGON_STIPPLE 463, 464
GL_READ_BUFFER 464
GL_RED_BIAS 464
GL_RED_SCALE 464
GL_SCISSOR_TEST 463, 464
GL_SHADE_MODE 464
GL_STENCIL_TEST 463, 464
GL_TEXTURE_1D 463
GL_TEXTURE_2D 463
GL_TEXTURE_GEN 463
GL_TEXTURE_GEN_MODE 464
GL_TEXTURE_GEN_x 464
GL_ZOOM_X 464
GL_ZOOM_Y 464 znacznik krawdzi 181 znaczniki OpenGL 660 znaczniki uytkownika 600
znajdowanie normalnej 286 rda wiata 271

You might also like