Smoothing
Daniele Marini
1
Calcoli sui vettori
• Vettore normale
• equazione del piano: ax+by+cz+d=0; si può
anche scrivere come luogo:
n.(p  p0 )  0
e p è un qualunque punto nel piano; il vettore
n è dato da:
a
 
n  b
 
c 
a 
 
b 
e in coordinate omogenee : n   
c 

0 

2
In generale possiamo partire da tre punti non allineati:
p0, p1, p2 con i quali determiniamo il piano (superfici
approssimate con poliedri triangolarizzati).
Le differenze p2 - p0 e p1 - p0 sono coplanari e il loro
prodotto dà la normale:
n = (p2 - p0) x (p1 - p0)
L’ordine è rilevante
3
Per il calcolo di normali di superfici curve dipende da
come la superficie è rappresentata, ma in generale si
stima un gradiente.
Es. sfera - equazione
f(x,y,z): x2 + y2 + z2 -1=0
In forma vettoriale:
f(p): p.p -1 = 0
Il vettore gradiente è dato da:
f 
 
x  2x 
f   
n    2y 2p
y   
f  2z

z 

4
Se la sfera è rappresentata in forma parametrica il metodo
di calcolo cambia:
x  x(u,v)  cos(u)sin(v)
y  y(u,v)  cos(u)sin(v)
z  z(u,v)  sin(u)


con   u,v 
2
2
La normale si può ricavare dal piano tangente in p:
5
x 
 
u 
p y 
   ,
u u 
z 

u 

n
x 
 
v 
p y 
  
v v 
z 

v 

Individuano due vettori
tangenti il cui prodotto vettore
individua la normale - poiché ci
interessa solo la direzione si
può dividere per cos(u)
ottenendo un vettore unitario
p p

u v
cos(u)sin(v) 


n  cos(u)cos(u)cos(v)  cos(u)p


 sin(u) 
6
Quando calcolare le normali?
• L’architettura a pipe line dei sistemi di rendering
prevede che la normale di una faccia sia nota a
priori (viene elaborato un vertice per volta e non
tutta l’informazione è disponibile)
• in generale è compito del programma applicativo
calcolare la normale. OpenGL permette di
associare a ogni vertice una normale (che
dobbiamo calcolare noi nell’applicativo):
glNormal3f(nx,ny,nz);
glNormal3fv(pointer_to_normal);
7
Shading di poligoni
(flat shading)
• N, V ed L variano su ogni poligono
• se si assume osservatore “distante” e
sorgente di luce distante (in OGL si setta a falso il flag
near_viewer) V e L sono costanti
• anche N è quindi costante sull’intero
poligono
• Il calcolo di shading viene fatto per l’intero
poligono una sola volta
8
OGL e flat shading
glShadeModel(GL_FLAT);
La normale che OGL utilizza è quella associata al
primo vertice del poligono
Per i triangle strip OGL usa la normale del terzo
vertice per il primo triangolo, la normale del
quarto per il secondo e così via
Per altre primitive valgono regole simili (vedi
manuali)
9
Triangle strip
10
Flat vs Smooth
Smooth shading
Flat shading
11
Effetti di flat shading
Bande di mach
12
Smooth shading (interpolato)
• Interpolazione di Gouraud
glShadeModel(GL_SMOOTH)
• Interpolazione di Phong
13
Gouraud
Le normali ai vertici di un poliedro vengono interpolate:
n1  n2  n3  n4
n
n1  n2  n3  n4
Gouraud usa interpolazione bilineare per calcolare il colore
dei pixel lungo i singoli poligoni, quindi:
-prima calcola colore ai vertici
-poi interpola colore
14
Interpolazione bilineare
interpoliamo lungo una
linea di scansione
descriviamo i lati
in forma parametrica,
aè il parametro
C4 (a )  (1  a )C0  aC1
C5 (a )  (1  a )C2  aC3
C45 (a )  (1 a )C4  aC5
15
Dipende
dall’orientamento
16
Phong Smoothing
• Basato sull’interpolazione
delle normali
• il colore si calcola alla fine sul
singolo pixel
na  (1  a )nC  a nB
n(a ,  )  (1   )n C  n D
17
Gouraud vs. Phong shading
• hardware
• veloce
• continuo fino al I
ordine
• effetti lucentezza
limitati (migliorano se
si aumenta la
triangolazione)
• software
• lento
• continuo fino al II
ordine
• si può applicare
modello di Phong per
lucentezza
18
Sorgenti di luce in OGL
glLightfv(source, parameter, pointer_to_array)
glLightf(source, parameter, value)
I parametri sono:
Posizione (direzione) della sorgente
Livelli di
Ambiente
Diffusa
Speculare
Associati alla sorgente
19
GLFloat light0_pos[]={1.0, 2.0, 3.0, 1.0}
Se si pone quarta componente a 0 la sorgente è all’infinito e
definita come “direzione”
GLFloat light0_dir[]={1.0, 2.0, 3.0, 0.0}
Sorgente bianca con componenti di tutti e tre i tipi:
GLFloat diffuse0[]={1.0, 0.0, 0.0, 1.0}
GLFloat ambient0[]={1.0, 0.0, 0.0, 1.0}
GLFloat specular0[]={1.0, 0.0, 0.0, 1.0}
20
glEnable{GL_LIGHTING};
glEnable{GL_LIGHT0};
glLightfv(GL_LIGHT0,
glLightfv(GL_LIGHT0,
glLightfv(GL_LIGHT0,
glLightfv(GL_LIGHT0,
GL_POSITION, light0_pos);
GL_AMBIENT, ambient0);
GL_DIFFUSE, diffuse0);
GL_SPECULAR, specular0);
Se vogliamo comunque un contributo ambiente indipendente:
GLFloat global_ambient[]={0.1, 0.1, 0.1, 1.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,
global_ambient);
21
Se vogliamo inserire un termine di attenuazione
1
f (d) 
2
a  bd  cd
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, a);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, b);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, c);
Si può convertire la sorgente da puntiforme a spot, specificando:
direzione
GL_SPOT_DIRECTION
esponente
GL_SPOT_EXPONENT
angolo di soglia
GL_SPOT_CUTOFF
Si usa sempre la
glLightf o glLightfv
22
• OGL assume sempre l’osservatore a
distanza infinita, in modo da considerare
costante la direzione del viewer da ogni
punto della scena
• Per forzare l’osservatore a condizioni di
distanza non infinita si usa la:
glLightModel(GL_LIGHT_MODEL_LOCAL_VIEWER,
GL_TRUE)
23
• OGL non si preoccupa di fare shading delle
facce nascoste; se si desidera vedere facce
nascoste si può forzare con:
glLightModel(GL_LIGHT_MODEL_TWO_SIDED,GL_TRUE)
24
OGL e i materiali
glMaterialf(face, value)
glMaterialfv(face, type, pointer_to_array)
GLFloat diffuse1[]={1.0, 0.8, 0.0, 1.0}
GLFloat ambient1[]={0.2, 0.2, 0.2, 1.0}
GLFloat specular1[]={1.0, 1.0, 1.0, 1.0}
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
ambient1);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
diffuse1);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
specular1);
25
Con GL_FRONT e GL_BACK si specificano proprietà differente per le facce
frontali e nascoste
L’esponente nella componente speculare si specifica con:
GL_SHININESS
OGL permette di definire oggetti con componente emissiva:
GLFloat emission[]={0.0, 0.3, 0.3, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,
emission)
26
Scarica

Document