gKit2 light
Loading...
Searching...
No Matches
tuto5GL_cubemap.cpp File Reference

dessiner une cubemap a l'infini. More...

#include <stdio.h>
#include "window.h"
#include "vec.h"
#include "mat.h"
#include "program.h"
#include "uniforms.h"
#include "texture.h"
#include "mesh.h"
#include "wavefront.h"
#include "orbiter.h"
#include "image_io.h"

Go to the source code of this file.

Functions

int init ()
int quit ()
int draw ()
int main (int argc, char **argv)

Variables

GLuint program
GLuint program_cubemap
GLuint texture
GLuint vao
GLuint vao_null
GLuint vertex_buffer
GLuint normal_buffer
int vertex_count
Orbiter camera

Detailed Description

dessiner une cubemap a l'infini.

Definition in file tuto5GL_cubemap.cpp.

Function Documentation

◆ init()

int init ( )

Definition at line 35 of file tuto5GL_cubemap.cpp.

36{
37 // etape 1 : shaders
38 // . dessiner le reflet de la cubemap sur un objet
39 program= read_program("gkit2_tutos/tuto5GL_cubemap.glsl");
40 program_print_errors(program);
41
42 // . dessiner la cubemap a l'infini
43 program_cubemap= read_program("gkit2_tutos/cubemap.glsl");
44 program_print_errors(program_cubemap);
45
46 // etape 2 : charger un mesh, (avec des normales), vao + vertex buffer
47 //~ Mesh mesh= read_mesh("data/bigguy.obj");
48 Mesh mesh= read_mesh("data/cube.obj");
49 if(mesh.vertex_count() == 0)
50 return -1; // gros probleme, pas de sommets...
51
52 vertex_count= mesh.vertex_count();
53
54 Point pmin, pmax;
55 mesh.bounds(pmin, pmax);
56 camera.lookat(pmin, pmax);
57
58 // vertex format : position + normal,
59 glGenVertexArrays(1, &vao);
60 glBindVertexArray(vao);
61
62 // vertex buffer
63 glGenBuffers(1, &vertex_buffer);
64 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
65 glBufferData(GL_ARRAY_BUFFER, mesh.vertex_buffer_size(), mesh.vertex_buffer(), GL_STATIC_DRAW);
66
67 // configurer l'attribut position, cf declaration dans le vertex shader : in vec3 position;
68 GLint position= glGetAttribLocation(program, "position");
69 if(position >= 0)
70 {
71 glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, 0);
72 glEnableVertexAttribArray(position);
73 }
74
75 // normal buffer
76 if(!mesh.normal_buffer_size())
77 {
78 printf("[oops] pas de normales...\n");
79 return -1;
80 }
81
82 glGenBuffers(1, &normal_buffer);
83 glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
84 glBufferData(GL_ARRAY_BUFFER, mesh.normal_buffer_size(), mesh.normal_buffer(), GL_STATIC_DRAW);
85
86 GLint normal= glGetAttribLocation(program, "normal");
87 if(normal >= 0)
88 {
89 glVertexAttribPointer(normal, 3, GL_FLOAT, GL_FALSE, 0, 0);
90 glEnableVertexAttribArray(normal);
91 }
92
93 // nettoyage
94 mesh.release();
95 glBindVertexArray(0);
96 glBindBuffer(GL_ARRAY_BUFFER, 0);
97
98 // etape 3 : texture
99#if 0
100 ImageData tmp= read_image_data("data/debug2x2red.png");
101 //~ ImageData image= flipX(flipY(tmp));
102 ImageData image= flipY(tmp);
103
104 // solution 1, utiliser une seule texture *carree* et la copier sur les 6 faces de la cubemap
105 int size= image.width;
106
107 GLenum data_format;
108 GLenum data_type= GL_UNSIGNED_BYTE;
109 if(image.channels == 3)
110 data_format= GL_RGB;
111 else // par defaut
112 data_format= GL_RGBA;
113
114 // creer la texture
115 glGenTextures(1, &texture);
116 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
117
118 // creer les 6 faces
119 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0,
120 GL_RGBA, size, size, 0,
121 data_format, data_type, image.data());
122
123 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0,
124 GL_RGBA, size, size, 0,
125 data_format, data_type, image.data());
126
127 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,
128 GL_RGBA, size, size, 0,
129 data_format, data_type, image.data());
130
131 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,
132 GL_RGBA, size, size, 0,
133 data_format, data_type, image.data());
134
135 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,
136 GL_RGBA, size, size, 0,
137 data_format, data_type, image.data());
138
139 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,
140 GL_RGBA, size, size, 0,
141 data_format, data_type, image.data());
142#endif
143
144#if 0
145 // les 6 faces sur une bande
146 ImageData image= read_image_data("gkit2_tutos/cubemap_debug.png");
147
148 // les 6 images sont regroupees sur une bande horizontale.
149 int size= image.width / 6;
150
151 GLenum data_format;
152 GLenum data_type= GL_UNSIGNED_BYTE;
153 if(image.channels == 3)
154 data_format= GL_RGB;
155 else // par defaut
156 data_format= GL_RGBA;
157
158 // creer la texture
159 glGenTextures(1, &texture);
160 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
161
162 // creer les 6 faces
163 // chaque face de la cubemap est un bloc [image.width/6 x image.height] dans l'image originale
164 int faces[]= { 0, 1, 2, 3, 4, 5 };
165
166 // largeur totale de l'image
167 for(int i= 0; i < 6; i++)
168 {
169 // extrait la face
170 ImageData face= flipX(flipY(copy(image, faces[i]*size, 0, size, size)));
171 //~ ImageData face= copy(image, faces[i]*size, 0, size, size);
172
173 // transferer les pixels
174 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X +i, 0,
175 GL_RGBA, size, size, 0,
176 data_format, data_type, face.data());
177 }
178#endif
179
180#if 1
181// http://paulbourke.net/miscellaneous/cubemaps/
182
183 // les 6 faces sur une croix
184 ImageData image= read_image_data("canyon2.jpg");
185 //~ ImageData image= read_image_data("html/cubemap_debug_cross.png");
186
187 int w= image.width / 4;
188 int h= image.height / 3;
189 assert(w == h);
190
191 GLenum data_format;
192 GLenum data_type= GL_UNSIGNED_BYTE;
193 if(image.channels == 3)
194 data_format= GL_RGB;
195 else // par defaut
196 data_format= GL_RGBA;
197
198 // creer la texture
199 glGenTextures(1, &texture);
200 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
201
202 // creer les 6 faces
203 // chaque face de la cubemap est un rectangle [image.width/4 x image.height/3] dans l'image originale
204 struct { int x, y; } faces[]= {
205 {0, 1}, // X+
206 {2, 1}, // X-
207 {1, 2}, // Y+
208 {1, 0}, // Y-
209 {1, 1}, // Z+
210 {3, 1}, // Z-
211 };
212
213 for(int i= 0; i < 6; i++)
214 {
215 ImageData face= flipX(flipY(copy(image, faces[i].x*w, faces[i].y*h, w, h)));
216 //~ ImageData face= copy(image, faces[i].x*w, faces[i].y*h, w, h);
217
218 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X +i, 0,
219 GL_RGBA, w, h, 0,
220 data_format, data_type, face.data());
221 }
222#endif
223
224#if 0
225 // 6 images
226 const char *filenames[]= {
227 "data/cubemap/cubemap_opensea/opensea_posx.png",
228 "data/cubemap/cubemap_opensea/opensea_negx.png",
229 "data/cubemap/cubemap_opensea/opensea_posy.png",
230 "data/cubemap/cubemap_opensea/opensea_negy.png",
231 "data/cubemap/cubemap_opensea/opensea_posz.png",
232 "data/cubemap/cubemap_opensea/opensea_negz.png"
233 //~ "data/cubemap/skybox/left.jpg",
234 //~ "data/cubemap/skybox/right.jpg",
235 //~ "data/cubemap/skybox/top.jpg",
236 //~ "data/cubemap/skybox/bottom.jpg",
237 //~ "data/cubemap/skybox/back.jpg",
238 //~ "data/cubemap/skybox/front.jpg",
239 };
240
241 // creer la texture
242 glGenTextures(1, &texture);
243 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
244
245 for(int i= 0; i < 6; i++)
246 {
247 ImageData tmp= read_image_data(filenames[i]);
248 //~ ImageData image= flipX(flipY(tmp));
249 ImageData image= flipY(tmp); // les faces haut/bas sont retouchees a la main...
250
251 GLenum data_format;
252 GLenum data_type= GL_UNSIGNED_BYTE;
253 if(image.channels == 3)
254 data_format= GL_RGB;
255 else // par defaut
256 data_format= GL_RGBA;
257
258 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X +i, 0,
259 GL_RGBA, image.width, image.height, 0,
260 data_format, data_type, image.data());
261 }
262#endif
263
264 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
265
266 // filtrage "correct" sur les bords du cube...
267 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
268 //~ glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
269 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
270
271 // etape 4 : vao pour dessiner la cubemap a l'infini
272 glGenVertexArrays(1, &vao_null);
273 glBindVertexArray(vao_null);
274 // pas de buffer, c'est le vertex shader qui genere directement les positions des sommets
275
276 glUseProgram(0);
277 glBindVertexArray(0);
278
279 // etat par defaut
280 glClearColor(0.2f, 0.2f, 0.2f, 1);
281 glClearDepthf(1);
282
283 glDepthFunc(GL_LEQUAL); // !! attention !! le support de la cube map est dessine exactement sur le plan far
284 // et le test "classique" GL_LESS est toujours faux, la cubemap ne sera pas dessinee.
285
286 glEnable(GL_DEPTH_TEST);
287
288 glFrontFace(GL_CCW);
289 glCullFace(GL_BACK);
290 //~ glEnable(GL_CULL_FACE);
291 glDisable(GL_CULL_FACE);
292 return 0;
293}
representation d'un objet / maillage.
Definition mesh.h:121
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
Image flipY(const Image &image)
retourne l'image
Definition image_io.cpp:113
Image flipX(const Image &image)
retourne l'image
Definition image_io.cpp:130
ImageData read_image_data(const void *buffer, const unsigned size, const bool flipY)
charge les donnees d'un fichier png stocke en memoire. renvoie une image initialisee par defaut en ca...
Definition image_io.cpp:335
Image copy(const Image &image, const unsigned xmin, const unsigned ymin, const unsigned width, const unsigned height)
renvoie un bloc de l'image
Definition image_io.cpp:146
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:217
int program_print_errors(const GLuint program, const char *filename)
affiche les erreurs de compilation.
Definition program.cpp:461
stockage temporaire des donnees d'une image.
Definition image_io.h:55
representation d'un point 3d.
Definition vec.h:21

◆ quit()

int quit ( )

Definition at line 295 of file tuto5GL_cubemap.cpp.

296{
297 release_program(program);
298 release_program(program_cubemap);
299 glDeleteVertexArrays(1, &vao);
300 glDeleteVertexArrays(1, &vao_null);
301 glDeleteBuffers(1, &vertex_buffer);
302 glDeleteBuffers(1, &normal_buffer);
303 glDeleteTextures(1, &texture);
304 return 0;
305}
int release_program(const GLuint program)
detruit les shaders et le program.
Definition program.cpp:240

◆ draw()

int draw ( void )

Definition at line 307 of file tuto5GL_cubemap.cpp.

308{
309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310
311#if 1
312 // recupere les mouvements de la souris, utilise directement SDL2
313 int mx, my;
314 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
315
316 // deplace la camera
317 if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
318 // tourne autour de l'objet
319 camera.rotation(mx, my);
320
321 else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
322 // approche / eloigne l'objet
323 camera.move(mx);
324
325 else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
326 // deplace le point de rotation
327 camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
328#endif
329
330 /* config pipeline :
331 vertex array object
332 program
333 uniforms
334 texture
335 */
336 // recupere le point de vue et la projection de la camera
337 Transform model= Identity();
338 Transform view= camera.view();
339 Transform projection= camera.projection(window_width(), window_height(), 45);
340
341 // compose les matrices pour passer du repere local de l'objet au repere projectif
342 Transform mvp= projection * view * model;
343
344 // dessine l'objet avec le reflet de la cubemap
345 {
346 glBindVertexArray(vao);
347 glUseProgram(program);
348
349 program_uniform(program, "mvpMatrix", mvp);
350 program_uniform(program, "mMatrix", model);
351 program_uniform(program, "camera_position", Inverse(view)(Point(0, 0, 0)));
352
353 // texture
354 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
355
356 // sampler2D declare par le fragment shader
357 GLint location= glGetUniformLocation(program, "texture0");
358 glUniform1i(location, 0);
359 // ou program_uniform(program, "texture0", texture);
360
361 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
362 }
363
364 // dessine la cubemap sur les autres pixels...
365 {
366 glBindVertexArray(vao_null);
367 glUseProgram(program_cubemap);
368
369 // texture
370 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
371
372 // sampler2D declare par le fragment shader
373 GLint location= glGetUniformLocation(program_cubemap, "texture0");
374 glUniform1i(location, 0);
375 // ou program_uniform(program, "texture0", texture);
376
377 program_uniform(program_cubemap, "vpInvMatrix", Inverse(projection * view));
378 program_uniform(program_cubemap, "camera_position", Inverse(view)(Point(0, 0, 0)));
379
380 // dessine un triangle qui couvre tous les pixels de l'image
381 glDrawArrays(GL_TRIANGLES, 0, 3);
382 }
383
384 if(key_state('s'))
385 {
386 clear_key_state('s');
387 static int calls= 0;
388 screenshot("cubemaps", ++calls);
389 }
390
391 // nettoyage
392 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
393 glUseProgram(0);
394 glBindVertexArray(0);
395
396 return 1;
397}
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition window.cpp:27
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition window.cpp:59
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:53
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition window.cpp:23
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition mat.cpp:197
Transform Identity()
construit la transformation identite.
Definition mat.cpp:187
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
Definition texture.cpp:178
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition mat.h:21

◆ main()

int main ( int argc,
char ** argv )

Definition at line 400 of file tuto5GL_cubemap.cpp.

401{
402 // etape 1 : creer la fenetre
403 Window window= create_window(1024, 640);
404 if(window == NULL)
405 return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
406
407 // etape 2 : creer un contexte opengl pour pouvoir dessiner
408 Context context= create_context(window);
409 if(context == NULL)
410 return 1; // erreur lors de la creation du contexte opengl
411
412 // etape 3 : creation des objets
413 if(init() < 0)
414 {
415 printf("[error] init failed.\n");
416 return 1;
417 }
418
419 // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee. ou que draw() ne renvoie pas 0
420 run(window, draw);
421
422 // etape 5 : nettoyage
423 quit();
424 release_context(context);
425 release_window(window);
426 return 0;
427}
Context create_context(Window window)
cree et configure un contexte opengl
Definition window.cpp:358
void release_window(Window window)
destruction de la fenetre.
Definition window.cpp:328
int run(Window window, int(*draw)())
boucle de gestion des evenements de l'application.
Definition window.cpp:158
Window create_window(const int w, const int h, const int major, const int minor)
creation d'une fenetre pour l'application.
Definition window.cpp:262
void release_context(Context context)
detruit le contexte openGL.
Definition window.cpp:439
int init(std::vector< const char * > &options)

Variable Documentation

◆ program

GLuint program

Definition at line 21 of file tuto5GL_cubemap.cpp.

◆ program_cubemap

GLuint program_cubemap

Definition at line 22 of file tuto5GL_cubemap.cpp.

◆ texture

GLuint texture

Definition at line 24 of file tuto5GL_cubemap.cpp.

◆ vao

GLuint vao

Definition at line 26 of file tuto5GL_cubemap.cpp.

◆ vao_null

GLuint vao_null

Definition at line 27 of file tuto5GL_cubemap.cpp.

◆ vertex_buffer

GLuint vertex_buffer

Definition at line 28 of file tuto5GL_cubemap.cpp.

◆ normal_buffer

GLuint normal_buffer

Definition at line 29 of file tuto5GL_cubemap.cpp.

◆ vertex_count

int vertex_count

Definition at line 30 of file tuto5GL_cubemap.cpp.

◆ camera

Orbiter camera

Definition at line 32 of file tuto5GL_cubemap.cpp.