Chapitre 1 : Introduction - Programmation 3D - Master

Preview:

Citation preview

Chapitre 1 : Introduction - Programmation 3DMaster Informatique - UE Modélisation 3D

2021-2022

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 1 / 30

1 Objectifs de M3D

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 2 / 30

Fondations d’une application 3D

I Modélisation 3D : représentation et construction informatique des objets 3D (forme,position).

I Visualisation 3D : rendu projectif et par lancer de rayons, éclairage, texture.

I Interaction 3D : navigation/sélection/manipulation.

I Animation 3D : représentation et algorithme du mouvement.

I Programmation 3D : développement/réalisation.

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 3 / 30

Orientation du cours

I Approche "bas-niveau" du développement 3D pour acquérir les fondements :

• Eléments algébriques : coordonnées, repères, produit scalaire, ... (applicationinformatique)

• Représentations et algorithmes fondamentaux : modèles 3D, élimination partiescachées, ...

• Librairie de programmation 3D : OpenGL.

I Nous n’utiliserons pas d’outils "haut-niveau" :

• Pas d’infographie : 3D Studio Max, Blender, Maya, Rhino 3D, ...• Pas de Conception Assistée par Ordinateur (CAO) : SolidWorks, CATIA, ...• Pas d’utilisation de frameworks de développement 3D : Unity3D, jMonkeyEngine,

Ogre3D, Open SceneGraph, Unreal Engine,...

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 4 / 30

Environnement TPs

I C++17

I OpenGL (> 3.0)

I Qt (editeur de projets + framework pour C++)

I Basé sur des squelettes à compléter

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 5 / 30

2 Introduction à OpenGL

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 6 / 30

OpenGL

I tracer des triangles...

I API de rendu 3D dédiée aux cartes graphiques.

I librairies majeures sur desktop : OpenGL, Direct3D, Vulkan

I déclinaison sur mobile : OpenGL ES

I déclinaison pour le web : WebGL

I Spécifications définies par le consortium http ://www.khronos.org/

I Site officiel : http ://www.opengl.org/

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 7 / 30

Tutoriels OpenGL

I http ://ogldev.atspace.co.uk/

I http ://www.opengl-tutorial.org/

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 8 / 30

Mise en place

I Initialisation d’un contexte OpenGL par le serveur graphique (Windows, X11, etc).

I Opération très bas-niveau⇒• les frameworks GUI "usuels" (Qt, GTK+, wxWidgets, ...) proposent de gérer une

fenêtre/widget OpenGL.• ou passer par une librairie dédiée simple (exemple : freeGlut).

I ⇒ les squelettes des tps utilisent le framework Qt (ouverture de la fenêtre OpenGL, etc,assuré par les squelettes).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 9 / 30

Squelette des TP

I Mise en oeuvre usuelle (événementiel ; démarche similaire dans tous les frameworks) :

GLAppl icat ion : : GLAppl icat ion ( ) {/ / cons t ruc teu r => i n i t i a l i s a t i o n des données de l ’ a p p l i c a t i o n. . .

}

void GLAppl icat ion : : i n i t i a l i z e ( ) {/ / appelée 1 seule f o i s à l ’ i n i t i a l i s a t i o n du contexte OpenGL/ / => i n i t i a l i s a t i o n s concernant OpenGLg lC learCo lo r ( 1 , 1 , 1 , 1 ) ;/ / . . .

}

void GLAppl icat ion : : res i ze ( i n t width , i n t he igh t ) {/ / appelée à chaque dimensionnement du widget OpenGL/ / ( i n c l u s l ’ ouver ture de l a fenê t r e )/ / => r églages l i és à l a t a i l l e de l a fenê t r eg lV iewpor t (0 ,0 , width , he igh t ) ;/ / . . .

}

void GLAppl icat ion : : update ( ) {/ / appelée tou tes les 20ms (60Hz)/ / => met t re à j o u r les données de l ’ a p p l i c a t i o n/ / avant l ’ a f f i chage de l a prochaine image ( animat ion )/ / . . .

}

void GLAppl icat ion : : draw ( ) {/ / appelée après chaque update/ / => t r a c e r tou te l ’ imageg lC lea r (GL_COLOR_BUFFER_BIT ) ;/ / . . .

}

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 10 / 30

Premier exemple

I Se familiariser avec le vocabulaire technique de la prog3D

• Vertex Buffer Object (VBO)• Vertex Array Object (VAO)• Program Shader (Vertex Shader et Fragment Shader).• Commandes de tracé.

???======================⇒

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 11 / 30

Sommets des triangles

I On doit définir la position des 6 sommets des triangles (sommet = vertex en anglais).

I Les coordonnées (x,y,z) du volume de visualisation sont normalisées : NDC = NormalizedDevice Coordinates

• x (horizontal), y (vertical) et z (profondeur) sont comprises dans [−1,1]

GLAppl icat ion . h :−−−−−−−−−−−−−−−−class GLAppl icat ion {

. . .GLAppl icat ion ( ) ;. . .

private :s td : : vector < f loa t > pos i t ionData_ ;. . .

}

GLAppl icat ion . cpp :−−−−−−−−−−−−−−−−−−GLAppl icat ion : : GLAppl icat ion ( ) {

pos i t ionData_ ={−0.8 f , 0.0 f , −0.3 f , / / ve r tex 0 / / f i r s t t r i a n g l e

0.3 f , −0.7 f , −0.3 f , / / ve r tex 10.0 f , 0.9 f , −0.3 f , / / ve r tex 20.4 f , −0.5 f , 0.4 f , / / ve r tex 3 / / second t r i a n g l e0.9 f , 0.4 f , 0.4 f , / / ve r tex 40.8 f , −0.9 f , 0.4 f / / ve r tex 5

} ;}

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 12 / 30

Copie sur le serveur OpenGL

I Il faut copier les données de l’application (client) dans la mémoire OpenGL (serveur)

I ⇒ Manipulation des Vertex Buffer Objects (VBO) = zone mémoire OpenGL identifiée parun entier.

GLAppl icat ion . h :−−−−−−−−−−−−−−−−class GLAppl icat ion {

. . .GLAppl icat ion ( ) ;void in i tVBO ( ) ;. . .

private :s td : : vector < f loa t > pos i t ionData_ ;GLuint p o s i t i o n B u f f e r _ ; / / un i d e n t i f i a n t pour un VBO. . .

}

I Copie des données positionData_ dans le VBO positionBuffer_

GLAppl icat ion . cpp :−−−−−−−−−−−−−−−−−−void GLAppl icat ion : : in i tVBO ( ) {

g lGenBuffers (1 ,& p o s i t i o n B u f f e r _ ) ;g lB indBu f fe r (GL_ARRAY_BUFFER, p o s i t i o n B u f f e r _ ) ;g lBu f fe rDa ta (GL_ARRAY_BUFFER, pos i t ionData_ . s ize ( ) * s i z e o f ( f l o a t ) , pos i t ionData_ . data ( ) ,GL_STATIC_DRAW ) ;

}

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 13 / 30

VBO : Vertex Buffer Object

GLAppl icat ion . cpp :−−−−−−−−−−−−−−−−−−void GLAppl icat ion : : in i tVBO ( ) {

g lGenBuffers (1 ,& _ p o s i t i o n B u f f e r ) ;g lB indBu f fe r (GL_ARRAY_BUFFER, p o s i t i o n B u f f e r _ ) ;g lBu f fe rDa ta (GL_ARRAY_BUFFER, pos i t ionData_ . s ize ( ) * s i z e o f ( f l o a t ) , pos i t ionData_ . data ( ) ,GL_STATIC_DRAW ) ;

}

I glGenBuffers : génère un nouvel identifiant (c’est un entier) pour une zone mémoire OpenGL (unbuffer). L’identifiant positionBuffer_ est encore appelé handle ou référence.

I glBindBuffer : indique quel est le VBO courant actif. Après ce bind, toutes les instructions quiconcernent ARRAY_BUFFER concerneront le VBO positionBuffer_ (indirection).

I glBufferData : recopie les données clientes (contenues dans _positionData) dans le buffer OpenGLréférencé par ARRAY_BUFFER (ici l’identifiant positionBuffer_).

I Remarque 1 : si la valeur des données est dynamique (modifications de la position dessommets par exemple), on utilisera glSubBufferData pour mettre à jour les buffers(glBufferData réalloue la mémoire nécessaire à chaque appel).

I Remarque 2 : le contenu des VBO n’a aucune interprétation à priori (seulement unesuccession d’octets).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 14 / 30

Résumé copie dans VBO 1/4

I But : copier les données de positionData_ dans un VBO.

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 15 / 30

Résumé copie dans VBO 2/4

I 1) Récupérer un identifiant d’un buffer disponible parglGenBuffers(1,&positionBuffer_);

I (sur l’exemple on suppose que cela donne l’identifiant 52).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 16 / 30

Résumé copie dans VBO 3/4

I 2) Indiquer à OpenGL le buffer courant parglBindBuffer(GL_ARRAY_BUFFER,positionBuffer_);

I (affecte la variable interne OpenGL ARRAY_BUFFER à 52 sur cet exemple)

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 17 / 30

Résumé copie dans VBO 4/4

I 3) Faire la copie des données dans le buffer courant parglBufferData(GL_ARRAY_BUFFER,...,positionData_.data(),...);

I (ARRAY_BUFFER contient l’identifiant du buffer courant)

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 18 / 30

Commande de tracé

void GLAppl icat ion : : draw ( ) {g lC lea r (GL_COLOR_BUFFER_BIT ) ;

. . .glDrawArrays (GL_TRIANGLES, 0 , 6 ) ;. . .

}

I Tracer des triangles en prenant 6 sommets (0 = début = à partir du premier sommet).

I Il faut préciser avant glDrawArrays quelles sont les données des sommets à tracer (rôledes VAO) et comment les tracer (rôle des shaders).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 19 / 30

Pipeline OpenGL (principe)

I 1 Vertex Shader + 1 Fragment Shader (= Program Shader)

• Ce sont des programmes qu’il faut fournir à OpenGL (sources, compilation, linkage).• Langage : GLSL (GL Shading Language). Proche du C. Très orienté 3D (types

prédéfinis, fonctions).

I Etapes successives (= pipeline) lors du glDrawArrays :

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 20 / 30

Vertex Shader

I Exemple de vertex shader simple (exécuté pour chaque sommet) :

# vers ion 330

layou t ( l o c a t i o n =0) i n vec3 p o s i t i o n ; / / un a t t r i b u t correspondant à ( x , y , z )

void main ( ) {g l _ P o s i t i o n =vec4 ( pos i t i on , 1 . 0 ) ;

}

I attribut position = données d’entrées pour chaque sommet. location=0 identifieposition comme l’attribut numéro 0 (identifiant nécessaire pour l’alimentation del’attribut : cf plus loin avec les VAO)

I gl_Position = variable prédéfinie à affecter obligatoirement (objectif du vertex shader =affecter la position du sommet).

I vec4 = 4 coordonnées?? gl_Position est un vec4 (i.e. x,y,z et w) : coordonnéeshomogènes (décrites plus tard).

I Pour l’instant on fixe w = 1.0 ; les coordonnées (x ,y ,z) de gl_Position sont interprétéesen NDC (Normalized Device Coordinates).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 21 / 30

Fragment shader

I Exemple de fragment shader simple (exécuté pour chaque pixel affiché) :

# vers ion 330

out vec4 f ragCo lo r ; / / s o r t i e = données du p i x e l

void main ( ) {f ragCo lo r=vec4 ( 1 , 0 , 0 , 1 ) ; / / rouge , ver t , bleu , alpha

}

I obligatoire de donner au minimum une sortie (fragColor ici) qui sera la couleur du pixel.

I remarque : toutes les données associées à un pixel sont regroupées sous le nom defragment.

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 22 / 30

Shaders en OpenGL

Il faut :I Créer un identifiant pour un program shader : un program shader regroupera un vertex

shader et un fragment shader.

I Créer les identifiants pour le fragment et le vertex shader.

I Affecter les codes sources à ces identifiants.

I Compiler le fragment et le vertex shader.

I Linker le program shader.

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 23 / 30

Shaders en OpenGL

void GLAppl icat ion : : in i tProgramShader ( ) {s t r i n g vertexSource =

" # vers ion 330\n "" l ayou t ( l o c a t i o n =0) i n vec3 p o s i t i o n ; "" vo id main ( ) { "" g l _ P o s i t i o n =vec4 ( pos i t i on , 1 . 0 ) ; "" } " ;

s t r i n g fragmentSource =" # vers ion 330\n "" out vec4 f ragCo lo r ; "" vo id main ( ) { "" f ragCo lo r=vec4 ( 1 , 0 , 0 , 1 ) ; "" } " ;

program_=glCreateProgram ( ) ; / / membre GLuint _program ;

GLuint vertexShader=glCreateShader (GL_VERTEX_SHADER) ;GLuint fragmentShader=glCreateShader (GL_FRAGMENT_SHADER) ;glAt tachShader ( program_ , vertexShader ) ;g lAt tachShader ( program_ , fragmentShader ) ;

const char * source ;source=vertexSource . c_s t r ( ) ;glShaderSource ( vertexShader ,1 ,& source ,NULL ) ;source=fragmentSource . c_s t r ( ) ;glShaderSource ( fragmentShader ,1 ,& source ,NULL ) ;glCompileShader ( vertexShader ) ;glCompileShader ( fragmentShader ) ;

glLinkProgram ( program_ ) ;}

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 24 / 30

Tracé OpenGL

void GLAppl icat ion : : draw ( ) {/ / appelée après chaque update/ / => t r a c e r tou te l ’ image

g lC lea r (GL_COLOR_BUFFER_BIT ) ;

glUseProgram ( program_ ) ;. . .glDrawArrays (GL_TRIANGLES, 0 , 6 ) ;

glUseProgram ( 0 ) ;. . .

}

I On a indiqué avec quel programme shader il faut tracer les triangles.

I glUseProgram(0)?? précaution pour éviter tout effet de bord.

I Il reste encore à préciser les données des sommets, c’est-à-dire comment affecter lesattributs du vertex shader (i.e. sur cet exemple, indiquer où se trouvent les valeurs del’attribut position du vertex shader)⇒ rôle des VAO.

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 25 / 30

Vertex Array Objects (VAO)

I Le rôle d’un VAO est d’indiquer quelles seront les valeurs des attributs du vertex shader actif lors du tracé : il fait lelien entre les buffers (les VBO) et les attributs du vertex shader ("variables" in ).

I VAO = indiquer pour chaque attribut du Vertex Shader quel VBO sera utilisé.I Un même VAO peut être appliqué à différents shaders (et le même shader à différents VAO).I Comme la très grande majorité des "Objects" OpenGL, il faut : générer un identifiant de VAO, puis faire un bind pour

le rendre actif et travailler dessus :

void GLAppl icat ion : : in i tVAO ( ) {glGenVertexArrays (1 ,& vao_ ) ;g lB indVer texAr ray ( vao_ ) ; / / VAO courant

g lB indBu f fe r (GL_ARRAY_BUFFER, p o s i t i o n B u f f e r _ ) ; / / b u f f e r courant

g l V e r t e x A t t r i b P o i n t e r (0 ,3 ,GL_FLOAT,GL_FALSE, 0 , 0 ) ; / / a t t r i b u t numéro 0

g lEnab leVe r texA t t r i bA r ray ( 0 ) ;

g lB indVer texAr ray ( 0 ) ; / / par pré caut ion ( é v i t e e f f e t de bord sur VAO courant )}

I glVertexAttribPointer(0,...) : associe l’attribut numéro 0 du shader (cflayout(location=0) in vec3 position du vertex shader) au buffer courant (donc positionBuffer_ ici)

I ...,3,GL_FLOAT, ... : Il faut explicitement préciser à quoi correspond la succession d’octets du buffer pour unevaleur de l’attribut (ici 3 float pour correspondre au vec3 de l’attribut position du shader).

I ...,GL_FALSE,0,0) : paramètres précisés plus tard en TP.

I glEnableVertexAttribArray(0) : active l’affectation de l’attribut 0 (i.e. position) par le buffer (sans cela,l’attribut position du shader serait affecté avec une valeur constante).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 26 / 30

VAO/Vertex Shader

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 27 / 30

Tracé OpenGL

void GLAppl icat ion : : i n i t i a l i z e ( ) {/ / appelé 1 f o i sg lC learCo lo r ( 1 , 1 , 1 , 1 ) ;

in i tProgramShader ( ) ;in i tVBO ( ) ;in i tVAO ( ) ;

}

void GLAppl icat ion : : draw ( ) {/ / appelé 60 f o i s par secondeg lC lea r (GL_COLOR_BUFFER_BIT ) ;

glUseProgram ( program_ ) ;g lB indVer texAr ray ( vao_ ) ;glDrawArrays (GL_TRIANGLES, 0 , 6 ) ;glUseProgram ( 0 ) ;g lB indVer texAr ray ( 0 ) ;

}

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 28 / 30

Résumé

I Les données sont gérées par l’application indépendamment d’OpenGL (sur l’exemple letableau positionData_ des coordonnées des triangles).

I Généralement les données (i.e. les modèles) sont plus complexes qu’un simple tableau :une phase de copie/transformation dans un tableau est nécessaire pour pouvoir ensuitecopier les données dans les buffers OpenGL.

I Pour afficher les données :

• Initialiser les• Program Shader (inclut un Vertex Shader et un Fragment Shader) :

compiler/linker les shaders (souvent fait une fois pour toute à l’initialisation).• VBO : copier les données de l’application (positions, couleurs, etc des

sommets) dans des buffers OpenGL (peut être dynamique avec une mise à jourde ces buffers).

• VAO : indiquer quel VBO affectera chaque attribut des shaders (souvent fait unefois pour toute à l’initialisation).

• Tracer :• Activer un Program Shader (inclut un Vertex et un Fragment Shaders)• Activer un VAO (associe pour chaque attribut du Vertex Shader un VBO)• Faire un (ou plusieurs) glDraw (parcourt les VBO : 3 premiers sommets =

premier triangle ; 3 sommets suivans = second triangle ; etc).

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 29 / 30

Résumé

I "Lourd"?

• la démarche est systématique (démarche identique pour chaque VAO, VBO et aisé àabstraire ; 2 ou 3 shaders pour une application simple).

• beaucoup de framework allègent la gestion des shaders (lecture du code sourcedepuis des fichiers, puis compilation/link en une méthode), des VBO, et des VAO(avec le risque de réduire leur richesse/souplesse).

• comprendre l’intérêt : lors d’un glDrawArrays(GL_TRIANGLES,0,1500000)⇒ leCPU ne fait rien (tout est assuré par la carte graphique).

• souplesse de programmation des vertex/fragment shaders

https ://www.shadertoy.com/

fabrice.aubert@univ-lille.fr M3D/ 1 - Introduction - Programmation 3D 2021-2022 30 / 30

Recommended