gKit2 light
tuto4GL_normals.cpp
Go to the documentation of this file.
1 
7 #include "window.h"
8 #include "vec.h"
9 #include "mat.h"
10 
11 #include "program.h"
12 #include "uniforms.h"
13 
14 #include "orbiter.h"
15 #include "mesh.h"
16 #include "wavefront.h"
17 
18 #include <stdio.h>
19 
20 // shader program
21 GLuint program;
22 
23 // vertex array object
24 GLuint vao;
25 GLuint vertex_buffer;
26 GLuint normal_buffer;
27 unsigned int vertex_count;
28 
29 // camera
30 Orbiter camera;
31 
32 
33 int init( )
34 {
35  // compile un shader program
36  program= read_program("tutos/tuto4GL_normals.glsl");
37  program_print_errors(program);
38 
39  // charge un objet
40  Mesh mesh= read_mesh("data/bigguy.obj");
41  vertex_count= mesh.vertex_count();
42 
43  // camera
44  Point pmin, pmax;
45  mesh.bounds(pmin, pmax);
46 
47  camera.lookat(pmin, pmax);
48 
49  glGenBuffers(1, &vertex_buffer);
50  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
51 
52  // dimensionne le buffer actif sur array_buffer, l'alloue et l'initialise avec les positions des sommets de l'objet
53  glBufferData(GL_ARRAY_BUFFER,
54  /* length */ mesh.vertex_buffer_size(),
55  /* data */ mesh.vertex_buffer(),
56  /* usage */ GL_STATIC_DRAW);
57  // GL_STATIC_DRAW decrit l'utilisation du contenu du buffer. dans ce cas, utilisation par draw, sans modifications
58 
59  // on recommence avec les normales
60  glGenBuffers(1, &normal_buffer);
61  glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
62  glBufferData(GL_ARRAY_BUFFER, mesh.normal_buffer_size(), mesh.normal_buffer(), GL_STATIC_DRAW);
63 
64 /* attention: c'est normal_buffer qui est selectionne maintenant sur array_buffer, plus vertex_buffer...
65  */
66 
67  // creation d'un vertex array object
68  glGenVertexArrays(1, &vao);
69  glBindVertexArray(vao);
70 
71  // recuperer l'identifiant de l'attribut : cf in vec3 position; dans le vertex shader
72  GLint attribute= glGetAttribLocation(program, "position");
73  if(attribute < 0)
74  return -1;
75 
76  // re-selectionne vertex buffer pour configurer les positions
77  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
78  // format et organisation des donnees dans le vertex buffer selectionne sur array_buffer,
79  glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ 0);
80  glEnableVertexAttribArray(attribute);
81 
82  // on recommence pour les normales
83  attribute= glGetAttribLocation(program, "normal");
84  if(attribute < 0)
85  return -1;
86 
87  // re-selectionne normal_buffer pour configurer les normales
88  glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
89  glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ 0); // in vec3 normal;
90  glEnableVertexAttribArray(attribute);
91 
92 
93 /* creer 2 buffers pour ranger les positions et les normales est arbitraire, on peut tres bien ne creer qu'un seul buffer,
94  par contre, la description du format / de l'organisation sera differente...
95  ce sont les parametres stride et offset de glVertexAttribPointer() qui permettent d'organiser les donnees librement,
96  ils permettent d'iterer sur les donnees, offset definit le premier element et stride permet de passer au suivant.
97 
98  exemple 1: un seul buffer, toutes les positions, puis toutes les normales
99 
100  PPPPPPPPNNNNNNNN
101 
102  offset(position)= 0;
103  stride(position)= 0; // par definition stride(position) == sizeof(vec3)
104 
105  offset(normal)= sizeof(vec3) * size(positions);
106  stride(normal)= 0; // ou sizeof(vec3)
107 
108  exemple 2: un seul buffer, alterner les donnees, position + normale sommet 0, position + normale sommet 1, etc.
109 
110  PNPNPNPNPNPNPN
111 
112  offset(position)= 0;
113  stride(position)= sizeof(vec3) + sizeof(vec3); // la prochaine position se trouve apres la normale du sommet
114 
115  offset(normal)= sizeof(vec3); // la premiere normale se trouve apres la premiere position
116  stride(normal)= sizeof(vec3) + sizeof(vec3);
117 
118  exemple 3: et pour normale suivie de position ?
119 
120  NPNPNPNPNPNPNPNP
121 
122  */
123 
124  // nettoyage
125  glBindVertexArray(0);
126  glBindBuffer(GL_ARRAY_BUFFER, 0);
127 
128  // etat par defaut openGL
129  glClearColor(0.2f, 0.2f, 0.2f, 1);
130  glClearDepthf(1);
131 
132  glDepthFunc(GL_LESS);
133  glEnable(GL_DEPTH_TEST);
134 
135  glEnable(GL_CULL_FACE);
136  // glViewport(0, 0, window_width(), window_height()) // deja fait dans run( )
137  return 0;
138 }
139 
140 int quit( )
141 {
142  release_program(program);
143  glDeleteBuffers(1, &vertex_buffer);
144  glDeleteVertexArrays(1, &vao);
145  return 0;
146 }
147 
148 int draw( )
149 {
150  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
151 
152  // todo recuperez les mouvements de la souris pour deplacer la camera, cf tutos/tuto6.cpp
153  // recupere les mouvements de la souris, utilise directement SDL2
154  int mx, my;
155  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
156 
157  // deplace la camera
158  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
159  // tourne autour de l'objet
160  camera.rotation(mx, my);
161 
162  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
163  // approche / eloigne l'objet
164  camera.move(mx);
165 
166  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
167  // deplace le point de rotation
168  camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
169 
170 
171 /* configuration minimale du pipeline
172  vertex array
173  shader program
174  uniforms du shader program
175  */
176  glBindVertexArray(vao);
177 
178  glUseProgram(program);
179 
180  // recupere le point de vue et la projection de la camera
181  Transform model= Identity();
182  Transform view= camera.view();
183  Transform projection= camera.projection(window_width(), window_height(), 45);
184 
185  // compose les matrices pour passer du repere local de l'objet au repere projectif
186  Transform mvp= projection * view * model;
187  Transform mv= view * model;
188 
189  GLuint location;
190  location= glGetUniformLocation(program, "mvpMatrix");
191  glUniformMatrix4fv(location, 1, GL_TRUE, mvp.data());
192 
193  // les normales ne subissent pas tout a fait la meme transformation que les sommets
194  program_uniform(program, "mvMatrix", mv.normal());
195 
196  program_uniform(program, "color", vec3(1, 0.5, 0.));
197 
198  glDrawArrays(GL_TRIANGLES, 0, vertex_count);
199 
200  // nettoyage
201  glUseProgram(0);
202  glBindVertexArray(0);
203  return 1;
204 }
205 
206 
207 int main( int argc, char **argv )
208 {
209  // etape 1 : creer la fenetre
210  Window window= create_window(1024, 640);
211  if(window == NULL)
212  return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
213 
214  // etape 2 : creer un contexte opengl pour pouvoir dessiner
215  Context context= create_context(window);
216  if(context == NULL)
217  return 1; // erreur lors de la creation du contexte opengl
218 
219  // etape 3 : creation des objets
220  if(init() < 0)
221  {
222  printf("[error] init failed.\n");
223  return 1;
224  }
225 
226  // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee. ou que draw() ne renvoie pas 0
227  run(window, draw);
228 
229  // etape 5 : nettoyage
230  quit();
231  release_context(context);
232  release_window(window);
233  return 0;
234 }
representation d'un objet / maillage.
Definition: mesh.h:112
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL....
Definition: mesh.h:296
void bounds(Point &pmin, Point &pmax) const
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:503
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:298
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:291
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:303
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3,...
Definition: mesh.h:301
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition: orbiter.h:17
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
Transform projection(const int width, const int height, const float fov)
fixe la projection reglee pour une image d'aspect width / height, et une demi ouverture de fov degres...
Definition: orbiter.cpp:47
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
Context create_context(Window window)
cree et configure un contexte opengl
Definition: window.cpp:356
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:325
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
Window create_window(const int w, const int h, const int major, const int minor, const int samples)
creation d'une fenetre pour l'application.
Definition: window.cpp:259
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:422
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition: wavefront.cpp:14
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
void program_uniform(const GLuint program, const char *uniform, const std::vector< unsigned > &v)
affecte un tableau de valeurs a un uniform du shader program.
Definition: uniforms.cpp:94
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:96
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m.
Definition: mat.cpp:181
const float * data() const
renvoie l'adresse de la premiere valeur de la matrice.
Definition: mat.h:75
vecteur generique, utilitaire.
Definition: vec.h:146
int run(Window window, int(*draw)())
boucle de gestion des evenements de l'application.
Definition: window.cpp:147