gKit2 light
Loading...
Searching...
No Matches
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
21struct 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
30struct 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
39class TP : public App
40{
41public:
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(!GLAD_GL_ARB_indirect_parameters)
48 return -1;
49 printf("GL_ARB_indirect_parameters ON\n");
50
51 if(!GLAD_GL_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("gkit2_tutos/M2/indirect_cull.glsl"); // tests de visibilite
101 program_print_errors(m_program_cull);
102
103 m_program= read_program("gkit2_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
236protected:
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
260int main( int argc, char **argv )
261{
262 TP tp;
263 tp.run();
264
265 return 0;
266}
classe application.
Definition app.h:20
App(const int width, const int height, const int major=3, const int minor=3, const int samples=0)
constructeur, dimensions de la fenetre et version d'openGL.
Definition app.cpp:11
int run()
execution de l'application.
Definition app.cpp:36
representation d'un objet / maillage.
Definition mesh.h:121
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition orbiter.h:17
Definition alpha.cpp:58
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:27
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:23
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:218
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition program.cpp:446
int release_program(const GLuint program)
detruit les shaders et le program.
Definition program.cpp:225
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:67