29const char *program_filename;
33std::string program_log;
38const char *mesh_filename;
47std::vector<const char *> texture_filenames;
48std::vector<GLuint> textures;
63GLuint debug_framebuffer= 0;
70GLuint debug_program= 0;
71GLuint debug_wireframe_program= 0;
77GLuint make_debug_framebuffer(
const int w,
const int h )
79 glGenFramebuffers(1, &debug_framebuffer);
80 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, debug_framebuffer);
88 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, debug_depth, 0);
89 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, debug_color, 0);
90 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, debug_position, 0);
91 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, debug_normal, 0);
92 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, debug_data, 0);
94 GLenum buffers[]= { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
95 glDrawBuffers(4, buffers);
97 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
98 glBindTexture(GL_TEXTURE_2D, 0);
100 return debug_framebuffer;
103void clear_debug_framebuffer( )
106 glClearBufferfv(GL_DEPTH, 0, one);
108 float zero[]= { 0, 0, 0, 0 };
109 glClearBufferfv(GL_COLOR, 0, zero);
110 glClearBufferfv(GL_COLOR, 1, zero);
111 glClearBufferfv(GL_COLOR, 2, zero);
112 glClearBufferfv(GL_COLOR, 3, zero);
115void release_debug_framebuffer( )
117 glDeleteTextures(1, &debug_depth);
118 glDeleteTextures(1, &debug_color);
119 glDeleteTextures(1, &debug_position);
120 glDeleteTextures(1, &debug_normal);
121 glDeleteTextures(1, &debug_data);
122 glDeleteFramebuffers(1, &debug_framebuffer);
126vec4 read_debug(
const int x,
const int y,
const GLenum attach )
128 glReadBuffer(attach);
131 glReadPixels(x - 2, y - 2, 4, 4, GL_RGBA, GL_FLOAT, tmp);
134 for(
int i= 0; i < 16; i++)
135 if(tmp[i].x || tmp[i].y || tmp[i].z || tmp[i].w)
138 return vec4(0, 0, 0, 0);
141vec4 read_debug_color(
const int x,
const int y )
143 return read_debug(x, y, GL_COLOR_ATTACHMENT0);
145vec4 read_debug_position(
const int x,
const int y )
147 return read_debug(x, y, GL_COLOR_ATTACHMENT1);
149vec4 read_debug_normal(
const int x,
const int y )
151 return read_debug(x, y, GL_COLOR_ATTACHMENT2);
153vec4 read_debug_data(
const int x,
const int y )
155 return read_debug(x, y, GL_COLOR_ATTACHMENT3);
158float read_depth(
const int x,
const int y )
160 glReadBuffer(GL_BACK);
163 glReadPixels(x - 2, y - 2, 4, 4, GL_DEPTH_COMPONENT, GL_FLOAT, tmp);
166 for(
int i= 0; i < 16; i++)
175void reload_program( )
180 reload_program(program, program_filename);
183 last_load= timestamp(program_filename);
188 if(program_log.size() > 0)
189 printf(
"[boom]\n%s\n", program_log.c_str());
191 program_failed= (program_log.size() > 0);
196const char *option_find( std::vector<const char *>& options,
const char *ext )
198 for(
unsigned int i= 0; i < (
unsigned int) options.size() ; i++)
200 if(options[i] !=
nullptr && std::string(options[i]).rfind(ext) != std::string::npos)
202 const char *option= options[i];
213int init( std::vector<const char *>& options )
220 option= option_find(options,
".glsl");
221 if(option !=
nullptr)
223 program_filename= option;
231 option= option_find(options,
".obj");
232 if(option !=
nullptr)
235 if(mesh.vertex_count() > 0)
237 mesh_filename= option;
239 vao= mesh.create_buffers(mesh.has_texcoord(), mesh.has_normal(), mesh.has_color(), mesh.has_material_index());
240 vertex_count= mesh.vertex_count();
242 mesh.bounds(mesh_pmin, mesh_pmax);
243 mesh_camera.lookat(mesh_pmin, mesh_pmax);
251 glGenVertexArrays(1, &vao);
256 for(
int i= 0; i < int(options.size()); i++)
258 if(options[i] ==
nullptr)
264 texture_filenames.push_back(options[i]);
265 textures.push_back(texture);
278 glBindTexture(GL_TEXTURE_2D, 0);
279 glBindVertexArray(0);
280 glBindBuffer(GL_ARRAY_BUFFER, 0);
281 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
284 glClearColor(0.2f, 0.2f, 0.2f, 1.f);
290 glDisable(GL_CULL_FACE);
292 glDepthFunc(GL_LESS);
293 glEnable(GL_DEPTH_TEST);
305 glDeleteTextures(textures.size(), textures.data());
315 debug= (debug +1) %2;
321 debug_camera= mesh_camera;
324 mesh_camera= debug_camera;
327 if(wireframe && !debug)
330 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
336 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
340 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
343 static float last_time= 0;
347 if(timestamp(program_filename) != last_load)
369 Orbiter& camera= debug ? debug_camera : mesh_camera;
373 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
375 SDL_GetMouseState(&mousex, &mousey);
378 if(mb & SDL_BUTTON(1))
379 camera.rotation(mx, my);
380 else if(mb & SDL_BUTTON(3))
382 else if(mb & SDL_BUTTON(2))
389 camera.move(8.f * wheel.y);
393 static float time= 0;
396 static int freeze= 0;
397 static int reset_camera= 0;
398 static int copy_camera= 0;
399 static int paste_camera= 0;
407 Transform mvp= projection * view * model;
415 freeze= (freeze+1) % 2;
426 wireframe= !wireframe;
429 if(debug && !debug_capture)
431 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
432 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
434 glBindVertexArray(vao);
435 glUseProgram(debug_program);
437 int mode= debug_mode;
440 program_uniform(debug_program,
"mode", mode);
443 program_uniform(debug_program,
"mvpMatrix", mvp * debug_mvpi_inv);
444 program_uniform(debug_program,
"mvMatrix", mv * debug_mvpi_inv);
458 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
460 glUseProgram(debug_wireframe_program);
461 program_uniform(debug_wireframe_program,
"mvpMatrix", mvp);
464 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
474 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, debug_framebuffer);
475 clear_debug_framebuffer();
477 debug_mvpi_inv=
Inverse(viewport * mvp);
480 glBindVertexArray(vao);
481 glUseProgram(program);
485 program_uniform(program,
"modelMatrix", model);
486 program_uniform(program,
"modelInvMatrix", model.inverse());
487 program_uniform(program,
"viewMatrix", view);
488 program_uniform(program,
"viewInvMatrix", view.inverse());
489 program_uniform(program,
"projectionMatrix", projection);
490 program_uniform(program,
"projectionInvMatrix", projection.
inverse());
491 program_uniform(program,
"viewportMatrix", viewport);
492 program_uniform(program,
"viewportInvMatrix", viewport.
inverse());
494 program_uniform(program,
"mvpMatrix", mvp);
495 program_uniform(program,
"mvpInvMatrix", mvpInv);
497 program_uniform(program,
"mvMatrix", mv);
498 program_uniform(program,
"mvInvMatrix", mv.
inverse());
499 program_uniform(program,
"normalMatrix", mv.
normal());
503 program_uniform(program,
"time", time);
504 program_uniform(program,
"motion",
vec3(mx, my, mb & SDL_BUTTON(1)));
505 program_uniform(program,
"mouse",
vec3(mousex,
window_height() - mousey -1, mb & SDL_BUTTON(1)));
508 for(
int i= 0; i < int(textures.size()); i++)
511 sprintf(uniform,
"texture%d", i);
516 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
522 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
523 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
529 label(widgets,
"[error] program '%s'", program_filename);
531 text_area(widgets, 20, program_log.c_str(), program_area);
536 button(widgets,
"[d] debug", debug);
539 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
540 float x= mousex + 0.5f;
542 float z= read_depth(x, y);
549 glBindFramebuffer(GL_READ_FRAMEBUFFER, debug_framebuffer);
550 vec4 position= read_debug_position(debug_fragment.x, debug_fragment.y);
551 vec4 color= read_debug_color(debug_fragment.x, debug_fragment.y);
552 vec4 normal= read_debug_normal(debug_fragment.x, debug_fragment.y);
553 vec4 data= read_debug_data(debug_fragment.x, debug_fragment.y);
556 label(widgets,
"debug (%f, %f, %f)", x, y, z);
559 select(widgets,
"draw position", 0, debug_mode);
560 label(widgets,
"(%f, %f, %f, %f)", position.x, position.y, position.z, position.w);
563 select(widgets,
"draw color ", 1, debug_mode);
564 label(widgets,
"(%f, %f, %f, %f)", color.x, color.y, color.z, color.w);
567 select(widgets,
"draw normal ", 2, debug_mode);
568 label(widgets,
"(%f, %f, %f)", normal.x, normal.y, normal.z);
571 select(widgets,
"draw data ", 3, debug_mode);
572 label(widgets,
"(%f, %f, %f, %f)", data.x, data.y, data.z, data.w);
575 select(widgets,
"draw triangles", 4, debug_mode);
578 glReadBuffer(GL_COLOR_ATTACHMENT0);
579 glBlitFramebuffer(debug_fragment.x -16, debug_fragment.y -16, debug_fragment.x +16, debug_fragment.y +16,
581 GL_COLOR_BUFFER_BIT, GL_NEAREST);
586 label(widgets,
"debug (%f, %f)", x, y);
589 select(widgets,
"draw position", 0, debug_mode);
592 select(widgets,
"draw color ", 1, debug_mode);
595 select(widgets,
"draw normal ", 2, debug_mode);
598 select(widgets,
"draw data ", 3, debug_mode);
601 select(widgets,
"draw triangles", 4, debug_mode);
607 button(widgets,
"[d] debug", debug);
608 button(widgets,
"[s] screenshot ", frame);
609 button(widgets,
"capture frames", video);
612 button(widgets,
"[t] freeze time", freeze);
613 button(widgets,
"[f] reset camera", reset_camera);
614 button(widgets,
"[c] copy/save camera", copy_camera);
615 button(widgets,
"[v] paste/read camera", paste_camera);
619 label(widgets,
"program '%s' running...", program_filename);
620 if(mesh_filename && mesh_filename[0])
623 label(widgets,
"mesh '%s', %d vertices %s %s", mesh_filename, mesh.vertex_count(),
624 mesh.texcoord_buffer_size() ?
"texcoords" :
"", mesh.normal_buffer_size() ?
"normals" :
"");
626 for(
unsigned int i= 0; i < (
unsigned int) texture_filenames.size(); i++)
629 label(widgets,
"texture%u '%s'", i, texture_filenames[i]);
642 printf(
"screenshot %d...\n", calls);
653 camera.write_orbiter(
"orbiter.txt");
659 if(camera.read_orbiter(
"orbiter.txt") < 0)
662 camera.lookat(mesh_pmin, mesh_pmax);
672 camera.lookat(mesh_pmin, mesh_pmax);
679int main(
int argc,
char **argv )
683 printf(
"usage: %s shader.glsl [mesh.obj] [texture0.png [texture1.png]]\n", argv[0]);
688 if(window ==
nullptr)
692 if(context ==
nullptr)
696 std::vector<const char *> options(argv + 1, argv + argc);
697 if(
init(options) < 0)
699 printf(
"[error] init failed.\n");
representation d'un objet / maillage.
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
const char * smart_path(const char *filename)
renvoie le chemin(path) vers le fichier 'filename' apres l'avoir cherche dans un repertoire standard....
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Widgets create_widgets()
cree une interface graphique. a detruire avec release_widgets( ).
void release_widgets(Widgets &w)
detruit l'interface graphique.
Context create_context(Window window)
cree et configure un contexte opengl
bool button(Widgets &w, const char *text, int &status)
int window_height()
renvoie la hauteur de la fenetre de l'application.
void release_window(Window window)
destruction de la fenetre.
int run(Window window, int(*draw)())
boucle de gestion des evenements de l'application.
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
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().
bool select(Widgets &w, const char *text, const int option, int &status)
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.
void release_context(Context context)
detruit le contexte openGL.
void clear_wheel_event()
desactive l'evenement.
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
void text_area(Widgets &w, const int height, const char *text, int &begin_line)
void begin_line(Widgets &w)
place les prochains elements sur une nouvelle ligne.
SDL_MouseWheelEvent wheel_event()
renvoie le dernier evenement. etat de la molette de la souris / glisser sur le pad.
int window_width()
renvoie la largeur de la fenetre de l'application.
float global_time()
renvoie le temps ecoule depuis le lancement de l'application, en millisecondes.
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Transform Identity()
construit la transformation identite.
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
int capture(const char *prefix)
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
GLuint read_program(const char *filename, const char *definitions)
GLuint make_vec4_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
int release_program(const GLuint program)
detruit les shaders et le program.
void program_use_texture(const GLuint program, const char *uniform, const int unit, const GLuint texture, const GLuint sampler)
configure le pipeline et le shader program pour utiliser une texture, et des parametres de filtrage,...
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
int program_format_errors(const GLuint program, std::string &errors)
renvoie les erreurs de compilation.
GLuint make_depth_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
int init(std::vector< const char * > &options)
representation d'un point 3d.
representation d'un vecteur 3d.
vecteur generique, utilitaire.
vecteur generique, utilitaire.
vecteur generique 4d, ou 3d homogene, utilitaire.