laborator 1 - graphics.cs.pub.rographics.cs.pub.ro/graphicswiki/images/2/2e/lab1_spg.pdf · sisteme...

21
10/2/2009 Laborator 1 FACULTATEA DE AUTOMATICA SI CALCULATOARE SISTEME DE PRELUCRARE GRAFICA

Upload: lyxuyen

Post on 06-Feb-2018

236 views

Category:

Documents


3 download

TRANSCRIPT

10/2/2009

Laborator 1

FACULTATEA

DE

AUTOMATICA SI

CALCULATOARE

SISTEME DE PRELUCRARE

GRAFICA

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 2

OpenGL - Basics

OpenGL este un API (Application Programming Interface) standard pentru grafica

3D. Inainte de aparitia sa fiecare producator de hardware avea propria sa biblioteca grafica. Nu este greu de imaginat cat de costisitor era de produs o

aplicatie grafica pentru mai multe platforme.

Ce poate face?

• In primul rand scuteste efortul de a transpune scena 3D pe ecran. Acest lucru se face automat ( lantul de transformari si etapele benzii grafice )

• Implementeaza transformarile de: rotatie, translatie, scalare.

• Ofera o stiva de matrici in care putem pastra transformarile aplicate

anterior

• Poate desena diverse primitive cu diverse proprietati de material (obiectele

pot sa para metalice, de plastic etc.)

• Texturile (imagini aplicate pe obiecte) pot face o scena simpla sa arate mult mai realist

• Pot fi create obiecte transparente (mecanismul de blending)

• OpenGL ofera diverse modele de iluminare si mai multe surse de lumina.

Totusi modelul de iluminare folosit este unul basic pentru ca tine cont doar de pozitia obiectului fata de sursa de lumina nu si de celelalte obiecte din

scena. Insa facilitatile oferite de OpenGL micsoreaza efortul necesar

pentru a produce umbrele.

• Etc

Conventii de numire a functiilor

Desi la prima vedere numele functiilor par neintuitive, ele urmeaza o regula simpla. Majoritatea sunt de forma:

• gl{nume functie}{numar de parametri}{sufix care arata tipul

parametrilor}{v (daca parametrul este un vector} ( .......)

Fiind independent de platforma OpenGL prevede cateva tipuri de date. Pentru a

obtine o aplicatie portabila este recomandat sa le folositi pe acestea si nu altele

de aceasi marime caracteristice sistemului de operare folosit:

Nume Descriere sufix

GLbyte intreg pe 8 biti b

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 3

GLshort intreg pe 16 biti s

GLint, GLsizei intreg pe 32 de biti i

GLfloat, GLclampf reprezentare in virgula mobila pe 32 de

biti f

GLdouble, GLclampd reprezentare in virgula mobila pe 64 de

biti d

GLubyte, GLboolean intreg fara semn pe 8 biti Ub

GLushort intreg fara semn pe 16 biti Us

GLuint, GLenum, GLbitfield intreg fara semn pe 32 de biti Ui

Cateva exemple: glVertex3d -primeste 3 parametri de tip GLdouble

glColor3f -3 parametri de tip GLfloat Totusi exista si cateva exceptii in care

lipsesc numarul si tipul parametrilor (de exemplu glBegin) sau care incep cu un alt prefix (gluLookAt).

Sistem de coordonate

OpenGL foloseste un sistem de coordonate dreapta.

Avem ordinea axelor xyz. Un sistem de coordonate este dreapta, daca privind de-a lungul unei axe dinspre +infinit spre origine, o rotatie in sens trigonometric

va aduce o axa pozitiva, peste axa pozitiva urmatoare. De exemplu: (ox peste

oy) sau (oy peste oz) sau (oz peste ox).

Transformari ale obiectelor 3D in OpenGL

Orice secventa de transformari, inclusiv proiectia se poate reprezenta printr-o

matrice. OpenGL reprezinta intern punctele ca vectori coloana. Din acest motiv o

secventa de doua transformari T1 apoi T2 aplicate punctului p produc rezultatul:

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 4

p' = T2 T1 p

OpenGL foloseste constantele: GL_MODELVIEW, GL_PROJECTION pentru a identifica matricea de modelare-vizualizare, respectiv matricea de proiectie.

Functiile OpenGL care reprezinta transformari modifica matricea curenta. Trebuie

sa aveti grija ca inainte de a le aplica sa apelati

glMatrixMode(constanta_care_identifica_matricea) pentru a va asigura ca transformarile vor produce efectul dorit.

Transformarea de modelare pozitioneaza un obiect undeva in lume. Puteti

folosi rotatii, translatii, scalari. Transformarea de vizualizare pozitioneaza observatorul. Acelasi efect poate fi obtinut in ambele moduri, de aceea OpenGL le pastreaza ca o singura matrice: GL_MODELVIEW.

Pentru a stabili pozitia observatorului puteti folosi functia:

• gluLookAt (GLdouble ex, GLdouble ey, GLdouble ez,GLdouble cx,

GLdouble cy, GLdouble cz,GLdouble upx, GLdouble upy, GLdouble

upz) o (ex, ey, ez) reprezinta noua pozitie a observatorului

o (cx, cy, cz) va arata directia in care priveste acesta o (upx, upy, upz) reprezinta directia sus din planul de vizualizare

Implicit observatorul e situat in origine, priveste in directia negativa a axei oz, iar

directia sus a planului de vizualizare este directia pozitiva a axei oy (0,1,0).

In acest moment matricea de modelare-vizualizare este matricea identitate.

Cand apelati gluLookAt transformarea descrisa de aceasta este compusa cu cea

deja existenta. De aceea daca o apelati de doua ori, al doilea apel s-ar putea sa

produca alte rezultate decat cele pe care le asteptati.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 5

Inainte de gluLookAt puteti apela secventa :

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

pentru a incarca matricea identitate in matricea de modelare-vizualizare.

Obiectele le puteti aseza/transforma in scena folosind:

• glScalef(GLfloat x, GLfloat y, GLfloat z) • glTranslatef( GLfloat x, GLfloat y, GLfloat z) • glRotatef (GLfloat unghi, GLfloat x, GLfloat y, GLfloat z)

Singura a carei semnificatie nu e evidenta este glRotatef. Aceasta functie roteste in sens trigonometric in jurul axei x,y,z cu unghiul unghi.

O astfel de functie modifica matricea curenta, astfel incat transformarea se va

aplica tuturor obiectelor pe care le vom desena de acum incolo, lasandu-le

neschimbate pe cele deja desenate. Insa comportamentul lor este diferit de ceea ce ne-am astepta. Transformarile sunt aplicate obiectului in ordinea inversa

apelurilor.

Pana acum am vazut cum stabilim pozitia si orientarea observatorului in raport cu obiectele din lume. Insa pentru a face scena sa apara pe ecran trebuie sa

delimitam spatiul vizibil: volumul de vizualizare. OpenGL permite mai multe

moduri de a face acest lucru.

Proiectia ortografica se realizeaza cu ajutorul functiei:

• glOrtho(GLdouble left, GLdouble right, GLdouble bottom,

GLdouble top, GLdouble near, GLdouble far)

Volumul de vizualizare este un paralelipiped dreptunghic. Nu uitati insa ca

pozitia observatorul este implicit in origine si priveste in directia negativa a axei oz. Deci obiectele cu z intre -near si -far vor fi vizibile.

Proiectia perspectiva se poate realiza in doua moduri:

• glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)

left, right, bottom, top se refera in acest caz la fereastra din planul apropiat.

Cum stim pozitia observatorului ( e cea implicita sau cea setata de noi cu gluLookAt) putem calcula volumul de vizualizare. Distantele near si far trebuie

sa fie pozitive.

Un alt mod de a specifica acest volum de vizualizare este cu ajutorul functiei:

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 6

• void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble

near, GLdouble far)

Ati recunoscut deja parametrii near si far. Parametrul aspect reprezinta raportul

dintre lungimea si inaltimea ferestrei in planul de aproape. Pentru a obtine o imagine nedistorsionata acest raport trebuie sa corespunda cu cel al ferestrei

de afisare. Parametrul fovy este unghiul de vizualizare in planul xOz si trebuie

sa fie in intervalul [0.0, 180.0]

Transformarea in poarta de vizualizare se defineste folosind functia:

• glViewport (GLint px, GLint py, GLint pz, GLsizei width, GLsizei

height)

px, py reprezinta coordonatele in fereastra ale coltului stanga jos al portii. Implicit sunt 0,0.

width, height sunt latimea si inaltimea portii. Valorile implicite sunt date de

latimea si inaltimea ferestrei in care se afiseaza.

Setarea culorii

Inainte de a face vreun desen trebuie sa setam o culoare de fond:

• glClearColor(GLclampf R, GLclampf G, GLclampf B, GLclampf A)

A reprezinta opacitatea.Apoi vom sterge imaginea:

• glClear(GL_COLOR_BUFFER_BIT)

Constanta data ca parametru arata ce buffer vrem sa stergem. OpenGL foloseste

mai multe buffere in diverse scopuri. Putem sterge mai multe cu acelasi apel astfel:

• glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

In acest caz am sters imaginea si bufferul folosit pentru a determina care figuri sunt vizibile (folosit de algoritmul z-buffer).

Acum putem seta o culoare care va fi folosita pentru urmatoarele desenari

(pana o schimbam din nou):

• glColor3f(GLfloat R, GLfloat G, GLfloat B);

Desenarea diverselor primitive

Exista mai multe tipuri de primitive pe care le putem desena folosind

OpenGL. Pentru inceput insa nu le voi prezenta pe toate.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 7

Putem desena ceva pe ecran folosind functia:

• glVertex3f(GLfloat x, GLfloat y, GLfloat z)

Pentru a avea vreun efect apelurile acestei functii trebuiesc incadrate intre

apelurile glBegin(GLenum tip_primitiva) si glEnd( ).

Tipul primitivei este identificat printr-una din constantele:

• GL_POINTS - deseneaza puncte • GL_LINES - deseneaza segmente. Doua puncte definesc un

segment, urmatoarele doua alt segment etc. • GL_POLYGON - deseneaza un poligon • GL_TRIANGLES - fiecare grup de 3 varfuri defineste un dreptunghi • GL_QUADS -patrulatere • GL_LINESTRIP - doar primul segment e definit prin doua puncte.

Urmatoarele au un capat comun cu cel anterior • GL_LINE_LOOP - Se deseneaza un segment si intre primul si ultimul punct • GL_TRIANGLE_STRIP - banda de triunghiuri. Toate in afara de primul (care

e definit prin 3 varfuri) au primele doua varfuri egale cu ultimele doua ale

triunghiului anterior • GL_TRIANGLE_FAN - toate triunghiurile au primul varf comun. Doua

triunghiuri succesive au o latura comuna • GL_QUAD_STRIP - asemanator cu triangle strip, dar sunt patrulatere

Este recomandat sa folositi GL_TRIANGLE_STRIP sau GL_TRIANGLE_FAN in loc de GL_TRIANGLES oricand este posibil si sa introduceti cat mai multe varfuri

intre un singur apel glBegin si glEnd pentru ca placile grafice sunt optimizate

pentru desenarea in acest mod si trebuie sa comunicam cat mai putine date placii.

Intre glBegin si glEnd puteti apela si glColor* pentru a stabili culoarea

varfurilor urmatoare.

Modul in care sunt afisate poligoanele se poate stabili (inainte de glBegin!) folosind:

• glPolygonMode (GLenum face, GLenum mode) o face poate fi :

� GL_FRONT_AND_BACK sau GL_FRONT sau GL_BACK. � Aceste constante identifica fetele fata sau spate (in mod

implicit fetele care sunt definite prin varfuri parcurse in sens

trigonometric sunt considerate fete fata o mode poate fi GL_POINT, GL_LINE sau GL_FILL

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 8

Stive de matrici

Stiti deja ca putem stabili o transformare care sa fie aplicata tuturor varfurilor de

acum incolo. Insa uneori avem nevoie sa definim o transformare nu fata de cea dinaintea ei, ci fata de una mai veche. De exemplu avem nevoie sa desenam o

masina. Desenam masina. Aplicam o translatie si desenam prima roata. Ne este

mai usor sa calculam pozitia celorlalte roti fata de masina, nu fata de prima roata.

OpenGL ne ofera o posibilitate de a face acest lucru prin existenta unei stive de

matrici. Cea din varful stivei este matricea curenta.

In momentul in care apelam glPushMatrix( ) matricea curenta este salvata in

stiva. Putem sa modificam si sa folosim matricea curenta.

Apoi cand vrem sa ne intoarcem la transformarea pastrata in stiva apelam

glPopMatrix( ).

Singurul lucru la care trebuie sa fim atenti este sa nu apelam glPopMatrix daca nu avem nici o matrice in stiva si sa nu depasim capacitatea stivei. Desi exista implementari care ofera stive foarte mari sau chiar nelimitate, standardul

prevede o stiva de 32 de matrici de modelare-vizualizare si o stiva de 2 matrici de proiectie. Stiva pe care lucreaza glPushMatrix si glPopMatrix este stabilita cu

ajutorul functiei glMatrixMode.

Gestiunea ferestrelor folosind biblioteca glut

Pe langa standardul OpenGL, glut ofera si functii care usureaza realizarea unei

interfete cu utilizatorul. Voi enumera cateva dintre ele (pentru mai multe informatii va puteti uita in indrumarul de laborator):

glutInit(int* argc, char** argv) initializeaza variabilele interne si

prelucreaza argumentele din linia de comanda. Trebuie apelata inaintea

oricarei alte functii glut.

glutInitDisplayMode( unsigned int mode) initializeaza modul de afisare.

mode specifica:

• modelul de culoare folosit. Se recomanda GLUT_RGB • folosirea unei ferestre cu buffer simplu sau dublu: GLUT_SINGLE sau

GLUT_DOUBLE

• folosirea bufferului de adancime pentru algoritmul z-buffer: GLUT_DEPTH Pentru a obtine valoarea lui mode putem aplica | intre valorile care ne intereseaza.

glutInitWindowPosition(int x, int y) >pozitioneaza fereastra fata de coltul stanga sus al ecranului.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 9

glutInitWindowSize(int width, int height) evident stabileste

dimensiunea ferestrei

int glutCreateWindow(char* nume) creaza o fereastra cu un context OpenGL

int glutDestroyWindow(int window) distruge fereastra window impreuna

cu toate subferestrele ei.

Functii pentru controlul evenimentelor de intrare

glutReshapeFunc( void (*f) (int width, int height) primeste ca parametru un pointer la o functie care trebuie apelata de fiecare data cand fereastra e

redimensionata.

glutKeyboardFunc( void (*f) (unsigned char key, int x, int y)) primeste ca parametru o functie care trebuie apelata de fiecare data cand se

apasa/elibereaza o tasta. key este valoarea ASCII. x si y reprezinta pozitia

mouse-ului la apasarea tastei.

glutMouseFunc( void (*f) (int buton, int stare, int x, int y) . *f va fi

apelata la apasarea sau eliberarea unui buton de mouse. buton poate fi:

GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON. Parametrul state poate fi: GLUT_UP sau GLUT_DOWN. Parametrii x si y

reprezinta pozitia mouse-ului la aparitia evenimentului

glutMotionFunc( void (*f) (int x, int y) . *f va fi apelata la deplasarea mouse-ului in timp ce un buton este apasat. Parametrii x si y reprezinta pozitia

mouse-ului in momentul apasarii.

Executia aplicatiei

glutDisplayFunc( void (*f)(void)) stabileste functia de afisare. Functia de afisare va fi apelata automat de fiecare data cand este necesara redesenarea

continutului ferestrei. Putem cere explicit acest lucru apeland:

glutPostRedisplay( ). In cazul in care folosim un buffer dublu, la sfarsitul lui *f

trebuie sa cerem schimbarea bufferelor prin glutSwapBuffers( ) .

glutIdleFunc(void (*f) (void)) . Parametrul este o functie care va fi

executata in perioadele in care nu exista evenimente in curs de tratare. NULL inseamna ca functia idle e dezactivata. Poate fi folosita pentru crearea unei

animatii.

glutMainLoop(void) este ultima functie care se apeleaza in main. Contine o bucla in care aplicatia asteapta evenimente.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 10

Iluminare si proprietati de material in OpenGL

Redarea luminilor in OpenGl este o sarcina care implica setari in mai multe

directii:

• setari generale ale mediului OpenGL si ale interpretarii luminii pe diferite

fete

• surse de lumini

• propietatile surselor de lumini • materiale

• normale la suprafata

Daca una din aceste setari este gresita, atunci nu va merge nimic corect.

Ca deobicei, pentru a avea succes trebuie sa programam de la inceput

foarte atent si foarte curat. De asemenea, este foarte putin probabil sa se

reuseasca sa un efect interesant daca nu este inteles bine mecanismul

luminilor.

Interpretarea modelului luminii naturale in OpenGL

Pentru inceput sa ne imaginam o scena complexa din lumea reala. Ea este

formata din obiecte cu diferite forme si texturi, dar si din multe lumini,

reflexii de lumini sau umbre. Din punct de vedere fizic, lumina este o

energie fotonica care se misca prin spatiu aproape instantaneu. Cand un

obiect primeste o raza de lumina, el pastreaza o parte din energie pentru

el, iar restul o imprastie in mediu. Partea care o primeste pentru el se

transforma in caldura, iar partea care o emana va determina practic culoarea obiectului.

Cum sunt structuralizate toate acestea intr-un model de lumini? In

OpenGL, se considera ca intr-o scena oarecare pot apare mai multe tipuri de lumini de felul urmator:

1. lumina ambientala

2. lumina difuza

3. lumina speculara

4. lumina emisa

Lumina ambientala

Aceasta este lumina care este prezenta in atmosfera “pur si simplu”. Nu

putem spune despre ea nici ca vine dintr-o anumita sursa, , nici ca este

stralucitoare , nici ca se reflecta de oglinda. Este provenita de la alte surse

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 11

de lumini in urma reflexilor repetate, nu se mai poate stabili exact unde a

fost sursa si cum a ajuns lumina in locul respectiv.

Un exemplu bun de lumina ambientala este cea vazuta intr-un hol care

primeste lumina numai de la sursele din camerele vecine. Lumina venita

poate fi amestecata din razele de lumina venite din numeroase reflexii.

Doar lumina ambientala nu ne ajuta sa vedem formele obiectelor colorate la fel. Motivul? Energia luminoasa este identica pt fiecare fata(nu depinde

de orientare) si prin urmare culoarea vazuta este exact aceiasi.

Lumina Difuza

Aceasta este lumina provenita de la o sursa anume. Ea este formata din

mai multe raze care se imprastie in toate directile. Acum lumina obiectului

este si calculata in functie de directia razei care lumineaza respectivul

obiect. Sursa de lumina poate fi la infinit (imaginati-va lumina solara intr-o zi senina) sau poate fi apropiata de obiect (imaginati-va un bec).

Diferenta dintre cele doua tipuri de surse se observa si in directia razelor.

La soare razele vin paralele, la bec razele chiar se vad cum emana dintr-un punct fix. Lumina difuza se apropie cel mai mult de majoritatea

luminilor din lumea reala, reprezinta clasa luminilor cu sursa si directie. De

retinut ca pozitia observatorului nu influenteaza culoarea obiectului in

acest caz, cu alte cuvinte culoarea este transmisa la fel in toate directiile.

Lumina speculara

Aceasta este componenta care da stralucire obiectelor. Se aseamana cu

lumina difuza, insa singura diferenta este ca speculara este focalizata. Pentru a intelege conceptul e bine sa ne imaginam o raza laser, sau un

reflector de foarte buna calitate. Razele care pleaca din reflector trebuie sa

fie paralele. Obiectele resping aceasta lumina tot intr-un mod specular si

prin urmare aceasta lumina nu poate fi vazuta din orice pozitie. Ochiul

trebuie sa se afle chiar pe directia ei.

Lumina emisa

Aceasta este lumina pe care un obiect o emite prin el insusi. In OpenGL

aceasta nu mai devine si sursa pentru alte obiecte din jurul lui. De regula

nu este nevoie sa fie folosita decat daca se doreste obtinerea de obiecte

incandescente (lampi, focuri, etc.. )

Culorile luminii si materialelor in OpenGL

De remarcat ca lumina are si culoare. Exista in lumea reala si lumini verzi

si lumini albastre, dar si lumini obisnuite albe. De cele mai multe ori,

obiectul amesteca culorile primite de la lumina cu culorile sale naturale,

putand rezulta chiar o culoare diferita de culoarea initiala a obiectului.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 12

In OpenGL culoarea poate fi specificata prin cele 3 componente RGB.

Acestea sunt niste valori reale intre 0 si 1. De exemplu o lumina cu

(R,G,B)=(1,1,1) reprezinta o lumina alba, cea mai puternica. O lumina

(0,0,1) reprezinta o lumina albastruie. In openGL atat lumina cat si corpul

au setate aceste valori pentru fiecare tip de lumina (ambientala, difuza si

speculara). Lumina reflectata de un anumit obiect se obtine inmultind

valoarea culorii cu valoarea luminii – bineinteles ambele trebuie sa se

refere la acelasi tip de lumina.

Din punct de vedere fizic se pot intampla lucruri mult mai interesanta cu

raza de lumina in momentul in care aceasta atinge corpul. De ce nu mai e

alba zapada cand se topeste? Pentru ca de regula zapada reflecta in

totalitate lumina primita, dar daca se topeste incepe sa si absoarba.

Pasii necesari pentru a seta un mediu propice luminii in OpenGL

Pentru a incepe sa folosim luminile avem nevoie de urmatoarele setari

1. Initializarea mediului

glEnable(GL_LIGHTING) : fara aceasta functie, OpenGL nu efectueaza calcule pentur iluminare

2. Activarea luminilor

glEnable(GL_LIGHT0) : acesta functie activeaza sursa de lumina

cu numarul 1

glEnable(GL_LIGHT1) : acesta functie activeaza sursa de lumina

cu numarul 2

....

glEnable(GL_LIGHT7) : acesta functie activeaza sursa de lumina

nr. 8

Toate propietatile luminii pe care le vom da in continuare se vor seta

in una din aceste 8 lumini. Acesta este numarul maxim de lumini

intr-o scena OpenGL (in anumite implementari acest numar poate fi

mai mare).

Cu toate acestea, mai exista o sursa in scena introdusa automat

chiar daca nu sunt aprinse aceste lumini: Lumina Ambientala Globala

GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 13

Aceasta este lumina prin care se pot vedea obiectele chiar daca noi

nu adaugam explicit lumina, ea defineste o lumina ambinetala de

baza, cam palida.

3. Setarea modelului de iluminare

Se pot seta diversi parametrii ai iluminarii:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE) : aceasta functie seteaza pozitia ochiului in (0,0,0). Avem nevoie de

ea atunci cand calculam reflexile speculare. Deobicei observatorul se

considera a fi la infinit astfel incat unghiul format de raza incidenta pe un punct si de linia observator-punct depinde doar de raza

incidenta.

glLightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE): aceasta

functie spune openGL-ului sa faca toate calculele si pentru fetele considerate ca sunt cu spatele la lumina. Deobicei aceste fete sunt

orientate spre interiorul corpurilor deci nu avem nevoie de lumina pe

ele. Insa daca vrem sa iluminam si partea interioara a unei jumatati

de sfera, trebui sa setam si acest parametru.

ShadeModel : Acesta nu face parte neaparat din modelul de

iluminare, insa e destul de important in acest context. Se seteaza cu

glShadeModel si poate fi de doua feluri: smooth sau flat. Modul flat

pune aceiasi culoare pe toata fata, in timp ce modul shade

interpoleaza valorile din colturi. Trebuie sa fim atenti la cazul in care

o lumina de tip spot cade pe centrul unui obiect fara sa ii atinga colturile. Daca se intampla asta, lumina va fi practic ignorata.

4. Setarea parametrilor obiectelor

Dupa ce am parcurs pasii de mai sus, putem sa incepem sa setam

parametrii efectivi ai luminilor. Ne alegem una din cele 8 surse de

lumina, sa zicem GL_LIGHT0, si vom opera asupra ei.

Un exemplu simplu - pentru a seta un parametru oarecare din cei

care urmeaza, se apeleaza un cod ca cel de mai jos:

GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);

Acest cod seteaza propietatea GL_AMBIENT la valorile precizate

pentru sursa de lumina GL_LIGHT0. Cei 4 parametrii reprezinta

valorile RGBA ale luminii – intre 0 si 1. RGB este destul de clar ce

inseamna, alfa este folosit daca vrem sa facem, de exemplu, culoarea luminii mai importanta decat culoarea obiectului. Daca

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 14

obiectul are alfa mai mic decat 1.0, atunci culoarea naturala a

obiectului va fi mai putin importanta decat culoarea luminii atunci

cand se va calcula valoarea luminii reflectate.

Sa trecem acum la definirea completa a parametrilor luminii.

• GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR

Aceste valori sunt toate definite ca in exemplul de mai sus si

reprezinta culoarea luminii pentru cele 3 tipuri de lumini prezentate.

Pentru a crea un efect realistic e bine ca acestea sa aiba aceiasi valori – adica lumina difuza si ambientala sa fie de aceiasi culoare.

• GL_POSITION

Aceasta valoare e folosita pentru luminile care trebuie sa aiba o

sursa specificata: SPECULAR si DIFFUSE. Aceste tipuri de lumini au

nevoie de o pozitionare, trebuie sa stiu de unde pleaca lumina.

GLfloat light_position[] = { x,y,z,w};

glLightfv(GL_LIGHT0, GL_POSITION, light_position);

Precum vedeti, apelul este similar celui de la GL_AMBIENT. Daca w,

componenta a 4-a este 0 atunci se considera ca sursa este undeva

la infinit pe directia x,y,z (Directional Light). Altfel ea se afla exact la pozitia x,y,z (Positional Light).

• GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION,

GL_QUADRATIC_ATTENUATION

Acesti parametrii afecteaza factorii de atenuare a luminii. In lumea

reala teoretic lumina se poate atenua. OpenGL permite atenuarea

intensitatii luminii in functie de distanta, patratatul distantei sau

cubul distantei. Acesti parametrii se folosesc doar la luminile

positionale.

• GL_SPOT_DIRECTION, GL_SPOT_EXPONENT, GL_SPOT_CUTOFF

Acesti parametrii se folosesc la luminile positionale, atat pentru

componenta difuza cat si pentru componenta speculara. Dand acesti

3 parametrii, lumina emanata dintr-un punct (nu de la infinit) nu mai pleaca in toate directile ci numai dupa o anumita orientare. Se

doreste simularea luminilor de genul reflectoarelor de la concerte.

GL_SPOT_DIRECTION reprezinta directia (x,y,z) in care este orientat

spotul, GL_SPOT_EXPONENT reprezinta concentratia luminii in interiorul spotului (poate fi constanta sau mai puternica spre centru

si mai mica spre margini).

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 15

GL_SPOT_CUTOFF care reprezinta ungiul, sau deschiderea spotului.

Initial aceste e de 180 care inseamna (180*2=360) ca spotul este

de fapt tot o lumina emanata in toate directiile. Dar daca setam alt

unchi, suntem obligati sa dam o valoare intre 0 si 90 de grade, adica

sa determinam un spot realistic (fata de o anume directie – centru

spotului).

5. Un exemplu de setare lumini

nr light_position[] = { 0.0, 100.0, 0.0, 1.0 }; //seteaza pozitia

nr light_ambient [] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta ambientala

nr light_difusion[] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta de

difuzie

nr light_specular[] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta

speculara

nr direction [] = { 1.0, -1.0, 1.0}; //seteaza directia spotului

glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);

glLightfv(GL_LIGHT1, GL_AMBIENT , light_ambient);

glLightfv(GL_LIGHT1, GL_DIFFUSE , light_difusion);

glLightfv(GL_LIGHT1, GL_POSITION, light_position);

glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, direction);

glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);

glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 3.0);

Acest exemplu seteaza o lumina rosiatica (0.9>0.4), pozitionata la inaltimea 100 (observati ca ultimul parametru al pozitiei nu este 0, deci

avem lumina pozitionala) si apoi ii definim si propietati de spot. Directia

este in jos, unghiul de deschidere totala va fi 45*2=90 si exponentul este

3 ca sa concentram lumina catre interiorul spotului. Matematic vorbind,

intensitatea luminii intr-o anumita parte a spotului, va fi cos(unghi(raza in

cadrul spotului, directia generala a spotului))) la puterea a 3-a.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 16

6. Setarea parametrilor materialului

Majoritatea caracteristicilor luminii trebuie sa se regaseasca in

propietatile de material pentru ca un obiect sa reflecte o culoare.

Aceasta va fi determinata pe baza propietatilor luminii dar si a

propietatilor materialului.

Pentru luminile neambientale trebuiesc intotdeauna setate normalele suprafetelor ce vor fi iluminate.

Caracteristicile materialelor sunt urmatoarele:

• GL_AMBIENT reprezinta partea ambientala a luminii ce va fi

reflectate de obiect. Acest parametru se va amesteca cu

GL_AMBIENT al sursei de lumina. De remarcat ca este de

forma (r,g,b,alfa) insa alfa nu conteaza intrucat in momentul

cand se va face blending, se ia in considerare o singura

valoare alfa – aceea a lui GL_DIFFUSE

• GL_DIFFUSE reprezinta componenta difuza a culorii

materialului. E de forma (r,g,b,alfa)

• GL_AMBIENT_AND_DIFFUSE acest parametru este folosit

deoarece in lumea reala sunt extrem de rare(practic nu exista)

obiectele care sa aiba valori diferite al culorii relflexiei

ambientale si difuze

• GL_SPECULAR aceasta este valoarea culorii speculare,

oglindite de obiect. Acest parametru poate fi diferit, el

reprezinta valoarea reflectata. De exemplu, la un diamanat,

culoarea reflectata nu e acelasi lucru cu culoarea obiectului. O

piatra pretioasa poate reflecta si raze colorate cu alte culori.

• GL_SHININESS este o valoare care ne spune cat de mult

este focalizata raza speculara reflectata. Maximul este 128 si

corespunde unei lumini concentrate practic practic la

maximum intr-o singura raza.

• GL_EMISSION este o setare prin care putem da

incandescenta unui obiect. Dand acest parametru, obiectul va

aparea generand lumina prin el insusi fara sa o primeasca din

alta parte

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 17

8. Alte idei de care sa tinem cont

Matricea ModelView influenteaza pozitia luminii doar in momentul

cand a fost setat prima oara GL_POSITION. Prin urmare, daca

modificam pozitia observatorului sau pozitia unor obiecte si astfel

modificam ModelView, vom avea surpriza sa nu gasim lumina la

locul ei. Trebuie sa resetam valoarea GL_POSITION de fiecare data cand schimbam ModelView. Deasemenea, ModelView modifica si

valorile normalelor. De aceea e bine sa apelam si

glEnable(GL_NORMALIZE) pentru a fi siguri ca normalele sunt puse

corect (normalele se seteaza pentru fiecare varf folosind de exemplu

glNormal3f. Aceasta functie poate fi apelata intre glBegin si glEnd. Functioneaza asemanator cu glColor: varfurile definite dupa apel vor

avea asociata ultima normala setata cu glNormal).

Daca vrem sa iluminam doar anumite obiecte putem face asta

setand glEnable (GL_LIGHT0) doar inainte de a desena obiectul in

cauza.

OpenGL nu ne da nici un mecanism prin care sa facem reflexii de

lumini sau umbre. O raza reflectata nu mai devine sursa de lumina

pentru alte obiecte.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 18

OpenGL - Advanced

Liste de afisare

O lista de afisare reprezinta un grup de comenzi OpenGL stocate pentru o

executie ulterioara. La invocarea unei liste de afisaree ccomenzile din ea

sunt executate un ordinea in care sunt intalnite. Majoritatea comenzilor

OpenGL pot fi stocate intr-o lista de afisare. listele de afisare pot

imbunatati programul deoarece instructiunile sunt stocate pentru executii ulterioare. Este indicat sa se foloseasca liste de afisare in cazul in care se

redeseneaza de mai multe ori aceeasi figura geometrica sau daca trebuie

aplicat de mai multe ori un set de modificari de stare.

Listele de afisare au si dezavantaje. Listele foarte mici nu vor imbunatati

executia programului datorita overheadului executiei listei. Un alt

dezavantaj consta din faptul ca o lista de afisare nu poate fi modificata si

continutul sau nu poate fi citit.

Fiecare lista de afisare este identificata printr-un index intreg. La crearea

unei liste trebuie sa nu se aleaga un index deja folosit altfel se va sterge

lista de afisare corespunzatoare acelui indice. Pentru a evita acest lucru se

poate folosi :

W GLuint glGenLists(GLsize i range); Aceasta functie va genera unul sau mai

multi indici nefolositi. Functia aloca un domeniu de range numere nefolosite si

valoarea intoarsa reprezinta indicele de inceput al intervalului. Functia intoarce 0

daca nu este disponibil numarul de indici ceruti sau daca range este 0.

W void glNewList(GLuint list, GLenum mode);

• list : un intreg pozitiv diferit de 0 care identifica in mod unic lista de

afisare

• valorile posibile ale parametrului mode sunt :

o GL_COMPILE : nu se doreste executarea intructiunilor la plasarea in lista

o GL_COMPILE_AND_EXECUTE : se doreste executarea intructiunilor

la plasarea in lista

Functia specifica inceputul unei liste de afisare.Functiile care vor fi apelate (pana

la intalnirea functie glEndList() ) sunt stocate in lista de afisare.

W void glNewList(GLuint list, GLenum mode); Functia marcheaza sfarsitul unei

liste de afisare

W void glCallList(GLuint list); Functia executa lista de afisare specificata de

parametrul list. O lista de afisare poate fi executata de mai multe ori si de

asemenea se poate imbina cu apeluri in modul imediat.

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 19

Alpha Testing & Z-Buffer & Blending & Obiecte transparente

Testul alpha permite acceptarea sau respingerea desenarii unui fragment

in functie de valoarea alpha (opacitatea) asociata acelui fragment. Pentru

activarea acestui test se apeleaza :

W void glEnable(GL_ALPHA_TEST); Testul consta in compararea valorii de

opacitatea asociata fragmentului cu o valoare de referinta ref

W void glAlphaFunc(GLenum func, GLclampf ref); Functia de comparatie (func

poate fi una din constantele :

• GL_LESS • GL_LEQUAL

• GL_EQUAL • GL_NOTEQUAL

• GL_GEQUAL

• GL_GREATER • GL_NEVER

• GL_ALWAYS

Testul de adancime (z-buffer) este folosit pentru a determina daca o primitiva va

fi sau nu afisata in functie de "adancimea" sa. Pentru a fi folosit fereastra de

afisare trebuie sa aiba asociata un buffer de adancime. Astfel parametrul intreg

al functiei GLUT InitDisplayMode trebuie sa contina bitul GLUT_DEPTH pozitionat

pe valoarea 1 si pentru a activa testul trebuie folosit si apelul :

W glEnable(GL_DEPTH_TEST)

Functia de comparatie intre adancimea fragmentului si ce a valorii

corespunzatoare care a fost deja memorata in z-buffer poate fi specificata prin

apelul functiei :

W void glDepthFunc(GLenum func); Parametrul func are aceleasi valori posibile

ca in cazul functiei glAlphaFunc

Testul de combinare (blending) este specific modului RGBA de specificare a

culorilor scenei de vizualizat. In acest mode de afisare fiecarui fragment i se

asociaza o pondere de amestec a colorii sale.

Daca valoarea A este 0 sau lipseste atunci fiecare nou fragment va suprascrie

pixelul corespunzator din memoria video. Se poate deci considera ca valoarea A

reprezinta gradul de opacitate (sau de transparenta a unui fragment). Modul de

combinare a culorilor fragmentului nou care se deseneaza (si care va fi numit in

continuare sursa) si respectiv a pixelului corespunzator din memoria video

(numit in continuare destinatie) este specificat cu ajutorul functiei :

W void glBlendFunc(GLenum fsursa, GLenum fdest); Parametrii fsursa sifdest

sunt asociati celor 2 factori de amestec sursa si destinatie

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 20

Cei 2 factori de amestec au fiecare cate 4 componente care corespund

coeficientilor de amestec pentru fiecare culoare fundamentala si factorului de

opacitate. Fie (Sr,Sr,Sg,Sa) si (Dr,Dg,Db,Da) cei 2 factori de amestec. Notam cu

(Rs,Gs,Bs,As) respectiv (Rd,Gd,Bd,Ad) informatia de culoare asociata

fragmentului sursa respectiv destinatiei. In urma procesului de blending va

rezulta un pixel cu coeficientii RGBA :

(RsSr+RdDr,GsSg+GdDg,BsSb+BdDb,AsSa+AdDa)

Parametrii functiei (glBlendFunc pot fi :

• GL_ZERO -> corespunde unui factor de amestec (0,0,0,0)

• GL_ONE -> (1,1,1,1)

• GL_SRC_ALPHA -> (As,As,As,As) • GL_ONE_MINUS_SRC_ALPHA -> (1-As,1-As,1-As,1-As)

• GL_DST_ALPHA -> (Ad,Ad,Ad,Ad) • GL_ONE_MINUS_DST_ALPHA -> (1-Ad,1-Ad,1-Ad,1-Ad)

Spre exemplu pentru a afisa un desen rezultat prin compunerea in proportii egale

a doua imagini se pot genera pe rand cele doua imagini setand factorul destinatie

la GL_ONE si factorul sursa la valoarea GL_SRC_APLHA unde valoarea A asociata

fiecarui fragment este 0.5

Modul de lucru cu compunerea culorilo se ativeaza cu glEnable(GL_BLEND) si

dezactiveaza cu glDisable(GL_BLEND)

Vizualizarea obiectelor transparente se poate simula in modul urmator :

• se afiseaza scena acceptand numai fragmentele cu alpha egal cu 1 (perfect opace)

• se dezactiveaza scrierea in z-buffer

• se redeseneaza scena acceptand numai fragmente cu alpha mai mic decat 1 (transparente) si folosindu-se ca functie de amestecare

glBlendFunc(GL_SRC_APLHA,GL_DST_ALPHA)

Observatie : in mod normal pentru a fi redat corect fenomenul de transparenta

ar trebui ca si corpurile transparente sa fie afisate in ordinea adancimii lor

realizandu-de o sortare a acestora.

Picking(selectie)

OpenGL pune la dispozitie un mecanism de selectie a obiectelor in spatiul

3D. Pasii pentru a realiza aceasta operatie sunt urmatorii :

• 1. Preluarea coordonatelor de la mouse din interiorul ferestrei de afisare • 2. Intrarea in modul de selectie

• 3. Redefinirea volumului vizual in jurul cursorului mouselui

• 4. Randarea scenei • 5. Iesirea modului de selectie si identificarea primitivelor care au fost

desenate in volumul vizual redefinit

SISTEME DE PRELUCRARE GRAFICA Laborator 1

Pagina 21

• Pentru a identifica obiectele renderizate acestea trebuiesc sa fie numite.

API-ul OpenGL permite acest lucru numele asignate obiectelor regasindu-se intr-o stiva de nume Numele in realitate sunt reprezentate prin intregi.

Manipularea stivei de nume se realizeaza astfel :

o void glInitNames(void); creaza o stiva de nume goala o void glPushName(GLuint name); adauga in varful stivei pe name

o void glPopName(void); sterge un nume din varful stivei

o void glLoadName(GLuint name); inlocuieste varful stivei cu name

In mod normal atunci cand primitivele sunt randate pentru selectie ele sunt

desenate intre un glPushName(name) si glPopName() care identifica primitiva

sau grupul de primitive (de exemplu cele sase fete ale unui cub pot fi desenate

intre glPushName(CUB) ... glPopName() )

• In modul de selectie nici un obiect nu este de fapt randat in memoria video

(framebuffer). In schimb numele obiectelor (plus informatia de adancime) sunt colectate intr-un vector.

• In terminologia OpenGL un hit are loc de fiecare data cand o primitiva este

desenata in modul de selectie . Hit recordurile sunt stocate in bufferul de selectie

• Cand OpenGL iese din modul de selectie intoarce bufferul de selectie ce va

contine un set de hit records Avand in vedere ca pentru fiecare hit record

sunt disponibile si informatiile de adancime se poate determina usor care obiect a fost selectat chiar daca unul sau mai mult obiecte sunt suprapuse.

• Structura unui hit record este urmatoarea :

o primul camp reprezinta numarul de nume care le contine hit recordul (un obiect poate sa aiba mai multe nume)

o al doilea si al treilea camp reprezinta adancimea minima si cea

maxima asociata pt hit o o secventa de nume avand totalul corespunzator cu numarul

acestora din primul camp (poate sa si lipseasca daca primul camp

are valoarea 0)

• Inainte de intrarea in modul de selectie trebuie specificat bufferul de selectie astfel :

o void glSelectBuffer(GLsizei size, GLuint *buffer);

• Intrarea in modul de selectie se face astfel : o void glRenderMode(GL_SELECT);

• Intoarcerea in modul normal de randare se face astfel : o nhits glRenderMode(GL_RENDER);

Functia intoarce numarul de hit records ce au fost create si stocate in bufferul de

selectie in cadrul procesului de selectie