gKit2 light
Loading...
Searching...
No Matches
tuto5GL_dynamic_cubemap.cpp
Go to the documentation of this file.
1
3
4#include <stdio.h>
5
6#include "window.h"
7#include "vec.h"
8#include "mat.h"
9
10#include "program.h"
11#include "uniforms.h"
12
13#include "mesh.h"
14#include "wavefront.h"
15
16#include "orbiter.h"
17#include "image_io.h"
18
19
20GLuint program;
21GLuint program_cubemap;
22GLuint program_render_cubemap;
23
24GLuint texture_cubemap;
25GLuint depth_cubemap;
26GLuint framebuffer;
27
28GLuint vao;
29GLuint vao_null;
30GLuint vertex_buffer;
31GLuint normal_buffer;
32int vertex_count;
33
34Orbiter camera;
35
36int init( )
37{
38 // etape 1 : shaders
39 // . dessiner le reflet de la cubemap sur un objet
40 program= read_program("gkit2_tutos/cubemap.glsl");
41 program_print_errors(program);
42
43 // . dessiner la cubemap a l'infini
44 program_cubemap= read_program("gkit2_tutos/cubemap.glsl");
45 program_print_errors(program_cubemap);
46
47 // . dessiner dans une cube map
48 program_render_cubemap= read_program("gkit2_tutos/render_cubemap.glsl");
49 program_print_errors(program_render_cubemap);
50
51 // etape 2 : charger un mesh, (avec des normales), vao + vertex buffer
52 Mesh mesh= read_mesh("data/bigguy.obj");
53 //~ Mesh mesh= read_mesh("data/cube.obj");
54 if(mesh.vertex_count() == 0)
55 return -1; // gros probleme, pas de sommets...
56
57 vertex_count= mesh.vertex_count();
58
59 Point pmin, pmax;
60 mesh.bounds(pmin, pmax);
61 camera.lookat(pmin, pmax);
62
63 // vertex format : position + normal,
64 glGenVertexArrays(1, &vao);
65 glBindVertexArray(vao);
66
67 // vertex buffer
68 glGenBuffers(1, &vertex_buffer);
69 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
70 glBufferData(GL_ARRAY_BUFFER, mesh.vertex_buffer_size(), mesh.vertex_buffer(), GL_STATIC_DRAW);
71
72 // configurer l'attribut position, cf declaration dans le vertex shader : in vec3 position;
73 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
74 glEnableVertexAttribArray(0);
75
76 // normal buffer
77 if(!mesh.has_normal())
78 {
79 printf("[oops] pas de normales...\n");
80 return -1;
81 }
82
83 glGenBuffers(1, &normal_buffer);
84 glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
85 glBufferData(GL_ARRAY_BUFFER, mesh.normal_buffer_size(), mesh.normal_buffer(), GL_STATIC_DRAW);
86
87 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
88 glEnableVertexAttribArray(1);
89
90 // nettoyage
91 mesh.release();
92 glBindVertexArray(0);
93 glBindBuffer(GL_ARRAY_BUFFER, 0);
94
95 // etape 3 : textures + framebuffer
96 {
97 int w= 1024;
98 int h= 1024;
99
100 // 6 faces couleur
101 glGenTextures(1, &texture_cubemap);
102 glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
103 for(int i= 0; i < 6; i++)
104 {
105 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X +i, 0,
106 GL_RGBA, w, h, 0,
107 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
108 }
109 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
110
111 // 6 faces profondeur
112 glGenTextures(1, &depth_cubemap);
113 glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap);
114 for(int i= 0; i < 6; i++)
115 {
116 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X +i, 0,
117 GL_DEPTH_COMPONENT, w, h, 0,
118 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
119 }
120
121 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
122 }
123
124 // framebuffer, attache les 6 faces couleur + profondeur
125 glGenFramebuffers(1, &framebuffer);
126 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
127 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_cubemap, 0);
128 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0);
129
130 glBindFramebuffer(GL_FRAMEBUFFER, 0);
131
132
133 // filtrage "correct" sur les bords du cube...
134 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
135 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
136
137 // etape 4 : vao pour dessiner la cubemap a l'infini
138 glGenVertexArrays(1, &vao_null);
139 glBindVertexArray(vao_null);
140 // pas de buffer, c'est le vertex shader qui genere directement les positions des sommets
141
142 glUseProgram(0);
143 glBindVertexArray(0);
144
145 // etat par defaut
146 glClearColor(0.2f, 0.2f, 0.2f, 1);
147 glClearDepthf(1);
148
149 glDepthFunc(GL_LEQUAL); // !! attention !! le support de la cube map est dessine exactement sur le plan far
150 // et le test "classique" GL_LESS est toujours faux, la cubemap ne sera pas dessinee.
151
152 glEnable(GL_DEPTH_TEST);
153
154 glFrontFace(GL_CCW);
155 glCullFace(GL_BACK);
156 //~ glEnable(GL_CULL_FACE);
157 glDisable(GL_CULL_FACE);
158 return 0;
159}
160
161int quit( )
162{
163 release_program(program);
164 release_program(program_cubemap);
165 release_program(program_render_cubemap);
166 glDeleteVertexArrays(1, &vao);
167 glDeleteVertexArrays(1, &vao_null);
168 glDeleteBuffers(1, &vertex_buffer);
169 glDeleteBuffers(1, &normal_buffer);
170 glDeleteTextures(1, &texture_cubemap);
171 glDeleteTextures(1, &depth_cubemap);
172 glDeleteFramebuffers(1, &framebuffer);
173 return 0;
174}
175
176int draw( )
177{
178 // partie 1 : dessiner dans la cubemap dynamique
179 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
180 glViewport(0, 0, 1024, 1024);
181
182 // efface les 6 faces couleur + profondeur attachees au framebuffer
183 //~ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
184 float black[4]= { 0, 0, 0, 0 };
185 glClearBufferfv(GL_COLOR, 0, black);
186
187 float one= 1;
188 glClearBufferfv(GL_DEPTH, 0, &one);
189
190 {
191 // prepare les 6 matrices view, une par face de la cubemap
192 // !! attention a la direction 'up' de lookat... rappel : orientation des textures des cubemaps...
193 Transform faces[6];
194 faces[0]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(1, 0, 0), /* up */ Vector(0, -1, 0)); // +X
195 faces[1]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(-1, 0, 0), /* up */ Vector(0, -1, 0)); // -X
196
197 faces[2]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(0, 1, 0), /* up */ Vector(0, 0, 1)); // +Y
198 faces[3]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(0, -1, 0), /* up */ Vector(0, 0, -1)); // -Y
199
200 faces[4]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(0, 0, 1), /* up */ Vector(0, -1, 0)); // +Z
201 faces[5]= Lookat(/* from */ Point(0, 0, 0), /* to */ Point(0, 0, -1), /* up */ Vector(0, -1, 0)); // -Z
202
203 Transform model= Identity();
204 Transform projection= Perspective(45, 1, 0.01, 100);
205
206 // dessine 6 fois la scene
207 glBindVertexArray(vao);
208 glUseProgram(program_render_cubemap);
209 glUniformMatrix4fv(glGetUniformLocation(program_render_cubemap, "projectionMatrix"), 1, GL_TRUE, projection.buffer());
210 glUniformMatrix4fv(glGetUniformLocation(program_render_cubemap, "modelMatrix"), 1, GL_TRUE, model.buffer());
211 glUniformMatrix4fv(glGetUniformLocation(program_render_cubemap, "viewMatrix"), 6, GL_TRUE, faces[0].buffer());
212
213 // mais avec un seul draw... qui dessine chaque triangle 6 fois, une fois par face de la cubemap, avec les 6 transformations correspondantes
214 glDrawArraysInstanced(GL_TRIANGLES, 0, vertex_count, 6);
215 }
216
217 // mise a jour des mipmaps des faces de la cubemap
218 glBindFramebuffer(GL_FRAMEBUFFER, 0);
219 glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
220 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
221
222 // partie 2 : dessiner avec la cubemap dynamique
223 glBindFramebuffer(GL_FRAMEBUFFER, 0);
224 glViewport(0, 0, window_width(), window_height());
225
226 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
227
228 // recupere les mouvements de la souris, utilise directement SDL2
229 int mx, my;
230 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
231
232 // deplace la camera
233 if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
234 // tourne autour de l'objet
235 camera.rotation(mx, my);
236
237 else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
238 // approche / eloigne l'objet
239 camera.move(mx);
240
241 else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
242 // deplace le point de rotation
243 camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
244
245 /* config pipeline :
246 vertex array object
247 program
248 uniforms
249 texture
250 */
251 // recupere le point de vue et la projection de la camera
252 Transform model= Identity();
253 Transform view= camera.view();
254 Transform projection= camera.projection(window_width(), window_height(), 45);
255
256 // compose les matrices pour passer du repere local de l'objet au repere projectif
257 Transform mvp= projection * view * model;
258
259 // dessine l'objet avec le reflet de la cubemap
260 {
261 glBindVertexArray(vao);
262 glUseProgram(program);
263
264 program_uniform(program, "mvpMatrix", mvp);
265 program_uniform(program, "modelMatrix", model);
266 program_uniform(program, "camera_position", Inverse(view)(Point(0, 0, 0)));
267
268 // texture
269 glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
270
271 // sampler2D declare par le fragment shader
272 GLint location= glGetUniformLocation(program, "texture0");
273 glUniform1i(location, 0);
274 // ou program_uniform(program, "texture0", texture);
275
276 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
277 }
278
279 // dessine la cubemap sur les autres pixels...
280 {
281 glBindVertexArray(vao_null);
282 glUseProgram(program_cubemap);
283
284 // texture
285 glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
286
287 // sampler2D declare par le fragment shader
288 GLint location= glGetUniformLocation(program_cubemap, "texture0");
289 glUniform1i(location, 0);
290 // ou program_uniform(program, "texture0", texture);
291
292 program_uniform(program_cubemap, "vpInvMatrix", Inverse(projection * view));
293 program_uniform(program_cubemap, "camera_position", Inverse(view)(Point(0, 0, 0)));
294
295 // dessine un triangle qui couvre tous les pixels de l'image
296 glDrawArrays(GL_TRIANGLES, 0, 3);
297 }
298
299 // nettoyage
300 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
301 glUseProgram(0);
302 glBindVertexArray(0);
303
304 return 1;
305}
306
307
308int main( int argc, char **argv )
309{
310 // etape 1 : creer la fenetre
311 Window window= create_window(1024, 640);
312 if(window == NULL)
313 return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
314
315 // etape 2 : creer un contexte opengl pour pouvoir dessiner
316 Context context= create_context(window);
317 if(context == NULL)
318 return 1; // erreur lors de la creation du contexte opengl
319
320 // verifier que l'extension est disponible
321 if(GLEW_ARB_shader_viewport_layer_array)
322 printf("ARB_shader_viewport_layer_array supported\n");
323
324 else
325 {
326 printf("[error] ARB_shader_viewport_layer_array NOT supported...\n");
327 return 1;
328 }
329
330 // etape 3 : creation des objets
331 if(init() < 0)
332 {
333 printf("[error] init failed.\n");
334 return 1;
335 }
336
337 // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee. ou que draw() ne renvoie pas 0
338 run(window, draw);
339
340 // etape 5 : nettoyage
341 quit();
342 release_context(context);
343 release_window(window);
344 return 0;
345}
representation d'un objet / maillage.
Definition mesh.h:121
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition orbiter.h:17
Context create_context(Window window)
cree et configure un contexte opengl
Definition window.cpp:358
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition window.cpp:27
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
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)
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 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
Transform Perspective(const float fov, const float aspect, const float znear, const float zfar)
renvoie la matrice representant une transformation projection perspective.
Definition mat.cpp:329
Transform Lookat(const Point &from, const Point &to, const Vector &up)
renvoie la matrice representant le placement et l'orientation d'une camera pour observer le point to.
Definition mat.cpp:369
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
int release_program(const GLuint program)
detruit les shaders et le program.
Definition program.cpp:240
int init(std::vector< const char * > &options)
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
representation d'un vecteur 3d.
Definition vec.h:67