gKit2 light
tuto_mdi.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 
10 #include "wavefront.h"
11 #include "texture.h"
12 
13 #include "orbiter.h"
14 #include "draw.h"
15 
16 #include "app.h"
17 #include "text.h"
18 
19 
20 // representation des parametres
22 {
23  unsigned int vertex_count;
24  unsigned int instance_count;
25  unsigned int first_vertex;
26  unsigned int first_instance;
27 };
28 
29 
30 
31 class TP : public App
32 {
33 public:
34  TP( ) : App(1024, 640, 4, 3) {} // openGL version 4.3, ne marchera pas sur mac.
35 
36  int init( )
37  {
38  // verifie l'existence des extensions
39  if(!GLEW_ARB_shader_draw_parameters)
40  return -1;
41  printf("GL_ARB_shader_draw_parameters ON\n");
42 
43  m_objet= read_mesh("data/bigguy.obj");
44  Point pmin, pmax;
45  m_objet.bounds(pmin, pmax);
46 
47  m_camera.lookat(pmin - Vector(200, 200, 0), pmax + Vector(200, 200, 0));
48 
49  // genere les parametres des draws et les transformations
50  for(int y= -15; y <= 15; y++)
51  for(int x= -15; x <= 15; x++)
52  {
53  m_multi_model.push_back( Translation(x *20, y *20, 0) );
54  m_multi_indirect.push_back( { unsigned(m_objet.vertex_count()), 1, 0, 0} );
55  }
56  // oui c'est la meme chose qu'un draw instancie, mais c'est juste pour comparer les 2 solutions...
57 
58  // stockage des parametres du multi draw indirect
59  glGenBuffers(1, &m_indirect_buffer);
60  glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirect_buffer);
61  glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(IndirectParam) * m_multi_indirect.size(), &m_multi_indirect.front(), GL_DYNAMIC_DRAW);
62 
63  // stockage des matrices des objets
64  glGenBuffers(1, &m_model_buffer);
65  glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_model_buffer);
66  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Transform) * m_multi_model.size(), &m_multi_model.front(), GL_DYNAMIC_DRAW);
67 
68  // creation des vertex buffer, uniquement les positions
69  m_vao= m_objet.create_buffers(/* texcoord */ false, /* normal */ false, /* color */ false, /* material */ false);
70 
71  // shader programs
72  m_program_direct= read_program("tutos/M2/indirect_direct.glsl"); // affichage classique N draws
73  program_print_errors(m_program_direct);
74 
75  m_program= read_program("tutos/M2/indirect.glsl"); // affichage indirect 1 multi draw
76  program_print_errors(m_program);
77 
78  // affichage du temps cpu / gpu
79  m_console= create_text();
80 
81  // mesure du temps gpu de glDraw
82  glGenQueries(1, &m_time_query);
83 
84  // etat openGL par defaut
85  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
86 
87  glClearDepth(1.f); // profondeur par defaut
88  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
89  glEnable(GL_DEPTH_TEST); // activer le ztest
90 
91  return 0; // ras, pas d'erreur
92  }
93 
94  int quit( )
95  {
96  glDeleteQueries(1, &m_time_query);
97  release_text(m_console);
98 
99  release_program(m_program);
100  m_objet.release();
101  glDeleteBuffers(1, &m_indirect_buffer);
102 
103  return 0;
104  }
105 
106  int update( const float time, const float delta )
107  {
108  m_model= RotationY(time / 20);
109  return 0;
110  }
111 
112  int render( )
113  {
114  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
115 
116  // deplace la camera
117  int mx, my;
118  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
119  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
120  m_camera.rotation(mx, my);
121  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
122  m_camera.move(mx);
123  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
124  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
125 
126  // mesure le temps d'execution du draw
127  glBeginQuery(GL_TIME_ELAPSED, m_time_query); // pour le gpu
128  std::chrono::high_resolution_clock::time_point cpu_start= std::chrono::high_resolution_clock::now(); // pour le cpu
129 
130  #if 0
131  // dessine n copies de l'objet avec 1 glDrawArrays par copie
132  glBindVertexArray(m_vao);
133  glUseProgram(m_program_direct);
134 
135  program_uniform(m_program_direct, "modelMatrix", m_model);
136  program_uniform(m_program_direct, "vpMatrix", m_camera.projection(window_width(), window_height(), 45) * m_camera.view());
137  program_uniform(m_program_direct, "viewMatrix", m_camera.view());
138 
139  // dessine l'objet avec 1 draw par copie
140  for(int i= 0; i < int(m_multi_model.size()); i++)
141  {
142  program_uniform(m_program_direct, "objectMatrix", m_multi_model[i]);
143  glDrawArrays(GL_TRIANGLES, 0, m_objet.vertex_count());
144  }
145  // dans ce cas particulier, on pourrait utiliser un draw instancie, mais ce n'est pas le but du tuto...
146 
147  #else
148  // dessine n copies de l'objet avec 1 seul appel a glMultiDrawArraysIndirect
149  glBindVertexArray(m_vao);
150  glUseProgram(m_program);
151 
152  // uniforms...
153  program_uniform(m_program, "modelMatrix", m_model);
154  program_uniform(m_program, "vpMatrix", m_camera.projection(window_width(), window_height(), 45) * m_camera.view());
155  program_uniform(m_program, "viewMatrix", m_camera.view());
156 
157  // buffers...
158  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_model_buffer);
159  glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirect_buffer);
160 
161  glMultiDrawArraysIndirect(m_objet.primitives(), 0, m_multi_indirect.size(), 0);
162  #endif
163 
164 
165  // affiche le temps
166  std::chrono::high_resolution_clock::time_point cpu_stop= std::chrono::high_resolution_clock::now();
167  long long int cpu_time= std::chrono::duration_cast<std::chrono::nanoseconds>(cpu_stop - cpu_start).count();
168 
169  glEndQuery(GL_TIME_ELAPSED);
170 
171  // recupere le resultat de la requete gpu
172  GLint64 gpu_time= 0;
173  glGetQueryObjecti64v(m_time_query, GL_QUERY_RESULT, &gpu_time);
174 
175  clear(m_console);
176  printf(m_console, 0, 0, "cpu %02dms %03dus", (int) (cpu_time / 1000000), (int) ((cpu_time / 1000) % 1000));
177  printf(m_console, 0, 1, "gpu %02dms %03dus", (int) (gpu_time / 1000000), (int) ((gpu_time / 1000) % 1000));
178 
179  draw(m_console, window_width(), window_height());
180 
181  printf("cpu %02dms %03dus ", (int) (cpu_time / 1000000), (int) ((cpu_time / 1000) % 1000));
182  printf("gpu %02dms %03dus\n", (int) (gpu_time / 1000000), (int) ((gpu_time / 1000) % 1000));
183 
184  return 1;
185  }
186 
187 protected:
188  GLuint m_indirect_buffer;
189  GLuint m_model_buffer;
190  GLuint m_time_query;
191 
192  GLuint m_vao;
193  GLuint m_program;
194  GLuint m_program_direct;
195 
196  Text m_console;
197 
198  Transform m_model;
199  Mesh m_objet;
200  Orbiter m_camera;
201 
202  std::vector<IndirectParam> m_multi_indirect;
203  std::vector<Transform> m_multi_model;
204 
205 };
206 
207 
208 int main( int argc, char **argv )
209 {
210  TP tp;
211  tp.run();
212 
213  return 0;
214 }
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
GLuint create_buffers(const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index)
construit les buffers et le vertex array object necessaires pour dessiner l'objet avec openGL....
Definition: mesh.cpp:579
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
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:291
GLenum primitives() const
renvoie le type de primitives.
Definition: mesh.h:336
void release()
detruit les objets openGL.
Definition: mesh.cpp:62
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_mdi.cpp:112
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_mdi.cpp:94
int update(const float time, const float delta)
a deriver et redefinir pour animer les objets en fonction du temps.
Definition: tuto_mdi.cpp:106
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_mdi.cpp:36
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 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
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
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
tuto_mdi_elements.cpp exemple d'utilisation de multidrawindirect pour des triangles indexes.
Definition: tuto_mdi.cpp:22
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
representation d'un vecteur 3d.
Definition: vec.h:59