gKit2 light
Loading...
Searching...
No Matches
framebuffer.cpp
Go to the documentation of this file.
1
3
4#include <cstdio>
5#include <cstring>
6
7#include "glcore.h"
8#include "texture.h"
9#include "uniforms.h"
10#include "framebuffer.h"
11
12
13GLuint Framebuffer::create( const int width, const int height )
14{
15 glGenFramebuffers(1, &m_fbo);
16
17 // etat par defaut
18 m_draw_buffers= std::vector<GLenum>(8, GL_NONE);
19 m_color_textures= std::vector<GLuint>(8, 0);
20 m_depth_texture= 0;
21
22 m_clear_colors= std::vector< std::array<unsigned, 4> >(8);
23 m_clear_depth= 1;
24
25 m_color_units= std::vector<int>(8, -1);
26 m_depth_unit= -1;
27
28 m_width= width;
29 m_height= height;
30 return m_fbo;
31}
32
34{
35 glDeleteTextures(8, m_color_textures.data());
36 glDeleteTextures(1, &m_depth_texture);
37 glDeleteFramebuffers(1, &m_fbo);
38}
39
41{
42 return m_width;
43}
44
46{
47 return m_height;
48}
49
50
51void Framebuffer::bind( const GLuint program, const bool color, const bool depth, const bool position, const bool texcoord, const bool normal, const bool material_id )
52{
53 if(m_fbo == 0)
54 create(m_width, m_height);
55
56 // desactive les textures associees au framebuffer, si necessaire (ie l'application ne l'a pas fait... mais non ca n'arrive jamais)
57 // todo ou generer une erreur ?
59
60 // selectionne le framebuffer
61 assert(m_fbo > 0);
62 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
63
64 // verifier que le fragment shader declare chaque sortie...
65 // openGL 4.3 / glGetProgramInterface() et glGetProgramResoucre()
66 // uniquement en mode debug...
67#ifndef GK_RELEASE
68 if(program > 0)
69 {
70 // recuperer le nom du shader... si possible
71 char label[2048]= { 0 };
72 #ifdef GL_VERSION_4_3
73 {
74 char tmp[1024];
75 glGetObjectLabel(GL_PROGRAM, program, sizeof(tmp), nullptr, tmp);
76 sprintf(label, "program( %u '%s' )", program, tmp);
77 }
78 #else
79 sprintf(label, "program( %u )", program);
80 #endif
81
82 #if 0
83 // verifie que le program est selectionne
84 GLuint current;
85 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &current);
86 if(current != program)
87 printf("[oops] %s: not active... undefined draw !!\n", label);
88 #endif
89
90 #ifdef GL_VERSION_4_3
91 // lister les sorties du fragment shader
92 // fonctionnalite openGL 4.3, n'existe pas sur mac...
93 GLint outputs= 0;
94 glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &outputs);
95
96 char name[1024];
97 for(int i= 0; i < outputs; i++)
98 {
99 int location= -1;
100 GLenum props[]= { GL_LOCATION };
101 glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, i, 1, props, 1, nullptr, &location);
102 glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, i, sizeof(name), nullptr, name);
103
104 if(location == 0) // sortie color
105 {
106 if(!color)
107 printf("[oops] color output '%s' in %s not stored...\n", name, label);
108 }
109 else if(location == 1) // sortie position
110 {
111 if(!position)
112 printf("[oops] position output '%s' in %s not stored...\n", name, label);
113 }
114 else if(location == 2) // sortie texcoord
115 {
116 if(!texcoord)
117 printf("[oops] texcoord output '%s' in %s not stored...\n", name, label);
118 }
119 else if(location == 3) // sortie normal
120 {
121 if(!normal)
122 printf("[oops] normal output '%s' in %s not stored...\n", name, label);
123 }
124 else if(location == 4) // sortie material_id
125 {
126 if(!material_id)
127 printf("[oops] material output '%s' in %s not stored...\n", name, label);
128 }
129 }
130 #endif
131 }
132#endif
133
134 // configuration du framebuffer, et creation des textures, si necessaire
135 if(depth)
136 {
137 if(m_depth_texture == 0)
138 m_depth_texture= make_depth_texture(0, m_width, m_height);
139
140 assert(m_depth_texture > 0);
141 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_depth_texture, /* mipmap */ 0);
142 }
143 else
144 {
145 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, /* mipmap */ 0);
146 }
147
148 //
149 bool draw_buffers= false;
150 if(color)
151 {
152 if(m_color_textures[0] == 0)
153 m_color_textures[0]= make_vec4_texture(0, m_width, m_height);
154
155 assert(m_color_textures[0] > 0);
156 if(m_draw_buffers[0] == GL_NONE)
157 {
158 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_color_textures[0], /* mipmap */ 0);
159 m_draw_buffers[0]= GL_COLOR_ATTACHMENT0;
160 draw_buffers= true;
161 }
162 }
163 else
164 {
165 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, /* mipmap */ 0);
166 m_draw_buffers[0]= GL_NONE;
167 draw_buffers= true;
168 }
169
170 if(position)
171 {
172 if(m_color_textures[1] == 0)
173 m_color_textures[1]= make_vec3_texture(0, m_width, m_height);
174
175 assert(m_color_textures[1] > 0);
176 if(m_draw_buffers[1] == GL_NONE)
177 {
178 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_color_textures[1], /* mipmap */ 0);
179 m_draw_buffers[1]= GL_COLOR_ATTACHMENT1;
180 draw_buffers= true;
181 }
182 }
183 else
184 {
185 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, /* mipmap */ 0);
186 m_draw_buffers[1]= GL_NONE;
187 draw_buffers= true;
188 }
189
190 if(texcoord)
191 {
192 if(m_color_textures[2] == 0)
193 m_color_textures[2]= make_vec2_texture(0, m_width, m_height);
194
195 assert(m_color_textures[2] > 0);
196 if(m_draw_buffers[2] == GL_NONE)
197 {
198 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, m_color_textures[2], /* mipmap */ 0);
199 m_draw_buffers[2]= GL_COLOR_ATTACHMENT2;
200 draw_buffers= true;
201 }
202 }
203 else
204 {
205 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, 0, /* mipmap */ 0);
206 m_draw_buffers[2]= GL_NONE;
207 draw_buffers= true;
208 }
209
210 if(normal)
211 {
212 if(m_color_textures[3] == 0)
213 m_color_textures[3]= make_vec3_texture(0, m_width, m_height);
214
215 assert(m_color_textures[3] > 0);
216 if(m_draw_buffers[3] == GL_NONE)
217 {
218 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, m_color_textures[3], /* mipmap */ 0);
219 m_draw_buffers[3]= GL_COLOR_ATTACHMENT3;
220 draw_buffers= true;
221 }
222 }
223 else
224 {
225 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, /* mipmap */ 0);
226 m_draw_buffers[3]= GL_NONE;
227 draw_buffers= true;
228 }
229
230 if(material_id)
231 {
232 if(m_color_textures[4] == 0)
233 m_color_textures[4]= make_uint_texture(0, m_width, m_height);
234
235 assert(m_color_textures[4] > 0);
236 if(m_draw_buffers[4] == GL_NONE)
237 {
238 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, m_color_textures[4], /* mipmap */ 0);
239 m_draw_buffers[4]= GL_COLOR_ATTACHMENT4;
240 draw_buffers= true;
241 }
242 }
243 else
244 {
245 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, 0, /* mipmap */ 0);
246 m_draw_buffers[4]= GL_NONE;
247 draw_buffers= true;
248 }
249
250 if(draw_buffers)
251 glDrawBuffers(8, m_draw_buffers.data());
252
253 // verifie la configuration du framebuffer
254 if(!status())
255 return;
256
257 // prepare le rendu dans le framebuffer
258 glViewport(0, 0, m_width, m_height);
259
260 // pas joli, mais plus simple que declarer n variables du bon type...
261 if(depth)
262 glClearBufferfv(GL_DEPTH, 0, &m_clear_depth);
263 if(color)
264 glClearBufferfv(GL_COLOR, 0, (const GLfloat *) &m_clear_colors[0]);
265 if(position)
266 glClearBufferfv(GL_COLOR, 1, (const GLfloat *) &m_clear_colors[1]);
267 if(texcoord)
268 glClearBufferfv(GL_COLOR, 2, (const GLfloat *) &m_clear_colors[2]);
269 if(normal)
270 glClearBufferfv(GL_COLOR, 3, (const GLfloat *) &m_clear_colors[3]);
271 if(material_id)
272 glClearBufferuiv(GL_COLOR, 4, (const GLuint *) &m_clear_colors[4]);
273}
274
275
276void Framebuffer::unbind( const int width, const int height )
277{
278 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
279 glViewport(0, 0, width, height);
280}
281
282
284{
285 // desactive les textures associees au framebuffer, si necessaire
286 // le pipeline ne peut pas lire et modifier les textures en meme temps.
287 for(int i= 0; i < 8; i++)
288 if(m_color_units[i] != -1)
289 {
290 glActiveTexture(GL_TEXTURE0 + m_color_units[i]);
291 glBindTexture(GL_TEXTURE_2D, 0);
292
293 m_color_units[i]= -1;
294 }
295
296 if(m_depth_unit != -1)
297 {
298 glActiveTexture(GL_TEXTURE0 + m_depth_unit);
299 glBindTexture(GL_TEXTURE_2D, 0);
300
301 m_depth_unit= -1;
302 }
303}
304
305
306
307void Framebuffer::clear_depth( const float value )
308{
309 if(m_fbo == 0)
310 printf("[error] uninitialized framebuffer...\n");
311
312 m_clear_depth= value;
313}
314
315void Framebuffer::clear_color( const Color& value )
316{
317 if(m_fbo == 0)
318 printf("[error] uninitialized framebuffer...\n");
319
320 float values[4]= { value.r, value.g, value.b, value.a };
321 memcpy(&m_clear_colors[0], values, sizeof(values));
322}
323
325{
326 if(m_fbo == 0)
327 printf("[error] uninitialized framebuffer...\n");
328
329 float values[4]= { value.x, value.y, value.z, 0 };
330 memcpy(&m_clear_colors[1], values, sizeof(values));
331}
332
334{
335 if(m_fbo == 0)
336 printf("[error] uninitialized framebuffer...\n");
337
338 float values[4]= { value.x, value.y, 0, 0 };
339 memcpy(&m_clear_colors[2], values, sizeof(values));
340}
341
343{
344 if(m_fbo == 0)
345 printf("[error] uninitialized framebuffer...\n");
346
347 float values[4]= { value.x, value.y, value.z, 0 };
348 memcpy(&m_clear_colors[3], values, sizeof(values));
349}
350
351void Framebuffer::clear_material( const unsigned value )
352{
353 if(m_fbo == 0)
354 printf("[error] uninitialized framebuffer...\n");
355
356 unsigned values[4]= { value, 0, 0, 0 };
357 memcpy(&m_clear_colors[4], values, sizeof(values));
358}
359
360
361bool Framebuffer::status( )
362{
363 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
364 GLenum code= glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
365
366 if(code == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER)
367 printf("[error] framebuffer: incomplete draw buffer... can't draw!\n");
368 else if(code == GL_FRAMEBUFFER_UNSUPPORTED)
369 printf("[error] framebuffer: unsupported format... can't draw!\n");
370
371 return (code == GL_FRAMEBUFFER_COMPLETE);
372}
373
374
375void Framebuffer::use_depth_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
376{
377 m_depth_unit= unit;
378 program_use_texture(program, uniform, unit, m_depth_texture, sampler);
379}
380
381void Framebuffer::use_color_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
382{
383 m_color_units[0]= unit;
384 program_use_texture(program, uniform, unit, m_color_textures[0], sampler);
385}
386
387void Framebuffer::use_position_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
388{
389 m_color_units[1]= unit;
390 program_use_texture(program, uniform, unit, m_color_textures[1], sampler);
391}
392
393void Framebuffer::use_texcoord_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
394{
395 m_color_units[2]= unit;
396 program_use_texture(program, uniform, unit, m_color_textures[2], sampler);
397}
398
399void Framebuffer::use_normal_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
400{
401 m_color_units[3]= unit;
402 program_use_texture(program, uniform, unit, m_color_textures[3], sampler);
403}
404
405void Framebuffer::use_material_texture( const GLuint program, const char *uniform, const int unit, const GLuint sampler )
406{
407 m_color_units[4]= unit;
408 program_use_texture(program, uniform, unit, m_color_textures[4], sampler);
409}
410
411
412
413void Framebuffer::blit_depth( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
414{
415 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
416
417 glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
418
419 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
420}
421
422void Framebuffer::blit_color( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
423{
424 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
425 glReadBuffer(GL_COLOR_ATTACHMENT0);
426
427 glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
428
429 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
430}
431
432void Framebuffer::blit_position( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
433{
434 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
435 glReadBuffer(GL_COLOR_ATTACHMENT1);
436
437 glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
438
439 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
440}
441
442void Framebuffer::blit_texcoord( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
443{
444 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
445 glReadBuffer(GL_COLOR_ATTACHMENT2);
446
447 glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
448
449 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
450}
451
452void Framebuffer::blit_normal( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
453{
454 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
455 glReadBuffer(GL_COLOR_ATTACHMENT3);
456
457 glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
458
459 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
460}
461
462
463// marche pas, utiliser un shader pour convertir les valeurs en couleurs...
464//~ void Framebuffer::blit_material( const int dstX0, const int dstY0, const int dstX1, const int dstY1 )
465//~ {
466 //~ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
467 //~ glReadBuffer(GL_COLOR_ATTACHMENT4);
468
469 //~ glBlitFramebuffer(0, 0, m_width, m_height, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
470
471 //~ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
472//~ }
473
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
GLuint make_vec2_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
Definition texture.cpp:161
GLuint make_vec3_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
Definition texture.cpp:166
GLuint make_vec4_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
Definition texture.cpp:171
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 filtrage,...
Definition uniforms.cpp:198
GLuint make_uint_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
Definition texture.cpp:151
GLuint make_depth_texture(const int unit, const int width, const int height, const GLenum texel_type)
creation de textures pour stocker des donnees (autres qu'une couleur).
Definition texture.cpp:146
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
void release()
destruction.
int height() const
renvoie la hauteur du framebuffer.
void clear_texcoord(const vec2 &value)
texcoord par defaut.
void clear_position(const Point &value)
position par defaut.
void clear_material(const unsigned value)
indice de matiere par defaut.
int width() const
renvoie la largeur du framebuffer.
void unbind(const int width, const int height)
desactive le framebuffer, selection du framebuffer par defaut associe a la fenetre.
GLuint create(const int width, const int height)
creation du framebuffer
void clear_color(const Color &value)
couleur par defaut.
void clear_depth(const float value)
profondeur par defaut.
void unbind_textures()
nettoyage, desactive les textures utilisees par les autres shaders, cf use_color_texture(),...
void bind(const GLuint program, const bool store_color, const bool store_depth, const bool store_position, const bool store_texcoord, const bool store_normal, const bool store_material)
selection du framebuffer, stocker les sorties du fragment shader. les textures sont initialisees avec...
void clear_normal(const Vector &value)
normale par defaut.
representation d'un point 3d.
Definition vec.h:21
representation d'un vecteur 3d.
Definition vec.h:67
vecteur generique, utilitaire.
Definition vec.h:152