19 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
22 glGenTextures(1, &texture);
23 glBindTexture(GL_TEXTURE_2D, texture);
26 glTexImage2D(GL_TEXTURE_2D, 0, settings.internal_format,
27 settings.width, settings.height, 0,
28 settings.format, settings.type,
nullptr);
31 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, settings.min_filter);
32 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, settings.mag_filter);
33 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, settings.wrap_s);
34 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, settings.wrap_t);
37 const uint32_t attachment_point = GL_COLOR_ATTACHMENT0 + color_attachments_.size();
38 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment_point, GL_TEXTURE_2D, texture, 0);
40 color_attachments_.push_back(texture);
41 color_settings_.push_back(settings);
44 std::vector<GLenum> draw_buffers;
45 for (size_t i = 0; i < color_attachments_.size(); i++) {
46 draw_buffers.push_back(GL_COLOR_ATTACHMENT0 + i);
48 glDrawBuffers(draw_buffers.size(), draw_buffers.data());
50 glBindTexture(GL_TEXTURE_2D, 0);
51 glBindFramebuffer(GL_FRAMEBUFFER, 0);
54 void Framebuffer::attach_texture_by_id(
const uint32_t texture_id, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum target = GL_FRAMEBUFFER) {
56 glFramebufferTexture2D(target, attachment,
57 GL_TEXTURE_2D, texture_id, 0);
62 std::cerr <<
"Depth attachment already exists!" << std::endl;
66 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
69 glBindTexture(GL_TEXTURE_2D, depth_attachment_);
72 const GLenum internal_format = settings.internal_format == GL_RGBA8
73 ? GL_DEPTH_COMPONENT32F
74 : settings.internal_format;
75 constexpr GLenum format = GL_DEPTH_COMPONENT;
76 const GLenum type = settings.type == GL_UNSIGNED_BYTE ? GL_FLOAT : settings.type;
79 glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
80 settings.width, settings.height, 0,
81 format, type,
nullptr);
84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, settings.min_filter);
85 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, settings.mag_filter);
86 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, settings.wrap_s);
87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, settings.wrap_t);
90 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_attachment_, 0);
93 glBindTexture(GL_TEXTURE_2D, 0);
94 glBindFramebuffer(GL_FRAMEBUFFER, 0);
96 depth_settings_ = settings;
102 std::cerr <<
"Stencil attachment already exists!" << std::endl;
106 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
109 glBindTexture(GL_TEXTURE_2D, stencil_attachment_);
112 constexpr GLenum internal_format = GL_STENCIL_INDEX8;
113 constexpr GLenum format = GL_STENCIL_INDEX;
114 constexpr GLenum type = GL_UNSIGNED_BYTE;
116 glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
117 settings.width, settings.height, 0,
118 format, type,
nullptr);
120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, settings.wrap_s);
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, settings.wrap_t);
125 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencil_attachment_, 0);
127 glBindTexture(GL_TEXTURE_2D, 0);
128 glBindFramebuffer(GL_FRAMEBUFFER, 0);
130 stencil_settings_ = settings;
136 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
139 if (!color_settings_.empty()) {
140 glViewport(0, 0, color_settings_[0].width, color_settings_[0].height);
145 glBindFramebuffer(GL_FRAMEBUFFER, 0);
148 void Framebuffer::resize(
const uint32_t width,
const uint32_t height) {
153 std::vector<FrameBufferAttachmentSettings> old_color_settings = color_settings_;
164 for (
auto &settings: old_color_settings) {
165 settings.width = width;
166 settings.height = height;
167 attach_color_texture(settings);
171 old_depth_settings
.width = width;
172 old_depth_settings
.height = height;
177 old_stencil_settings
.width = width;
178 old_stencil_settings
.height = height;
183 std::cerr <<
"Framebuffer incomplete after resize!" << std::endl;
187 uint32_t
Framebuffer::read_pixel_from_texture(
const uint32_t texture_id,
const int x,
const int y) {
189 std::cout <<
"Texture ID: " << texture_id <<
", is valid: " << (glIsTexture(texture_id) ?
"yes" :
"no") << std::endl;
194 attach_texture_by_id(texture_id, GL_COLOR_ATTACHMENT0, GL_READ_FRAMEBUFFER);
197 glReadBuffer(GL_COLOR_ATTACHMENT0);
200 uint32_t pixel_data = 0;
201 glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixel_data);
210 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
211 const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
212 glBindFramebuffer(GL_FRAMEBUFFER, 0);
214 if (status != GL_FRAMEBUFFER_COMPLETE) {
215 std::cerr <<
"Framebuffer not complete! Status: ";
217 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
218 std::cerr <<
"INCOMPLETE_ATTACHMENT" << std::endl;
220 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
221 std::cerr <<
"INCOMPLETE_MISSING_ATTACHMENT" << std::endl;
223 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
224 std::cerr <<
"INCOMPLETE_DRAW_BUFFER" << std::endl;
226 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
227 std::cerr <<
"INCOMPLETE_READ_BUFFER" << std::endl;
229 case GL_FRAMEBUFFER_UNSUPPORTED:
230 std::cerr <<
"UNSUPPORTED" << std::endl;
233 std::cerr <<
"UNKNOWN (" << status <<
")" << std::endl;
243 return !color_settings_.empty() ? color_settings_[0].width : 0;
247 return !color_settings_.empty() ? color_settings_[0].height : 0;
255 if (!color_attachments_.empty()) {
256 glDeleteTextures(
static_cast<GLsizei>(color_attachments_.size()), color_attachments_.data());
257 color_attachments_.clear();
258 color_settings_.clear();
uint32_t get_width() const
uint32_t get_height() const
void attach_depth_texture(const FrameBufferAttachmentSettings &settings={})
void attach_color_texture(const FrameBufferAttachmentSettings &settings={})
void attach_stencil_texture(const FrameBufferAttachmentSettings &settings={})
void create_framebuffer()
uint32_t stencil_attachment_
uint32_t depth_attachment_