gKit2 light
tuto1GL.cpp
Go to the documentation of this file.
1 
3 
4 #include <fstream>
5 #include <sstream>
6 #include <string>
7 
8 #include "glcore.h"
9 
10 #include "SDL2/SDL.h"
11 
12 /* une application opengl est composee de plusieurs composants :
13  1. une fenetre pour voir ce que l'on dessine
14  2. un contexte openGL pour dessiner
15  3. 3 fonctions :
16  init( ) pour creer les objets que l'on veut dessiner,
17  draw( ) pour les afficher / dessiner
18  quit( ) pour detruire les objets openGL crees dans init( ), a la fermeture de l'application
19 
20  ces 3 fonctions sont appelees dans le main.
21  */
22 
23 
24 // identifiants des shaders
25 GLuint vertex_shader;
26 GLuint fragment_shader;
27 // identifiant du shader program
28 GLuint program;
29 
30 // identifiant du vertex array object
31 GLuint vao;
32 
33 
34 // utilitaire : charger un fichier texte et renvoyer une chaine de caracteres.
35 std::string read( const char *filename )
36 {
37  std::stringbuf source;
38  std::ifstream in(filename);
39  // verifie que le fichier existe
40  if(in.good() == false)
41  printf("[error] loading program '%s'...\n", filename);
42  else
43  printf("loading program '%s'...\n", filename);
44 
45  // lire le fichier, le caractere '\0' ne peut pas se trouver dans le source de shader
46  in.get(source, 0);
47  // renvoyer la chaine de caracteres
48  return source.str();
49 }
50 
51 
52 // creation des objets openGL
53 bool init_program( )
54 {
55  // charger le source du vertex shader
56  std::string vertex_source= read("tutos/tuto1GL_vertex.glsl");
57  // creer un objet openGL : vertex shader
58  vertex_shader= glCreateShader(GL_VERTEX_SHADER);
59 
60  // preparer les chaines de caracteres pour compiler le shader
61  const char *vertex_strings[]= { vertex_source.c_str() };
62  glShaderSource(vertex_shader, 1, vertex_strings, NULL);
63  // compiler les sources
64  glCompileShader(vertex_shader);
65 
66  // pareil pour le fragment shader
67  std::string fragment_source= read("tutos/tuto1GL_fragment.glsl");
68  fragment_shader= glCreateShader(GL_FRAGMENT_SHADER);
69  const char *fragment_strings[]= { fragment_source.c_str() };
70  glShaderSource(fragment_shader, 1, fragment_strings, NULL);
71  glCompileShader(fragment_shader);
72 
73  // creer un object openGL : shader program
74  program= glCreateProgram();
75  // inclure les 2 shaders dans le program
76  glAttachShader(program, vertex_shader);
77  glAttachShader(program, fragment_shader);
78  // linker les shaders
79  glLinkProgram(program);
80 
81  // verifier que tout c'est bien passe, si les shaders ne se sont pas compiles correctement, le link du program va echouer.
82  GLint status;
83  glGetProgramiv(program, GL_LINK_STATUS, &status);
84  if(status == GL_FALSE)
85  {
86  printf("[error] compiling shaders / linking pogram...\n");
87  return false;
88  }
89 
90  // ok, pas d'erreur
91  return true;
92 }
93 
94 bool init_vao( )
95 {
96  // creer un objet openGL : vertex array object
97  glGenVertexArrays(1, &vao);
98 
99  return true;
100 }
101 
102 bool init( )
103 {
104  // init shader program
105  if(!init_program())
106  return false;
107 
108  // init vao
109  if(!init_vao())
110  return false;
111 
112  // options globales du pipeline
113  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // dessiner dans les images associees a la fenetre
114  glDrawBuffer(GL_BACK); // dessiner dans l'image non affichee de la fenetre
115 
116 /* cf l'option SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); dans main() qui demande la creation d'au moins 2 images, GL_FRONT et GL_BACK.
117  GL_FRONT est l'image affichee par la fenetre, on peut dessiner dans GL_BACK sans perturber l'affichage. lorsque le dessin est fini, on echange les 2 images...
118 
119  remarque : si une seule image est associee a la fenetre,
120  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
121  utiliser :
122  glDrawBuffer(GL_FRONT);
123  */
124 
125  glViewport(0, 0, 1024, 640); // definir la region (x, y, largeur, hauteur) de la fenetre dans laquelle dessiner
126 
127  glClearColor(0.2, 0.2, 0.2, 1); // definir la couleur par defaut (gris)
128 
129  glDisable(GL_DEPTH_TEST); // pas de test sur la profondeur
130  glDisable(GL_CULL_FACE); // pas de test sur l'orientation
131 
132  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // dessiner tous les pixels du triangle
133 
134  return true;
135 }
136 
137 
138 // destruction des objets openGL
139 void quit( )
140 {
141  glDeleteShader(vertex_shader);
142  glDeleteShader(fragment_shader);
143  glDeleteProgram(program);
144  glDeleteVertexArrays(1, &vao);
145 }
146 
147 
148 // affichage
149 void draw( )
150 {
151  // effacer la fenetre : copier la couleur par defaut dans tous les pixels de la fenetre
152  // cf init(): glClearColor(0.2, 0.2, 0.2, 1);
153  glClear(GL_COLOR_BUFFER_BIT);
154 
155  // configurer le pipeline, selectionner le vertex array a utiliser
156  glBindVertexArray(vao);
157 
158  // configurer le pipeline, selectionner le shader program a utiliser
159  glUseProgram(program);
160 
161  // pas d'uniforms dans le shader program, donc rien a faire...
162 
163  // dessiner 1 triangle, soit 3 indices (gl_VertexID varie de 0 a 3)
164  glDrawArrays(GL_TRIANGLES, 0, 3);
165 }
166 
167 
168 int main( int argc, char **argv )
169 {
170  // init sdl
171  if(SDL_Init(SDL_INIT_VIDEO) < 0)
172  {
173  printf("[error] SDL_Init() failed:\n%s\n", SDL_GetError());
174  return 1; // erreur lors de l'init de sdl2
175  }
176 
177  // enregistre le destructeur de sdl
178  atexit(SDL_Quit);
179 
180  // etape 1 : creer la fenetre, utilise sdl
181  SDL_Window *window= SDL_CreateWindow("gKit", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 640, SDL_WINDOW_OPENGL);
182  if(window == NULL)
183  {
184  printf("[error] SDL_CreateWindow() failed.\n");
185  return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
186  }
187 
188  // etape 2 : creer un contexte opengl core profile pour dessiner, utilise sdl2
189  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // version 3.3
190  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
191  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); // infos de debug
192  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // version moderne
193 
194  // dessiner dans une image differente de celle affichee par la fenetre de l'application
195  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
196 
197  SDL_GLContext context= SDL_GL_CreateContext(window);
198  if(context == NULL)
199  {
200  printf("[error] creating openGL context.\n");
201  return 1;
202  }
203 
204  SDL_GL_SetSwapInterval(1); // attendre l'ecran pour echanger les images affichee et buffer de dessin
205 
206 #ifndef NO_GLEW
207  // initialise les extensions opengl, si necessaire
208  glewExperimental= 1;
209  GLenum err= glewInit();
210  if(err != GLEW_OK)
211  {
212  printf("[error] loading extensions\n%s\n", glewGetErrorString(err));
213  SDL_GL_DeleteContext(context);
214  SDL_DestroyWindow(window);
215  return 1; // erreur lors de l'init de glew / import des fonctions opengl
216  }
217 
218  // purge les erreurs opengl generees par glew !
219  while(glGetError() != GL_NO_ERROR) {;}
220 #endif
221 
222  // etape 3 : creation des objets
223  if(!init())
224  {
225  printf("[error] init failed.\n");
226  return 1;
227  }
228 
229  // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee.
230  bool done= false;
231  while(!done)
232  {
233  // gestion des evenements
234  SDL_Event event;
235  while(SDL_PollEvent(&event))
236  {
237  if(event.type == SDL_QUIT)
238  done= true; // sortir si click sur le bouton de la fenetre
239  else if(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)
240  done= true; // sortir si la touche esc / echapp est enfoncee
241  }
242 
243  // dessiner
244  draw();
245 
246  // presenter / montrer le resultat, echanger les images associees a la fenetre, GL_FRONT et GL_BACK, cf init()
247  SDL_GL_SwapWindow(window);
248  }
249 
250  // etape 5 : nettoyage
251  quit();
252 
253  SDL_GL_DeleteContext(context);
254  SDL_DestroyWindow(window);
255  return 0;
256 }
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
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:96