Computer Graphics
Marco Tarini
Università dell’Insubria Corso di Laurea in Informatica Anno Accademico 2014/15
Lezione 12: occlusioni e test per frammento
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Rimozioni delle superfici nascoste
• Gli oggetti più vicini devono coprire quelli più lontani
– gli oggetti lontani sono "occlusi"
da quelli più vicini
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Rimozioni delle superfici nascoste
• Back-face culling non basta
– esempio:
superfici non back-facing, non totalmente occluse ma parzialemnte occluse
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Rimozioni delle superfici nascoste
• Soluzione 1:
– dividere ogni triangolo parzialmente occluso
in parte visibile e parte occlusa?
• facendo una operazione di clipping Come si trovano le coppie occluso/occlusore?
Clipping di un triangolo e un altro?
E dove, nel pipeline HW?
SOLUZIONE IMPROPONIBILE
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Rimozioni delle superfici nascoste
• Soluzione 2:
– disegnare solo poligoni interi, ma nell' ordine giusto
• (back-to-front)
– noto come "algoritmo del pittore"
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
• Data una scena (composta da primitive)
– ordinare le primitive per profondità
• (cioe’ in ordine di z… in spazio vista!) – mandarle tutte (in ordine)
Sorting!
Complessità pesudolineare (n log(n)) col numero di primitive.
in comp graph, peggio di lineare vuol
dire MALE
Una primitiva non ha una sola profondità!
piuttosto ha una profondità max e una min
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
Fr am m en ti & at tri bu ti in te rp ol at i Ve rti ci & lo ro a ttr ib ut i
Screen buffer Ve rti ci p or ie tta ti & at tri bu ti co m pu ta ti
rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to rasterizer
segmenti rasterizer punti
co m pu ta zi on i pe r v er tic e
DOVE?
x y
z
v
0v
1v
2v
0v
1v
2prima di mandare i triangoli.
Fatto dalla CPU !
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
• Ma va prima C o D?
• Ma poi, esiste sempre
un "ordine giusto"? P ro fo
n d it à
z
minPrimitive B
z
maxA
E D
C
• La primitiva A può essere
disegnata per prima
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
• La primitiva A può essere disegnata per prima
• Ma va prima C o D?
• Ma poi, esiste sempre un "ordine giusto"?
– NO:
• intersezioni – NO:
• cicli di sovrapposizioni
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
• Oneroso
– sorting: (n log (n)) – e nella parte software!
• Mal adattato allo schema HW – deve lavorare in spazio occhio
...ma prima della proiezione HW ?!
– lavorare globalmente su tutta la scena prima di mandare la prima primitiva
• Scomodo all'atto pratico
– le primitive sono già "ordinate" semanticamente (scene-graph)
• Test difficili
– in alcuni casi (quando gli intervalli min z e max z non sono disgiunti)
• Bisogna comunque fare clipping – in altri casi (intersezione, cicli)
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo del pittore (depth sorting)
• usabile sse è
facile ordinare preventivamente le primitive
– in fase di preprocessing
• Esempio: terreno come campo di altezza
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Rimozioni delle superfici nascoste
• Soluzione 3:
– rimuovere le superfici nascoste con un TEST PER FRAMMENTO
– algoritmo dello "Z-buffer"
• o "Depth-buffer"
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer
Fr am m en ti & at tri bu ti in te rp ol at i
Ve rti ci & lo ro a ttr ib ut i Screen
buffer Ve rti ci & at tri bu ti co m pu ta ti
rasterizer triangoli set- up
rasterizer segmenti set- up
rasterizer punti set- up
co m pu ta zi on i pe r v er tic e
Depth buffer
co m pu ta zi on i pe r f ra m m en to
profondità di ogni pixel
RGB finale per ogni pixel
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer
Fr am m en ti & at tri bu ti in te rp ol at i
Ve rti ci & lo ro a ttr ib ut i Screen
buffer Ve rti ci & at tri bu ti co m pu ta ti
rasterizer triangoli set- up
rasterizer segmenti set- up
rasterizer punti set- up
co m pu ta zi on i pe r v er tic e
Depth buffer
co m pu ta zi on i pe r f ra m m en to
Transform.
Metti la z finale come
attributo aggiuntivo
Interpola (come tutti la z gli attributi)
per un frammento con
screen coordinates (x,y), colore (r,g,b) e profondità z:
if ( z <= DepthBuffer[x,y] ) {
ScreenBuffer[x,y] = (r , g , b) ; DepthBuffer[x,y] = z ; } else scarta (“discard”, “kill”) frammento
depth test
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer
Fr am m en ti & at tri bu ti in te rp ol at i
Ve rti ci & lo ro a ttr ib ut i Screen
buffer Ve rti ci & at tri bu ti co m pu ta ti
rasterizer triangoli set- up
rasterizer segmenti set- up
rasterizer punti set- up
co m pu ta zi on i pe r v er tic e
Depth buffer
co m pu ta zi on i pe r f ra m m en to
ho bisogno di precisione!
floats di almeno 16 o 24 bits
Rappresentazione reali in virgola fissa
• Rarppresento i numeri reali in un intervallo predefinito (es: da 0 a 1) come interi
• Es: se ho 32 bit, allora,
memorizzo l’intero X (da 0 a 2^32-1) per rappresentare il reale X / (2^32-1)
• Rispetto alla virgola mobile:
– intervallo limitato
– niente esponente! solo mantissa
– distribuzione uniforme dei valori rappresentabili
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer:
esempio
(con depth buffer ipotetico di interi a 6 bit: valori da 0 a 63) 63 63 63 63 63 63 63 6363 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
5 5
5
5 5 5 5 5 5 5 63 5 5 5 5 5 5 63 63 5 5 5 5 5 63 63 63 5 5 5 5 63 63 63 63 5 5 5 63 63 63 63 63 5 5 63 63 63 63 63 63 5 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
+ =
5 5 5 5 5 5 5 63 5 5 5 5 5 5 63 63 5 5 5 5 5 63 63 63 5 5 5 5 63 63 63 63 5 5 5 63 63 63 63 63 5 5 63 63 63 63 63 63 5 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
7
2 7
5 5 5 5 5 5 5 63 5 5 5 5 5 5 63 63 5 5 5 5 5 63 63 63 5 5 5 5 63 63 63 63 4 5 5 7 63 63 63 63 3 4 5 6 7 63 63 63 2 3 4 5 6 7 63 63 63 63 63 63 63 63 63 63
+ =
5 5
5 5
5 5
5 5
5 5
5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
7 6 7
5 7
4 7
3 7
2 7
7 6 7 5 6 7 4 5 6 7 3 4 5 6 7 2 3 4 5 6 7
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer:
proprietà
• il rendering diventa “order independent” ☺!!!
• Funziona su tutto ☺ – anche su:
• Operazione per frammento – Viene svolto durante
"computazioni per frammento"
• Adatto all'implementazione HW ☺
5 5 5 5 5 5 5 63 5 5 5 5 5 5 63 63 5 5 5 5 5 63 63 63 5 5 5 5 63 63 63 63 4 5 5 7 63 63 63 63 3 4 5 6 7 63 63 63 2 3 4 5 6 7 63 63 63 63 63 63 63 63 63 63
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Algoritmo dello z-buffer:
issues
• Costa un po’ di memoria (GPU)
– spesso: sizeof( depth buffer ) = sizeof(screen buffer ) / 2
• Problemi di aliasing sulla z
– causa problema detto: “z-fighting”
– avviene quando la precisione non è sufficiente
es., se si renderizzano due superfici parallele molto vicine
• Assume superfici del tutto opache
– problemi con le superfici semitrasparenti (come vedremo…)
• Dati condivisi in lettura e scrittura
– complicazione per chi implementa HW
– efficienza ameno in parte impattata (ma test molto ottimizzato) – è un test HardWired in GPU
Z-figthing
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Z-figthing
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Depth test, in OpenGL
• Devo abilitare il depth test:
glEnable(GL_DEPTH_TEST);
primitivequipixels tutto il pipeline
(proiezione, setup, rasterizzazione...) stato di OpenGL manipolazioni di stato (es. settare la matrice)
Posso anche decidere le condizioni per passare il test:
glDepthFunc( GL_LESS ) GL_NEVER
GL_EQUAL GL_LEQUAL GL_GREATER GL_NOTEQUAL GL_LESS GL_GEQUAL GL_ALWAYS
(dafault)
• Depth test: viene eseguito automaticamente alla fine del nostro fragment shader
– (se abilitato)
– motivo: è un op. critica, read/write su dati condiviso – motivo: HW deve poter fare le sue ottimizzazioni
• (es depth buffer gerarchico)
==> il fragment shader
dovrà determinare in output:
– un valore RGB, – un valore di depth
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Depth test, in OpenGL Depth test, in OpenGL
• Il rasterizzatore produce un valore di depth di default
– per ogni frammento prodotto
– interpolando la Z dei vertici proiettati in input
• Possiamo sovrascrivere questo valore se vogliamo nel fragment shader
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
// fragment shader void main() {
...
gl_FragColor = ... // un vec4 gl_FragDepth = ... // un float }
assegnamento opzionale.
(ha un costo grande
farlo! depth test
va rimandato e alcune
ottimizzazioni HW
disabilitate
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Depth test, in OpenGL
• Quando si cancella lo schermo, cancellare il depth buffer
...
glClear(
GL_COLOR_BUFFER_BIT );
...
| GL_DEPTH_BUFFER_BIT
Altri per-fragment tests Tests automtici:
discard a fragment or pass it to the next step?
• Scissor test
discards fragments falling outside a scissor rectangle , used to specify rectangles inside the viewport
• Stencil buffer
is used as a mask to discard fragments
• Depth test , uses the z-buffer to discard fragments that are not visible
screento
RGBa + Depth Stencil +
Il pipeline: da più vicino
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 4 / 1 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a