Documente Academic
Documente Profesional
Documente Cultură
ACADEMIA TEHNICA
grafic computerizat
Aplicaii n OpenGL
Ediia a II-a
Cristian MOLDER
004.92
Imagini coperta I:
Artificial Intelligence Virtual Assistant Denise
c Guilherme Lindroth
Confederate Wraith Motorcycle
Josh Flores
c
Imagini coperta IV:
Ferrari F2007 3D Model Project
c Mario Cordova
VFX of Rush
c Double Negative (Dneg)
Imagine coperta interioar
a:
Formula 1 Car 3D Models
c boscorelli3D
Cuprins
1 Introducere n OpenGL 5
1.1 OpenGL vs. Direct3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Biblioteci grafice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
7 Texturi 63
7.1 Initializarea texturilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
7.2 Coordonate poligonale de texturare . . . . . . . . . . . . . . . . . . . . . . 66
7.3 Coordonate automate de texturare . . . . . . . . . . . . . . . . . . . . . . 78
8 Animatii cu sprite-uri 82
8.1 Sprite-uri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3
4 CUPRINS
11 Fonturi 113
11.1 Fonturi bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
11.2 Fonturi stroke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
A Materiale 131
Bibliografie 136
Capitolul 1
Introducere n OpenGL
5
6 CAPITOLUL 1. INTRODUCERE IN OPENGL
Windows Vista ofera trei tipuri de implementare OpenGL. Prima dintre acestea efec-
tueaza corespondenta directa dintre OpenGL si Direct3D prin traducerea comenzilor
OpenGL n comenzi Direct3D. Acest lucru permite accelerare hardware OpenGL pana
la versiunea 1.4, versiunile ulterioare putand fi apelate ca extensii. Al doilea tip utilizeaza
drivere de producator ce necesita a fi instalate pe Windows XP. Cea de-a treia posibili-
tate este o implementare completa ce permite accesul direct OpenGL peste versiunea 2
pe procesoarele grafice.
Exista, totusi, diferente. Direct3D a fost creata pentru gestionarea resurselor hardware
de catre aplicatie, n timp ce OpenGL face gestiunea prin intermediul implementarii.
Acest compromis permite ca OpenGL sa scada nivelul de dificultate n crearea API, n
acelasi timp cu cresterea complexitatii implementarii. In cazul Direct3D, programatorul
gestioneaza resursele hardware independent, implementarea fiind simpla, avand posibili-
tatea de a aloca resursele aplicatiei n modul cel mai eficient.
La scurt timp dupa aparitia bibliotecilor grafice Direct3D si OpenGL, Microsoft si SGI
au intrat n asa-numitul API War sau razboi al interfetelor de programare a aplicatiilor.
Microsoft a argumentat faptul ca Direct3D este cel mai rapid n raport cu OpenGL, de-
ficitul de performanta al celui din urma fiind justificat pe baza cerintelor de rigurozitate
n programarea aplicatiilor OpenGL. In anul 1996, n schimb, n cadrul conferintei SI-
GGRAPH (Special Interest Group on Computer Graphics), SGI a demonstrat faptul ca
performantele mai scazute ale OpenGL se datorau slabei implementari a OpenGL pe sis-
temele Windows si nu datorita unor eventuale lipsuri ale bibliotecii OpenGL.
Initial, OpenGL a fost creat pentru a fi utilizat pe platformele grafice SGI care, la
momentul respectiv, erau foarte puternice. Interfata continea circa 250 de instructiuni,
dar doar un subset de 100 de instructiuni putea fi utilizat n cadrul aplicatiilor de dezvol-
tare a jocurilor video. Firma 3Dfx a creat ulterior un set incomplet de instructiuni sub
denumirea MiniGL, care a stat la baza crearii nucleului grafic al jocului Quake. Acest
lucru a reprezentat un punct de nceput pentru dezvoltarea bibliotecii OpenGL.
xel shader, Direct3D a oferit un singur standard Pixel Shader 1.1 cu care GeForce 3 si,
ulterior, Radeon 8500 au confirmat compatibilitatea. Sub OpenGL, nsa, toate aceste
posibilitati au putut fi accesate prin intermediul unor extensii.
Versiune An Particularit
ati
OpenGL 1.0 1992 Prima versiune realizata
OpenGL 1.1 1997 Introducerea utilizarii texturilor
OpenGL 1.2 1998 Introducerea subseturilor de imagini
OpenGL 1.2.1 1998 Extensie ARB, versiune minora
OpenGL 1.3 2001
OpenGL 1.4 2002
OpenGL 1.5 2003
OpenGL 2.0 2004 Proiectata de 3Dlabs, prima varianta a formatului actual de OpenGL
OpenGL 2.1 2006 Introducerea versiunii 1.20 a OpenGL Shading Language
OpenGL 3.0 2008 Introducerea versiunii 1.30 a OpenGL Shading Language
OpenGL 3.1 2009 Introducerea versiunii 1.40 a OpenGL Shading Language
OpenGL 3.2 2009 Introducerea versiunii 1.50 a OpenGL Shading Language
OpenGL 3.3 2010 Compatibilitate hardware cu Direct3D 10.0
OpenGL 4.0 2010 Compatibilitate hardware cu Direct3D 11.0
OpenGL 4.1 2010 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 2.0
OpenGL 4.2 2011
OpenGL 4.3 2012 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 3.0
OpenGL 4.4 2013
OpenGL 4.5 2014 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 3.1
8 CAPITOLUL 1. INTRODUCERE IN OPENGL
Bibliotec
a grafic
a Prefix instructiune Exemplu de instructiune
OpenGL Utility Toolkit (GLUT) glut glutMainLoop()
OpenGL Utility Library (GLU) glu gluOrtho2D()
OpenGL Mathematics(GLM) glm glmReadOBJ()
OpenGL User Interface Library (GLUI) - -
OpenGL Easy Extension Library (GLee) - -
OpenGL Extension Wrangler Library (GLEW) - -
OpenGL FrameWork (GLFW) - -
Capitolul 2
9
10 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT
Detaliind arborele test se poate observa ca directorul Source Files care trebuie sa
contina fisierul sursa este gol. Prin urmare, este necesara fie (A) crearea unui fisier sursa,
fie (B) adaugarea unuia deja existent.
12 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT
A. Crearea unui fisier surs a nou. Situatia de fata apare atunci cand programatorul
se afla n situatia n care nu exista un cod sursa, fiind necesara crearea acestuia. Pentru
a crea un fisier sursa nou este necesara parcurgerea urmatorilor pasi:
1. se efectueaza click dreapta pe meniul Source Files din tab-ul Solution Explorer al
interfetei mediului de programare si se selecteaza optiunea Add;
2. se selecteaza optiunea New Item (Ctrl+Shift+A);
3. se selecteaza tipului de fisier C++ File (.cpp) n noua fereastra Add New Item;
4. se introduc directorul (Location) si numele fisierului sursa (Name) si apoi se apasa
butonul (Add).
In acest moment, n folderul proiectului corespunzator codului sursa a aparut (ca exem-
plu al autorului) fisierul cod.cpp, iar n meniul de editare acesta este deschis pentru
introducerea codului C.
2.3. CREAREA UNUI COD SURSA 13
B. Ad augarea unui fisier surs a. Aceasta operatie se face, de obicei, atunci cand
programatorul doreste introducerea n cadrul proiectului a unui cod sursa care este deja
scris ntr-un fisier pe calculator. Pentru aceasta se parcurg urmatoarele etape:
1. se efectueaza click dreapta pe meniul Source Files din tab-ul Solution Explorer al
interfetei mediului de programare si se selecteaza optiunea Add;
2. se selecteaza optiunea Existing Item (Shift+Alt+A);
3. la aparitia ferestrei Add Existing Item se selecteaza fisierul sursa dorit si se apasa
butonul Add.
14 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT
In cazul n care nu sunt erori se poate trece la crearea executabilului prin apelarea
optiunii Build Solution (F7) din meniul Build sau prin butonul dedicat din bara de
meniu.
In final, programul ruleaza prin apelarea optiunii Start Debugging (F5) din meniul
Pentru a afisa o fereastra dupa ce aceasta a fost initializata, se utilizeaza rutinele GLUT
de afisare. Cea mai importanta dintre acestea o reprezinta rutina glutDisplayFunc(void
(*func)(void)). De oricate ori este necesara o reafisare a continutului ferestrei grafice,
aceasta rutina apeleaza o functie asociata, definita prin numele func.
16
3.2. GESTIONAREA EVENIMENTELOR 17
scenei vor fi stocate n procedura init(), iar operatiile grafice sunt dispuse n procedura
display(), apelata cu ajutorul rutinei glutDisplayFunc.
#include <GL/glut.h>
Programul este structurat n trei module. Primul dintre acestea, n ordinea importantei,
l reprezinta modulul principal main. In aceasta regiune se efectueaza initializarile obliga-
torii ale ferestrei grafice si se apeleaza celelalte proceduri din program. Celelalte doua
module, display si init, contin comenzile grafice OpenGL si, respectiv, atributele sce-
nei.
are asociata n program o functie corespunzatoare, aceasta este apelata prin intermediul
procedurilor GLUT. In caz contrar se apeleaza functia asociata starii idle.
#include <GL/glut.h>
Functia init() are rolul de a seta parametrii grafici ai scenei. In acest loc se definesc
de obicei matricele obiectelor geometrice, culorile utilizate s.a. La sfarsitul aceste functii
este de preferat ca toate specificatiile initiale ale scenei sa fie deja definite.
Functia idle() este apelata n situatiile n care nu are loc niciun alt eveniment,
executia acesteia fiind independenta de utilizator. Pentru afisarea modificarilor pro-
duse de instructiunile din functie, este necesara includerea la sfarsitul secventei de cod a
instructiunii glutPostRedisplay() care apeleaza automat functia display().
main()
init()
init()
glutDisplayFunc(display) glutPostRedisplay()
display() glutReshapeFunc(reshape)
reshape()
glutKeyboardFunc(keyboard)
Event? keyboard()
Yes
glutIdleFunc(idle) No
glutMouseFunc(mouse)
mouse()
idle()
S
tergerea ferestrei grafice. Afisarea pe un monitor se face diferit fata de cazul unei
coli de hartie. Diferenta este realizata prin faptul ca hartia este deja alba sau avand o
anumita culoare prestabilita, n timp ce n cazul monitorului culoarea de fundal trebuie
specificata, iar eventualele artefacte deja existente trebuie eliminate prin stergerea buffe-
rului. Toate operatiile sunt efectuate n cadrul functiei de initializare init().
GL_DEPTH_BUFFER_BIT Buffer de ad
ancime
20
4.1. PARAMETRII INIT
IALI 21
Pentru a putea sterge mai multe buffere, instructiunea glClear() se poate utiliza
repe-titiv prin modificarea parametrului
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glClear(GL_ACCUM_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT);
In ultimul caz durata necesara efectuarii operatiilor de stergere este potential mai mica
decat n situatia enumerarii succesive.
Alegerea unei culori. Trasarea unui obiect grafic se efectueaza n OpenGL independent
de alegerea culorii asociate obiectului. Odata aleasa o anumita culoare, toate obiectele
care vor fi trasate ulterior vor avea culoarea respectiva, astfel ncat daca se doreste afisarea
unor obiecte n culori diferite, de fiecare data este necesara modificarea culorii curente.
Alegerea unei culori curente se face n cadrul functiei display() cu ajutorul instructiu-
nii glColor(). In functie de tipul argumentelor introduse, functia capata un sufix specific
(n cazul parametrilor de tip real, functia devine glColor3f()). Exemplul de mai jos
permite alegerea unei culori curente rosii.
Parametrii de culoare specifici celor trei culori primare (RGB) iau valori reale cuprinse
ntre 0 (lipsa) si 1 (maxim). Astfel, cele opt culori elementare pot fi definite cu ajutorul
urmatoarelor opt variante de instructiuni.
Prima dintre ele asigura nceperea executiei instructiunilor precedente acesteia, n timp
ce a doua forteaza executia tuturor instructiunilor anterioare. Doar n cazul n care, pen-
tru o aplicatie data, simpla utilizare a lui glFlush() nu este suficienta, se recomanda
includerea lui glFinish().
Punctele reprezinta numere reale, denumite si vertex-uri, definite fie n plan, prin spe-
cificarea coordonatelor x si y, fie n spatiu, prin specificarea celor trei coordonate x, y si
z. In cazul coordonatelor omogene poate exista o a patra coordonata, notata w. Daca w
este nenul, coordonatele punctului n spatiul tridimensional sunt (x/w, y/w, z/w).
GL_POINTS punct
GL_TRIANGLES triunghi
GL_QUADS patrulater
GL_POLYGON poligon
Exemplul urmator permite definirea unui segment de dreapta situat ntre doua puncte
din spatiul de coordonate (2, 3, 1) si (1, 1, 3), avand culoarea rosie.
De asemenea, fiecare nod din cadrul unei primitive grafice poate avea propria culoare,
caz n care instructiunea glColor() se repreta n interiorul structurii glBegin() pentru
fiecare modificare de culoare n parte.
1 4 3 1 3 2
0 5 1
4
5 3
0
2 3 5 0
2 0 6 4
1 2
4
GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP
3 3 5
1 2 5 6
0 1
7
2
0 4 3 1 0 6
4 7 2
4
GL_POLYGON GL_QUADS GL_QUAD_STRIP
4 6 1
0 2 3 5 3 4
2
5
1
3 7 0 5
1 2 0
8 4
GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN
In exemplul 4.1 se prezinta secventa completa de instructiuni a unei aplicatii care per-
mite afisarea unui patrat umplut alb pe fundal negru.
#include <GL/glut.h>
De remarcat faptul ca, n afara de functiile init() si display(), nu exista alte functii
de gestionare a evenimentelor, astfel ncat la redimensionarea sau repozitionarea ferestrei,
imaginea rezultata nu va fi ajustata. Pentru a elimina acest lucru fara a face apel la o
functie reshape(), instructiunea glClearColor() poate fi introdusa n cadrul functiei
display(), nsa aspectul imaginii nu poate fi controlat, imaginea fiind redimensionata la
scara n functie de noua forma a ferestrei grafice.
4.3 Tipare
In mod implicit, primitivele grafice de tipul punctelor sau al liniilor sunt trasate pe
ecran cu latimea de 1 pixel, iar poligoanele sunt umplute. Acesti parametri pot fi nsa
modificati, dupa cum urmeaza.
Puncte. Controlul dimensiunii unui punct poate fi facut prin intermediul instructiunii
glPointSize() al carui argument reprezinta dimensiunea n pixeli, pozitiva si nenula.
Instructiunea trebuie inclusa naintea unei primitive grafice.
glPointSize(4);
glBegin(GL_POINTS);
...
glEnd();
Linii. In cazul segmentelor de dreapta (linii) se poate controla atat grosimea, cat si ti-
parul liniei curente. Setarea grosimii liniei se face cu ajutorul instructiunii glLineWidth()
4.3. TIPARE 27
avand ca argument grosimea n numar de pixeli pozitiv si nenul, implicit fiind 1. Setarea
tiparului unei linii se face prin intermediul instructiunii glLineStipple(), avand ca ar-
gumente un factor de alungire (valori ntregi cuprinse ntre 1 si 255) si un tipar descris
sub forma unui numar binar pe 16 biti exprimat sub forma hexazecimala. Activarea sau
dezactivarea proprietatii de tipar unei linii se face prin instructiunile glEnable() sau
glDisable() avand ca parametru GL_LINE_STIPPLE.
Prin conventie, poligoanele ale caror noduri sunt enumerate n sens invers orar au
fateta exterioara ndreptata catre ecran (reprezinta fateta vizibila). In mod implicit,
ambele fatete ale unei suprafete sunt umplute, dar acest lucru poate fi modificat prin
intermediul instructiunii glPolygonMode(). Cele doua argumente specifica fateta modifi-
cata (GL_FRONT, GL_BACK sau GL_FRONT_AND_BACK) si, respectiv, umplerea (GL_FILL) sau
golirea (GL_LINE) acesteia. Variante de combinatii sunt prezentate n cele ce urmeaza.
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
In cazul n care se doreste schimbarea tipului de fateta rezultat implicit la definirea n
sens invers orar a punctelor unui poligon, se poate utiliza instructiunea glFrontFace(),
care permite setarea fatetei exterioare la enumerarea nodurilor n sens orar (GL_CW) sau
n sens invers orar (GL_CCW).
glFrontFace(GL_CW);
glFrontFace(GL_CCW);
In exemplul 4.2 se prezinta o aplicatie care permite trasarea a patru patrare definite
prin enumerarea nodurilor n sens orar (1 si 3) sau n sens invers orar (2 si 4). Fatetele
exterioare sunt umplute, iar cele interioare sunt goale.
In unele aplicatii este utila eliminarea fatetelor interioare sau chiar a celor exterioare,
deoarece acestea sunt invizibile, lucru posibil cu ajutorul instructiunii glCullFace(),
unde argumentul reprezinta fatetele eliminate.
28 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE
#include <GL/glut.h>
y
(-1, 1) (1, 1)
4 2
3 1
glutDisplayFunc (display);
glutMainLoop ();
return 0;
}
Activarea sau dezactivarea eliminarii unor fatete cu glCullFace() se face prin inter-
mediul instructiunii glEnable() sau glDisable() cu argumentul GL_CULL_FACE. Pen-
tru instructiunea glCullFace() se poate folosi ca argument GL_FRONT, GL_BACK sau
GL_FRONT_AND_BACK.
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
...
glDisable(GL_CULL_FACE);
In OpenGL se poate specifica o normala pentru fiecare poligon sau vertex. Vertex-
urile aceluiasi poligon pot avea aceeasi normala (n cazul suprafetelor plane) sau pot fi
diferite (n cazul suprafetelor curbe). Vectorii normala pot fi calculati n OpenGL doar
pentru noduri si servesc n principal la determinarea cantitatii de lumina receptionate de
suprafata n nodul respectiv.
Instructiunea care permite calculul unui vector normala este glNormal3(), avand ca
argumente coordonatele tridimensionale ale vertexului respectiv.
1. Activarea matricelor. Primul pas n definirea matricelor de date este activarea aces-
tora cu ajutorul instructiunii glEnableClientState(), avand ca argument una din cele
sase matrice posibile. Variantele posibile sunt matricele de puncte (GL_VERTEX_ARRAY), de
culoare (GL_COLOR_ARRAY), indexurile de culoare (GL_INDEX_ARRAY), matricele normale-
lor (GL_NORMAL_ARRAY), a texturilor (GL_TEXTURE_COORD_ARRAY) si a etichetelor laturilor
poligonale (GL_EDGE_FLAG_ARRAY).
In practica este putin probabil sa fie activate toate cele sase matrice. De exemplu, n
cazul utilizarii n scena a unor surse de lumina, se utilizeaza matricele de puncte si de
normale.
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
Daca este necesara dezactivarea uneia dintre matrice, se poate utiliza instructiunea
glDisableClientState(), cu acelasi argument ca si n cazul instructiunii de activare.
specifica tipul datelor, stride reprezinta offsetul n bytes dintre doua date consecutive,
iar *pointer determina adresa de memorie a primei date din matrice.
GL_UNSIGNED_SHORT, GL_INT,
GL_FLOAT, GL_DOUBLE
glEdgeFlagPointer 1 GLboolean
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
Argumentul stride are rolul de a defini pasul cu care sunt citite datele dintr-un vec-
tor. Acest lucru este util atunci cand toate datele (noduri, culori, normale etc.) sunt
compactate ntr-un singur vector de date.
4.5. MATRICE DE DATE 33
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
De exemplu, utilizand datele din vectorii colors si vertices din exemplul anterior,
se poate trasa un triunghi cu elementele de la pozitiile 3, 5 si 6 ale vectorilor.
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(2, GL_INT, 0, vertices);
glBegin(GL_TRIANGLES);
glArrayElement(2);
glArrayElement(3);
glArrayElement(5);
glEnd();
Ultimele cinci linii de cod au acelasi efect ca si urmatoarea lista de instructiuni.
glBegin(GL_TRIANGLES);
glColor3fv(colors+(2*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(2*3*sizeof*(GL_INT));
glColor3fv(colors+(3*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(3*3*sizeof*(GL_INT));
glColor3fv(colors+(5*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(5*3*sizeof*(GL_INT));
glEnd();
34 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE
3 2
7 6
0 1
4 5
Exemplul 4.3 permite definirea unui model de forma unei case, alcatuit din doua obiecte
poligonale avand culori diferite ale nodurilor.
#include <GL/glut.h>
// vector de date
static GLfloat allData[] = {
0.8, 0.8, 0.8, -0.5, 0.2, // 4x vertexuri corp casa
0.8, 0.8, 0.8, -0.5, -0.6,
0.8, 0.8, 0.8, 0.5, -0.6,
0.8, 0.8, 0.8, 0.5, 0.2,
1.0, 0.0, 0.0, -0.8, 0.2, // 3x vertexuri acoperis
0.0, 1.0, 0.0, 0.8, 0.2,
0.0, 0.0, 1.0, 0.0, 0.7
};
// vector de indici de ordine a utilizarii datelor
static GLubyte allIndices[] = {4, 5, 6, 0, 1, 2, 3};
glClear(GL_COLOR_BUFFER_BIT);
36 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE
// desenare acoperis
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, allIndices);
glFlush();
}
Proiectii si transform
ari
5.1 Proiectii
Spatiul 3D al lumii reale poate fi privit ca un spatiul traditional definit ntr-un sistem
de coordonate carteziene XY Z, avand axele X si Y dispuse normal, iar axa Z a adancimii
este negativa n directia de privire a observatorului (figura 5.1). Aceasta orientare a axelor
este specifica modelarii n grafica computerizata, deoarece planul imaginii proiectate este
reprezentat de planul XY , iar proiectia se face de-a lungul axei de adancime Z.
y
Vector de orientare
Sistemul de coordonate
x al lumii reale
37
38 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI
Toate argumentele sunt de tip GLdouble si exprima urmatoarele: eyex, eyey si eyez
reprezinta coordonatele punctului de vizualizare, centerx, centery si centerz sunt coor-
donatele varfului vectorului directiei de vizualizare, iar upx, upy si upz sunt coordonatele
varfului vectorului directiei verticale.
y
(upx, upy, upz)
Orice transformare sau proiectie este efectuata prin intermediul unei matrice caracte-
ristice de transformare, activata prin intermediul instructiunii glMatrixMode(). Prin in-
termediul argumentului instructiunii glMatrixMode() se specifica tipul matricei utilizate
la momentul respectiv, care poate fi: matricea de vizualizare (GL_MODELVIEW), matricea
de proiectie (GL_PROJECTION) sau matricea texturilor (GL_TEXTURE).
5.1. PROIECT
II 39
top
left
right
bottom
near far
Secventa de cod urmatoare permite definirea unei proiectii ortografice al carei volum
de vizualizare este un paralelipiped cu dimensiunea 6 6 4.
40 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-3.0, 3.0, -3.0, 3.0, 1.5, 5.5);
In cazul particular al coordonatelor 2D, se poate utiliza instructiunea glOrtho2D()
pastrand doar primele patru argumente ale instructiunii glOrtho(), valorile parametrilor
near si far fiind luati implicit -1.0 si 1.0.
aspect
w
fovy
near
far
Figura 5.4: Definirea volumului de vizualizare pentru proiectia perspectiva n OpenGL cu instructiunea
gluPerspective()
In exemplul de mai jos se prezinta instructiunile necesare pentru aplicarea unei proiectii
perspective al carei volum de vizualizare este definit printr-un unghi de deschidere pe
verticala de 60 , un factor de forma de 800/600 si coordonatele de adancime 4.0 si 12.0.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 800/600, 4.0, 12.0);
left
top
bottom
right
near
far
Figura 5.5: Definirea volumului de vizualizare pentru proiectia perspectiva n OpenGL cu instructiunea
glFrustum()
Nedistorsionat Distorsionat
In cazul n care se doreste afisarea n regiuni diferite ale ferestrei grafice, valorile lui
width si height vor fi, de asemenea, diferite.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, w/h, 4.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(10.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
Modul full screen. Pentru a intra n modul full screen se poate utiliza instructiunea
glutFullScreen().
glutFullScreen();
Pentru a iesi din modul full screen se utilizeaza instructiunile glutReshapeWindow()
si glutPositionWindow().
glutReshapeWindow(width, height);
glutPositionWindow(x, y);
Amble seturi de instructiuni se introduc, n cazul intrarii sau iesirii automate n modul
full screen, n cadrul functiei display() sau idle() iar, n cazul comenzii cu ajutorul
mouse-ului sau a tastaturii, n functiile mouse() sau keyboard().
5.1. PROIECT
II 43
In exemplul 5.1 se prezinta o aplicatie care permite desenarea scheletului unei case
schematizate, afisate n proiectie perspectiva.
#include <GL/glut.h>
Figura 5.8: Definirea coordonatelor polare pentru deplasarea punctului de vizualizare n jurul obiectului
Daca se considera doar deplasarea pe azimut, acest lucru presupune modificarea punc-
tului de vizualizare pe conturul unui cerc din planul XoZ, conform relatiilor 5.1.
eyex = R sin()
(5.1)
eyez = R cos()
unde [0, 2) si [, ].
#include <GL/glut.h>
#include "math.h"
#define PI 3.1415
float r=3; // valoare initiala raza
float a,b=0; // valori initiale unghiuri
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
7, 8, 9,
1, 6, 7, 2,
2, 7, 8, 3,
9, 4, 3, 8,
5, 0, 4, 9
};
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, house);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, indices);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[4]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[7]);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[11]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[14]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[18]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[22]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[26]);
glFlush();
}
5.2 Transform
ari
Operatiile de transformare permit pozitionarea unui sistem de coordonate local (de
exemplu, al unui model) n sistemul de coordonate al sistemului lumii reale (al scenei).
Cele trei transformari de baza sunt translatia, rotatia si scalarea.
glTranslate{fd}(x, y, z);
unde x, y si z sunt argumentele care definesc valoarea translatiei pe fiecare dintre axele
de coordonate.
glRotate{fd}(angle, x, y, z);
unde x, y si z sunt argumentele care definesc varful vectorului de rotatie, acesta avand
originea n originea sistemului de coordonate al modelului, iar angle reprezinta unghiul
cu care modelul este rotit.
glScale{fd}(x, y, z);
unde x, y si z sunt factorii de scalare corespunzatori fiecareia din cele trei axe de coordo-
nate ale modelului.
#include <GL/glut.h>
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glPolygonMode(GL_FRONT, GL_LINE);
glEnableClientState(GL_VERTEX_ARRAY);
glColor3f(0.5, 0.5, 0.5);
glVertexPointer(2, GL_FLOAT, 0, axe);
glDrawArrays(GL_LINES, 0, 4); // axe de coordonate 2D
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 6*sizeof(GLfloat), patrat);
glVertexPointer(3, GL_FLOAT, 6*sizeof(GLfloat), &patrat[3]);
glDrawArrays(GL_QUADS, 0, 4); // pozitie initiala
glTranslatef(0.7, 0.6, 0.0);
glRotatef(15, 0.0, 0.0, 1.0);
glScalef(0.4, 0.2 ,0.0);
glDrawArrays(GL_QUADS, 0, 4); // pozitie finala
glDisableClientState(GL_VERTEX_ARRAY);
50 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI
glDisableClientState(GL_COLOR_ARRAY);
glFlush();
}
Un exemplu clasic este modelarea unui automobil ale carui roti pot fi reprezentate
printr-un singur obiect redesenat de patru ori, la alte coordonate. Succesiunea de operatii
poate fi descrisa succint, astfel: modeleaza caroseria, memoreaza pozitia curenta, depla-
seaza la pozitia rotii stanga-fata, modeleaza roata, revino la pozitia anterioara, memo-
reaza pozitia curenta, deplaseaza la pozitia rotii dreapta-fata, modeleaza roata s.a.m.d.
Stiva Stiva
matricelor matricelor
de vizualizare de proiecie
0 0
1 32 matrice 4 x 4 1 2 matrice 4 x 4
31
curenta n stiva, si glPopMatrix(), care extrage matricea din stiva si o face matrice
curenta. Tipul matricei manipulate este ales cu ajutorul instructiunii glMatrixMode(),
avand ca argument posibil GL_PROJECTION sau GL_MODELVIEW.
glGetIntegerv(matrix, *params);
glPushMatrix() glPopMatrix()
Stiv Stiv
Figura 5.11: Operatii de depunere sau extragere a unei matrice din stiva
52 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI
#include <GL/glut.h>
glPopMatrix();
glPushMatrix();
glTranslatef(-4.0, 0.5, 4.0); // sfera verde
glColor3f(0.0, 0.8, 0.0);
glutWireSphere(0.5, 15, 15);
glPopMatrix();
glFlush();
}
In exemplul 5.4 se prezinta modelarea unei suprafete pe care sunt dispuse patru sfere,
fiecare dintre acestea fiind pozitionate relativ la centrul suprafetei, prin utilizarea stivelor
matricelor de vizualizare.
...
glMatrixMode(GL_MODELVIEW);
glTranslatef(4.0, 0.5, 4.0); // sfera rosie
glColor3f(0.8, 0.0, 0.0);
glutWireSphere(0.5, 15, 15);
glTranslatef(0.0, 0.0, -8.0); // sfera alba
glColor3f(0.8, 0.8, 0.8);
glutWireSphere(0.5, 15, 15);
glTranslatef(-8.0, 0.0, 0.0); // sfera albastra
glColor3f(0.0, 0.0, 0.8);
glutWireSphere(0.5, 15, 15);
glTranslatef(0.0, 0.0, 8.0); // sfera verde
glColor3f(0.0, 0.8, 0.0);
glutWireSphere(0.5, 15, 15);
glFlush();
...
In ambele situatii, rezultatul obtinut este cel prezentat n figura 5.3.
Fiecare dintre cele sase planuri de decupare este definit cu ajutorul coeficientilor
ecuatiei proprii.
Ax + By + Cz + D = 0. (5.3)
Activarea sau dezactivarea unui plan de decupare se poate face cu ajutorul instructiu-
nilor glEnable() si, respectiv, glDisable(), avand ca argument GL_CLIP_PLANEi, unde
i reprezinta indexul planului.
glClipPlane(plane, *equation);
unde plane reprezinta indexul planului, definit sub forma GL_CLIP_PLANEi, iar equation
este vectorul coeficientilor reali ai ecuatiei planului (5.3).
5.4. PLANURI DE DECUPARE SUPLIMENTARE 55
#include <GL/glut.h>
Toate versiunile OpenGL admit cel putin sase planuri de decupare, dar numarul real
al acestora poate fi determinat cu ajutorul instructiunii glGetIntegerv() avand ca ar-
56 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI
glGetIntegerv(GL_MAX_CLIP_PLANES, *params);
Aplicatia din exemplul 5.5 permite decuparea unui sfert dintr-o sfera prin intermediul
a doua planuri de decupare, unul orizontal si unul vertical.
Capitolul 6
Randarea finala a unei scene tine cont de tipul si numarul surselor de iluminare utili-
zate, precum si de materialul cu care obiectele din scena sunt modelate. OpenGL permite
manipularea iluminarii si a obiectelor dintr-o scena n scopul generarii diferitelor efecte.
Afisarea unei scene n tridimensional trebuie sa tina cont de pozitia n care se afla obser-
vatorul, astfel ncat, pentru obiectele situate pe aceeasi axa de adancime, suprafetele as-
cunse sa nu fie vizibile. Pentru a le elimina, se efectueaza un test de pozitionare cu ajutorul
unui buffer de adancime (depth buffer), care este executat prin intermediul instructiunii
glEnable(GL_DEPTH_TEST). Pentru ca bufferul de adancime sa fie activat, este necesara
initilizarea acestuia n functia main().
void init (void){
...
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT|...);
...
}
Rezultatul randarii unei scene este obtinut prin determinarea interactiunii dintre sur-
sele de lumina si parametrii de material ai obiectelor din scena respectiva. De exemplu, un
obiect de culoare rosie care este iluminat de o sursa de lumina galbena va deveni invizibil,
n timp ce, pentru o sursa de lumina alba, obiectul al redeveni vizibil n rosu.
57
58 CAPITOLUL 6. ILUMINAREA SCENELOR SI CULOAREA OBIECTELOR
1. Activarea sursei de lumina se face n doua etape, prin activarea initiala a iluminarii
globale a unei scene cu ajutorul instructiunii glEnable(GL_LIGHTNING), urmata de acti-
varea individuala a surselor de lumina, prin instructiunea glEnable(GL_LIGHTi), unde i
reprezinta indexul sursei de lumina (cu valori cuprinse ntre 0 si 7).
GL_POSITION (0.0, 0.0, 1.0, 0.0) coordonatele (x, y, z, w) ale sursei de lumina
Valorile implicite ale parametrilor GL_DIFFUSE si GL_SPECULAR sunt valabile doar pen-
tru sursa GL_LIGHT0, pentru restul surselor acesteia fiind (0.0, 0.0, 0.0, 1.0).
1
Ip = Il , (6.1)
kc + kl d + kp d2
6.1. SURSE DE LUMINA 59
unde Ip este intensitatea la distanta d fata de sursa, iar Il este intensitatea emisa de sursa.
In plus fata de setarile surselor de lumina individuale, mai exista posibilitatea definirii
unor parametri suplimentari, denumiti parametri ai modelului de iluminare global. Acesti
parametri sunt modificati prin intermediul instructiunii glLightModel() cu urmatoarea
sintaxa:
glLightModel{i|f}(pname, param);
glLightModel{i|f}v(pname, *param);
unde pname este numele parametrului, iar param reprezinta valoarea parametrului pname.
GL_LIGHT_MODEL_AMBIENT (0.2, 0.2, 0.2, 1.0) intensitatea RGBA a luminii ambientale a sce-
nei
culara
exterioare
Calculul iluminarii se face pentru fiecare poligon n parte, fie ca acesta este interior
sau exterior. In mod implicit, calculele sunt efectuate doar pentru suprafata exterioara,
dar pot exista aplicatii n cadrul carora este necesara si iluminarea fatetelor interioare.
6.2 Propriet
atile de material ale obiectelor
Fiecare obiect dintr-o scena contine o serie de proprietati de material, precum culorile
de reflexie, speculare sau ambientale sau, n situatia n care obiectul are si lumina proprie,
culoarea luminii emise. Toti acesti parametri pot fi definiti n OpenGL cu ajutorul unor
functii specifice.
In OpenGL sunt implementate doua modele de iluminare (plata si Gouraud) care pot
fi activate prin intermediul instructiunii glShadeModel(), avand ca argumente posibile
GL_FLAT (pentru modelul plat):
glShadeModel(GL_FLAT);
sau GL_SMOOTH (pentru modelul Gouraud):
glShadeModel(GL_SMOOTH);
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.1, 0.1, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // model de iluminare Gouraud
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // activarea sursei de lumina rosie
glEnable(GL_LIGHT1); // activarea sursei de lumina albastra
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Figura 6.1: Iluminarea unei sfere solide cu doua surse de lumina, rosie si albastra, n model plat si
Gouraud
De remarcat faptul ca, n cazul utilizarii unui model de tip plat, pentru aceiasi parame-
tri ai sferei rezultatul este mai slab din punct de vedere perceptual, suprafetele poligonale
avand iluminare constanta (figura 6.1).
Capitolul 7
Texturi
Operatia de texturare reprezinta modalitatea care ofera cele mai bune rezultate n
generarea imaginilor realiste. Texturarea presupune aplicarea unei texturi pe un obiect
grafic fara operatii de calcul geometric suplimentare. In cadrul scenelor, obiectele sunt
n mare parte definite poligonal, astfel ncat n calculul intensitatilor pixelilor intra, pe
langa informatia de culoare furnizata de catre modelul de iluminare, si o informatie supli-
mentara extrasa dintr-o matrice denumita harta a texturii (texture map). Aceasta harta
poate contine date provenite de la o imagine naturala sau sintetica, precum si date supli-
mentare precum intensitatea sau transparenta.
In cadrul procesului de texturare, atat obiectul grafic modelat, cat si textura contin
informatie de culoare. Cea mai simpla modalitate de texturare presupune nlocuirea
informatiei de culoare a obiectului cu informatia de culoare a texturii, desi sunt posibile
si variante de combinare a acestora.
63
64 CAPITOLUL 7. TEXTURI
glEnable(GL_TEXTURE_2D);
...
glDisable(GL_TEXTURE_2D);
Definirea unei texturi se face prin asocierea unui nume si a datelor specifice, cu ajutorul
instructiunilor glGenTextures() si glBindTexture() cu urmatoarele sintaxe:
glGenTextures(n, textureNames);
unde n este numarul de texturi utilizate, iar textureNames contine denumirile celor n
texturi si
glBindTexture(target, textureName);
unde textureName este numele texturii asociate tipului texturii target (GL_TEXTURE_1D,
GL_TEXTURE_2D sau GL_TEXTURE_3D).
unde target este setat ca fiind GL_TEXTURE_ENV, pname specifica parametrul de texturare
modificat (GL_TEXTURE_ENV_MODE sau GL_TEXTURE_ENV_COLOR).
Pentru parametrul GL_TEXTURE_ENV_MODE, variabila param poate lua una din valorile
GL_DECAL, GL_REPLACE (nlocuiri), GL_MODULATE (modulare) sau GL_BLEND (amestec), iar
pentru parametrul GL_TEXTURE_ENV_COLOR, variabila param este definita sub forma a
patru componente reale R, G, B si A.
GL_ALPHA Cf Cf nedefinit Cf C
At Af At Af At A
GL_LUMINANCE Lt Cf Lt nedefinit Cf (1 Lt ) + Cc Lt C
Af Af Af A
GL_LUMINANCE_ALPHA Lt Cf Lt nedefinit Cf (1 Lt ) + Cc Lt C
At Af At Af At A
GL_INTENSITY It Cf It nedefinit Cf (1 It ) + Cc It C
It Af I t Af (1 It ) + Ac It A
GL_RGB Ct Cf Ct Ct Cf Ct C
Af Af Af Af A
GL_RGBA Ct Cf Ct Cf (1 At ) + Ct At Cf (1 Ct ) + Cc Ct C
At Af At Af Af At A
7.1. INIT
IALIZAREA TEXTURILOR 65
Pentru a asocia unei texturi parametrii principali ai acesteia, precum formatul intern
sau numarul coordonatelor de culoare, se utilizeaza instructiunea glTexImage2D(), astfel:
glTexImage2D(target, level, internalFormat, width, height, border,
format, type, pixels);
unde target are valoarea GL_TEXTURE_2D, level precizeaza numarul de rezolutii al tex-
turii (implicit 0), internalFormat specifica formatul intern al texturii si poate avea una
din valorile enumerate mai jos:
GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16,
GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12,
GL_LUMINANCE16,
GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2,
GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12,
GL_LUMINANCE16_ALPHA16,
GL_INTESITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSITY12,
GL_INTENSITY16,
GL_RGBA, GL_R3_G3_B3, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10,
GL_RGB12, GL_RGB16,
GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2,
GL_RGBA12, GL_RGBA16
Cifrele de la sfarsitul valorilor specifica numarul de biti pe care este exprimat pa-
rametrul respectiv. De exemplu, GL_RGB5_A1 precizeaza faptul ca fiecare din cele trei
componente RGB este exprimata pe 5 biti, iar componenta de transparenta A este speci-
ficata pe 1 bit.
Parametrii width si height definesc dimeniunile hartii texturii sub forma unor puteri
ale lui 2, iar border determina dimensiunea marginii texturii n pixeli (0 = fara margine).
Parametrii format si type descriu formatul si tipul de date al hartii texturii. Acestia
pot lua valorile, pentru parametrul format:
GL_COLOR_INDEX
GL_RGB
GL_RGBA
GL_RED
GL_GREEN
GL_BLUE
GL_ALPHA
GL_LUMINANCE
GL_LUMINANCE_ALPHA
66 CAPITOLUL 7. TEXTURI
GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
glVertex2v(v2);
glTexCoord2v(t3); glTexCoord2v(t2);
glVertex2v(v3);
glVertex2v(v0);
glTexCoord2v(t0); glTexCoord2v(v1);
glTexCoord2v(t1); glVertex2v(v1);
Poligon
Textur
In exemplul 7.1 se prezinta aplicarea unei texturi RGB, citita dintr-un fisier RAW
(texture.raw), pe o fateta poligonala a unui cub.
In cadrul setarii parametrilor de texturare, una din optiuni este reprezentata de tipul
filtrului de interpolare utilizat n cazul maririi (GL_TEXTURE_MIN_FILTER) sau micsorarii
imaginii (GL_TEXTURE_MAG_FILTER). Aceasta alegere se face prin intermediul instructiunii
glTexParameter() prezentate anterior. Tipurile posibile de interpolare sunt de tip liniar
(GL_LINEAR) sau prin determinarea texelului asociat cel mai apropiat (GL_NEAREST).
Pentru a observa efectul acestor filtre n cazul maririi imaginii rezultate din exemplul
7.1, se modifica n cod prin interschimbare comenzile:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
si
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
detaliul rezultatului putand fi observat n figura 7.3.
Din exemplul 7.1 se poate observa ca ntreaga suprafata poligonala laterala a cubului
este acoperita n ntregime de catre textura, aceasta fiind scalata astfel ncat sa se ajus-
teze pe dimensiunea suprafetei texturate. In unele aplicatii este nsa necesara repetarea
texturii pe suprafata poligonala respectiva si nu scalarea ei. Acest lucru este posibil prin
modificarea coordonatelor de texturare.
In cazul texturarii suprafetei prin scalare, nodurilor poligonale le erau asociate nodurile
terminale ale texturii, de coordonate (0.0, 0.0), (0.0, 1.0), (1.0, 1.0) si (0.0, 1.0), dupa
cum se poate observa din secventa de cod urmatoare:
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
ceea ce semnifica faptul ca ntr-o suprafata poligonala exista doar o singura textura ele-
mentara, scalata.
Determinarea noilor coordonate ale texturii se face prin calcularea numarului de tex-
turi elementare (de dimensiunea imaginii ncarcate) care sunt necesare pentru umplerea
suprafetei poligonale respective.
7.2. COORDONATE POLIGONALE DE TEXTURARE 69
GL_NEAREST GL_LINEAR
Figura 7.3: Utilizarea filtrelor de interpolare n cazul maririi unei imagini (detaliu al exemplului 7.1)
Texturarea se poate face n doua moduri, pentru fiecare din directiile verticala si orizon-
tala, fie prin repetare (GL_REPEAT), fie prin prelungirea ultimei linii a texturii (GL_CLAMP).
Cele patru combinatii posibile de texturare sunt prezentate n secventele de cod urma-
toare:
pixel
texel
Mrire Micorare
Figura 7.4: Asocierea dintre pixeli si texeli la marirea sau micsorarea unei imagini
#include <GL/glut.h>
#include <stdio.h>
file=fopen("texture.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
readTexture();
glGenTextures(1, texName); // definire textura
7.2. COORDONATE POLIGONALE DE TEXTURARE 71
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.5,0.5,0.5);
glBegin(GL_QUADS);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glEnd();
glEnable(GL_TEXTURE_2D); // activarea texturarii 2D
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glEnd();
glDisable(GL_TEXTURE_2D); // dezactivarea texturarii 2D
glBegin(GL_QUADS);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glEnd();
glFlush();
}
72 CAPITOLUL 7. TEXTURI
a) b)
c) d)
Deoarece textura prezinta continuitate la margini, tranzitia dintre doua texturi elemen-
tare nu este sesizabila n cadrul exemplului d). Aceasta caracteristica este importanta n
alegerea texturilor elementare, astfel ncat acestea sa permita o texturare continua fara
introducerea unor artefacte sau a unor discontinuitati perceptuale.
In exemplul 7.2 se prezinta texturarea unei suprafete plane cuprinse ntre coordonatele
(-0.6, -0.4) si (0.6, 0.4). Textura de dimensiune 256 256 pixeli este aplicata prin repetare
de trei ori pe orizontala si de doua ori pe verticala.
#include <GL/glut.h>
#include <stdio.h>
file=fopen("wall.raw", "rb");
for (i=0; i<256; i++){
for (j=0; j<256; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
readTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
74 CAPITOLUL 7. TEXTURI
(1, 0) (1, 1)
Polul nord
Latitudini de 20
Ecuator
Polul sud
(0, 0) (0, 1)
Longitudini de 20
(1, 0) (1, 1)
(0, 0) (0, 1)
O aplicatie complexa este reprezentata de texturarea unei sfere prin proiectia unei
texturi. Complexitatea problemei este data de modelarea sferei, prin intermediul poli-
goanelor triunghiulare sau rectangulare. desi este preferata prima dintre variante. O alta
problema este asocierea coordonatelor de texturare nodurilor fiecaruia dintre poligoanele
elementare.
Modelarea sferei se poate face prin discretizarea domeniului de valori al unghiurilor de
azimut si de elevatie, corespunzatoare longitudinilor si, respectiv, latitudinilor. Azimutul
ia valori n intervalul [0, 2], n timp ce elevatia are valorile cuprinse ntre si .
Astfel, pentru o sfera modelata printr-un numar de m sectiuni latitudinale si n sectiuni
longitudinale, pasurile unghiurilor vor fi = 2/m si = /n.
Pentru a obtine rezultatul din figura 7.7 se poate utiliza exemplul 7.3, cu parametrii
m = 30, n = 20 si textura de dimensiune 512 256 texeli. Functia CreateSphere() nou
creata are ca rol generarea unei sfere discrete poligonale. Sintaxa functiei este:
CreateSphere(centerx, centery, centerz, r, m, n, method);
unde centerx, centery si centerz sunt coodonatele centrului sferei, r este raza sferei,
76 CAPITOLUL 7. TEXTURI
m si n sunt numarul de sectiuni latitudinale si, respectiv, longitudinale, iar method re-
prezinta tipul de poligonale elementare utilizate (0 pentru poligoane triunghiulare sau 1
pentru poligoane rectangulare).
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
void ReadTexture(void) {
FILE * file;
GLubyte data;
int i,j,k;
file=fopen("earth.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
ReadTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,4,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1,2,5,0,0,0,0,1,0);
}
if (method == 0)
glBegin(GL_QUAD_STRIP); // poligonare rectangulara
else
glBegin(GL_TRIANGLE_STRIP); // poligonare triunghiulara
t3 = i * 2 * PI / m; // theta i
}
glEnd();
}
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
CreateSphere(0.0, 0.0, 0.0, 1.0, 30, 20, 1);
glDisable(GL_TEXTURE_2D);
glFlush();
}
In cazul n care pname este GL_TEXTURE_GEN_MODE, valorile posibile ale lui param sunt
GL_OBJECT_LINEAR, GL_EYE_LINEAR sau GL_SPHERE_MAP si specifica tipul functiei utili-
zate la generarea coordonatelor de texturare.
In exemplul 7.4 se prezinta o aplicatie care are ca scop proiectia obiectelor din scena
pe o suprafata sferica (Sphere Environment Mapping).
7.3. COORDONATE AUTOMATE DE TEXTURARE 79
#include <GL/glut.h>
#include <stdio.h>
void ReadTexture(void) {
FILE * file;
GLubyte data;
int i,j,k;
file=fopen("scena.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
ReadTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glutSolidSphere(1,60,64);
glDisable(GL_TEXTURE_2D);
glFlush();
}
De remarcat faptul ca, pentru a obtine un rezultat cat mai realist, imaginea utilizata
ca textura trebuie sa reprezinte proiectia sferica ntr-un unghi solid de 180 a scenei re-
flectate pe sfera pe care se aplica texturarea. Daca se doreste un realism cat mai apropiat
de reflexia obtinuta pe o sfera metalica, trebuie inclusi si parametrii de material ai sferei,
precum si activarea unei surse de iluminare a scenei.
GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
Animatii cu sprite-uri
8.1 Sprite-uri
Un sprite reprezinta o imagine compusa din cadre succesive cu aceiasi dimensiune. De
obicei sprite-urile reprezinta caractere sau obiecte animate ale unei aplicatii sau jocuri.
Fiecare cadru contine pictograma caracterului sau a obiectului, reprezentata pe un fundal
transparent.
Figura 8.1: Imagine de tip sprite cu sase cadre succesive ale unui caracter
Sprite-urile sunt suprapuse n aplicatie pe un fundal care este afisat decupat doar ntr-
o portiune rectangulara. Regiunea se poate deplasa lateral pentru a simula miscarea n
spatiu. Acest tip de fundal se numeste Side-Scrolling Background. La modificarea pozitiei
sprite-ului, regiunea afisata se va deplasa lateral cu o anumita viteza pe principiul unei
ferestre glisante.
Regiunea transparenta a fiecarui cadru din sprite este utila pentru a vizualiza fundalul
si a elimina efectul nedorit al unui obiect opac rectangular. In acest scop se vor utiliza
propritatile de afisare cu transparenta a texturilor.
82
8.1. SPRITE-URI 83
K WW K WW + WW
HW
WW
B[K] = IB [K WW : K WW + WW , 0 : HW ] . (8.1)
Simultan, cadrul curent afisat S[K] al spirite-ului IS este dat de valoarea modulo N a
valorii variabile contor K, unde N este numarul total de cadre din imaginea sprite.
Suprapunerea cadrului curent din imaginea sprite peste fundal se face prin aplicarea
unei combinari cu transparenta pentru cele doua imagini considerate ca fiind doua texturi
poligonale suprapuse.
(K { 1)/N WS K/N WS
HS
WS
glBlendFunc(sFactor, dFactor)
unde sFactor specifica modul de calcul al coeficientilor de combinare ai sursei, iar dFactor
specifica modul de calcul al coeficientilor de combinare ai destinatiei pentru fiecare din
cele patru argumente de culoare (R, G, B si A). Prin sursa se nteleg cele patru argumente
care se doresc a fi suprapuse (sosesc n buffer-ul video), n timp ce destinatia reprezinta
valorile celor patru argumente deja existente n buffer-ul video la momentul suprapunerii.
GL_ZERO (0, 0, 0, 0)
GL_ONE (1, 1, 1, 1)
GL_ONE_MINUS_SRC_COLOR (1, 1, 1, 1) (Rs0 /kR , Gs0 /kG , Bs0 /kB , As0 /kA )
GL_ONE_MINUS_DST_COLOR (1, 1, 1, 1) (Rd0 /kR , Gd0 /kG , Bd0 /kB , Ad0 /kA )
GL_ONE_MINUS_SRC_ALPHA (1, 1, 1, 1) (As0 /kA , As0 /kA , As0 /kA , As0 /kA )
GL_ONE_MINUS_DST_ALPHA (1, 1, 1, 1) (Ad0 /kA , Ad0 /kA , Ad0 /kA , Ad0 /kA )
GL_CONSTANT_COLOR (Rc , Gc , Bc , Ac )
GL_CONSTANT_ALPHA (Ac , Ac , Ac , Ac )
GL_SRC_ALPHA_SATURATE (i, i, i, 1)
GL_ONE_MINUS_SRC1_COLOR (1, 1, 1, 1) (Rs1 /kR , Gs1 /kG , Bs1 /kB , As1 /kA )
GL_ONE_MINUS_SRC1_ALPHA (1, 1, 1, 1) (As1 /kA , As1 /kA , As1 /kA , As1 /kA )
Relatia de calcul pentru fiecare din cele patru canale de culoare (RGBA) este determi-
nata cu ajutorul ecuatiei 8.3.
Obiect (384x128x3)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),
ceea ce seminifica faptul ca fiecare canal de culoare rezultat va fi compus ca suma dintre cu-
loarea imaginii sursa si culoarea deja existenta multiplicata cu coeficientul de transparenta
al imaginii sursa.
Canalul ALPHA este considerat ca fiind opacitatea unui obiect si are valori normate
curpinse n intervalul [0, 1]. Prin urmare, valoarea 0 reprezinta transparenta totala, n
timp ce valoarea 1 este caracteristica unei opacitati totale.
Canal R (Red)
Canal G (Green)
Canal B (Blue)
Canal A (Alpha)
Figura 8.6: Canalele de culoare si transparenta ale obiectului din figura 8.5
86 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI
In cazul n care fundalul este reprezentat doar pe cele trei canale de culoare (RGB),
canalul de transparenta al acestuia este considerat implicit opac.
#include <GL/glut.h>
#include <stdio.h>
spImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glGenTextures(2, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bg_w, bg_h, 0,
GL_RGB, GL_UNSIGNED_BYTE, bgImage);
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ob_w, ob_h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, spImage);
void display(void) {
glBindTexture(GL_TEXTURE_2D, texName[0]); // Selectare fundal
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1.0, 1.0);
glTexCoord2f(1, 0);
glVertex2f(1.0, 1.0);
glTexCoord2f(1, 1);
glVertex2f(1.0, -1.0);
glTexCoord2f(0, 1);
glVertex2f(-1.0, -1.0);
glEnd();
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-0.9, 0.8);
glTexCoord2f(1, 0);
glVertex2f(0.612, 0.8);
glTexCoord2f(1, 1);
glVertex2f(0.612, 0.05);
glTexCoord2f(0, 1);
glVertex2f(-0.9, 0.05);
glEnd();
glFlush();
}
In figura 8.7 sunt prezentate comparativ rezultatele posibile ale combinarii imaginilor
din figura 8.5 cu diferite argumente ale functiei glBlendFunc().
8.1. SPRITE-URI 89
#include <GL/glut.h>
#include <stdio.h>
fread(&data, 1, 1, file);
spImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
readBG();
readSP();
readMK();
glGenTextures(2, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bg_w, bg_h, 0,
GL_RGB, GL_UNSIGNED_BYTE, bgImage);
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ob_w, ob_h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, spImage);
glEnable(GL_TEXTURE_2D);
}
void display(void) {
glBindTexture(GL_TEXTURE_2D, texName[0]);
glBegin(GL_QUADS);
glTexCoord2f(W1, 0);
glVertex2f(-1.0, 1.0);
glTexCoord2f(W1+0.5, 0);
glVertex2f(1.0, 1.0);
glTexCoord2f(W1+0.5, 1);
glVertex2f(1.0, -1.0);
glTexCoord2f(W1, 1);
glVertex2f(-1.0, -1.0);
glEnd();
if (sensDirect) {
W3=0.16*K;
W4=0.16*(K-1);
}
else {
W3=0.16*(K-1);
W4=0.16*K;
}
glBindTexture(GL_TEXTURE_2D, texName[1]);
glEnable(GL_BLEND);
glBegin(GL_QUADS);
glTexCoord2f(W3, 0);
glVertex2f(-0.2, -0.25);
glTexCoord2f(W4, 0);
glVertex2f(0.2, -0.25);
glTexCoord2f(W4, 1);
glVertex2f(0.2, -0.67);
glTexCoord2f(W3, 1);
glVertex2f(-0.2, -0.67);
glEnd();
glDisable(GL_BLEND);
glFlush();
}
Curbele si suprafetele parametrice sunt definite cu ajutorul unor puncte de control care,
n functie de tipul acestora (Bezier, Spline etc.), au diferite semnificatii. In OpenGL, pen-
tru generarea curbelor si a suprafetelor parametrice se utilizeaza polinoamele Bezier n
cadrul evaluatorilor.
9.1 Curbe B
ezier
O curba Bezier reprezinta o functie de o variabila (parametru):
unde u variaza ntr-un domeniu finit (de obicei, n intervalul [0, 1]).
Pentru a construi curba C(u), este necesara determinarea tuturor valorilor celor trei
functii asociate axelor de coordonate, n functie de variatia parametrului u n intervalul
de definitie. Acest lucru este efectuat n OpenGL prin intermediul evaluatorilor.
O curba Bezier cubica este definita prin intermediul a patru puncte de control. Astfel,
pentru a initializa o astfel de curba este necesara apelarea instructiunii glMap1(), astfel:
unde target specifica tipul punctelor de control si, implicit, determina numarul de puncte
necesare a fi incluse n vectorul *points, umin si umax definesc limitele de variatie ale pa-
rametrului u, stride reprezinta numarul de puncte din vectorul *points dintre doua
puncte de control succesive, iar order este ordinul curbei (gradul polinomului plus 1).
glEvalCoord1{f|d}(u);
glEvalCoord1{f|d}v(*u);
95
96 CAPITOLUL 9. CURBE SI SUPRAFET
E PARAMETRICE
GL_MAP1_COLOR_4 R, G, B, A
unde mode poate lua valorile GL_POINT sau GL_LINE, iar p1 si p2 definesc intervalul de
variatie al parametrului, conform formulei:
In exemplul 9.1 se prezinta trasarea unei curbe Bezier de ordinul 4 (cubica) cu patru
puncte de control si cu parametrul u n intervalul [0, 1] si 30 de puncte de subdivizare.
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
9.1. CURBE BEZIER 97
void display(void) {
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glFlush();
}
(4, 4)
t
g en
tan c u rb
(-4, 0)
tangent
(-4, -4) (4, -4)
Figura 9.1: Generarea unei curbe Bezier cubice prin intermediul a patru puncte de control
9.2 Suprafete B
ezier
Suprafetele Bezier sunt generate similar curbelor de acelasi tip, exceptand faptul ca de
aceasta data avem de a face cu doi parametri, u si v.
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
void display(void) {
int i, j;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
y
B
C
A
F
D
E
J
G
H
I N
L
M K
z O x
P
Figura 9.2: Generarea unei suprafete Bezier cubice prin intermediul a 16 puncte de control
glPointSize(5.0);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
glVertex3fv(&puncte_control[i][j][0]);
glEnd();
glFlush();
}
Pentru simplificarea codului, n locul utilizarii n procedura display a celor trei cicluri
for pentru trasarea suprafetei, acestea pot fi nlocuite cu comanda echivalenta:
glEvalMesh2(GL_LINE, 0, 16, 0, 16);
Capitolul 10
Procedura care determina efectele apasarii unei taste este definita prin argumentul
instructiunii glutKeyboardFunc(). In functia argument keyboard, n functie de tasta
apasata (memorata automat de catre sistem n variabila key), se modifica valoarea unei
variabile tip care defineste tipul obiectului. Valoarea implicita este precizata la nceputul
codului, fiind 1 (obiecte de tip triunghi).
In procedura display obiectul este decis printr-o functie de tip switch care verifica
valoarea variabilei tip si stabileste argumentul functiei glBegin().
101
102 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)
#include <GL/glut.h>
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Tastatura");
init ();
glutDisplayFunc (display);
glutKeyboardFunc (keyboard); // evenimentului tip tastatura
glutMainLoop ();
return 0;
}
Cod tast
a special
a Denumire tast
a Cod tast
a special
a Denumire tast
a
GLUT_KEY_F1 Tasta F1 GLUT_KEY_LEFT Tasta sageata stanga
GLUT_KEY_F2 Tasta F2 GLUT_KEY_RIGHT Tasta sageata dreapta
GLUT_KEY_F3 Tasta F3 GLUT_KEY_UP Tasta sageata sus
GLUT_KEY_F4 Tasta F4 GLUT_KEY_DOWN Tasta sageata jos
GLUT_KEY_F5 Tasta F5 GLUT_KEY_PAGE_UP Tasta pagina sus
GLUT_KEY_F6 Tasta F6 GLUT_KEY_PAGE_DOWN Tasta pagina jos
GLUT_KEY_F7 Tasta F7 GLUT_KEY_HOME Tasta HOME
GLUT_KEY_F8 Tasta F8 GLUT_KEY_END Tasta END
GLUT_KEY_F9 Tasta F9 GLUT_KEY_INSERT Tasta Insert
GLUT_KEY_F10 Tasta F10
GLUT_KEY_F11 Tasta F11
GLUT_KEY_F12 Tasta F12
In exemplul 10.2 este prezentata o aplicatie care deplaseaza n plan un obiect grafic
simplu cu ajutorul celor patru taste sageti, permite comutarea ntre afisarea pe ntreg
ecranul sau n fereastra prin apasarea tastei ENTER, precum si terminarea programului
cu ajutorul tastei ESC.
Exemplul 10.2 Utilizarea tastelor speciale pentru deplasarea pe ecran a unui obiect grafic
#include <GL/glut.h>
if (fullscreen) {
glutReshapeWindow(320, 320);
glutPositionWindow(100, 100);
fullscreen=false;
}
else {
glutFullScreen(); // mod Full Screen
fullscreen=true;
}
break;
default:break;
}
glutPostRedisplay();
}
x y
1 320 1
1
y
-1 1 x
320
-1
Figura 10.2: Modificarea coordonatelor din valori absolute ale ecranului n coordonate unitare centrate
#include <GL/glut.h>
GLUT_LEFT_BUTTON
GL
UT
_D
OW
N
Figura 10.3: Aparitia continu
a a cursorului prin tinerea apasata a butonului stanga a mouse-ului si
deplasarea acestuia
Initial se definesc doua variabile, x0 si y0, de tip float, care vor avea ca scop memo-
rarea pozitiei mouse-ului n momentul aparitiei unui eveniment asociat dispozitivului.
Acestea sunt initializate n mijlocul ecranului. Procedura mouse are ca scop crearea unui
cursor n forma de cruce la pozitia curenta n momentul n care este apasat (GLUT_DOWN)
butonul din stanga al mouse-ului (GLUT_LEFT_BUTTON).
Daca mouse-ul este deplasat si butonul din stanga ramane apasat, exista n consecinta
un eveniment continuu care este gestionat prin apelarea procedurii motion prin interme-
diul functiei glutMotionFunc(motion). La fiecare miscare a mouse-ului n aceasta stare
este memorata din nou pozitia curenta, dupa care se reafiseaza cursorul.
In cazul n care se doreste modificarea aplicatiei astfel ncat cursorul sa fie afisat
oricand, indiferent de starea de apasare a butoanelor mouse-ului, se utilizeaza functia
glutPassiveMotionFunc(), noul cod fiind prezentat n exemplul 10.4.
In acest caz, functia glutMouseFunc() nu mai este utila, fiind eliminata mpreuna
cu procedura mouse asociata. In schimb, procedura motion ramane neschimbata, fiind
apelata atat de catre functia glutPassiveMotionFunc() (n cazul n care nu se apasa
niciun buton), cat si de functia glutMotionFunc() (n cazul n care unul dintre butoane
este apasat).
10.1. INTERACT
IUNEA CU MOUSE SI TASTATURA 109
#include <GL/glut.h>
Optiunile meniului creat anterior sunt introduse una cate una cu ajutorul instructiunii
glutAddMenuEntry(), avand ca argumente denumirea optiunii si valoarea acesteia.
In final, meniul trebuie asociat unui buton de mouse, specificand acest buton ca argu-
ment al instructiunii glutAttachMenu().
In exemplul 10.5 este prezentata o aplicatie care permite selectarea culorii de umplere
a unui obiect poligonal cu ajutorul unui meniu apelabil prin intermediul butonului din
dreapta al mouse-ului.
10.2. CREAREA MENIURILOR 111
#include <GL/glut.h>
glutIdleFunc (display);
glutCreateMenu (color); // creare meniu
glutAddMenuEntry ("Red", Opt1); // creare optiunea 1
glutAddMenuEntry ("Green", Opt2); // creare optiunea 2
glutAddMenuEntry ("Blue", Opt3); // creare optiunea 3
glutAttachMenu (GLUT_RIGHT_BUTTON); // asociere buton mouse
glutMainLoop ();
return 0;
}
Fonturi
Pentru afisarea unui caracter se parcurg doua etape. Prima dintre acesta presupune sta-
bilirea coordonatei pozitiei n care se va afisa caracterul dorit prin intermediul instructiunii
glRasterPos(). Pozitia poate fi specificata n plan sau n spatiu, n functie de tipul
aplicatiei (2D sau 3D).
glRasterPos2d(x,y);
glRasterPos3d(x,y,z);
glutBitmapCharacter(font, caracter);
unde font este denumirea fontului utilizat, iar caracter este caracterul afisat, exprimat
sub forma directa sau prin cod ASCII.
113
114 CAPITOLUL 11. FONTURI
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glRasterPos2d(0.0,0.6);
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, A);
glRasterPos2d(0.0,0.4);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, A);
glRasterPos2d(0.0,0.2);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, A);
glRasterPos2d(0.0,0.0);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, A);
glRasterPos2d(0.0,-0.2);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, A);
glRasterPos2d(0.0,-0.4);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, A);
glRasterPos2d(0.0,-0.6);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, A);
glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (320, 240);
glutCreateWindow("Bitmap text");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
11.1. FONTURI BITMAP 115
In exemplul 11.1 se prezinta afisarea unui singur simbol (A) cu toate cele sapte tipuri
de fonturi enumerate anterior. Afisarea se face la coordonata x=0 si ncepand cu y=0.6
cu pas de -0.2.
Pentru a afisa siruri de caractere este necesara repetarea instructiunii pentru fiecare
caracter din sir, specificand pozitia initiala doar pentru primul caracter al sirului.
Exemplul 11.2 prezinta afisarea unui sir de caractere stocate n vectorul *text si ac-
cesate secvenctial prin intermediul pointerului *c. Sirul este parcurs pana cand pointerul
curent devine un pointer NULL (0) care semnifica sfarsitul sirului.
Afisarea textului Hello world! se face pornind de la coordonata (x, y)=(-0.8, 0.0).
Figura 11.2: Exemplu de afisare a sirului Hello world! cu fonturi de tip bitmap
116 CAPITOLUL 11. FONTURI
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glFlush();
}
In exemplul 11.3 este prezentata afisarea textului Hello world! cu fontul stroke de
tip GLUT_STROKE_ROMAN n pozitie initiala (cu culoare rosie) si translatat pe axa Ox cu
-1.5 si pe axa Oz cu 1.0 (cu culoare galbena). In ambele situatii, fontul a fost rescalat pe
cele trei axe cu factorul de 0.005.
#include <GL/glut.h>
void init(void) {
glClearColor(0,0,0,0);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3, 3, 3, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glColor3f(0.5,0.5,0.5);
glBegin(GL_LINES); // axe de coordonate normate
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glVertex3f(0,-1,0);
glVertex3f(0,1,0);
glVertex3f(0,0,-1);
glVertex3f(0,0,1);
glEnd();
Figura 11.3: Exemplu de afisare a sirului Hello world! cu fonturi de tip stroke
glColor3f(1,0,0); // rosu
for (c=text;*c;c++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
glColor3f(1,1,0); // galben
for (c=text;*c;c++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
glFlush();
}
Fisierele de tip *.OBJ pot contine o serie de informatii, cele mai importante (pentru
obiecte poligonale) fiind:
Vertexuri:
geometrice (v);
texturi (vt);
normale (vn);
Elemente:
puncte (p);
linii (l);
fatete (f);
Grupuri:
nume de grup (g);
nume de obiect (o);
Atribute de afisare/randare:
interpolare de culoare (c_interp);
interpolare de dizolvare (d_interp);
nume de material (usemtl);
biblioteca de material (mtllib).
Biblioteca GLM permite definirea mai multor tipuri de structuri, gestionarea datelor
din fisiere de tip *.OBJ (obiect), .MTL (material) sau din fisiere imagini (pentru textu-
rare), precum si manipularea obiectelor prin instructiuni specifice, prezentate n cele ce
urmeaza.
119
120 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE
Alte instructiuni utile oferite de catre biblioteca GLM sunt prezentate n tabelul 12.2.
f 1 2 3 4 # fateta 1
Extrapoland cazul precedent, se poate genera un fisier *.OBJ care sa contina un obiect
de tip cub. Pentru descrierea acestuia sunt necesare opt vertexuri si sase fatete (fisierul
12.2). De retinut faptul ca fiecare fateta este definita prin indexul punctelor utilizate la
trasarea acesteia, ordinea enumerarii vertexurilor n lista fiind importanta.
f 1 2 3 4 # fateta 1
f 8 7 6 5 # fateta 2
f 4 3 7 8 # fateta 3
f 5 1 4 8 # fateta 4
f 5 6 2 1 # fateta 5
f 2 6 7 3 # fateta 6
In exemplul 12.1 se prezinta codul necesar alocarii memoriei, ncarcarii si afisarii obiec-
tului. Pentru ncarcarea bibliotecii GLM, spre deosebire de GLUT si GLU, se apeleaza
fisierul sursa glm.cpp:
#include <GL/glm.cpp>
In continuare se defineste modelul (obiectul) grafic si se aloca memoria necesara ca
variabila de tip GLMmodel:
122 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE
Exemplul 12.1 Incarcarea unui obiect grafic dintr-un fisier Alias/Wavefront (*.OBJ)
#include <GL/glut.h>
#include <GL/glm.cpp> // incarcare biblioteca GLM
void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj"); // incarcare date din fisier
glmFacetNormals(obiect); // calcul normale fatete
glmDraw(obiect, GLM_FLAT); // desenare obiect
glFlush();
}
obiect = glmReadOBJ("patrat.obj");
Pentru afisare este necesar calculul normalelor fatetelor obiectului:
glmFacetNormals(obiect);
dupa care se aplica instructiunea de afisare glmDraw():
glmDraw(obiect, GLM_FLAT);
Pe langa coordonatele si indecsii fatetelor, se mai pot preciza tipurile de material speci-
ficate ntr-un fisier *.MTL si utilizate pentru fiecare grup de fatete n parte. Materialul
este definit printr-o structura de tip GLMmaterial care are urmatoarele componente:
newmtl - denumirea materialului;
Ns - exponentul specular Phong (intre 0 si 200);
Kd - coeficientul de culoare difuza;
Ka - coeficientul de culoare ambientala;
Ks - coeficientul de culoarea speculara;
d - factorul de dizolvare (transparenta);
map_Kd - textura difuza;
map_Ka - textura ambientala;
map_Ks - textura speculara;
124 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE
Pentru aceasta, fatetele care utilizeaza acelasi material vor constitui un grup cu eti-
cheta proprie (de exemplu, g fatete14). Dupa definirea numelui de grup se specifica
tipul materialului utilizat prin instructiunea usemtl urmata de numele materialului.
In fisierul 12.4 sunt exemplificate modificarile aduse fisierului cub.obj fata de exemplul
12.2 pentru a utiliza materiale.
Fisierul 12.4 Descrierea unui cub cu materialele asociate ntr-un fisier cub.obj
g fatete14 # grupul 1
usemtl bronze # utilizare material 1
f 1 2 3 4
f 8 7 6 5
g fatete25 # grupul 2
usemtl silver # utilizare material 2
f 5 1 4 8
f 5 6 2 1
g fatete36 # grupul 3
usemtl gold # utilizare material 3
f 4 3 7 8
f 2 6 7 3
Exemplul 12.2 Incarcarea unui obiect grafic cu materiale dintr-un fisier Alias/Wavefront
(*.OBJ)
#include <GL/glut.h>
#include <GL/glm.cpp>
void init(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj");
glmFacetNormals(obiect);
glmVertexNormals(obiect, 90);
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL);
glFlush();
}
In mod implicit, fisierele de tip *.MTL pot contine si informatie de textura, dar aceasta
nu poate fi citita direct n mediul OpenGL. Pentru a include, totusi, texturile, se poate
utiliza ncarcarea fisierelor imagine de tip *.PPM care contin texturile cu instructiunea
glmReadPPM():
int w, h;
GLubyte *textura = 0;
textura = glmReadPPM ("textura.ppm", &w, &h);
Instructiunea are ca efect ncarcarea datelor n variabila textura, precum si a dimen-
siunilor acesteia n variabilele w si h, necesare ulterior pentru parametrizarea texturii.
Dupa cum se poate observa n exemplul 12.3, texturarea se face n mod similar unei tex-
turari poligonale utilizand instructiuni specifice, precum: glGenTextures(), glTexEnvi(),
glTexParameteri(), glTexImage2D() si glBindTexture(), .
Fisierul 12.5 Descrierea unui cub cu materialele si texturile asociate ntr-un fisier cub.obj
mtllib materiale.mtl
Exemplul 12.3 Incarcarea unui obiect grafic cu materiale dintr-un fisier Alias/Wavefront
(*.OBJ) si texturarea obiectului
#include <GL/glut.h>
#include <GL/glm.cpp>
void init(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj"); // incarcare obiect
glmUnitize(obiect);
glmFacetNormals(obiect);
glmVertexNormals(obiect, 90);
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL|GLM_TEXTURE);
glmLinearTexture(obiect);
glFlush();
}
a) b)
c) d)
a) b)
c) d)
Figura 12.2: Rezultatul afis arii obiectelor n modul de iluminare interpolat: a) fara material, b) cu
material, c) cu textur
a si d) cu material si textura
Materiale
Valorile din tabelul urmator pot fi utilizate pentru alegerea proprietat, ilor de material
ale obiectelor.
131
ANEXA A. MATERIALE
133
134 ANEXA A. CODURI ASCII STANDARD (0-127)
[1] Astle, D., and Hawkins, K. Beginning OpenGL Game Programming. Premier
Press, 2004.
[2] Chin, N., Frazier, C., Ho, P., Liu, Z., and Smith, K. P. The OpenGL
Graphics System Utility Library (Version 1.3). Silicon Graphics.
[3] Foley, J. D., van Dam, A., Feiner, S. K., and Hughes, J. F. Computer
Graphics. Principle and Practice in C, 2nd ed. Addison-Wesley, 1997.
[4] Gonzalez, R. C., and Woods, R. E. Digital Image Processing, 3rd ed. Prentice
Hall, 2008.
[5] Hearn, D., and Baker, M. P. Computer Graphics. C Version, 2nd ed. Prentice
Hall, 1996.
[6] Hill, Jr., F. S., and Kelley, S. M. Computer Graphics using OpenGL, 3rd ed.
Prentice Hall, 2006.
[7] Kilgard, M. J. The OpenGL Utility Toolkit (GLUT) Programming Interface. API
Version 3. Silicon Graphics.
[8] Martz, P. OpenGL Distilled. Addison-Wesley, 2006.
[9] Molder, C. Grafica computerizata. Editura Albastra, 2009.
[10] Poynton, C. Digital Video and HDTV. Algorithms and Interfaces, 1st ed. Morgan
Kaufmann, 2003.
[11] Rost, R. J. OpenGL Shading Language, 2nd ed. Addison-Wesley, 2006.
[12] Seddon, C. OpenGL Game Development. Wordware Publishing, 2005.
[13] Segal, M., and Akeley, K. The OpenGL Graphics System: A Specification
(Version 2.1). Silicon Graphics.
[14] Segal, M., and Akeley, K. The OpenGL Graphics System: A Specification
(Version 3.0). Silicon Graphics.
[15] Shreiner, D., Woo, M., Neider, J., and Davis, T. OpenGL Programming
Guide: The Official Guide to Learning OpenGL, Version 2.1, 6th ed. Addison-
Wesley, 2008.
[16] Wright, Jr., R. S., Lipchak, B., and Haemel, N. OpenGL Super Bible:
Comprehensive Tutorial and Reference, 4th ed. Addison-Wesley, 2007.
136