PICCANTE  0.4
The hottest HDR imaging library!
fbo.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_UTIL_GL_FBO_HPP
19 #define PIC_UTIL_GL_FBO_HPP
20 
21 #include <iostream>
22 
23 #include "../../base.hpp"
24 
25 namespace pic {
26 
27  //NOTE: this class needs to be used with an active OpenGL context!
28 
32  class Fbo
33  {
34  public:
35  GLuint fbo; // framebuffer object
36  GLuint tex; // we render into this texture
37  GLuint depth; // and to this depth buffer
38  int width, height, frames; // width and height of the framebuffer
39  bool bDepth; // do we have a depth buffer?
40 
41  //MRT
42  GLuint *texMRT;
43  unsigned int nMRT;
44  GLuint *attachmentsMRT;
45 
46  Fbo();
47 
57  bool create(int width, int height, bool bDepth);
58 
66  bool create(int width, int height, int depth, bool bDepth, GLuint tex);
67 
75  bool createMRT(int width, int height, bool bDepth, unsigned int nMRT);
76 
83  void attachColorBuffer(GLuint tex, GLenum target, int slice = 0);
84 
91  void attachColorBuffer2(GLuint tex, GLenum target, int slice);
92 
97  bool release();
98 
102  void bind();
103 
107  void unbind();
108 
112  void bindSimple()
113  {
114  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
115  }
116 
121  {
122  glBindFramebuffer(GL_FRAMEBUFFER, 0);
123  }
124 
128  void bindMRT();
129 
133  void unbindMRT();
134 
139  Fbo *clone();
140 
145  static void checkStatus(GLenum fboStatus)
146  {
147  switch (fboStatus) {
148  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
149  std::cerr << "FBO Incomplete: Attachment" << std::endl;
150  break;
151 
152  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
153  std::cerr << "FBO Incomplete: Missing Attachment" << std::endl;
154  break;
155 
156  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
157  std::cerr << "FBO Incomplete: Draw Buffer" << std::endl;
158  break;
159 
160  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
161  std::cerr << "FBO Incomplete: Read Buffer" << std::endl;
162  break;
163 
164  default:
165  std::cerr << "Undefined FBO error" << std::endl;
166  break;
167  }
168  }
169  };
170 
172  {
173  depth = 0;
174  fbo = 0;
175  tex = 0;
176 
177  width = height = frames = 0;
178  }
179 
180  PIC_INLINE bool Fbo::release()
181  {
182  if (tex != 0) {
183  glDeleteTextures(1, &tex);
184  tex = 0;
185  }
186 
187  if (depth != 0) {
188  glDeleteRenderbuffers(1, &depth);
189  depth = 0;
190  }
191 
192  if (fbo != 0) {
193  glDeleteFramebuffers(1, &fbo);
194  fbo = 0;
195  }
196 
197  return true;
198  }
199 
200  PIC_INLINE Fbo *Fbo::clone()
201  {
202  Fbo *ret = new Fbo();
203  ret->create(width, height, frames, bDepth, 0);
204  return ret;
205  }
206 
207  PIC_INLINE bool Fbo::create(int width, int height, bool bDepth)
208  {
209  return create(width, height, 1, bDepth, 0);
210  }
211 
212  PIC_INLINE bool Fbo::create(int width, int height, int frames, bool bDepth, GLuint tex)
213  {
214  this->width = width;
215  this->height = height;
216  this->frames = frames;
217  this->bDepth = bDepth;
218 
219  //FBO with one COLOR ATTACHMENT
220  //setup texture (render target)
221  if (tex == 0) {
222  glGenTextures(1, &this->tex);
223 
224  if (frames == 1) {
225  glBindTexture(GL_TEXTURE_2D, this->tex);
226  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
227  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
228  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
229  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
230  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT,
231  0);
232  glBindTexture(GL_TEXTURE_2D, 0);
233  }
234  else {
235  glBindTexture(GL_TEXTURE_3D, this->tex);
236  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
237  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
238  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
239  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
240  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
241  glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, frames, 0, GL_RGBA,
242  GL_FLOAT, 0);
243  glBindTexture(GL_TEXTURE_3D, 0);
244  }
245  }
246  else {
247  this->tex = tex;
248  }
249 
250  //setup renderbuffer (depth buffer)
251  //assert(glGenRenderbuffers);
252  if (bDepth) {
253  glGenRenderbuffers(1, &depth);
254  glBindRenderbuffer(GL_RENDERBUFFER, depth);
255  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
256  glBindRenderbuffer(GL_RENDERBUFFER, 0);
257  }
258 
259  // setup FBO
260  if (fbo == 0) {
261  glGenFramebuffers(1, &fbo);
262  }
263 
264  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
265 
266  // attach color buffer (texture)
267  if (frames == 1) {
268  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
269  this->tex, 0);
270  }
271  else {
272  glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
273  this->tex, 0, 0);
274  }
275 
276  // attach depth buffer (renderbuffer)
277  if (bDepth) {
278  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
279  depth);
280  }
281 
282 #ifdef PIC_DEBUG_GL
283  // check framebuffer status
284  GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
285 
286  if (fboStatus != GL_FRAMEBUFFER_COMPLETE) {
287  checkStatus(fboStatus);
288  glDeleteFramebuffers(1, &fbo);
289  fbo = 0;
290  }
291 
292 #endif
293 
294  // unbind framebuffer
295  glBindFramebuffer(GL_FRAMEBUFFER, 0);
296  return fbo != 0;
297  }
298 
299  PIC_INLINE bool Fbo::createMRT(int width, int height, bool bDepth, unsigned int nMRT)
300  {
301  this->width = width;
302  this->height = height;
303  this->bDepth = bDepth;
304  this->nMRT = nMRT;
305 
306  texMRT = new GLuint[nMRT];
307  attachmentsMRT = new GLuint[nMRT];
308 
309  for (unsigned int i = 0; i < nMRT; i++) {
310  texMRT[i] = 0;
311  glGenTextures(1, &texMRT[i]);
312  glBindTexture(GL_TEXTURE_2D, texMRT[i]);
313  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
314  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
315  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
316  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
317  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
318  glBindTexture(GL_TEXTURE_2D, 0);
319  }
320 
321  if (bDepth) {
322  glGenRenderbuffers(1, &depth);
323  glBindRenderbuffer(GL_RENDERBUFFER, depth);
324  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
325  glBindRenderbuffer(GL_RENDERBUFFER, 0);
326  }
327 
328  // setup FBO
329  if (fbo == 0) {
330  glGenFramebuffers(1, &fbo);
331  }
332 
333  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
334 
335  // attach color buffer (texture)
336  for (unsigned int i = 0; i < nMRT; i++) {
337  attachmentsMRT[i] = GL_COLOR_ATTACHMENT0 + i;
338 
339  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
340  texMRT[i], 0);
341  }
342 
343 
344  // attach depth buffer (renderbuffer)
345  if (bDepth) {
346  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
347  depth);
348  }
349 
350 #ifdef PIC_DEBUG_GL
351  // check framebuffer status
352  GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
353 
354  if (fboStatus != GL_FRAMEBUFFER_COMPLETE) {
355  checkStatus(fboStatus);
356  glDeleteFramebuffers(1, &fbo);
357  fbo = 0;
358  }
359 
360 #endif
361 
362  // unbind framebuffer
363  glBindFramebuffer(GL_FRAMEBUFFER, 0);
364  return fbo != 0;
365  }
366 
367  PIC_INLINE void Fbo::attachColorBuffer(GLuint tex, GLenum target, int slice)
368  {
369  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
370 
371  GLuint texWork = (tex == 0) ? this->tex : tex;
372 
373  switch (target) {
374  case GL_TEXTURE_2D: {
375  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
376  texWork, 0);
377  }
378  break;
379 
380  case GL_TEXTURE_3D: {
381  glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
382  texWork, 0, slice);
383  }
384  break;
385  }
386 
387 #ifdef PIC_DEBUG_GL
388  // check framebuffer status
389  GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
390 
391  if (fboStatus != GL_FRAMEBUFFER_COMPLETE) {
392  checkStatus(fboStatus);
393  glDeleteFramebuffers(1, &fbo);
394  fbo = 0;
395  }
396 
397 #endif
398 
399  glBindFramebuffer(GL_FRAMEBUFFER, 0);
400  }
401 
402  PIC_INLINE void Fbo::attachColorBuffer2(GLuint tex, GLenum target, int slice)
403  {
404  GLuint texWork = (tex == 0) ? this->tex : tex;
405 
406  switch (target) {
407  case GL_TEXTURE_2D: {
408  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
409  texWork, 0);
410  }
411  break;
412 
413  case GL_TEXTURE_2D_ARRAY: {
414  glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
415  GL_TEXTURE_2D_ARRAY, texWork, 0, slice);
416  }
417  break;
418 
419  case GL_TEXTURE_3D: {
420  glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
421  texWork, 0, slice);
422  }
423  break;
424  }
425  }
426 
427  PIC_INLINE void Fbo::bind()
428  {
429  if (!fbo) {
430  return;
431  }
432 
433  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
434  glDrawBuffer(GL_COLOR_ATTACHMENT0);
435  glReadBuffer(GL_COLOR_ATTACHMENT0);
436 
437  if (bDepth) {
438  glBindRenderbuffer(GL_RENDERBUFFER, depth);
439  }
440  }
441 
442  PIC_INLINE void Fbo::unbind()
443  {
444  if (!fbo) {
445  return;
446  }
447 
448  glBindFramebuffer(GL_FRAMEBUFFER, 0);
449  glDrawBuffer(GL_BACK);
450  glReadBuffer(GL_BACK);
451 
452  if (bDepth) {
453  glBindRenderbuffer(GL_RENDERBUFFER, 0);
454  }
455  }
456 
457  PIC_INLINE void Fbo::bindMRT()
458  {
459  if (!fbo) {
460  return;
461  }
462 
463  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
464 
465  glDrawBuffers(nMRT, attachmentsMRT);
466  }
467 
469  {
470  if (!fbo) {
471  return;
472  }
473 
474  glBindFramebuffer(GL_FRAMEBUFFER, 0);
475  }
476 
477 
478 } // end namespace pic
479 
480 #endif /* PIC_UTIL_GL_FBO_HPP */
481 
void unbind()
unbind
static void checkStatus(GLenum fboStatus)
checkStatus
Definition: fbo.hpp:145
GLuint fbo
Definition: fbo.hpp:35
The Fbo class.
Definition: fbo.hpp:32
void bindSimple()
bindSimple
Definition: fbo.hpp:112
void unbindMRT()
unbind
int frames
Definition: fbo.hpp:38
GLuint depth
Definition: fbo.hpp:37
int height
Definition: fbo.hpp:38
Fbo * clone()
clone
GLuint * texMRT
Definition: fbo.hpp:42
bool createMRT(int width, int height, bool bDepth, unsigned int nMRT)
create
GLuint * attachmentsMRT
Definition: fbo.hpp:44
void bindMRT()
bindMRT
unsigned int nMRT
Definition: fbo.hpp:43
void unbindSimple()
unbindSimple
Definition: fbo.hpp:120
bool bDepth
Definition: fbo.hpp:39
int width
Definition: fbo.hpp:38
#define PIC_INLINE
Definition: base.hpp:33
bool create(int width, int height, bool bDepth)
create
Definition: bilateral_separation.hpp:25
bool release()
release
GLuint tex
Definition: fbo.hpp:36
void attachColorBuffer2(GLuint tex, GLenum target, int slice)
attachColorBuffer2
void attachColorBuffer(GLuint tex, GLenum target, int slice=0)
attachColorBuffer
void bind()
bind