-
Notifications
You must be signed in to change notification settings - Fork 7
/
fbo.cpp
150 lines (119 loc) · 4.71 KB
/
fbo.cpp
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>
#include <sstream>
#include "fbo.h"
using namespace std;
extern bool CheckGLErrors(const char * caller);
const char * FramebufferCompletenessError(GLint error_code)
{
switch (error_code)
{
case GL_FRAMEBUFFER_UNDEFINED:
return "GL_FRAMEBUFFER_UNDEFINED";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
case GL_FRAMEBUFFER_COMPLETE:
return "GL_FRAMEBUFFER_COMPLETE";
case GL_FRAMEBUFFER_UNSUPPORTED:
return "GL_FRAMEBUFFER_UNSUPPORTED";
default:
return "Unknown frame buffer error";
}
}
/* Frame buffer object demonstration class by Perry Kivolowitz, University of Wisconsin Madison.
Note this class provides the option of allocating multiple color attachments per frame buffer
object as well as the option to attach a depth buffer to the frame buffer object.
*/
FrameBufferObject::FrameBufferObject()
{
this->framebuffer_handle = GLuint(-1);
this->depth_buffer_handle = GLuint(-1);
this->texture_handles = NULL;
}
void FrameBufferObject::Bind(int color_attachment_index)
{
assert(color_attachment_index < this->number_of_color_attachments);
assert(this->framebuffer_handle != GLuint(-1));
glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer_handle);
glDrawBuffer(GL_COLOR_ATTACHMENT0 + color_attachment_index);
}
void FrameBufferObject::Unbind()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBufferObject::TakeDown()
{
if (this->framebuffer_handle != GLuint(-1))
{
glBindFramebuffer(GL_FRAMEBUFFER , 0);
glDeleteFramebuffers(1 , &this->framebuffer_handle);
}
if (this->depth_buffer_handle != GLuint(-1))
{
glBindRenderbuffer(GL_RENDERBUFFER , 0);
glDeleteFramebuffers(1 , &this->depth_buffer_handle);
}
if (this->texture_handles != NULL)
{
glBindTexture(GL_TEXTURE_2D , 0);
glDeleteTextures(this->number_of_color_attachments, this->texture_handles);
delete [] this->texture_handles;
}
}
bool FrameBufferObject::Initialize(glm::ivec2 size, int number_of_color_attachments, bool allocate_depth_buffer)
{
this->size = size;
this->number_of_color_attachments = number_of_color_attachments;
this->texture_handles = new GLuint[number_of_color_attachments];
for (int i = 0; i < number_of_color_attachments; i++)
this->texture_handles[i] = GLuint(-1);
if (!CheckGLErrors("FrameBufferObject::Initialize - purging errors prior to initializing frame buffer object."))
return false;
glGenFramebuffers(1, &this->framebuffer_handle);
glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer_handle);
if (!CheckGLErrors("FrameBufferObject::Initialize - purging errors prior to initializing textures."))
return false;
glGenTextures(number_of_color_attachments, this->texture_handles);
for (int i = 0; i < number_of_color_attachments; i++)
{
glBindTexture(GL_TEXTURE_2D, this->texture_handles[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, this->size.x, this->size.y, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, this->texture_handles[i], 0);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
cout << "FrameBufferObject::Initialize failed to complete texture buffer " << FramebufferCompletenessError(status) << endl;
return false;
}
if (allocate_depth_buffer)
{
glGenRenderbuffers(1, &this->depth_buffer_handle);
glBindRenderbuffer(GL_RENDERBUFFER, this->depth_buffer_handle);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, this->size.x, this->size.y);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->depth_buffer_handle);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
cout << "FrameBufferObject::Initialize failed to complete depth buffer " << FramebufferCompletenessError(status) << endl;
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return true;
}