gKit2 light
tuto_mdi_count.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
21 struct alignas(4) IndirectParam
22 {
23  unsigned int vertex_count;
24  unsigned int instance_count;
25  unsigned int first_vertex;
26  unsigned int first_instance;
27 };
28 // alignement GLSL correct...
29 
30 struct alignas(16) Object
31 {
32  Point pmin;
33  unsigned int vertex_count;
34  Point pmax;
35  unsigned int vertex_base;
36 };
37 // alignement GLSL correct...
38 
39 class TP : public App
40 {
41 public:
42  TP( ) : App(1024, 640, 4,3) {} // openGL version 4.3, ne marchera pas sur mac.
43 
44  int init( )
45  {
46  // verifie l'existence des extensions
47  if(!GLEW_ARB_indirect_parameters)
48  return -1;
49  printf("GL_ARB_indirect_parameters ON\n");
50 
51  if(!GLEW_ARB_shader_draw_parameters)
52  return -1;
53  printf("GL_ARB_shader_draw_parameters ON\n");
54 
55  m_object= read_mesh("data/bigguy.obj");
56  Point pmin, pmax;
57  m_object.bounds(pmin, pmax);
58  m_camera.lookat(pmin - Vector(200, 200, 0), pmax + Vector(200, 200, 0));
59 
60  // genere les parametres des draws et les transformations
61  for(int y= -15; y <= 15; y++)
62  for(int x= -15; x <= 15; x++)
63  {
64  m_multi_model.push_back( Translation(x *20, y *20, 0) );
65 
66  // calcule la bbox de chaque objet dans le repere du monde
67  m_objects.push_back( {pmin + Vector(x *20, y *20, 0), unsigned(m_object.vertex_count()), pmax + Vector(x *20, y *20, 0), 0} );
68  }
69  // oui c'est la meme chose qu'un draw instancie, mais c'est juste pour comparer les 2 solutions...
70 
71  // transformations des objets
72  glGenBuffers(1, &m_model_buffer);
73  glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_model_buffer);
74  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Transform) * m_multi_model.size(), m_multi_model.data(), GL_DYNAMIC_DRAW);
75 
76  // objets a tester
77  glGenBuffers(1, &m_object_buffer);
78  glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_object_buffer);
79  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Object) * m_objects.size(), m_objects.data(), GL_DYNAMIC_DRAW);
80 
81  // re-indexation des objets visibles
82  glGenBuffers(1, &m_remap_buffer);
83  glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_remap_buffer);
84  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * m_objects.size(), nullptr, GL_DYNAMIC_DRAW);
85 
86  // parametres du multi draw indirect
87  glGenBuffers(1, &m_indirect_buffer);
88  glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirect_buffer);
89  glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(IndirectParam) * m_objects.size(), nullptr, GL_DYNAMIC_DRAW);
90 
91  // nombre de draws de multi draw indirect count
92  glGenBuffers(1, &m_parameter_buffer);
93  glBindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameter_buffer);
94  glBufferData(GL_PARAMETER_BUFFER_ARB, sizeof(int), nullptr, GL_DYNAMIC_DRAW);
95 
96  // creation des vertex buffer, uniquement les positions
97  m_vao= m_object.create_buffers(/* texcoord */ false, /* normal */ false, /* color */ false, /* material */ false);
98 
99  // shader program
100  m_program_cull= read_program("tutos/M2/indirect_cull.glsl"); // tests de visibilite
101  program_print_errors(m_program_cull);
102 
103  m_program= read_program("tutos/M2/indirect_remap.glsl"); // affichage des objets visibles
104  program_print_errors(m_program);
105 
106  // affichage du temps cpu / gpu
107  m_console= create_text();
108 
109  // mesure du temps gpu de glDraw
110  glGenQueries(1, &m_time_query);
111 
112  // etat openGL par defaut
113  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
114 
115  glClearDepth(1.f); // profondeur par defaut
116  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
117  glEnable(GL_DEPTH_TEST); // activer le ztest
118 
119  return 0; // ras, pas d'erreur
120  }
121 
122  int quit( )
123  {
124  glDeleteQueries(1, &m_time_query);
125  release_text(m_console);
126 
127  release_program(m_program);
128  release_program(m_program_cull);
129 
130  m_object.release();
131 
132  glDeleteBuffers(1, &m_indirect_buffer);
133  glDeleteBuffers(1, &m_parameter_buffer);
134  glDeleteBuffers(1, &m_remap_buffer);
135  glDeleteBuffers(1, &m_object_buffer);
136 
137  return 0;
138  }
139 
140  int update( const float time, const float delta )
141  {
142  m_model= RotationY(time / 20);
143  return 0;
144  }
145 
146  int render( )
147  {
148  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
149 
150  // deplace la camera
151  int mx, my;
152  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
153  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
154  m_camera.rotation(mx, my);
155  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
156  m_camera.move(mx);
157  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
158  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
159 
160  // mesure le temps d'execution
161  glBeginQuery(GL_TIME_ELAPSED, m_time_query); // pour le gpu
162  std::chrono::high_resolution_clock::time_point cpu_start= std::chrono::high_resolution_clock::now(); // pour le cpu
163 
164  // etape 1: compute shader, tester l'inclusion des objets dans une boite
165  glUseProgram(m_program_cull);
166 
167  // uniforms...
168  program_uniform(m_program_cull, "bmin", Point(-60, -60, -10));
169  program_uniform(m_program_cull, "bmax", Point(60, 60, 10));
170  //~ program_uniform(m_program_cull, "bmin", Point(-120, -120, -10));
171  //~ program_uniform(m_program_cull, "bmax", Point(120, 120, 10));
172 
173  // storage buffers...
174  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_object_buffer);
175  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_remap_buffer);
176  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_indirect_buffer);
177 
178  // compteur
179  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_parameter_buffer);
180  // remet le compteur a zero
181  unsigned int zero= 0;
182  glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, &zero);
183  // ou
184  // glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(int), &zero);
185 
186  // nombre de groupes de shaders
187  int n= m_objects.size() / 256;
188  if(m_objects.size() % 256)
189  n= n +1;
190 
191  glDispatchCompute(n, 1, 1);
192 
193  // etape 2 : attendre le resultat
194  glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
195 
196  // etape 3 : afficher les objets visibles (resultat de l'etape 1) avec 1 seul appel a glMultiDrawArraysIndirectCount
197  glBindVertexArray(m_vao);
198  glUseProgram(m_program);
199 
200  // uniforms...
201  program_uniform(m_program, "modelMatrix", m_model);
202  program_uniform(m_program, "vpMatrix", m_camera.projection(window_width(), window_height(), 45) * m_camera.view());
203  program_uniform(m_program, "viewMatrix", m_camera.view());
204 
205  // storage buffers...
206  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_model_buffer);
207  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_remap_buffer);
208 
209  // parametres du multi draw...
210  glBindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameter_buffer);
211  glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirect_buffer);
212 
213  glMultiDrawArraysIndirectCountARB(m_object.primitives(), 0, 0, m_objects.size(), 0);
214 
215  // affiche le temps
216  glEndQuery(GL_TIME_ELAPSED);
217  std::chrono::high_resolution_clock::time_point cpu_stop= std::chrono::high_resolution_clock::now();
218  long long int cpu_time= std::chrono::duration_cast<std::chrono::nanoseconds>(cpu_stop - cpu_start).count();
219 
220  // recupere le resultat de la requete gpu
221  GLint64 gpu_time= 0;
222  glGetQueryObjecti64v(m_time_query, GL_QUERY_RESULT, &gpu_time);
223 
224  clear(m_console);
225  printf(m_console, 0, 0, "cpu %02dms %03dus", (int) (cpu_time / 1000000), (int) ((cpu_time / 1000) % 1000));
226  printf(m_console, 0, 1, "gpu %02dms %03dus", (int) (gpu_time / 1000000), (int) ((gpu_time / 1000) % 1000));
227 
228  draw(m_console, window_width(), window_height());
229 
230  printf("cpu %02dms %03dus ", (int) (cpu_time / 1000000), (int) ((cpu_time / 1000) % 1000));
231  printf("gpu %02dms %03dus\n", (int) (gpu_time / 1000000), (int) ((gpu_time / 1000) % 1000));
232 
233  return 1;
234  }
235 
236 protected:
237  GLuint m_parameter_buffer;
238  GLuint m_indirect_buffer;
239  GLuint m_model_buffer;
240  GLuint m_object_buffer;
241  GLuint m_remap_buffer;
242 
243  GLuint m_vao;
244  GLuint m_program;
245  GLuint m_program_cull;
246 
247  GLuint m_time_query;
248  Text m_console;
249 
250  Transform m_model;
251  Mesh m_object;
252  Orbiter m_camera;
253 
254  std::vector<Transform> m_multi_model;
255  std::vector<Object> m_objects;
256 
257 };
258 
259 
260 int main( int argc, char **argv )
261 {
262  TP tp;
263  tp.run();
264 
265  return 0;
266 }
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:581
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
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:64
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.
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int update(const float time, const float delta)
a deriver et redefinir pour animer les objets en fonction du temps.
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
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