Marco Tarini Università dell’Insubria
Facoltà di Scienze MFN di Varese Corso di Laurea in Informatica Anno Accademico 2012/13
Computer Graphics Lab
Note 1: OpenGL
Reminder: API
Scheda Grafica Driver Scheda grafica
API Applicazioni
Monitor Algoritmi
SDK ora vediamo
cosa c’è qui dentro
• Open Graphic Language
• Libreria C – Cross platform
– Qualche centinaio di routines
• www.opengl.org – specifiche
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Specifiche ver 4.1
(da luglio 2010)
(noi useremo sostanzialmente 2.0)Storia
• inizialmente sviluppato da Silicon Graphics
• dal 2002 al 2006:
OpenGL A AA A rchitecture R R R R eview BB B B oard
– mantiene e aggiorna le specifiche – industria 90%, accademia 10%
– ogni compagnia / gruppo, un voto
• dal 2006: Khronos Gruop
– come sopra
• ci sono anche le estensioni private – Soprattutto e
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
etc... etc... etc... etc...
: derivazioni
• OpenGL ES
– per device embedded – cur version: 2.0
•
– per web – javascript!
– HTML5
– soluz emergente per 3D sul Web
alternative
• Direct3D Direct3D Direct3D Direct3D
– Parte di DirectX
• Microsoft
– (proprietario, e non cross platform)– Stessi scopi di OpenGL
• un API per usare lo stesso hardware
• struttura non dissimile
– di solito, meno elegante, più macchinoso
• C (e C++)
– E’ l'alternativa più comune a OpenGL
• Grossomodo:
– Direct3D = industry standard
– OpenGL = academy standard
(ma la distinzione è molto sfumata)
sintassi
• Tutte le funzioni di Opengl si chiamano:
glSomeThing[xxx]
– “camel-case”
– dove xxx specifica numero e tipo dei parametri:
f: float i: intero s: short
(2 bytes)d: double b: byte
u*: unsigned [*] *v: vettore di [*] (puntatore)
– esempio:
glColor3f(float, float, float);
glColor3fv( float*);
– Perche? E' ANSI-C, non C++…
• no overloading di funzioni!
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
sintassi
• Tutte le costanti (macro) di Opengl:
GL_SOME_THING
- upper case (underscores per separare le parole)
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
sinassi
• Esempio:
glColor3b glColor3d glColor3f glColor3i glColor3s glColor3ub glColor3ui glColor3us glColor4b glColor4d glColor4f glColor4i glColor4s glColor4ub glColor4ui glColor4us glColor3bv glColor3dv glColor3fv glColor3iv glColor3sv glColor3ubv glColor3uiv glColor3usv glColor4bv glColor4dv glColor4fv glColor4iv glColor4sv glColor4ubv glColor4uiv glColor4usv
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
librerie amiche GLU
GLU GLU
GLU (GL utilites)
– insieme di funzioni di utility costruite sopra OpenGL,
(può far comodo)
– esempio: void gluLookAt(eyex,eyey,eyez, cx,cy,cz, upx, upy, upz);
– e funzioni per disegnare sfere, coni, … (e la Utha teapot :-)
(attraverso tri+quads)
– NB: da non confondersi con GLUT GLUT GLUT GLUT , che è il TTTToolkit di interfaccia con il SO
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
librerie amiche GLEW
GLEW GLEW
GLEW ( extension wrangler )
• si occupa delle estensioni 1.
2. prima di usare qualunque funz OpenGL:
(inizializza le funzioni estensione)
3. usare liberamente i comandi di OpenGL esteso es:
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
#include <GL/glew.h>
glewInit()
glUseProgram( 0 )
Alcuni comandi base:
• Cancellare lo screen 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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
glClearColor( r, g, b, a ); // ogni comp.: doubles // fra 0 e 1
glClear( GL_COLOR_BUFFER_BIT );
• Settare il viewport:
glViewport(int x, int y, int w, int h);
reminder: il rapporto fra w e h deve essere lo stesso specificato nella matrice di proiezione!
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Alcuni comandi base:
Specifica lo spazio schermo : - dove inizia (x,y), di solito 0,0 - quanto è largo e alto (w,h), (in pixels, all’interno del widget)
… è basato sullo stato
• Una state machine – ad esempio
• il clear color (colore di cancellamento)
• la posiz posizione luci
• matrici
fanno parte dello stato corrente
• Molti comandi OpenGL non fanno nulla di immediato – cambiano lo stato,
dunque il comportamento dei comandi successivi
• (queries sullo stato: glGet[tipo]( COSTANTE, valori_da_riempire ); )
• es:
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
double v[4];
glGetDoublev( GL_COLOR_CLEAR_VALUE, v );
Come si "sparano" i triangoli nel pipeline
glBegin (GL_TRIANGLES);
glVertex3d(x1,y1,z1);
glVertex3d(x2,y2,z2);
glVertex3d(x3,y3,z3);
glVertex3d(x4,y4,z4);
glVertex3d(x5,y5,z5);
glVertex3d(x6,y6,z6);
glVertex3d(x7,y7,z7);
glVertex3d(x8,y8,z8);
glVertex3d(x9,y9,z9);
...
glEnd();
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
primo triangolo
secondo triangolo
terzo triangolo
Come si "sparano" i triangoli nel pipeline
glVertex3d(x,y,z);
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
oppure glVertex3f(x,y,z);
oppure glVertex3i(x,y,z);
oppure glVertex2d(x,y);
oppure glVertex4d(x,y,z,w);
oppure glVertex4dv(vett);
oppure ...
coordinata z =0 sottointesa!
coordinata w=1 sottointesa!
Non solo glBegin (GL_TRIANGLES); linea finale quando
si fa la glEnd() Non solo glBegin (GL_TRIANGLES);
quanti triangoli rasterizzati
per quanti vertici proiettati ?
Le specifiche OpenGL non prescrivono quale
diagonale usare
(quindi dipende dall'implementazione
fra m m en ti
(candidati pixels)Reminder Reminder Reminder Reminder
Ve rti ce
(punto in R3)pixel finali
(nello screen-buffer)
Ve rti ce pr oi et ta to
(punto in R2)co m pu ta zi on i pe r v er tic e
rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to set- up
rasterizer segmenti set- up
rasterizer punti set- up
da l r es to de ll’a pp al m on ito r
Cosa avviene in queste fasi?
due opzioni…
a. Fixed Pipeline (deprecato nelle ultime vers)
b. Due programmi arbitrari
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Fixed Pipeline Fixed Pipeline Fixed Pipeline Fixed Pipeline:
in ciascuna delle due fasi…
• …avviene un certo numero di operazioni
operazioni operazioni
operazioni prefissate prefissate prefissate prefissate
• specifiche di quella fase
• possiamo solo:
– attivarle / disattivarle
• con comandi del tipo:
glEnable( GL_XXX ); glDisable( GL_XXX );
– cambiarne i parametri
• attivazione + parametri fanno parte dello stato
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Programmable shaders Programmable shaders Programmable shaders Programmable shaders:
in ciascuna delle due fasi…
• Si esegue un apposito programma scritto da noi – programmi detti “Shaders”
• “Vertex Vertex Vertex Vertex Shader Shader Shader”, “Fragment Shader Fragment Fragment Shader Fragment Shader Shader Shader”
1. Scrivere i due “shaders”
– in un apposito linguaggio: in OpenGL:
GLSL GLSL
GLSL GLSL (OpenGL Shading Language) 2. Compilarli (separatamente)
– NB: a tempo di esecuzione!
– tramite appositi comandi dell’API
• (che prendono in input i sorgenti sotto forma di stringhe)
3. “Linkarli” fra loro
– risultato del link: un “program”
4. Impostare il “program” risultante come programma corrente
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a in OpenGL…
un Program 1 Vertex-Shader = 1 Fragment-Shader +
linkati fra loro
Comandi 1/2 Comandi 1/2 Comandi 1/2 Comandi 1/2
1. Scrivere i due “shaders”:
2. Compilarli:
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a char * mioVertexShader= “ ... ”;
char * mioFragmentShader= “ ... ”;
int compilaShader(int type, const Glchar[]txt) {
GLuint shd= glCreateShader(type);
glShaderSource(shd, 1, &txt, 0);
glCompileShader(shd);
GLint tmp;
glGetShaderiv(shd,GL_COMPILE_STATUS,&tmp);
if (tmp == GL_FALSE) {
return -1; // ERRORI IN PROGRAMMA!!!
} return shd;
}
// e, per es, nel main:
int a= comiplaShader(
GL_VERTEX_SHADER, mioVertexShader );
int b= comiplaShader(
GL_FRAGMENT_SHADER, mioVertexShader );
...
crea un nuovo indice per uno shader setta la stringa come
sorgente compila lo shader testa se la comp è andata ok
Comandi 2/2 Comandi 2/2 Comandi 2/2 Comandi 2/2
3. “Linkarli” fra loro
4. Impostare il “program”
risultante come programma corrente
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a ...
int a= comiplaShader(
GL_VERTEX_SHADER, mioVertexShader );
int b= comiplaShader(
GL_FRAGMENT_SHADER, mioVertexShader );
GLuint progUno= glCreateProgram();
glAttachShader( progUno, a );
glAttachShader( progUno, b );
glLinkProgram( progUno );
...
glUseProgram( progUno );
su uso 0 come parametro, significa:
no shaders, usa la “FIXED PIPELINE”
… è basato sullo stato
• Stato comprende 2 matrici (e 2 stacks) – Model Model Model----View Model View View View
– Projection Projection Projection Projection
• Una di queste e’ sempre la matrice di lavoro – la matrice corrente
• I comandi che modificano matrici lavorano su questa matrice
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Matrici
• Nota: assume che siano memorizzate per colonne – detto anche in column major order
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
15 11 7 3
14 10 6 2
13 9 5 1
12 8 4 0
a a a a
a a a a
a a a a
a a a a
Matrici
• Per cambiare quale é la matrice di lavoro:
glMatrixMode(***);
GL_MODELVIEW GL_PROJECTION
• Per rimpiazzare la matrice di lavoro – glLoadIdentity();
– glLoadMatrixf( float* m );
• Tutti gli altri comandi modificano (moltiplicano per un altra matrice) la matrice corrente.
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Matrici
• Rotazioni
– glRotatef(angle,ax,ay,az);
• Traslazioni
– glTranslatef(dx,dy,dz);
• Scalature (non uniformi) – glScalef(ax,ay,az);
• Generica
– glMultMatrixf(float f*);
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
in gradi
asse di rotazione passante per l'origine
tutti i parametri: nello spazio CORRENTE!
Matrici
• Vista:
void gluLookAt(eyex,eyey,eyez, cx,cy,cz, upx, upy, upz);
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
centro dell’oggetto visto. La direzione
e' (c – eye)
spazio mondo!
• Operazione sullo Stack:
glPushMatrix() glPopMatrix()
Matrici
• Matrici di proiezione:
glOrtho2D (left, right, bottom, top);
void gluPerspective(
fovy, aspect, zNear, zFar);
Matrici di proiezione
field of view sulla Y (NB: in gradi)
spazio vista!
spazio vista!
Adattare la camera alla finestra:
proiezione ortografica
void myReshapeFunc(Glsizei w, Glsizei h) {
winSizeX= w;
winSizeY
= h;
}
void rendering() {
...
// set projection matrix & viewport...
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
float ratio=(float)
winSizeY /(float)winSizeX;glOrtho2D(-1,1,-ratio,ratio); // or: perspective glViewport (0, 0, (GLsizei) w, (GLsizei) h);
// set view matrix
glMatrixMode (GL_MODELVIEW);
...
// set model matrix
...
}
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 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a