1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#include "fbo.h"
#include <stdio.h>
#include <iostream>
fbo_t *fbo_new()
{
fbo_t *fbo = new fbo_t;
fbo->fbo_id = 0;
fbo->old_fbo_id = 0;
fbo->renderbuf_id = 0;
fbo->depthbuf_id = 0;
return fbo;
}
#define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } }
bool fbo_init(fbo_t *fbo, size_t width, size_t height)
{
if (!glewIsSupported("GL_ARB_framebuffer_object")) {
fprintf(stderr, "Framebuffer extension not found\n");
return false;
}
// Generate and bind FBO
glGenFramebuffers(1, &fbo->fbo_id);
glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo_id);
REPORTGLERROR("binding framebuffer");
// Generate depth and render buffers
glGenRenderbuffers(1, &fbo->depthbuf_id);
glGenRenderbuffers(1, &fbo->renderbuf_id);
// Create buffers with correct size
if (!fbo_resize(fbo, width, height)) return false;
// Attach render and depth buffers
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, fbo->renderbuf_id);
REPORTGLERROR("specifying color render buffer");
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Problem with OpenGL framebuffer after specifying color render buffer.\n");
return false;
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, fbo->depthbuf_id);
REPORTGLERROR("specifying depth render buffer");
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Problem with OpenGL framebuffer after specifying depth render buffer.\n");
return false;
}
return true;
}
bool fbo_resize(fbo_t *fbo, size_t width, size_t height)
{
glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthbuf_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
REPORTGLERROR("creating depth render buffer");
glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
REPORTGLERROR("creating color render buffer");
return true;
}
void fbo_delete(fbo_t *fbo)
{
delete fbo;
}
GLuint fbo_bind(fbo_t *fbo)
{
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&fbo->old_fbo_id);
glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo_id);
return fbo->old_fbo_id;
}
void fbo_unbind(fbo_t *fbo)
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo->old_fbo_id);
}
|