gKit2 light
tuto_deferred_decal.cpp
Go to the documentation of this file.
1 
3 
4 
5 #include "wavefront.h"
6 #include "texture.h"
7 #include "program.h"
8 #include "uniforms.h"
9 #include "framebuffer.h"
10 
11 #include "orbiter.h"
12 #include "draw.h"
13 #include "app_camera.h" // classe Application a deriver
14 
15 
16 // utilitaire. creation d'une grille / repere.
17 // n= 0 ne dessine que les axes du repere.
18 Mesh make_grid( const int n= 10 )
19 {
20  glLineWidth(2);
21  Mesh grid= Mesh(GL_LINES);
22 
23  // grille
24  grid.color(White());
25  for(int x= 0; x < n; x++)
26  {
27  float px= float(x) - float(n)/2 + .5f;
28  grid.vertex(px, 0, - float(n)/2 + .5f);
29  grid.vertex(px, 0, float(n)/2 - .5f);
30  }
31 
32  for(int z= 0; z < n; z++)
33  {
34  float pz= float(z) - float(n)/2 + .5f;
35  grid.vertex(- float(n)/2 + .5f, 0, pz);
36  grid.vertex(float(n)/2 - .5f, 0, pz);
37  }
38 
39  // axes XYZ
40  grid.color(Red());
41  grid.vertex(0, .1, 0);
42  grid.vertex(1, .1, 0);
43 
44  grid.color(Green());
45  grid.vertex(0, .1, 0);
46  grid.vertex(0, 1, 0);
47 
48  grid.color(Blue());
49  grid.vertex(0, .1, 0);
50  grid.vertex(0, .1, 1);
51 
52  return grid;
53 }
54 
55 // utilitaire. creation d'un plan / sol
56 Mesh make_ground( const int n= 10 )
57 {
58  Mesh grid= Mesh(GL_TRIANGLES);
59 
60  grid.normal(0, 1, 0);
61  int a= grid.vertex(-n/2, -1, n/2);
62  int b= grid.vertex( n/2, -1, n/2);
63  int c= grid.vertex( n/2, -1, -n/2);
64  int d= grid.vertex(-n/2, -1, -n/2);
65  grid.triangle(a, b, c);
66  grid.triangle(a, c, d);
67 
68  return grid;
69 }
70 
71 Mesh make_xyz( )
72 {
73  glLineWidth(2);
74  Mesh camera= Mesh(GL_LINES);
75 
76  // axes XYZ
77  camera.color(Red());
78  camera.vertex(Point(0, 0, 0));
79  camera.vertex(Point(1, 0, 0));
80 
81  camera.color(Green());
82  camera.vertex(Point(0, 0, 0));
83  camera.vertex(Point(0, 1, 0));
84 
85  camera.color(Blue());
86  camera.vertex(Point(0, 0, 0));
87  camera.vertex(Point(0, 0, 1));
88 
89  return camera;
90 }
91 
92 Mesh make_frustum( )
93 {
94  glLineWidth(2);
95  Mesh camera= Mesh(GL_LINES);
96 
97  camera.color(Yellow());
98  // face avant
99  camera.vertex(-1, -1, -1);
100  camera.vertex(-1, 1, -1);
101  camera.vertex(-1, 1, -1);
102  camera.vertex(1, 1, -1);
103  camera.vertex(1, 1, -1);
104  camera.vertex(1, -1, -1);
105  camera.vertex(1, -1, -1);
106  camera.vertex(-1, -1, -1);
107 
108  // face arriere
109  camera.vertex(-1, -1, 1);
110  camera.vertex(-1, 1, 1);
111  camera.vertex(-1, 1, 1);
112  camera.vertex(1, 1, 1);
113  camera.vertex(1, 1, 1);
114  camera.vertex(1, -1, 1);
115  camera.vertex(1, -1, 1);
116  camera.vertex(-1, -1, 1);
117 
118  // aretes
119  camera.vertex(-1, -1, -1);
120  camera.vertex(-1, -1, 1);
121  camera.vertex(-1, 1, -1);
122  camera.vertex(-1, 1, 1);
123  camera.vertex(1, 1, -1);
124  camera.vertex(1, 1, 1);
125  camera.vertex(1, -1, -1);
126  camera.vertex(1, -1, 1);
127 
128  return camera;
129 }
130 
131 class TP : public AppCamera
132 {
133 public:
134  // constructeur : donner les dimensions de l'image, et eventuellement la version d'openGL.
135  TP( ) : AppCamera(1024, 640) {}
136 
137  // creation des objets de l'application
138  int init( )
139  {
140  // decrire un repere / grille
141  m_repere= make_grid(20);
142  m_local= make_grid(2);
143  //~ m_ground= make_ground(20);
144  m_ground= read_mesh("ground.obj");
145  m_proxy= make_xyz();
146  m_frustum= make_frustum();
147  m_frustum_cube= read_mesh("data/frustum.obj");
148 
149  // charge l'element
150  m_objet= read_mesh("data/robot.obj");
151 
152  //~ m_texture= read_texture(0, "data/grid.png");
153  //~ m_texture= read_texture(0, "decal_shadow.png");
154  m_texture= read_texture(0, "orange_splash.png");
155  //~ m_texture= read_texture(0, "yellow_splash.png");
156  //~ m_texture= read_texture(0, "red_splash.png");
157 
158  m_mesh_program= read_program("tutos/deferred_mesh.glsl");
159  program_print_errors(m_mesh_program);
160  m_decal_program= read_program("tutos/deferred_decal.glsl");
161  program_print_errors(m_decal_program);
162 
163  // position initiale de l'objet
164  m_position= Identity();
165 
166  // si l'objet est "gros", il faut regler la camera pour l'observer entierement :
167  // recuperer les points extremes de l'objet (son englobant)
168  Point pmin, pmax;
169  m_ground.bounds(pmin, pmax);
170  // parametrer la camera de l'application, renvoyee par la fonction camera()
171  camera().lookat(pmin, pmax);
172 
173  m_framebuffer.create(window_width(), window_height());
174  m_framebuffer.clear_color(Black());
175  m_framebuffer.clear_depth(1);
176 
177  // etat openGL par defaut
178  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
179 
180  glClearDepth(1.f); // profondeur par defaut
181  glDepthFunc(GL_LEQUAL); // ztest, conserver l'intersection la plus proche de la camera
182  glEnable(GL_DEPTH_TEST); // activer le ztest
183 
184  return 0; // ras, pas d'erreur
185  }
186 
187  // destruction des objets de l'application
188  int quit( )
189  {
190  m_objet.release();
191  m_repere.release();
192  m_local.release();
193  m_ground.release();
194  m_proxy.release();
195 
196  m_framebuffer.release();
197  release_program(m_mesh_program);
198  release_program(m_decal_program);
199  glDeleteTextures(1, &m_texture);
200  return 0;
201  }
202 
203  // dessiner une nouvelle image
204  int render( )
205  {
206  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
207 
208  // modifie la position de l'objet en fonction des fleches de direction
209  if(key_state(SDLK_UP))
210  m_position= m_position * Translation(0, 0, 0.15); // en avant
211  if(key_state(SDLK_DOWN))
212  m_position= m_position * Translation(0, 0, -0.15); // en arriere
213  if(key_state(SDLK_PAGEUP))
214  m_position= m_position * Translation(0, 0.15, 0); // en haut
215  if(key_state(SDLK_PAGEDOWN))
216  m_position= m_position * Translation(0, -0.15, 0); // en bas
217 
218  if(key_state(SDLK_LEFT))
219  m_position= m_position * RotationY(2); // tourne vers la droite
220  if(key_state(SDLK_RIGHT))
221  m_position= m_position * RotationY(-2); // tourne vers la gauche
222 
223 
224  // transformations de la camera de l'application
225  Transform view= camera().view();
226  Transform projection= camera().projection();
227 
228  // dessine les objets dans le framebuffer... ceux sur lesquels on veut projetter le decal...
229  {
230  m_framebuffer.bind(0, /* store_color */ true, /* store_depth */ true, /* store_position */ false, /* store_texcoord */ false, /* store_normal */ false, /* store_material */ false);
231  // dessine le decor
232  draw(m_ground, /* model */ Identity(), view, projection);
233 
234  //~ // dessine l'objet, ou pas ...
235  //~ draw(m_objet, /* model */ m_position, view, projection);
236 
237  m_framebuffer.unbind(window_width(), window_height());
238  }
239 
240  // copie les textures vers la fenetre
241  m_framebuffer.blit_color(0, 0, window_width(), window_height());
242  m_framebuffer.blit_depth(0, 0, window_width(), window_height());
243 
244  // positionne le decal
245  Transform r= RotationX(-90);
246  Transform t= Translation(0,0, 8);
247  Transform m= r * t;
248 
249  Transform decal_view= Inverse(m_position * m);
250  //~ Transform decal_projection= Perspective(35, 1, float(0.1), float(10));
251  Transform decal_projection= Ortho(-2, 2, -2, 2, float(0.1), float(10));
252 
253  // dessine le frustum pour verifier que le placement est correct...
254  {
255  // passage repere projection vers global : inverse de projection*view
256  Transform decal_model= Inverse(decal_projection * decal_view);
257 
258  // juste les aretes
259  draw(m_frustum, decal_model, view, projection);
260  //~ // ou le proxy / un cube
261  //~ draw(m_frustum_cube, decal_model, view, projection);
262 
263  // dessine le repere utilise pour placer le decal...
264  draw(m_proxy, /* model */ m_position * m, view, projection);
265  }
266 
267  // dessine / projette le decal sur les objets dessines dans le framebuffer et modifie la couleur des pixels de la fenetre.
268  // == execute le fragment shader pour les pixels sur lesquels le decal peut se projetter
269  glUseProgram(m_decal_program);
270  {
271  // passage repere projection vers global : inverse de projection*view
272  {
273  Transform model= Inverse(decal_projection * decal_view);
274  Transform mv= view * model;
275  Transform mvp= projection * mv;
276 
277  program_uniform(m_decal_program, "mvpMatrix", mvp);
278  }
279 
280  {
281  // reprojette le fragment stocke dans le framebuffer dans le repere du monde
283  Transform m= Inverse(viewport * projection * view);
284  // puis passage du monde dans le repere de projection du decal
285  Transform decal_viewport= Viewport(1, 1);
286  Transform inv= decal_viewport * decal_projection * decal_view * m;
287 
288  program_uniform(m_decal_program, "invMatrix", inv);
289  }
290 
291  program_use_texture(m_decal_program, "decal_texture", 0, m_texture);
292  m_framebuffer.use_color_texture(m_decal_program, "color_texture", 1);
293  m_framebuffer.use_depth_texture(m_decal_program, "depth_texture", 2);
294 
295  // dessiner sans modifier le zbuffer / la profondeur stockee
296  glDepthMask(GL_FALSE);
297  m_frustum_cube.draw(m_decal_program, /* position */ true, /* texcoord */ false, /* normal */ false, /* color */ false, /* material id */ false);
298 
299  glDepthMask(GL_TRUE);
300  }
301 
302  // dessine les objets, sans decals...
303  // dessine l'objet, ou pas ...
304  draw(m_objet, /* model */ m_position, view, projection);
305 
306  // dessine aussi le repere local
307  draw(m_local, /* model */ m_position, view, projection);
308 
309  // screenshot
310  if(key_state('s'))
311  {
312  clear_key_state('s');
313  static int id= 1;
314  screenshot("camera", id++);
315  }
316 
317  // continuer...
318  return 1;
319  }
320 
321 protected:
322  Mesh m_objet;
323  Mesh m_repere;
324  Mesh m_local;
325  Mesh m_proxy;
326  Mesh m_frustum;
327  Mesh m_frustum_cube;
328  Mesh m_ground;
329  Transform m_position;
330  Framebuffer m_framebuffer;
331  GLuint m_texture;
332  GLuint m_mesh_program;
333  GLuint m_decal_program;
334 };
335 
336 
337 int main( int argc, char **argv )
338 {
339  // il ne reste plus qu'a creer un objet application et la lancer
340  TP tp;
341  tp.run();
342 
343  return 0;
344 }
classe application.
Definition: app_camera.h:19
const Orbiter & camera() const
renvoie l'orbiter gere par l'application.
Definition: app_camera.h:37
int run()
execution de l'application.
Definition: app.cpp:36
representation d'un objet / maillage.
Definition: mesh.h:112
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Definition: mesh.cpp:111
void bounds(Point &pmin, Point &pmax) const
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:503
void draw(const GLuint program, const bool use_position, const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index)
dessine l'objet avec un shader program.
Definition: mesh.cpp:770
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:192
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:90
void release()
detruit les objets openGL.
Definition: mesh.cpp:64
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Definition: mesh.cpp:80
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
Transform projection(const int width, const int height, const float fov)
fixe la projection reglee pour une image d'aspect width / height, et une demi ouverture de fov degres...
Definition: orbiter.cpp:47
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
Definition: alpha.cpp:59
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 init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:48
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:42
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
Color Red()
utilitaire. renvoie une couleur rouge.
Definition: color.cpp:57
Color Yellow()
utilitaire. renvoie une couleur jaune.
Definition: color.cpp:72
Color Blue()
utilitaire. renvoie une couleur bleue.
Definition: color.cpp:67
Color Black()
utilitaire. renvoie une couleur noire.
Definition: color.cpp:47
Color Green()
utilitaire. renvoie une couleur verte.
Definition: color.cpp:62
Color White()
utilitaire. renvoie une couleur blanche.
Definition: color.cpp:52
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:197
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition: mat.cpp:357
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Transform RotationX(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe X.
Definition: mat.cpp:230
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:242
Transform Ortho(const float left, const float right, const float bottom, const float top, const float znear, const float zfar)
renvoie la matrice representant une transformation orthographique, passage d'un cube []x[]x[] vers [-...
Definition: mat.cpp:343
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
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
Definition: texture.cpp:188
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
void program_uniform(const GLuint program, const char *uniform, const std::vector< unsigned > &v)
affecte un tableau de valeurs a un uniform du shader program.
Definition: uniforms.cpp:94
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
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,...
Definition: uniforms.cpp:198
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
Definition: texture.cpp:148
void release()
destruction.
Definition: framebuffer.cpp:33
void unbind(const int width, const int height)
desactive le framebuffer, selection du framebuffer par defaut associe a la fenetre.
GLuint create(const int width, const int height)
creation du framebuffer
Definition: framebuffer.cpp:13
void clear_color(const Color &value)
couleur par defaut.
void clear_depth(const float value)
profondeur par defaut.
void bind(const GLuint program, const bool store_color, const bool store_depth, const bool store_position, const bool store_texcoord, const bool store_normal, const bool store_material)
selection du framebuffer, stocker les sorties du fragment shader. les textures sont initialisees avec...
Definition: framebuffer.cpp:51
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21