gKit2 light

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

tuto_framebuffer.cpp
Go to the documentation of this file.
1
3
4 #include "vec.h"
5 #include "mat.h"
6
7 #include "mesh.h"
8 #include "wavefront.h"
9 #include "texture.h"
10
11 #include "program.h"
12 #include "uniforms.h"
13
14 #include "orbiter.h"
15 #include "app.h" // classe Application a deriver
16
17
18 class Framebuffer : public App
19 {
20 public:
21 // constructeur : donner les dimensions de l'image, et eventuellement la version d'openGL.
22 Framebuffer( ) : App(1024, 640) {}
23
24 int init( )
25 {
26 m_framebuffer_width= 512;
27 m_framebuffer_height= 512;
28
29 // etape 1 : creer une texture couleur...
30 glGenTextures(1, &m_color_buffer);
31 glBindTexture(GL_TEXTURE_2D, m_color_buffer);
32
33 glTexImage2D(GL_TEXTURE_2D, 0,
34 GL_RGBA, m_framebuffer_width, m_framebuffer_height, 0,
35 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
36
37 // ... et tous ses mipmaps
38 glGenerateMipmap(GL_TEXTURE_2D);
39
40 // etape 1 : creer aussi une texture depth, sinon pas de zbuffer...
41 glGenTextures(1, &m_depth_buffer);
42 glBindTexture(GL_TEXTURE_2D, m_depth_buffer);
43
44 glTexImage2D(GL_TEXTURE_2D, 0,
45 GL_DEPTH_COMPONENT, m_framebuffer_width, m_framebuffer_height, 0,
46 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
47
48 // un seul mipmap pour le zbuffer
49 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
50
51 // etape 2 : creer et configurer un framebuffer object
52 glGenFramebuffers(1, &m_framebuffer);
53 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
54 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, /* attachment */ GL_COLOR_ATTACHMENT0, /* texture */ m_color_buffer, /* mipmap level */ 0);
55 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, /* attachment */ GL_DEPTH_ATTACHMENT, /* texture */ m_depth_buffer, /* mipmap level */ 0);
56
57 GLenum buffers[]= { GL_COLOR_ATTACHMENT0 };
58 glDrawBuffers(1, buffers);
59
60 // nettoyage
61 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
62
63 // charge un mesh
64 Mesh mesh= read_mesh("data/cube.obj");
65 if(mesh == Mesh::error()) return -1;
66
67 Point pmin, pmax;
68 mesh.bounds(pmin, pmax);
69 m_camera.lookat(pmin, pmax);
70 m_framebuffer_camera.lookat(pmin, pmax);
71
72 m_vertex_count= mesh.vertex_count();
73
74 m_color_texture= read_texture(0, "data/debug2x2red.png");
75
76 // cree les buffers et le vao
77 glGenVertexArrays(1, &m_vao);
78 glBindVertexArray(m_vao);
79
80 // buffer : positions + texcoords + normals
81 glGenBuffers(1, &m_buffer);
82 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
83
84 size_t size= mesh.vertex_buffer_size() + mesh.texcoord_buffer_size() + mesh.normal_buffer_size();
85 glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
86
87 // transfere les positions des sommets
88 size_t offset= 0;
89 size= mesh.vertex_buffer_size();
90 glBufferSubData(GL_ARRAY_BUFFER, offset, size, mesh.vertex_buffer());
91 // configure l'attribut 0, vec3 position
92 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
93 glEnableVertexAttribArray(0);
94
95 // transfere les texcoords des sommets
96 offset= offset + size;
97 size= mesh.texcoord_buffer_size();
98 glBufferSubData(GL_ARRAY_BUFFER, offset, size, mesh.texcoord_buffer());
99 // configure l'attribut 1, vec2 texcoord
100 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
101 glEnableVertexAttribArray(1);
102
103 // transfere les normales des sommets
104 offset= offset + size;
105 size= mesh.normal_buffer_size();
106 glBufferSubData(GL_ARRAY_BUFFER, offset, size, mesh.normal_buffer());
107 // configure l'attribut 2, vec3 normal
108 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
109 glEnableVertexAttribArray(2);
110
111 //
112 mesh.release();
113 glBindVertexArray(0);
114 glBindBuffer(GL_ARRAY_BUFFER, 0);
115
116 // shaders
117 m_texture_program= read_program("tutos/texcoords.glsl");
118 program_print_errors(m_texture_program);
119
120 // etat openGL par defaut
121 glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
122
123 glClearDepthf(1.f); // profondeur par defaut
124 glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
125 glEnable(GL_DEPTH_TEST); // activer le ztest
126
127 return 0; // ras, pas d'erreur
128 }
129
130 // destruction des objets de l'application
131 int quit( )
132 {
133 glDeleteTextures(1, &m_color_buffer);
134 glDeleteTextures(1, &m_depth_buffer);
135 glDeleteFramebuffers(1, &m_framebuffer);
136
137 release_program(m_texture_program);
138 glDeleteTextures(1, &m_color_texture);
139 glDeleteVertexArrays(1, &m_vao);
140 glDeleteBuffers(1, &m_buffer);
141 return 0;
142 }
143
144 int update( const float time, const float delta )
145 {
146 m_model= RotationY(time / 20);
147 return 0;
148 }
149
150 // dessiner une nouvelle image
151 int render( )
152 {
153 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
154
155 // deplace la camera
156 int mx, my;
157 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
158 if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
159 m_camera.rotation(mx, my);
160 else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
161 m_camera.move(mx);
162 else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
163 m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
164
165
166 /* passe 1 : dessiner dans le framebuffer
167 */
168 {
169 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
170 glViewport(0, 0, m_framebuffer_width, m_framebuffer_height);
171 glClearColor(1, 1, 0, 1);
172 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
173
174 // draw "classique"
175 glBindVertexArray(m_vao);
176 glUseProgram(m_texture_program);
177
178 Transform m= m_model;
179 Transform v= m_framebuffer_camera.view();
180 Transform p= m_framebuffer_camera.projection(m_framebuffer_width, m_framebuffer_height, 45);
181 Transform mvp= p * v * m;
182 Transform mv= v * m;
183
184 program_uniform(m_texture_program, "mvpMatrix", mvp);
185 program_uniform(m_texture_program, "mvMatrix", mv);
186 program_uniform(m_texture_program, "normalMatrix", mv.normal());
187 program_use_texture(m_texture_program, "color_texture", 0, m_color_texture, 0);
188
189 glDrawArrays(GL_TRIANGLES, 0, m_vertex_count);
190 }
191
192 if(key_state(' '))
193 {
194 /* montrer le resultat de la passe 1
195 copie le framebuffer sur la fenetre
196 */
197
198 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
199 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
200 glViewport(0, 0, window_width(), window_height());
201 glClearColor(0, 0, 0, 1);
202 glClear(GL_COLOR_BUFFER_BIT);
203
204 glBlitFramebuffer(0, 0, m_framebuffer_width, m_framebuffer_height,
205 0, 0, m_framebuffer_width, m_framebuffer_height,
206 GL_COLOR_BUFFER_BIT, GL_LINEAR);
207 }
208 else
209 {
210 /* passe 2 : utiliser la texture du framebuffer
211 */
212
213 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
214 glViewport(0, 0, window_width(), window_height());
215 glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
216 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
217
218 // draw "classique"
219 glBindVertexArray(m_vao);
220 glUseProgram(m_texture_program);
221
222 Transform m= m_model;
223 Transform v= m_camera.view();
224 Transform p= m_camera.projection(window_width(), window_height(), 45);
225 Transform mvp= p * v * m;
226 Transform mv= v * m;
227
228 program_uniform(m_texture_program, "mvpMatrix", mvp);
229 program_uniform(m_texture_program, "mvMatrix", mv);
230 program_uniform(m_texture_program, "normalMatrix", mv.normal());
231
232 // utilise la texture attachee au framebuffer
233 program_uniform(m_texture_program, "color_texture", 0);
234
235 glBindTexture(GL_TEXTURE_2D, m_color_buffer);
236 // recalcule les mipmaps de la texture... ils sont necessaires pour afficher le cube texture,
237 // pourquoi ? un draw dans un framebuffer ne modifie que le mipmap 0, pas les autres, donc il faut les recalculer...
238 glGenerateMipmap(GL_TEXTURE_2D);
239
240 glDrawArrays(GL_TRIANGLES, 0, m_vertex_count);
241 }
242
243 return 1;
244 }
245
246 protected:
247 Transform m_model;
248 Orbiter m_camera;
249 Orbiter m_framebuffer_camera;
250
251 GLuint m_vao;
252 GLuint m_buffer;
253 GLuint m_texture_program;
254 int m_vertex_count;
255 GLuint m_color_texture;
256
257 GLuint m_color_buffer;
258 GLuint m_depth_buffer;
259 GLuint m_framebuffer;
260 int m_framebuffer_width;
261 int m_framebuffer_height;
262 };
263
264
265 int main( int argc, char **argv )
266 {
267 Framebuffer tp;
268 tp.run();
269
270 return 0;
271 }
272
Mesh::normal_buffer
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3...
Definition: mesh.h:200
Orbiter
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet...
Definition: orbiter.h:16
Mesh::vertex_buffer
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL...
Definition: mesh.h:195
uniforms.h
Mesh::bounds
void bounds(Point &pmin, Point &pmax)
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:153
Framebuffer::render
int render()
a deriver pour afficher les objets.
Definition: tuto_framebuffer.cpp:151
Transform::normal
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:97
mesh.h
Mesh::normal_buffer_size
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:202
Mesh
representation d'un objet / maillage.
Definition: mesh.h:88
Orbiter::move
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
Mesh::vertex_buffer_size
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:197
texture.h
App::run
int run()
execution de l'application.
Definition: app.cpp:21
read_texture
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
Definition: texture.cpp:98
Mesh::texcoord_buffer
const float * texcoord_buffer() const
renvoie l'adresse des coordonnees de textures du premier sommet. par convention, c'est un vec2...
Definition: mesh.h:205
program.h
program_uniform
void program_uniform(const GLuint program, const char *uniform, const unsigned int v)
affecte une valeur a un uniform du shader program. uint.
Definition: uniforms.cpp:68
program_use_texture
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 filtrages...
Definition: uniforms.cpp:118
Orbiter::view
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
window_width
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:14
Framebuffer::quit
int quit()
a deriver pour detruire les objets openGL.
Definition: tuto_framebuffer.cpp:131
Mesh::release
void release()
detruit les objets openGL.
Definition: mesh.cpp:19
mat.h
Orbiter::projection
Transform projection(const float width, const float height, const float fov) const
renvoie la projection reglee pour une image d'aspect width / height, et une ouverture de fov degres...
Definition: orbiter.cpp:47
program_print_errors
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:330
Orbiter::lookat
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
App::App
App(const int width, const int height, const int major=3, const int minor=3)
constructeur, dimensions de la fenetre et version d'openGL.
Definition: app.cpp:6
read_program
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:150
Mesh::error
static Mesh & error()
Definition: mesh.h:250
key_state
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:24
Framebuffer
Definition: tuto_framebuffer.cpp:18
Mesh::texcoord_buffer_size
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
Definition: mesh.h:207
Orbiter::translation
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
Framebuffer::init
int init()
a deriver pour creer les objets openGL.
Definition: tuto_framebuffer.cpp:24
wavefront.h
Orbiter::rotation
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
window_height
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:18
Transform
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
release_program
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:157
Point
representation d'un point 3d.
Definition: vec.h:19
Mesh::vertex_count
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:190
app.h
orbiter.h
RotationY
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:158
App
classe application.
Definition: app.h:20
Framebuffer::update
int update(const float time, const float delta)
a deriver et redefinir pour animer les objets en fonction du temps.
Definition: tuto_framebuffer.cpp:144
vec.h
read_mesh
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).
Definition: wavefront.cpp:8