35const char *program_filename;
39std::string program_log;
43const char *mesh_filename;
51std::vector<const char *> texture_filenames;
52std::vector<GLuint> textures;
64 reload_program(program);
67 last_load= timestamp(program_filename);
74 printf(
"[boom]\n%s\n", program_log.c_str());
79const char *option_find( std::vector<const char *>& options,
const char *ext )
81 for(
unsigned i= 0; i < options.size() ; i++)
83 if(options[i] && std::string(options[i]).rfind(ext) != std::string::npos)
85 const char *option= options[i];
96int init( std::vector<const char *>& options )
103 option= option_find(options,
".glsl");
104 if(option !=
nullptr)
106 program_filename= option;
114 option= option_find(options,
".obj");
115 if(option !=
nullptr)
121 if(mesh.vertex_count() > 0)
123 mesh_filename= option;
125 vao= mesh.create_buffers(mesh.has_texcoord(), mesh.has_normal(), mesh.has_color(), mesh.has_material_index());
126 vertex_count= mesh.vertex_count();
128 mesh.bounds(mesh_pmin, mesh_pmax);
129 camera.lookat(mesh_pmin, mesh_pmax);
137 glGenVertexArrays(1, &vao);
142 for(
unsigned i= 0; i < options.size(); i++)
144 if(options[i] ==
nullptr)
150 texture_filenames.push_back(options[i]);
151 textures.push_back(texture);
157 glBindTexture(GL_TEXTURE_2D, 0);
158 glBindVertexArray(0);
159 glBindBuffer(GL_ARRAY_BUFFER, 0);
160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
163 glClearColor(0.2f, 0.2f, 0.2f, 1.f);
169 glDisable(GL_CULL_FACE);
171 glDepthFunc(GL_LESS);
172 glEnable(GL_DEPTH_TEST);
184 glDeleteTextures(textures.size(), textures.data());
192 glClearColor(1, 1, 1, 1);
193 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
198 glClearColor(0.2f, 0.2f, 0.2f, 1);
199 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
203 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
206 static float last_time= 0;
210 if(timestamp(program_filename) != last_load)
227 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
229 SDL_GetMouseState(&mousex, &mousey);
232 if(mb & SDL_BUTTON(1))
233 camera.rotation(mx, my);
234 else if(mb & SDL_BUTTON(3))
236 else if(mb & SDL_BUTTON(2))
243 camera.move(8.f * wheel.y);
247 static float time= 0;
249 static int zbuffer= 0;
251 static int freeze= 0;
252 static int reset_camera= 0;
253 static int copy_camera= 0;
254 static int paste_camera= 0;
262 Transform mvp= projection * view * model;
270 freeze= (freeze+1) % 2;
276 if(program_failed ==
false)
281 wireframe= !wireframe;
285 glBindVertexArray(vao);
286 glUseProgram(program);
290 program_uniform(program,
"modelMatrix", model);
291 program_uniform(program,
"modelInvMatrix", model.inverse());
292 program_uniform(program,
"viewMatrix", view);
293 program_uniform(program,
"viewInvMatrix", view.inverse());
294 program_uniform(program,
"projectionMatrix", projection);
295 program_uniform(program,
"projectionInvMatrix", projection.
inverse());
296 program_uniform(program,
"viewportMatrix", viewport);
297 program_uniform(program,
"viewportInvMatrix", viewport.
inverse());
299 program_uniform(program,
"mvpMatrix", mvp);
300 program_uniform(program,
"mvpInvMatrix", mvpInv);
302 program_uniform(program,
"mvMatrix", mv);
303 program_uniform(program,
"mvInvMatrix", mv.
inverse());
304 program_uniform(program,
"normalMatrix", mv.
normal());
306 program_uniform(program,
"pmin", mesh_pmin);
307 program_uniform(program,
"pmax", mesh_pmax);
311 program_uniform(program,
"time", time);
312 program_uniform(program,
"motion",
vec3(mx, my, mb & SDL_BUTTON(1)));
313 program_uniform(program,
"mouse",
vec3(mousex,
window_height() - mousey -1, mb & SDL_BUTTON(1)));
316 for(
unsigned i= 0; i < textures.size(); i++)
319 sprintf(uniform,
"texture%u", i);
324 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
332 label(widgets,
"[error] program '%s'", program_filename);
334 text_area(widgets, 20, program_log.c_str(), program_area);
338 button(widgets,
"[s] screenshot ", frame);
339 button(widgets,
"[z] depth screenshot", zbuffer);
340 button(widgets,
"capture frames", video);
342 button(widgets,
"[t] freeze time", freeze);
343 button(widgets,
"[f] reset camera", reset_camera);
344 button(widgets,
"[c] copy/save camera", copy_camera);
345 button(widgets,
"[v] paste/read camera", paste_camera);
349 label(widgets,
"program '%s' running...", program_filename);
350 if(mesh_filename && mesh_filename[0])
353 label(widgets,
"mesh '%s', %d vertices %s %s", mesh_filename, mesh.vertex_count(),
354 mesh.texcoord_buffer_size() ?
"texcoords" :
"", mesh.normal_buffer_size() ?
"normals" :
"");
356 for(
unsigned i= 0; i < texture_filenames.size(); i++)
359 label(widgets,
"texture%u '%s'", i, texture_filenames[i]);
375 printf(
"zbuffer screenshot...\n");
379 std::vector<float> tmp(image.width() * image.height());
381 glReadBuffer(GL_BACK);
382 glReadPixels(0, 0, image.width(), image.height(), GL_DEPTH_COMPONENT, GL_FLOAT, tmp.data());
385 for(
unsigned i= 0; i < image.size(); i++)
386 image(i)=
Color(tmp[i]);
388 write_image_pfm(image,
"zbuffer_viewport.pfm");
392 for(
unsigned py= 0; py < image.height(); py++)
393 for(
unsigned px= 0; px < image.width(); px++)
395 unsigned i= py * image.width() + px;
399 image(i)=
Color(p.z);
402 write_image_pfm(image,
"zbuffer_camera.pfm");
405 for(
unsigned i= 0; i < image.size(); i++)
406 image(i)=
Color(std::abs(image(i).r));
408 write_image_pfm(image,
"zbuffer_color.pfm");
420 printf(
"screenshot %d...\n", calls);
431 camera.write_orbiter(
"orbiter.txt");
433 vec3 p= camera.translation();
434 vec2 r= camera.rotation();
435 printf(
"Translation( %f, %f, %f ) * RotationX( %f ) * RotationY( %f )\n", p.x, p.y, p.z, r.x, r.y );
442 if(camera.read_orbiter(
"orbiter.txt") < 0)
445 camera.lookat(mesh_pmin, mesh_pmax);
455 camera.lookat(mesh_pmin, mesh_pmax);
462int main(
int argc,
char **argv )
466 printf(
"usage: %s shader.glsl [mesh.obj] [texture0.png [texture1.png]]\n", argv[0]);
471 if(window ==
nullptr)
475 if(context ==
nullptr)
479 std::vector<const char *> options(argv + 1, argv + argc);
480 if(
init(options) < 0)
482 printf(
"[error] init failed.\n");
representation d'une image.
representation d'un objet / maillage.
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
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().
Window create_window(const int w, const int h, const int major, const int minor)
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_fast(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)
int release_program(const GLuint program)
bool program_errors(const GLuint program)
renvoie vrai si le programme n'est pas pret.
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.
int init(std::vector< const char * > &options)
representation d'une couleur (rgba) transparente ou opaque.
representation d'un point 3d.
representation d'un vecteur 3d.
vecteur generique, utilitaire.
vecteur generique, utilitaire.