gKit2 light
shader_kit.cpp
Go to the documentation of this file.
1 
3 
4 #include <cstdio>
5 #include <cstring>
6 
7 #include "glcore.h"
8 #include "window.h"
9 
10 #include "program.h"
11 #include "uniforms.h"
12 
13 #include "texture.h"
14 #include "mesh.h"
15 #include "wavefront.h"
16 #include "buffer.h"
17 
18 #include "vec.h"
19 #include "mat.h"
20 #include "orbiter.h"
21 
22 #include "text.h"
23 #include "widgets.h"
24 
25 
26 // utilitaire
27 struct Filename
28 {
29  char path[1024];
30 
31  Filename( ) { path[0]= 0; }
32  Filename( const char *_filename ) { strcpy(path, _filename); }
33  operator const char *( ) { return path; }
34 };
35 
36 // program
37 Filename program_filename;
38 GLuint program;
39 
40 // affichage des erreurs
41 std::string program_log;
42 int program_area;
43 bool program_failed;
44 
45 Filename mesh_filename;
46 Mesh mesh;
47 Point mesh_pmin;
48 Point mesh_pmax;
49 int vertex_count;
50 GLuint vao;
51 bool wireframe= false;
52 
53 std::vector<Filename> texture_filenames;
54 std::vector<GLuint> textures;
55 
56 Orbiter camera;
57 Widgets widgets;
58 
59 // application
60 void reload_program( )
61 {
62  if(program == 0)
63  program= read_program(program_filename);
64  else
65  reload_program(program, program_filename);
66 
67  // recupere les erreurs, si necessaire
68  program_area= program_format_errors(program, program_log);
69 
70  if(program_log.size() > 0)
71  printf("[boom]\n%s\n", program_log.c_str());
72 
73  program_failed= (program_log.size() > 0);
74 }
75 
76 
77 // cherche un fichier avec l'extension ext dans les options
78 const char *option_find( std::vector<const char *>& options, const char *ext )
79 {
80  for(unsigned int i= 0; i < (unsigned int) options.size() ; i++)
81  {
82  if(std::string(options[i]).rfind(ext) != std::string::npos)
83  {
84  const char *option= options[i];
85  options[i]= options.back();
86  options.pop_back();
87  return option;
88  }
89  }
90 
91  return NULL;
92 }
93 
96 int init( std::vector<const char *>& options )
97 {
98  widgets= create_widgets();
99  camera= Orbiter();
100 
101  program= 0;
102  const char *option;
103  option= option_find(options, ".glsl");
104  if(option != NULL)
105  {
106  program_filename= Filename(option);
107  reload_program();
108  }
109 
110  glGenVertexArrays(1, &vao);
111  vertex_count= 3;
112 
113  option= option_find(options, ".obj");
114  if(option != NULL)
115  {
116  mesh= read_mesh(option);
117  if(mesh.vertex_buffer_size() > 0)
118  {
119  mesh_filename= Filename(option);
120 
121  vao= mesh.create_buffers();
122  vertex_count= mesh.vertex_count();
123 
124  mesh.bounds(mesh_pmin, mesh_pmax);
125  camera.lookat(mesh_pmin, mesh_pmax);
126  }
127  }
128 
129  // charge les textures, si necessaire
130  for(unsigned int i= 0; i < (unsigned int) options.size(); i++)
131  {
132  GLuint texture= read_texture(0, options[i]);
133  if(texture > 0)
134  {
135  texture_filenames.push_back(Filename(options[i]));
136  textures.push_back(texture);
137  }
138  }
139 
140  // nettoyage
141  glUseProgram(0);
142  glBindTexture(GL_TEXTURE_2D, 0);
143  glBindVertexArray(0);
144  glBindBuffer(GL_ARRAY_BUFFER, 0);
145  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
146 
147  // etat openGL par defaut
148  glClearColor(0.2f, 0.2f, 0.2f, 1.f);
149  glClearDepth(1.f);
150 
151  glCullFace(GL_BACK);
152  glFrontFace(GL_CCW);
153  //~ glEnable(GL_CULL_FACE); // n'affiche que les faces correctement orientees...
154  glDisable(GL_CULL_FACE); // les faces mal orientees sont affichees avec des hachures oranges...
155 
156  glDepthFunc(GL_LESS);
157  glEnable(GL_DEPTH_TEST);
158 
159  return 0;
160 }
161 
162 int quit( )
163 {
164  // detruit les objets openGL
165  release_widgets(widgets);
166  release_program(program);
168  for(unsigned int i= 0; i < (unsigned int) textures.size(); i++)
169  glDeleteTextures(1, &textures[i]);
170  return 0;
171 }
172 
173 int draw( void )
174 {
175 
176  if(wireframe)
177  {
178  glClearColor(1, 1, 1, 1);
179  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
180  glLineWidth(2);
181  }
182  else
183  {
184  glClearColor(0.2f, 0.2f, 0.2f, 1);
185  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
186  }
187 
188  // effacer l'image
189  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
190 
191  if(key_state('r'))
192  {
193  clear_key_state('r');
194  reload_program();
195  }
196 
197  // recupere les mouvements de la souris
198  int mx, my;
199  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
200  int mousex, mousey;
201  SDL_GetMouseState(&mousex, &mousey);
202 
203  // deplace la camera
204  if(mb & SDL_BUTTON(1))
205  camera.rotation(mx, my); // tourne autour de l'objet
206  else if(mb & SDL_BUTTON(2))
207  camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height()); // deplace le point de rotation
208  else if(mb & SDL_BUTTON(3))
209  camera.move(mx); // approche / eloigne l'objet
210 
211  // recupere les transformations
212  Transform model= Identity();
213  Transform view= camera.view();
214  Transform projection= camera.projection(window_width(), window_height(), 45);
216 
217  Transform mvp= projection * view * model;
218  Transform mvpInv= Inverse(mvp);
219  Transform mv= model * view;
220 
221  // affiche l'objet
222  if(program_failed == false)
223  {
224  if(key_state('w'))
225  {
226  clear_key_state('w');
227  wireframe= !wireframe;
228  }
229 
230  // configuration minimale du pipeline
231  glBindVertexArray(vao);
232  glUseProgram(program);
233 
234  // affecte une valeur aux uniforms
235  // transformations standards
236  program_uniform(program, "modelMatrix", model);
237  program_uniform(program, "modelInvMatrix", model.inverse());
238  program_uniform(program, "viewMatrix", view);
239  program_uniform(program, "viewInvMatrix", view.inverse());
240  program_uniform(program, "projectionMatrix", projection);
241  program_uniform(program, "projectionInvMatrix", projection.inverse());
242  program_uniform(program, "viewportMatrix", viewport);
243  program_uniform(program, "viewportInvMatrix", viewport.inverse());
244 
245  program_uniform(program, "mvpMatrix", mvp);
246  program_uniform(program, "mvpInvMatrix", mvpInv);
247 
248  program_uniform(program, "mvMatrix", mv);
249  program_uniform(program, "normalMatrix", mv.normal());
250 
251  // interactions
252  program_uniform(program, "viewport", vec2(window_width(), window_height()));
253  program_uniform(program, "time", (float) SDL_GetTicks());
254  program_uniform(program, "motion", vec3(mx, my, mb & SDL_BUTTON(1)));
255  program_uniform(program, "mouse", vec3(mousex, mousey, mb & SDL_BUTTON(1)));
256 
257  // textures
258  for(unsigned int i= 0; i < (unsigned int) textures.size(); i++)
259  {
260  char uniform[1024];
261  sprintf(uniform, "texture%d", i);
262  program_use_texture(program, uniform, i, textures[i]);
263  }
264 
265  // go
266  glDrawArrays(GL_TRIANGLES, 0, vertex_count);
267  }
268 
269  // affiche les infos
270  begin(widgets);
271  if(program_failed)
272  {
273  label(widgets, "[error] program '%s'", program_filename.path);
274  begin_line(widgets);
275  text_area(widgets, 20, program_log.c_str(), program_area);
276  }
277  else
278  {
279  label(widgets, "program '%s' running...", program_filename.path);
280  if(mesh_filename[0] != 0)
281  {
282  begin_line(widgets);
283  label(widgets, "mesh '%s', %d vertices %s %s", mesh_filename.path, mesh.vertex_count(),
284  mesh.texcoord_buffer_size() ? "texcoords" : "", mesh.normal_buffer_size() ? "normals" : "");
285  }
286  for(unsigned int i= 0; i < (unsigned int) texture_filenames.size(); i++)
287  {
288  begin_line(widgets);
289  label(widgets, "texture%u '%s'", i, texture_filenames[i].path);
290  }
291  }
292 
293  end(widgets);
294 
295  draw(widgets, window_width(), window_height());
296 
297 
298  if(key_state('s'))
299  {
300  clear_key_state('s');
301  screenshot("shader_kit.png");
302  }
303 
304  static bool video= false;
305  if(key_state(SDLK_RETURN))
306  {
307  clear_key_state(SDLK_RETURN);
308  video= !video;
309 
310  if(video)
311  printf("start video capture...\n");
312  else
313  printf("stop video capture.\n");
314  }
315  if(video)
316  capture("shader_kit");
317 
318  if(key_state('c'))
319  {
320  clear_key_state('c');
321  camera.write_orbiter("orbiter.txt");
322  }
323  if(key_state('v'))
324  {
325  clear_key_state('v');
326  if(camera.read_orbiter("orbiter.txt") < 0)
327  camera= Orbiter(mesh_pmin, mesh_pmax);
328  }
329 
330  return 1;
331 }
332 
333 
334 int main( int argc, char **argv )
335 {
336  if(argc == 1)
337  {
338  printf("usage: %s shader.glsl [mesh.obj] [texture0.png [texture1.png]]\n", argv[0]);
339  return 0;
340  }
341 
342  Window window= create_window(1024, 640);
343  if(window == NULL)
344  return 1;
345 
346  Context context= create_context(window);
347  if(context == NULL)
348  return 1;
349 
350  // creation des objets opengl
351  std::vector<const char *> options(argv + 1, argv + argc);
352  if(init(options) < 0)
353  {
354  printf("[error] init failed.\n");
355  return 1;
356  }
357 
358  // affichage de l'application
359  run(window, draw);
360 
361  // nettoyage
362  quit();
363  release_context(context);
364  release_window(window);
365  return 0;
366 }
Context create_context(Window window, const int major, const int minor)
cree et configure un contexte opengl
Definition: window.cpp:251
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet...
Definition: orbiter.h:16
void end(Widgets &w)
termine la description des elements de l'interface graphique.
Definition: widgets.cpp:363
void bounds(Point &pmin, Point &pmax)
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:146
Transform inverse() const
renvoie l'inverse de la matrice.
Definition: mat.cpp:260
vecteur generique, utilitaire.
Definition: vec.h:104
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:94
vecteur generique, utilitaire.
Definition: vec.h:94
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:204
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:30
representation d'un objet / maillage.
Definition: mesh.h:87
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:31
void release_vertex_format(const GLuint vao)
detruit le vertex array vao et les buffers associes, crees par make_vertex_buffer() et make_index_buf...
Definition: buffer.cpp:31
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:96
Widgets create_widgets()
cree une interface graphique. a detruire avec release_widgets( ).
Definition: widgets.cpp:12
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:100
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:199
GLuint create_buffers(const bool use_texcoord=true, const bool use_normal=true, const bool use_color=true)
Definition: mesh.cpp:189
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition: mat.cpp:218
void program_uniform(const GLuint program, const char *uniform, const unsigned int v)
affecte une valeur a un uniform du shader program. uint.
Definition: uniforms.cpp:54
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 filtrages...
Definition: uniforms.cpp:104
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:38
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:14
int capture(const char *prefix)
Definition: texture.cpp:125
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:110
GLuint read_texture(const int unit, const char *filename)
cree une texture a partir d'un fichier filename. a detruire avec glDeleteTextures( )...
Definition: texture.cpp:97
int read_orbiter(const char *filename)
relit la position de l'orbiter depuis un fichier texte.
Definition: orbiter.cpp:77
Transform projection(const float width, const float height, const float fov) const
renvoie la projection reglee pour une image d'aspect width / height, et une ouverture de fov degres...
Definition: orbiter.cpp:45
void text_area(Widgets &w, const int height, const char *text, int &begin_line)
Definition: widgets.cpp:232
void release_widgets(Widgets &w)
detruit l'interface graphique.
Definition: widgets.cpp:23
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:6
Window create_window(const int w, const int h)
creation d'une fenetre pour l'application.
Definition: window.cpp:187
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:150
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition: window.cpp:24
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
Definition: mesh.h:209
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:25
int program_format_errors(const GLuint program, std::string &errors)
renvoie les erreurs de compilation.
Definition: program.cpp:257
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Definition: widgets.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
void begin_line(Widgets &w)
place les prochains elements sur une nouvelle ligne.
Definition: widgets.cpp:129
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:19
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:18
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:157
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:305
representation d'un point 3d.
Definition: vec.h:19
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:192
void label(Widgets &w, const char *format,...)
cree un texte. meme fonctionnement que printf().
Definition: widgets.cpp:142
int write_orbiter(const char *filename)
enregistre la position de l'orbiter dans un fichier texte.
Definition: orbiter.cpp:108
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier filename nom de l'image a ecrire. doit etre de type .png / .bmp
Definition: texture.cpp:104
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:222
int run(Window window, int(*draw)(void))
fonction principale. gestion des evenements et appel de la fonction draw de l'application.
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).
Definition: wavefront.cpp:8