gKit2 light
tuto4GL.cpp
Go to the documentation of this file.
1 
3 
4 #include "window.h"
5 #include "vec.h"
6 #include "mat.h"
7 
8 #include "program.h"
9 
10 #include "orbiter.h"
11 #include "mesh.h"
12 #include "wavefront.h"
13 
14 #include <stdio.h>
15 
16 // shader program
17 GLuint program;
18 
19 // vertex array object
20 GLuint vao;
21 GLuint vertex_buffer;
22 int vertex_count;
23 
24 // camera
25 Orbiter camera;
26 
27 
28 int init( )
29 {
30  // compile un shader program
31  program= read_program("tutos/tuto4GL.glsl");
32  program_print_errors(program);
33 
34  // charge un objet
35  Mesh mesh= read_mesh("data/bigguy.obj");
36  vertex_count= mesh.vertex_count();
37 
38  // camera
39  Point pmin, pmax;
40  mesh.bounds(pmin, pmax);
41  camera.lookat(pmin, pmax);
42 
43 /* creation du vertex buffer :
44  en plusieurs etapes : creer le buffer, allouer un espace de stockage et transferer des donnees
45 
46  rappel: l'objet manipule par les fonctions de l'api est implicite, il doit etre selectionne avant.
47  pour un vertex buffer, utiliser GL_ARRAY_BUFFER
48  */
49  glGenBuffers(1, &vertex_buffer);
50  // selectionne le buffer pour l'initialiser
51  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
52 
53  // dimensionne le buffer actif sur array_buffer, l'alloue et l'initialise avec les positions des sommets de l'objet
54  glBufferData(GL_ARRAY_BUFFER,
55  /* length */ mesh.vertex_buffer_size(),
56  /* data */ mesh.vertex_buffer(),
57  /* usage */ GL_STATIC_DRAW);
58  // GL_STATIC_DRAW decrit l'utilisation du contenu du buffer. dans ce cas, utilisation par draw, sans modifications
59 
60 /* le buffer est cree et initialise, mais il est toujours selectionne sur array_buffer,
61  on peut le de-selectionner (ou pas) pour revenir a l'etat par defaut :
62  glBindBuffer(GL_ARRAY_BUFFER, 0);
63  le buffer 0 est un objet null
64  */
65 
66 /* description du format des sommets :
67  creer un vertex array object, c'est l'objet qui represente le format des sommets
68  recuperer l'identifiant d'un attribut declare par le vertex shader,
69  decrire l'organisation des donnees a l'interieur du vertex buffer selectionne sur array_buffer
70  activer l'attribut
71  */
72  // creation d'un vertex array object
73  glGenVertexArrays(1, &vao);
74  // pour configurer le vao, il faut le selectionner
75  glBindVertexArray(vao);
76 
77  // recuperer l'identifiant de l'attribut : cf in vec3 position; dans le vertex shader
78  GLint attribute= glGetAttribLocation(program, "position");
79  if(attribute < 0)
80  // gros probleme...
81  return -1;
82  // le shader program doit etre compile sans erreurs avant...
83 
84  // format et organisation des donnees dans le vertex buffer selectionne sur array_buffer,
85  glVertexAttribPointer(attribute, 3, GL_FLOAT, // l'attribut est un vec3,
86  /* not normalized */ GL_FALSE, // les valeurs ne sont pas normalisees entre 0, et 1
87  /* stride */ 0, // les vec3 sont ranges les uns a la suite des autres
88  /* offset */ 0); // et se trouvent au debut du buffer
89 
90  glEnableVertexAttribArray(attribute);
91  // cette description est stockee dans le vertex array object selectionne...
92 
93 /* le vertex buffer utilise est celui actuellement selectionne sur array_buffer.
94  eventuellement, il faut selectionner le vertex buffer, avant glVertexAttribPointer()
95  */
96 
97  // nettoyage
98  glBindVertexArray(0);
99  glBindBuffer(GL_ARRAY_BUFFER, 0);
100 
101  // etat par defaut openGL
102  glClearColor(0.2f, 0.2f, 0.2f, 1);
103  glClearDepthf(1);
104  // glViewport(0, 0, window_width(), window_height()) // deja fait dans run( )
105 
106  glDepthFunc(GL_LESS);
107  glEnable(GL_DEPTH_TEST);
108 
109  glFrontFace(GL_CCW);
110  glCullFace(GL_BACK);
111  glEnable(GL_CULL_FACE);
112  return 0;
113 }
114 
115 int quit( )
116 {
117  release_program(program);
118  glDeleteBuffers(1, &vertex_buffer);
119  glDeleteVertexArrays(1, &vao);
120  return 0;
121 }
122 
123 int draw( )
124 {
125  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
126 
127  // todo recuperez les mouvements de la souris pour deplacer la camera, cf tutos/tuto6.cpp
128  // recupere les mouvements de la souris, utilise directement SDL2
129  int mx, my;
130  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
131 
132  // deplace la camera
133  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
134  // tourne autour de l'objet
135  camera.rotation(mx, my);
136 
137  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
138  // approche / eloigne l'objet
139  camera.move(mx);
140 
141  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
142  // deplace le point de rotation
143  camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
144 
145 
146 /* configuration minimale du pipeline
147  vertex array
148  shader program
149  uniforms du shader program
150  */
151  glBindVertexArray(vao);
152 
153  glUseProgram(program);
154 
155  // recupere le point de vue et la projection de la camera
156  Transform model= Identity();
157  Transform view= camera.view();
158  Transform projection= camera.projection(window_width(), window_height(), 45);
159 
160  // compose les matrices pour passer du repere local de l'objet au repere projectif
161  Transform mvp= projection * view * model;
162 
163  GLuint location;
164  location= glGetUniformLocation(program, "mvpMatrix");
165  glUniformMatrix4fv(location, 1, GL_TRUE, mvp.data());
166 
167 /* plus direct :
168  #include "uniforms.h"
169  program_uniform(program, "mvpMatrix", mvp);
170  */
171 
172  location= glGetUniformLocation(program, "color");
173  glUniform3f(location, 1, 0.5, 0);
174 // ou program_uniform(program, "color", 1, 0.5, 0);
175 
176  glDrawArrays(GL_TRIANGLES, 0, vertex_count);
177 
178  // nettoyage
179  glUseProgram(0);
180  glBindVertexArray(0);
181  return 1;
182 }
183 
184 
185 int main( int argc, char **argv )
186 {
187  // etape 1 : creer la fenetre
188  Window window= create_window(1024, 640);
189  if(window == NULL)
190  return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
191 
192  // etape 2 : creer un contexte opengl pour pouvoir dessiner
193  Context context= create_context(window);
194  if(context == NULL)
195  return 1; // erreur lors de la creation du contexte opengl
196 
197  // etape 3 : creation des objets
198  if(init() < 0)
199  {
200  printf("[error] init failed.\n");
201  return 1;
202  }
203 
204  // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee. ou que draw() ne renvoie pas 0
205  run(window, draw);
206 
207  // etape 5 : nettoyage
208  quit();
209  release_context(context);
210  release_window(window);
211  return 0;
212 }
representation d'un objet / maillage.
Definition: mesh.h:112
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL....
Definition: mesh.h:296
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
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:298
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:291
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition: orbiter.h:17
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
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
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
Context create_context(Window window)
cree et configure un contexte opengl
Definition: window.cpp:356
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:325
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
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.
Definition: window.cpp:259
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:422
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition: wavefront.cpp:14
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
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
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:96
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
const float * data() const
renvoie l'adresse de la premiere valeur de la matrice.
Definition: mat.h:75
int run(Window window, int(*draw)())
boucle de gestion des evenements de l'application.
Definition: window.cpp:147