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, program_filename);
67 last_load= timestamp(program_filename);
72 if(program_log.size() > 0)
73 printf(
"[boom]\n%s\n", program_log.c_str());
75 program_failed= (program_log.size() > 0);
80const char *option_find( std::vector<const char *>& options,
const char *ext )
82 for(
unsigned int i= 0; i < (
unsigned int) options.size() ; i++)
84 if(options[i] !=
nullptr && std::string(options[i]).rfind(ext) != std::string::npos)
86 const char *option= options[i];
97int init( std::vector<const char *>& options )
104 option= option_find(options,
".glsl");
105 if(option !=
nullptr)
107 program_filename= option;
115 option= option_find(options,
".obj");
116 if(option !=
nullptr)
122 if(mesh.vertex_count() > 0)
124 mesh_filename= option;
126 vao= mesh.create_buffers(mesh.has_texcoord(), mesh.has_normal(), mesh.has_color(), mesh.has_material_index());
127 vertex_count= mesh.vertex_count();
129 mesh.bounds(mesh_pmin, mesh_pmax);
130 camera.lookat(mesh_pmin, mesh_pmax);
138 glGenVertexArrays(1, &vao);
143 for(
unsigned i= 0; i < options.size(); i++)
145 if(options[i] ==
nullptr)
151 texture_filenames.push_back(options[i]);
152 textures.push_back(texture);
158 glBindTexture(GL_TEXTURE_2D, 0);
159 glBindVertexArray(0);
160 glBindBuffer(GL_ARRAY_BUFFER, 0);
161 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
164 glClearColor(0.2f, 0.2f, 0.2f, 1.f);
170 glDisable(GL_CULL_FACE);
172 glDepthFunc(GL_LESS);
173 glEnable(GL_DEPTH_TEST);
185 glDeleteTextures(textures.size(), textures.data());
193 glClearColor(1, 1, 1, 1);
194 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
199 glClearColor(0.2f, 0.2f, 0.2f, 1);
200 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
204 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
207 static float last_time= 0;
211 if(timestamp(program_filename) != last_load)
228 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
230 SDL_GetMouseState(&mousex, &mousey);
233 if(mb & SDL_BUTTON(1))
234 camera.rotation(mx, my);
235 else if(mb & SDL_BUTTON(3))
237 else if(mb & SDL_BUTTON(2))
244 camera.move(8.f * wheel.y);
248 static float time= 0;
250 static int zbuffer= 0;
252 static int freeze= 0;
253 static int reset_camera= 0;
254 static int copy_camera= 0;
255 static int paste_camera= 0;
263 Transform mvp= projection * view * model;
271 freeze= (freeze+1) % 2;
277 if(program_failed ==
false)
282 wireframe= !wireframe;
286 glBindVertexArray(vao);
287 glUseProgram(program);
291 program_uniform(program,
"modelMatrix", model);
292 program_uniform(program,
"modelInvMatrix", model.inverse());
293 program_uniform(program,
"viewMatrix", view);
294 program_uniform(program,
"viewInvMatrix", view.inverse());
295 program_uniform(program,
"projectionMatrix", projection);
296 program_uniform(program,
"projectionInvMatrix", projection.
inverse());
297 program_uniform(program,
"viewportMatrix", viewport);
298 program_uniform(program,
"viewportInvMatrix", viewport.
inverse());
300 program_uniform(program,
"mvpMatrix", mvp);
301 program_uniform(program,
"mvpInvMatrix", mvpInv);
303 program_uniform(program,
"mvMatrix", mv);
304 program_uniform(program,
"mvInvMatrix", mv.
inverse());
305 program_uniform(program,
"normalMatrix", mv.
normal());
307 program_uniform(program,
"pmin", mesh_pmin);
308 program_uniform(program,
"pmax", mesh_pmax);
312 program_uniform(program,
"time", time);
313 program_uniform(program,
"motion",
vec3(mx, my, mb & SDL_BUTTON(1)));
314 program_uniform(program,
"mouse",
vec3(mousex,
window_height() - mousey -1, mb & SDL_BUTTON(1)));
317 for(
unsigned i= 0; i < textures.size(); i++)
320 sprintf(uniform,
"texture%u", i);
325 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
333 label(widgets,
"[error] program '%s'", program_filename);
335 text_area(widgets, 20, program_log.c_str(), program_area);
339 button(widgets,
"[s] screenshot ", frame);
340 button(widgets,
"[z] depth screenshot", zbuffer);
341 button(widgets,
"capture frames", video);
343 button(widgets,
"[t] freeze time", freeze);
344 button(widgets,
"[f] reset camera", reset_camera);
345 button(widgets,
"[c] copy/save camera", copy_camera);
346 button(widgets,
"[v] paste/read camera", paste_camera);
350 label(widgets,
"program '%s' running...", program_filename);
351 if(mesh_filename && mesh_filename[0])
354 label(widgets,
"mesh '%s', %d vertices %s %s", mesh_filename, mesh.vertex_count(),
355 mesh.texcoord_buffer_size() ?
"texcoords" :
"", mesh.normal_buffer_size() ?
"normals" :
"");
357 for(
unsigned i= 0; i < texture_filenames.size(); i++)
360 label(widgets,
"texture%u '%s'", i, texture_filenames[i]);
376 printf(
"zbuffer screenshot...\n");
380 std::vector<float> tmp(image.width() * image.height());
382 glReadBuffer(GL_BACK);
383 glReadPixels(0, 0, image.width(), image.height(), GL_DEPTH_COMPONENT, GL_FLOAT, tmp.data());
386 for(
unsigned i= 0; i < image.size(); i++)
387 image(i)=
Color(tmp[i]);
389 write_image_pfm(image,
"zbuffer_viewport.pfm");
393 for(
unsigned py= 0; py < image.height(); py++)
394 for(
unsigned px= 0; px < image.width(); px++)
396 unsigned i= py * image.width() + px;
397 Point fragment=
Point(
float(px) +
float(0.5),
float(py) +
float(0.5), tmp[i]);
398 Point p= inv( fragment );
400 image(i)=
Color(p.z);
403 write_image_pfm(image,
"zbuffer_camera.pfm");
406 for(
unsigned i= 0; i < image.size(); i++)
407 image(i)=
Color(std::abs(image(i).r));
409 write_image_pfm(image,
"zbuffer_color.pfm");
421 printf(
"screenshot %d...\n", calls);
432 camera.write_orbiter(
"orbiter.txt");
434 vec3 p= camera.translation();
435 vec2 r= camera.rotation();
436 printf(
"Translation( %f, %f, %f ) * RotationX( %f ) * RotationY( %f )\n", p.x, p.y, p.z, r.x, r.y );
443 if(camera.read_orbiter(
"orbiter.txt") < 0)
446 camera.lookat(mesh_pmin, mesh_pmax);
456 camera.lookat(mesh_pmin, mesh_pmax);
463int main(
int argc,
char **argv )
467 printf(
"usage: %s shader.glsl [mesh.obj] [texture0.png [texture1.png]]\n", argv[0]);
472 if(window ==
nullptr)
476 if(context ==
nullptr)
480 std::vector<const char *> options(argv + 1, argv + argc);
481 if(
init(options) < 0)
483 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, 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_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)
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.
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.