gKit2 light
tuto_time.cpp
Go to the documentation of this file.
1 
3 
4 #include <chrono>
5 
6 #include "mat.h"
7 #include "program.h"
8 #include "uniforms.h"
9 #include "wavefront.h"
10 #include "texture.h"
11 
12 #include "orbiter.h"
13 #include "draw.h"
14 
15 #include "app.h" // classe Application a deriver
16 #include "text.h"
17 
18 
19 class TP : public App
20 {
21 public:
22  TP( ) : App(1024, 640)
23  {
24  // desactive vsync pour les mesures de temps
25  SDL_GL_SetSwapInterval(0);
26  }
27 
28  int init( )
29  {
30  // charge un objet et une texture a afficher
31  // mode 0 & 1
32  m_objet= read_mesh("data/bigguy.obj");
33  Point pmin, pmax;
34  m_objet.bounds(pmin, pmax);
35  m_camera.lookat(pmin - Vector(20, 20, 0), pmax + Vector(20, 20, 0));
36 
37  m_texture= read_texture(0, "data/debug2x2red.png");
38 
39  // mode 2
40  // configure le vertex array / format de sommet
41  glGenVertexArrays(1, &m_vao);
42  glBindVertexArray(m_vao);
43 
44  // buffer : positions + normals
45  glGenBuffers(1, &m_vertex_buffer);
46  glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
47  glBufferData(GL_ARRAY_BUFFER, m_objet.vertex_buffer_size() + m_objet.normal_buffer_size(), 0, GL_STATIC_DRAW);
48 
49  // transfere les positions des sommets
50  glBufferSubData(GL_ARRAY_BUFFER, /* offset */ 0, /* size */ m_objet.vertex_buffer_size(), /* data */ m_objet.vertex_buffer());
51  // configure l'attribut 0, vec3 position
52  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ 0);
53  glEnableVertexAttribArray(0);
54 
55  // transfere les normales des sommets
56  glBufferSubData(GL_ARRAY_BUFFER, /* offset */ m_objet.vertex_buffer_size(), /* size */ m_objet.normal_buffer_size(), /* data */ m_objet.normal_buffer());
57  // configure l'attribut 2, vec3 normal
58  glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ (const GLvoid *) m_objet.vertex_buffer_size());
59  glEnableVertexAttribArray(2);
60 
61  m_vertex_count= m_objet.vertex_count();
62 
63  m_program= read_program("tutos/M2/instance.glsl");
64  program_print_errors(m_program);
65 
66  // nettoyage
67  glBindVertexArray(0);
68  glBindBuffer(GL_ARRAY_BUFFER, 0);
69 
70  // mesure du temps gpu de glDraw
71  glGenQueries(1, &m_time_query);
72 
73  // affichage du temps dans la fenetre
74  m_console= create_text();
75 
76  // etat openGL par defaut
77  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
78 
79  glClearDepth(1.f); // profondeur par defaut
80  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
81  glEnable(GL_DEPTH_TEST); // activer le ztest
82 
83  return 0; // ras, pas d'erreur
84  }
85 
86  int quit( )
87  {
88  glDeleteQueries(1, &m_time_query);
89 
90  release_text(m_console);
91  m_objet.release();
92  glDeleteTextures(1, &m_texture);
93 
94  return 0;
95  }
96 
97  int update( const float time, const float delta )
98  {
99  m_model= RotationY(time / 20);
100  return 0;
101  }
102 
103  int render( )
104  {
105  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
106 
107  // deplace la camera
108  int mx, my;
109  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
110  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
111  m_camera.rotation(mx, my);
112  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
113  m_camera.move(mx);
114  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
115  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
116 
117  // mesure le temps d'execution du draw pour le gpu
118  glBeginQuery(GL_TIME_ELAPSED, m_time_query);
119 
120  // mesure le temps d'execution du draw pour le cpu
121  // utilise std::chrono pour mesurer le temps cpu
122  std::chrono::high_resolution_clock::time_point cpu_start= std::chrono::high_resolution_clock::now();
123 
124  static int mode= 0;
125  if(key_state(' '))
126  {
127  clear_key_state(' ');
128  mode= (mode + 1) % 3;
129  }
130 
131  if(mode == 0)
132  {
133  // dessine 1 objet
134  draw(m_objet, m_model, m_camera, m_texture);
135  }
136  else if(mode == 1)
137  {
138  // dessine 25 fois l'objet sur une grille
139  for(int y= -2; y <= 2; y++)
140  for(int x= -2; x <= 2; x++)
141  {
142  Transform t= Translation(x *20, y *20, 0);
143  draw(m_objet, t * m_model, m_camera, m_texture);
144  }
145  }
146  else if(mode == 2)
147  {
148  // dessine 25 copies de l'objet sur une grille avec un seul glDrawArrayInstanced( ), c'est le vertex shader qui calcule la translation
149  // cf gl_InstanceID qui contient l'indice de la copie
150  glBindVertexArray(m_vao);
151  glUseProgram(m_program);
152 
153  Transform m= m_model;
154  Transform v= m_camera.view();
155  Transform p= m_camera.projection(window_width(), window_height(), 45);
156  Transform mvp= p * v * m;
157  Transform mv= v * m;
158 
159  program_uniform(m_program, "mvpMatrix", mvp);
160  program_uniform(m_program, "normalMatrix", mv.normal());
161 
162  glDrawArraysInstanced(GL_TRIANGLES, 0, m_vertex_count, 25);
163  }
164 
165  std::chrono::high_resolution_clock::time_point cpu_stop= std::chrono::high_resolution_clock::now();
166  // conversion des mesures en duree...
167  int cpu_time= std::chrono::duration_cast<std::chrono::microseconds>(cpu_stop - cpu_start).count();
168 
169  glEndQuery(GL_TIME_ELAPSED);
170 
171  /* recuperer le resultat de la requete time_elapsed, il faut attendre que le gpu ait fini de dessiner...
172  utilise encore std::chrono pour mesurer le temps d'attente.
173  */
174  std::chrono::high_resolution_clock::time_point wait_start= std::chrono::high_resolution_clock::now();
175 
176  // attendre le resultat de la requete
177  GLint64 gpu_time= 0;
178  glGetQueryObjecti64v(m_time_query, GL_QUERY_RESULT, &gpu_time);
179 
180  std::chrono::high_resolution_clock::time_point wait_stop= std::chrono::high_resolution_clock::now();
181  int wait_time= std::chrono::duration_cast<std::chrono::microseconds>(wait_stop - wait_start).count();
182 
183  // affiche le temps mesure, et formate les valeurs... c'est un peu plus lisible.
184  clear(m_console);
185  if(mode == 0) printf(m_console, 0, 0, "mode 0 : 1 draw");
186  if(mode == 1) printf(m_console, 0, 0, "mode 1 : 25 draws");
187  if(mode == 2) printf(m_console, 0, 0, "mode 2 : 1 draw / 25 instances");
188  printf(m_console, 0, 1, "cpu %02dms %03dus", int(cpu_time / 1000), int(cpu_time % 1000));
189  printf(m_console, 0, 2, "gpu %02dms %03dus", int(gpu_time / 1000000), int((gpu_time / 1000) % 1000));
190  printf(m_console, 0, 3, "wait %02dms %03dus", int(wait_time / 1000), int(wait_time % 1000));
191 
192  // affiche le texte dans la fenetre de l'application, utilise console.h
193  draw(m_console, window_width(), window_height());
194 
195  // affiche le temps dans le terminal
196  printf("cpu %02dms %03dus ", int(cpu_time / 1000), int(cpu_time % 1000));
197  printf("gpu %02dms %03dus\n", int(gpu_time / 1000000), int((gpu_time / 1000) % 1000));
198 
199  return 1;
200  }
201 
202 protected:
203  GLuint m_time_query;
204  Text m_console;
205 
206  Transform m_model;
207  Mesh m_objet;
208  Orbiter m_camera;
209 
210  GLuint m_texture;
211  GLuint m_program;
212  GLuint m_vao;
213  GLuint m_vertex_buffer;
214  unsigned int m_vertex_count;
215 };
216 
217 
218 int main( int argc, char **argv )
219 {
220  TP tp;
221  tp.run();
222 
223  return 0;
224 }
classe application.
Definition: app.h:20
int run()
execution de l'application.
Definition: app.cpp:36
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:501
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
void release()
detruit les objets openGL.
Definition: mesh.cpp:62
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
Definition: alpha.cpp:59
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
Definition: tuto_time.cpp:103
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_time.cpp:86
int update(const float time, const float delta)
a deriver et redefinir pour animer les objets en fonction du temps.
Definition: tuto_time.cpp:97
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_time.cpp:28
void clear(Text &text)
efface le contenu de la console.
Definition: text.cpp:72
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:48
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
Text create_text()
cree une console. a detruire avec release_text( ).
Definition: text.cpp:14
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition: window.cpp:42
void release_text(Text &text)
detruit une console.
Definition: text.cpp:64
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:242
Transform Translation(const Vector &v)
renvoie la matrice representant une translation par un vecteur.
Definition: mat.cpp:216
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
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
Definition: texture.cpp:154
representation d'un point 3d.
Definition: vec.h:21
Definition: text.h:62
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
representation d'un vecteur 3d.
Definition: vec.h:59