13.07.2015 Views

Chapitre 5 : Rendu projectif en OpenGL Vertex et Fragment ... - FIL

Chapitre 5 : Rendu projectif en OpenGL Vertex et Fragment ... - FIL

Chapitre 5 : Rendu projectif en OpenGL Vertex et Fragment ... - FIL

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Chapitre</strong> 5 : <strong>R<strong>en</strong>du</strong> <strong>projectif</strong> <strong>en</strong> Op<strong>en</strong>GL<strong>Vertex</strong> <strong>et</strong> Fragm<strong>en</strong>t shadersModélisation 3D <strong>et</strong> SynthèseFabrice Aubertfabrice.aubert@lifl.frIEEA - Master Info - Parcours IVI2012-2013F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 1 / 58


Tracer les données des array buffers (Op<strong>en</strong>GL 2.1)◮ Op<strong>en</strong>GL 2.1 ? Pourquoi ?void Square : : drawBuffer ( ) {/ / a c t i v e r l ’ a l i m e n t a t i o n de l ’ a t t r i b u t gl_<strong>Vertex</strong> pour chaque somm<strong>et</strong> t r a c ég l E n a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;}/ / l e b u f f e r courant des données :g l B i n d B u f f e r (GL_ARRAY_BUFFER, b u f f e r V e r t e x ) ;/ / l e s a t t r i b u t s gl_<strong>Vertex</strong> seront l u s depuis l e b u f f e r b u f f e r V e r t e x ( i . e . l e b u f f e r courant ) :g l V e r t e x P o i n t e r ( 3 ,GL_FLOAT, 0 , 0 ) ;/ / commande de t r a c é ( exé c u t i o n du p i p e l i n e de t r a c é ) avec 4 somm<strong>et</strong>s :glDrawArrays (GL_TRIANGLE_STRIP , 0 , 4 ) ;g l D i s a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 6 / 58


Gestion mémoire◮ Toujours se rappeler qu’Op<strong>en</strong>GL "travaille" avec les valeurs courants des états(glBindBuffer(...) indique par exemple le buffer courant actif).◮ Ne pas oublier de gérer correctem<strong>en</strong>t la mémoire si besoin (cf tous les glDel<strong>et</strong>e(...),par exemple glDel<strong>et</strong>eBuffers).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 7 / 58


Pipeline de tracé⇒ tout somm<strong>et</strong> provoque l’exécution d’un programme appelé <strong>Vertex</strong> Shader.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 8 / 58


<strong>Vertex</strong> Shader◮ Chaque somm<strong>et</strong> subit le vertex shader.◮ = programme exécuté (par la carte graphique si possible).◮ = programme écrit dans un langage particulier : GLSL (Op<strong>en</strong>GL Shading Language).◮ Op<strong>en</strong>GL perm<strong>et</strong> de compiler/linker <strong>et</strong> activer des programmes GLSL# version 110void main ( ) {g l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ;}◮ ⇒ langage inspiré de C/C++◮ Tous les états sont accessibles par des "variables" id<strong>en</strong>tifiées par gl_.• gl_<strong>Vertex</strong> : de type vec4 correspond aux coordonnées (x,y,z,w) (fourni par lesdonnées lues dans le ARRAY_BUFFER).• gl_ModelViewMatrix : de type mat4 correspond à la valeur de la MODELVIEW.• gl_Projection : de type mat4 correspond à la valeur de la matrice PROJECTION.◮ Le vertex shader doit fournir obligatoirem<strong>en</strong>t gl_Position à la suite du pipeline.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 9 / 58


GLSL◮ Tout le langage GLSL est résumé sur les 4 dernières pages dehttp://www.khronos.org/files/op<strong>en</strong>gl-quick-refer<strong>en</strong>ce-card.pdfF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 10 / 58


Rasterization⇒ tout pixel qui est tracé provoque l’exécution d’un programme appelé Fragm<strong>en</strong>t Shader.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 11 / 58


Fragm<strong>en</strong>t shader◮ Même langage que vertex shader : GLSL◮ Doit fournir une couleur pour le pixel qui est <strong>en</strong> train d’être tracé (affecter gl_FragColorde type vec4).Exemple de base (listing du fichier essai.frag) :# version 110void main ( ) {/ / a f f e c t a t i o n avec du v e r t ( i . e . vec4 i n t e r p r é t é comme ( rouge , vert , bleu , alpha ) ) .gl_FragColor=vec4 ( 0 . 0 , 1 . 0 , 0 . 0 , 0 . 0 ) ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 12 / 58


Compilation <strong>et</strong> activation d’un shader◮ Compilation/link par l’application Op<strong>en</strong>GL :void create ( ) {programId=glCreateProgram ( ) ;v e r t e x I d =glCreateShader (GL_VERTEX_SHADER ) ;fragm<strong>en</strong>tId=glCreateShader (GL_FRAGMENT_SHADER) ;glAttachShader ( programId , v e r t e x I d ) ;glAttachShader ( programId , fragm<strong>en</strong>tId ) ;char ∗source= r e a d F i l e ( " essai . v e r t " ) ;glShaderSource ( v ertexId ,1 ,& source , NULL ) ;char ∗source= r e a d F i l e ( " essai . f r a g " ) ;glShaderSource ( fragm<strong>en</strong>tId ,1 ,& source , NULL ) ;glCompileShader ( v e r t e x I d ) ;glCompileShader ( fragm<strong>en</strong>tId ) ;glLinkProgram ( programId ) ;}◮ Utilisation (activation pour tous les tracés effectués par draw() par exemple) :void drawSc<strong>en</strong>e ( ) {. . .glUseProgram ( programId ) ;draw ( ) ;. . .}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 13 / 58


ResultatF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 14 / 58


Interpolation de variables : varying◮ Le vertex shader peut calculer des valeurs qui seront fournies à la suite du pipeline(variables <strong>en</strong> sortie).◮ Le fragm<strong>en</strong>t shader peut récupérer ces variables dont les valeurs ont subi une interpolationbilinéaire par rapport aux valeurs de chacun des somm<strong>et</strong>s (variables <strong>en</strong> <strong>en</strong>trée).◮ Ces variables, qui apparaiss<strong>en</strong>t avec le même nom dans le vertex <strong>et</strong> le fragm<strong>en</strong>t, sontqualifiées de varying.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 15 / 58


Exemple : interpolation des couleurs<strong>Vertex</strong> Shader :# version 110varying vec4 couleur ;void main ( ) {couleur=gl_Color ; / / gl_Color est alim<strong>en</strong>t é par l e b u f f e r d ’ a t t r i b u t GL_COLOR_ARRAYg l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ;}Fragm<strong>en</strong>t Shader :# version 110varying vec4 couleur ;void main ( ) {gl_FragColor=couleur ;}Tracé Op<strong>en</strong>GL :g l E n a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, b u f f e r V e r t e x ) ;g l V e r t e x P o i n t e r ( 3 ,GL_FLOAT, 0 , 0 ) ;g l E n a b l e C l i e n t S t a t e (GL_COLOR_ARRAY ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, b u f f e r C o l o r ) ;g l C o l o r P o i n t e r ( 3 ,GL_FLOAT, 0 , 0 ) ;glDrawArrays (GL_TRIANGLE, 0 , 3 ) ;F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 16 / 58


Tracé de faces avec indicesf l o a t cube[]={−1,−1,−1, / / <strong>Vertex</strong> 0−1,1,−1, / / <strong>Vertex</strong> 11,−1,−1, / / <strong>Vertex</strong> 21 ,1 , −1 , / / <strong>Vertex</strong> 3−1,−1,1, / / <strong>Vertex</strong> 4−1 ,1 ,1 , / / <strong>Vertex</strong> 51 , −1 ,1 , / / <strong>Vertex</strong> 61 ,1 ,1 , / / <strong>Vertex</strong> 7} ;unsigned i n t i n d i c e [ ] = { 0 , 1 , 2 , 3 , 6 , 7 , 4 , 5 , 0 , 1 ,5 ,7 ,1 ,3 , / / " couvercle dessus "6 , 4 , 2 , 0 } ; / / " couvercle dessous "F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 17 / 58


Exemple du cube : initialisation buffersGLuint vertexCube , indiceCube ;void i n i t B u f f e r C u b e ( ) {f l o a t cube[]={−1 ,−1 ,−1 ,−1 ,1 ,−1 ,1 ,−1 ,−1 ,1 ,1 ,−1 ,−1 ,−1 ,1 ,−1 ,1 ,1 ,1 ,−1 ,1 ,1 ,1 ,1};}unsigned i n t i n d i c e [ ] = { 0 , 1 , 2 , 3 , 6 , 7 , 4 , 5 , 0 , 1 ,5 ,7 ,1 ,3 ,6 , 4 , 2 , 0 } ;glG<strong>en</strong>Buffers (1 ,& vertexCube ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, vertexCube ) ;g l B u f f e r D a t a (GL_ARRAY_BUFFER,24∗ s i z e o f ( GLfloat ) , cube ,GL_STATIC_DRAW ) ;glG<strong>en</strong>Buffers (1 ,& indiceCube ) ;g l B i n d B u f f e r (GL_ELEMENT_ARRAY_BUFFER, indiceCube ) ;g l B u f f e r D a t a (GL_ELEMENT_ARRAY_BUFFER,18∗ s i z e o f ( GLuint ) , indice ,GL_STATIC_DRAW ) ;F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 18 / 58


Exemple du cube : tracég l E n a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, vertexCube ) ;g l V e r t e x P o i n t e r ( 3 ,GL_FLOAT, 0 , 0 ) ;g l B i n d B u f f e r (GL_ELEMENT_ARRAY_BUFFER, indiceCube ) ;/ / s t y l e de p r i m i t i v e s , nombre de somm<strong>et</strong>s , type des indices , début de l e c t u r e dans l e s i n d i c e s ( <strong>en</strong> u n i t machine )glDrawElem<strong>en</strong>ts (GL_TRIANGLE_STRIP,10 ,GL_UNSIGNED_INT , ( void ∗)( s i z e o f ( GLuint )∗0));glDrawElem<strong>en</strong>ts (GL_TRIANGLE_STRIP, 4 ,GL_UNSIGNED_INT , ( void ∗)( s i z e o f ( GLuint )∗10));glDrawElem<strong>en</strong>ts (GL_TRIANGLE_STRIP, 4 ,GL_UNSIGNED_INT , ( void ∗)( s i z e o f ( GLuint )∗14));g l D i s a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 19 / 58


GL TRIANGLESPour le cube, le GL_TRIANGLE_STRIP n’est pas nécessairem<strong>en</strong>t bi<strong>en</strong> adapté.◮ On peut égalem<strong>en</strong>t spécifier tous les triangles dans le tableau d’indices.◮ Puis tracer avec un seulglDrawElem<strong>en</strong>ts(GL_TRIANGLES,??,GL_UNSIGNED_INT,(void *)0).Exercice : combi<strong>en</strong> de triangles à tracer ? quel est alors le tableau d’indices (indiquez le débutpour les 3 premiers triangles) ?F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 20 / 58


2 Eclairem<strong>en</strong>tF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 21 / 58


Réalisme◮ Pour ajouter du réalisme aux scènes 3D, Op<strong>en</strong>GL propose de calculer des couleurs poursimuler un éclairem<strong>en</strong>t de la scène par des sources lumineuses.⇒ calcul de la couleur prov<strong>en</strong>ant de 2 contributions : réflexion diffuse (couleur mat) <strong>et</strong> réflexionspéculaire (couleur brillante : tâche spéculaire).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 22 / 58


DonnéesLes données nécessaires au calcul d’éclairem<strong>en</strong>t sont :◮ Les sources (position, caractéristiques d’éclairem<strong>en</strong>t).◮ Le matériel des obj<strong>et</strong>s (caractéristiques qui traduis<strong>en</strong>t comm<strong>en</strong>t est réfléchie la lumière dessources).◮ On peut avoir jusqu’à 8 sources simultanées <strong>en</strong> Op<strong>en</strong>GL. Elles sont id<strong>en</strong>tifiées par lesconstantes GL_LIGHT0, GL_LIGHT1, ..., GL_LIGHT7.◮ L’instruction qui perm<strong>et</strong> de donner les caractéristiques des sources : glLight.◮ Il existe deux seuls matériels (un pour les faces FRONT <strong>et</strong> un pour les BACK). Il faut doncchanger les caractéristiques dès qu’on veut tracer un obj<strong>et</strong> avec un matériel différ<strong>en</strong>t del’obj<strong>et</strong> précédemm<strong>en</strong>t tracé.◮ L’instruction qui perm<strong>et</strong> de donner les caractéristiques des matériels : glMaterial.◮ Les composantes (rouge, vert, bleu) qui apparaiss<strong>en</strong>t dans la suite sont comprises <strong>en</strong>tre 0<strong>et</strong> 1.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 23 / 58


Modèle d’éclairem<strong>en</strong>t◮ Dans ce chapitre, pour illustrer l’éclairem<strong>en</strong>t on choisit le modèle empirique de Phong.◮ Très simple, mais aussi très éloigné de la réalité.◮ Le vecteur V est appelé vecteur d’observation, le vecteur L est appelé vecteurd’éclairem<strong>en</strong>t.◮ La position de la source 0 est donnée parglLightfv(GL_LIGHT0,GL_POSITION,) où pos=(x,y,z,w).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 24 / 58


Réflexion diffuse 1/2◮ On suppose qu’un obj<strong>et</strong> (un matériel) diffuse la lumière reçue de manière uniforme danstoutes les directions.◮ La lumière (i.e. la couleur) perçue ne dép<strong>en</strong>d donc pas de la position de l’observateur.◮ L’int<strong>en</strong>sité diffusée dép<strong>en</strong>d des caractéristiques du matériel (matériel rouge =« beaucoup »de rouge diffusé, matériel noir = aucune int<strong>en</strong>sité diffusée, <strong>et</strong>c).◮ ⇒ Définition d’un coeffici<strong>en</strong>t de matériel k d = (rouge,vert,bleu) pour définir c<strong>et</strong>tecaractéristique (toujours ∈ [0,1]).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 25 / 58


Réflexion diffuse 2/2◮ L’int<strong>en</strong>sité diffusée dép<strong>en</strong>d de l’angle d’incid<strong>en</strong>ce des rayons lumineux sur la surface del’obj<strong>et</strong>• un éclairem<strong>en</strong>t direct (i.e. la lumière arrive orthogonalem<strong>en</strong>t à la surface) donne unediffusion maximale.• un éclairem<strong>en</strong>t fuyant (i.e tang<strong>en</strong>t à la surface) donne un éclairem<strong>en</strong>t nul.• on souhaite que la diffusion varie « continuem<strong>en</strong>t »<strong>en</strong>tre ces 2 positions de la manièrela plus réaliste possible.• ⇒ prise <strong>en</strong> compte de la normale (i.e. vecteur orthogonal) à la surface au point P.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 26 / 58


Calcul du diffus◮ On suppose N <strong>et</strong> L sont normés (‖N‖ = ‖L‖ = 1).◮ Le calcul de l’int<strong>en</strong>sité du diffus par cos(N,L) = L · N est un « bon »choix.◮ On donnera une couleur de réflexion diffuse K d pour indiquer la couleur réfléchie par lematériel.⇒ Couleur diffus (P) = K d (N · L)◮ seul le « coté »dirigé par la normale est éclairé (si N · L < 0 alors éclairem<strong>en</strong>t nul).◮ ⇒ important de spécifier correctem<strong>en</strong>t les normales.◮ Composante Kd=(rouge,vert,bleu) couleur souhaitée pour le matériel.◮glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,);F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 27 / 58


Calcul aux somm<strong>et</strong>s◮ En Op<strong>en</strong>GL, on se cont<strong>en</strong>te souv<strong>en</strong>t de calculer l’éclairem<strong>en</strong>t diffus uniquem<strong>en</strong>t auxsomm<strong>et</strong>s.◮ ⇒ obt<strong>en</strong>tion d’une couleur <strong>en</strong> chaque somm<strong>et</strong>.◮ La couleur des pixels lors de la rasterization est alors simplem<strong>en</strong>t obt<strong>en</strong>ue par interpolationlinéaire des couleurs.◮ Le résultat est satisfaisant par rapport à un calcul sur chacun des points du triangle 3D(bi<strong>en</strong> que ce calcul d’éclairem<strong>en</strong>t diffus ne soit pas linéaire sur l’espace écran ! ⇒approximation conv<strong>en</strong>able).⇒ l’interpolation linéaire des couleurs, dans le cadre de l’éclairem<strong>en</strong>t est appelée interpolationde Gouraud.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 28 / 58


Normales 1/3◮ Pour le calcul d’éclairem<strong>en</strong>t il faut spécifier les normales.◮ Si le calcul s’effectue <strong>en</strong> chaque somm<strong>et</strong>, il faut fournir à chaque somm<strong>et</strong> une normale.g l E n a b l e C l i e n t S t a t e (GL_VERTEX_ARRAY ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, v e r t e x B u f f e r ) ;g l V e r t e x P o i n t e r ( 3 ,GL_FLOAT, 0 , 0 ) ;g l E n a b l e C l i e n t S t a t e (GL_NORMAL_ARRAY) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, normalBuffer ) ; / / a t t r i b u é auparavantglNormalPointer (GL_FLOAT, 0 , 0 ) ;glDrawArrays (GL_TRIANGLES , . . . ) ;◮ Fournir le vecteur orthogonal au polygone tracé ? ⇒ pas nécessairem<strong>en</strong>t ! (liberté totale dedonner la normale qu’on souhaite).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 29 / 58


Normales 2/3◮ Pouvoir spécifier une normale différ<strong>en</strong>te <strong>en</strong> chaque somm<strong>et</strong> perm<strong>et</strong> d’obt<strong>en</strong>ir le calculd’éclairem<strong>en</strong>t qui correspond au mieux à la forme souhaitée.◮ ⇒ perm<strong>et</strong> d’obt<strong>en</strong>ir une perception d’un obj<strong>et</strong> lisse <strong>en</strong> « jouant »uniquem<strong>en</strong>t avec lesnormales !F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 30 / 58


Normales 3/3◮ Résultat pour le diffus :F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 31 / 58


Exemple de spécification des normales pour un obj<strong>et</strong>complexe◮ La normale de l’obj<strong>et</strong> à représ<strong>en</strong>ter peut ne pas être connue (surface « réelle »inconnue).◮ ⇒ Pr<strong>en</strong>dre la moy<strong>en</strong>ne des normales aux fac<strong>et</strong>tes incid<strong>en</strong>tes au somm<strong>et</strong> peut donner unebonne approximation de la surface lisse.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 32 / 58


Eff<strong>et</strong>s « spéciaux »avec des normales◮ sur l’animation on ne voit pas tous les polygones (grille plus finem<strong>en</strong>t subdivisée).◮ il s’agit du principe appliqué par la technique dite du « Bump mapping » : spécifier lesnormales d’un relief sans toucher à la géométrie de l’obj<strong>et</strong>. Seul le calcul d’éclairem<strong>en</strong>tdonne la perception de relief.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 33 / 58


Eclairem<strong>en</strong>t dans les shaders◮ Tous les vecteurs apparaissant dans les calculs doiv<strong>en</strong>t être exprimés dans le mêmerepère : les calculs d’éclairem<strong>en</strong>t se feront dans le repère Eye.◮ Transformation des somm<strong>et</strong>s : vertexEye=gl_ModelViewMatrix*gl_<strong>Vertex</strong>;◮ Transformation des normales : nEye=gl_NormalMatrix*gl_Normal;. Att<strong>en</strong>tion :gl_NormalMatrix est une matrice 3x3 <strong>et</strong> gl_Normal est un vec3.◮ Pourquoi ? A cause des év<strong>en</strong>tuels scales :avant transformationaprès transformation par MODELVIEW◮ La matrice correcte pour transformer les normales est (M −1 ) t où M est la sous-matrice3x3 (3 premières lignes, 3 premières colonnes) de MODELVIEW.(cf http://www.lighthouse3d.com/op<strong>en</strong>gl/glsl/index.php?normalmatrix).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 34 / 58


Shader<strong>Vertex</strong> shader :# version 110varying vec4 couleur ;void main ( ) {f l o a t i n t e n s i t e D i f f u s ;vec3 N, L ;N=gl_NormalMatrix∗gl_Normal ;/ / Source supposée d i r e c t i o n n e l l e i c i :L=gl_LightSource [ 0 ] . p o s i t i o n . xyz ; / / dé j à exprimé dans l e repè re EyeL=normalize ( L ) ;N=normalize (N ) ;i n t e n s i t e D i f f u s =max( dot (N, L ) , 0 . 0 ) ;couleur= i n t e n s i t e D i f f u s∗g l _ F r o n t M a t e r i a l . d i f f u s e ;g l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ;}Fragm<strong>en</strong>t shader :# version 110varying vec4 couleur ;void main ( ) {gl_FragColor=couleur ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 35 / 58


Remarques sur GLSLOn dispose <strong>en</strong> GLSL des types propres à la 3D (vec, mat), <strong>et</strong> d’une manipulation assez soupledes variables :void main ( ) {vec4 a=vec4 ( 0 . 1 , 0 . 2 , 0 . 3 , 0 . 4 ) ; / / c o n s t r u c t e u rf l o a t b=a . x ; / / accès au champ xvec2 c=a . xy ; / / opé r a t i o n d i t e de s i z z l i n gf l o a t d=a .w;mat2 e = mat2 ( 1 . 0 , 0 . 0 , 1 . 0 , 0 . 0 ) ;f l o a t f =e [ 1 ] [ 1 ] ; / / accès tableauvec2 g=e [ 1 ] ; / / 2ieme colonne .. . .}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 36 / 58


Spéculaire◮ La spécularité traduit l’aspect « brillant »de l’obj<strong>et</strong>.◮ La réflexion spéculaire provi<strong>en</strong>t de la réflexion (au s<strong>en</strong>s « miroir ») des rayons lumineux surl’obj<strong>et</strong>.◮ ⇒ on considère alors la direction miroir R du vecteur d’éclairem<strong>en</strong>t L (R est le symétriquede L par rapport à N).◮ L’int<strong>en</strong>sité de la réflexion spéculaire est maximale dans la direction R <strong>et</strong> est atténuée autourde c<strong>et</strong>te direction R.⇒ L’int<strong>en</strong>sité perçue (i.e. la couleur) par l’observateur va donc dép<strong>en</strong>dre de sa position parrapport à la direction R.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 37 / 58


Calcul spéculaire◮ Le calcul de V.R (cosinus de l’angle <strong>en</strong>tre V <strong>et</strong> R) donne une approximation correcte del’eff<strong>et</strong> spéculaire (maximal dans la direction si R dirigé directem<strong>en</strong>t sur l’observateur ;atténué autour).◮ Comme pour le diffus : on affecte une caractéristique K s = (rouge,vert,bleu) pour lematériel.◮ Ne pas oublier : tous les vecteurs normés (V.R = cos(V,R) ∈ [0,1]).⇒ Couleur Spéculaire (P) = K s (V · R)F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 38 / 58


Résultat◮ Le calcul du spéculaire donne une « tache »lumineuse sur l’obj<strong>et</strong> (conséqu<strong>en</strong>ce de laréflexion des rayons lumineux).◮ Pour acc<strong>en</strong>tuer ou atténuer l’eff<strong>et</strong>, on donne égalem<strong>en</strong>t un coeffici<strong>en</strong>t de brillance s pouracc<strong>en</strong>tuer ou atténuer l’eff<strong>et</strong> autour de la direction principale.◮ ⇒ Couleur Spéculaire (P) = K s (V · R) sF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 39 / 58


Spécifier le spéculaire <strong>en</strong> Op<strong>en</strong>GLCe sont les même instructions que pour l’ambiant <strong>et</strong> le diffus :◮glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, );◮ Brillance : glMateriali (GL_FRONT_AND_BACK,GL_SHININESS,);On peut récupérer ces données dans les shaders avec les built-ingl_FrontMaterial.specular (de type vec4) <strong>et</strong> gl_FrontMaterial.shininess (de typefloat).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 40 / 58


Spéculaire calculé au somm<strong>et</strong>◮ Spéculaire : très mal r<strong>en</strong>du s’il est calculé uniquem<strong>en</strong>t au somm<strong>et</strong>.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 41 / 58


Interpolation de Phong◮ On calcule l’éclairem<strong>en</strong>t spéculaire <strong>en</strong> chacun des pixels (surcout <strong>en</strong> temps de calcul).◮ Avec quels vecteurs ? on pr<strong>en</strong>d les vecteurs L,V,N interpolés linéairem<strong>en</strong>t par rapport auxvaleurs aux somm<strong>et</strong>s (variables L,V,N définies comme varying).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 42 / 58


3 Variables uniformF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 43 / 58


Communiquer des valeurs aux shaders◮ Communiquer des valeurs spécifiques à chaque somm<strong>et</strong> ⇒ attributs de somm<strong>et</strong>s(gl<strong>Vertex</strong>Pointer, glColorPointer par exemple)◮ Communiquer des valeurs calculées dans le vertex <strong>et</strong> transmises par interpolation auxfragm<strong>en</strong>ts ⇒ variables qualifiées de varying◮ Communiquer des valeurs pour paramétrer les shaders (vertex ou fragm<strong>en</strong>t) ⇒ variablesqualifiées de uniform• Une variable uniforme peut changer <strong>en</strong>tre chaque tracé (glDraw...) par l’applicationOp<strong>en</strong>GL, mais leur valeur reste constante durant l’exécution des vertex/fragm<strong>en</strong>tshaders (lecture seule).Exemple : modifier les coordonnées des somm<strong>et</strong>s pour effectuer une dilatation.⇒ déplacer le somm<strong>et</strong> dans la direction de la normale selon un certain facteurF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 44 / 58


<strong>Vertex</strong> shader# version 110uniform f l o a t f a c t e u r ;varying vec4 c o u l e u r D i f f u s ;varying vec3 N, L , V ;void main ( ) {f l o a t i n t e n s i t e ;vec4 vertexLocal ;vec4 vertexEye ;/ / déplacem<strong>en</strong>t du somm<strong>et</strong>vertexLocal= f a c t e u r∗vec4 ( gl_Normal , 0 ) + gl_<strong>Vertex</strong> ;/ / t r a n s f o r m a t i o n & l i g h t i n gvertexEye=gl_ModelViewMatrix∗vertexLocal ;V=vec3(−gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ) ;L=gl_LightSource [ 0 ] . p o s i t i o n . xyz−vertexEye . xyz / vertexEye .w;N=gl_NormalMatrix∗gl_Normal ;L=normalize ( L ) ;V=normalize (V ) ;N=normalize (N ) ;i n t e n s i t e =dot (N, L ) ;c o u l e u r D i f f u s = g l _ F r o n t M a t e r i a l . d i f f u s e∗i n t e n s i t e ;g l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗vertexEye ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 45 / 58


Affecter les variables uniformDans l’application Op<strong>en</strong>GL on affecte les variables uniform des shaders avec glUniform :GLuint programId ;GLuint l o c a t i o n F a c t e u r ;void i n i t ( ) {programId=readMyShader ( " d i l a t a t i o n " ) ; / / f o n c t i o n u t i l i t a i r e pour l i r e / compiler / l i n k e r/ / l e s shaders des f i c h i e r s d i l a t a t i o n . v e r t <strong>et</strong> d i l a t a t i o n . f r a g par exemplel o c a t i o n F a c t e u r =glG<strong>et</strong>UniformLocation ( programId , " f a c t e u r " ) ; / / r écupé r e r où se trouve " f a c t e u r " dans l e shader}void draw ( ) {glUseProgram ( programId ) ;glUniform1f ( l o c a t i o n F a c t e u r , 0 . 1 ) ; / / a f f e c t e l a v a r i a b l e f a c t e u r du shader avec l a valeur 0.1obj . drawBuffer ( ) ; / / commande de t r a c églUseProgram ( 0 ) ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 46 / 58


4 TextureF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 47 / 58


Définition (intuitive)◮ Une texture est une « image », c’est à dire une grille de pixels.◮ Les pixels de la texture sont appelés texels (pour les différ<strong>en</strong>cier des pixels de l’écrangraphique).◮ Chaque texel est localisé dans la texture par ses coordonnées s <strong>et</strong> t.◮ Toute l’image de la texture est décrite par s ∈ [0,1] <strong>et</strong> t ∈ [0,1]F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 48 / 58


Plaquer une texture◮ Consiste à associer à chaque point 3D des coordonnées de texture pour lui associer untexel de l’image texture◮ Plaquage linéaire sur un triangle :• Il suffit d’associer des coordonnées de texture uniquem<strong>en</strong>t aux somm<strong>et</strong>s.• Les coordonnées de texture des pixels sont alors interpolées linéairem<strong>en</strong>t lors duremplissage du triangle.F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 49 / 58


Chargem<strong>en</strong>t d’une image de texture◮ On doit attribuer une zone mémoire Op<strong>en</strong>GL pour accueillir l’image (mémoire qualifiée d<strong>et</strong>exture buffer).GLuint t e x _ i d ;void i n i t T e x t u r e ( ) {/ / géné r a t i o n d ’ un i d e n t i f i a n tglG<strong>en</strong>Textures (1 ,& t e x _ i d ) ;/ / l a t e x t u r e courante sera l ’ u n i t é 0 à l a q u e l l e on a f f e c t e l a t e x t u r e t e x _ i dg l A c t i v e T e x t u r e (GL_TEXTURE0 ) ;glBindTexture (GL_TEXTURE_2D, t e x _ i d ) ; / / t outes l e s i n s t r u c t i o n s qui s u i v r o n t s ’ adresseront à t e x _ i d/ / a f f e c t a t i o n de l ’ image de l a t e x t u r eglTexImage2D (GL_TEXTURE_2D, / / t e x t u r e 2D (= image )0 , / / niveau de mipmap ( sera vu plus t a r d )3 , / / l e tableau est à i n t e r p r é t e r par " paqu<strong>et</strong> " de/ / t r o i s valeurs consé c u t i v e swidth , height , / / t a i l l e <strong>en</strong> p i x e l s de l ’ image0 , / / gestion des bords pour recollem<strong>en</strong>t/ / ( dans ce cours = 0)GL_RGB, / / i n t e r p r é t a t i o n par Op<strong>en</strong>GL ( image sera/ / stock ée <strong>en</strong> valeurs de Rouge , Vert , Bleu )GL_UNSIGNED_BYTE, / / format du tableau ( i c i unsigned byte )image ) ; / / l ’ image ( tableau cont<strong>en</strong>ant l e s t e x e l s ) .F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 50 / 58


Attribution des coordonnées de texture◮ On peut plaquer plusieurs textures simultaném<strong>en</strong>t lors d’un même tracé : gestion desunités de texture.◮ Pour chaque unité de texture, on peut spécifier :• Une texture distincte (i.e. un id<strong>en</strong>tifiant distinct)• Des coordonnées de textures indép<strong>en</strong>dantes <strong>et</strong> distinctes (i.e. plusieurs coordonnéesde texture pour chaque somm<strong>et</strong>).GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 placage des 3 unitésF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 51 / 58


Attribution des coordonnées de textureAffectation de la mémoire Op<strong>en</strong>GL avec des coordonnées de textures :void i n i t B u f f e r ( ) {f l o a t v e r t e x []={ −1 , −1 ,0 , −1 ,1 ,0 ,1 , −1 ,0 ,1 ,1 ,0};f l o a t t e x t u r e [ ] = { 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 } ;glG<strong>en</strong>Buffers (1 ,& b u f f e r V e r t e x ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, b u f f e r V e r t e x ) ;g l B u f f e r D a t a (GL_ARRAY_BUFFER,12∗ s i z e o f ( GLfloat ) , vertex ,GL_STATIC_DRAW ) ;glG<strong>en</strong>Buffers (1 ,& bufferTexCoord0 ) ;g l B i n d B u f f e r (GL_ARRAY_BUFFER, bufferTexCoord0 ) ;g l B u f f e r D a t a (GL_ARRAY_BUFFER,8∗ s i z e o f ( GLfloat ) , t e x t u r e ,GL_STATIC_DRAW ) ;}Pour que le tracé soit fait avec les coordonnées de textures comme attributs de somm<strong>et</strong> :. . .g l C l i e n t A c t i v e T e x t u r e (GL_TEXTURE0 ) ; / / on t r a v a i l l e avec l e premier jeu de coordonnées de t e x t u r e ( i . e . GL_TEXTURE0)g l E n a b l e C l i e n t S t a t e (GL_TEXTURE_COORD_ARRAY) ; / / a c t i v a t i o n de l ’ a l i m e n t a t i o n du premier jeu de coordonnees de t e x t u r e/ / ( i . e . a l i m e n t a t i o n de gl_MultiTexCoord0 dans l e v e r t e x shader ) .g l B i n d B u f f e r (GL_ARRAY_BUFFER, bufferTexCoord0 ) ;glTexCoordPointer ( 2 ,GL_FLOAT, 0 , 0 ) ; / / données du premier jeu de coordonnées de t e x t u r eglDrawArrays (GL_TRIANGLE_STRIP , 0 , 4 ) ;g l C l i e n t A c t i v e T e x t u r e (GL_TEXTURE0 ) ;g l D i s a b l e C l i e n t S t a t e (GL_TEXTURE_COORD_ARRAY ) ; / / dé s a c t i v e l e premier jeu de coordonnées de t e x t u r e sA noter : possibilité d’avoir plusieurs jeux de coordonnées de textures gérées indép<strong>en</strong>damm<strong>en</strong>t(glCli<strong>en</strong>tActiveTexture(GL_TEXTUREi)).F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 52 / 58


Type sampler2D◮ Dans les shaders, les images de texture sont accessibles gràce à des uniform de typesampler2D<strong>Vertex</strong> Shader (se cont<strong>en</strong>te d’interpoler les coordonnées de texture) :varying vec2 coordTex ;void main ( ) {coordTex=gl_MultiTexCoord0 . s t ; / / accès premier jeu de coordonneesg l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ;}Fragm<strong>en</strong>t shader (récupération des coordonnées de texture interpolées <strong>et</strong> lecture de la couleurdans l’image) :uniform sampler2D uneTexture ;varying vec2 coordTex ;void main ( ) {vec4 couleur ;couleur=texture2D ( uneTexture , coordTex ) ;gl_FragColor = couleur ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 53 / 58


Affectation de la texture depuis l’application◮ On affecte l’uniform uneTexture avec l’unité de texture souhaitée.glUseProgram ( monShader . i d ( ) ) ;GLuint locationSampler=glG<strong>et</strong>UniformLocation ( monShader . i d ( ) , " uneTexture " ) ; / / r écupé r e r où se trouve " uneTexture " dans l e shaderg l U n i f o r m 1 i ( locationSampler , 1 ) ; / / uneTexture correspondra à l ’ image de l ’ u n i t é de t e x t u r e 1draw ( ) ;glUseProgram ( 0 ) ;F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 54 / 58


Un exemple <strong>en</strong> multi-textureF. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 55 / 58


Dans l’applicationQuelques classes utilitaires pour alléger le code :class GLView : . . . {. . .Shader _earthShader ;Texture _earthDay , _earthNight ;Sphere _sphere ;. . .} ;void GLView : : i n i t ( ) {earthDay . read ( " earthD . jpg " ) ;e a r t h N i g h t . read ( " earthN . jpg " ) ;g l A c t i v e T e x t u r e (GL_TEXTURE0 ) ;earthDay . bind ( ) ;g l A c t i v e T e x t u r e (GL_TEXTURE1 ) ;e a r t h N i g h t . bind ( ) ;sphere . i n i t B u f f e r ( ) ; / / géné r a t i o n somm<strong>et</strong>s+coordonnées de t e x t u r e s}void draw ( ) {earthShader . <strong>en</strong>able ( ) ;earthShader . uniform ( " texJour " , 0 ) ;earthShader . uniform ( " t e x N u i t " , 1 ) ;sphere . drawBuffer ( ) ;earthShader . d i s a b l e ( ) ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 56 / 58


Le vertex shader<strong>Vertex</strong> :varying vec2 texCoord ;varying vec3 normal ;varying vec3 L ;void main ( ) {texCoord=gl_MultiTexCoord0 . s t ;/ / Source supposée d i r e c t i o n n e l l e i c i :L=gl_LightSource [ 0 ] . p o s i t i o n . xyz ; / / dé j à exprimé dans l e repè re Ey<strong>en</strong>ormal=gl_NormalMatrix∗gl_Normal ;g l _ P o s i t i o n = g l _ P r o j e c t i o n M a t r i x∗gl_ModelViewMatrix∗gl_<strong>Vertex</strong> ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 57 / 58


Le fragm<strong>en</strong>t shaderFragm<strong>en</strong>t :uniform sampler2D texJour , t e x N u i t ;varying vec2 texCoord ;varying vec3 normal ;varying vec3 L ;void main ( ) {vec4 couleurNuit , couleurJour ;vec3 normal2 , L2 ;normal2=normalize ( normal ) ;L2=normalize ( L ) ;f l o a t e c l a i r e =dot ( L2 , normal2 ) ;/ / e c l a i r e=−1 : compl<strong>et</strong>em<strong>en</strong>t n u i t/ / e c l a i r e =1 : compl<strong>et</strong>em<strong>en</strong>t j o u re c l a i r e =( e c l a i r e + 1 . 0 ) / 2 . 0 ; / / i n t e r v a l l e [ 0 , 1 ]c o u l e u r N u i t =texture2D ( texNuit , texCoord ) ;couleurJour=texture2D ( texJour , texCoord ) ;/ / mélange t e x t u r e j o u r + n u i t (mélange t r o p ét<strong>en</strong>du i c i )gl_FragColor = couleurJour∗(1− e c l a i r e )+ c o u l e u r N u i t∗e c l a i r e ;}F. Aubert (MS2) M3DS/ <strong>Chapitre</strong> 5 : Shaders GLSL 2012-2013 58 / 58

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!