galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
Framebuffer.cpp
Go to the documentation of this file.
1
7
8#include <glad/glad.h>
9
10#include "galaxy/error/Log.hpp"
11
12#include "Framebuffer.hpp"
13
14namespace galaxy
15{
16 namespace graphics
17 {
19 : m_id {0}
20 , m_width {0}
21 , m_height {0}
22 , m_colour {0}
23 , m_renderbuffer {0}
24 , m_storageattach {0}
25 , m_clear_colour {0.0f, 0.0f, 0.0f, 0.0f}
26 {
27 glCreateFramebuffers(1, &m_id);
28 }
29
31 {
32 if (this->m_id != 0)
33 {
34 glDeleteFramebuffers(1, &this->m_id);
35 }
36
37 if (this->m_colour != 0)
38 {
39 glDeleteTextures(1, &this->m_colour);
40 }
41
42 if (this->m_renderbuffer != 0)
43 {
44 glDeleteRenderbuffers(1, &this->m_renderbuffer);
45 }
46
47 if (this->m_storageattach != 0)
48 {
49 glDeleteTextures(1, &this->m_storageattach);
50 }
51
52 this->m_id = f.m_id;
53 this->m_width = f.m_width;
54 this->m_height = f.m_height;
55 this->m_colour = f.m_colour;
56 this->m_renderbuffer = f.m_renderbuffer;
57 this->m_storageattach = f.m_storageattach;
58 this->m_clear_colour = std::move(f.m_clear_colour);
59
60 f.m_id = 0;
61 f.m_colour = 0;
62 f.m_renderbuffer = 0;
63 f.m_storageattach = 0;
64 }
65
67 {
68 if (this != &f)
69 {
70 if (this->m_id != 0)
71 {
72 glDeleteFramebuffers(1, &this->m_id);
73 }
74
75 if (this->m_colour != 0)
76 {
77 glDeleteTextures(1, &this->m_colour);
78 }
79
80 if (this->m_renderbuffer != 0)
81 {
82 glDeleteRenderbuffers(1, &this->m_renderbuffer);
83 }
84
85 if (this->m_storageattach != 0)
86 {
87 glDeleteTextures(1, &this->m_storageattach);
88 }
89
90 this->m_id = f.m_id;
91 this->m_width = f.m_width;
92 this->m_height = f.m_height;
93 this->m_colour = f.m_colour;
94 this->m_renderbuffer = f.m_renderbuffer;
95 this->m_storageattach = f.m_storageattach;
96 this->m_clear_colour = std::move(f.m_clear_colour);
97
98 f.m_id = 0;
99 f.m_colour = 0;
100 f.m_renderbuffer = 0;
101 f.m_storageattach = 0;
102 }
103
104 return *this;
105 }
106
108 {
109 if (m_id != 0)
110 {
111 glDeleteFramebuffers(1, &m_id);
112 }
113
114 if (m_colour != 0)
115 {
116 glDeleteTextures(1, &m_colour);
117 }
118
119 if (m_renderbuffer != 0)
120 {
121 glDeleteRenderbuffers(1, &m_renderbuffer);
122 }
123
124 if (m_storageattach != 0)
125 {
126 glDeleteTextures(1, &m_storageattach);
127 }
128 }
129
130 void Framebuffer::add_colour_attachment(const int width, const int height)
131 {
132 m_width = width;
134
135 if (m_colour != 0)
136 {
137 glDeleteTextures(1, &m_colour);
138 }
139
140 glCreateTextures(GL_TEXTURE_2D, 1, &m_colour);
141 glTextureStorage2D(m_colour, 1, GL_RGBA8, m_width, m_height);
142 // glTextureSubImage2D(m_colour, 0, 0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
143 glTextureParameteri(m_colour, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
144 glTextureParameteri(m_colour, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
145 glTextureParameteri(m_colour, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
146 glTextureParameteri(m_colour, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
147 glTextureParameteri(m_colour, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
148 glTextureParameterf(m_colour, GL_TEXTURE_MAX_ANISOTROPY, 1.0f);
149
150 static auto s_fbo = 0;
151 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_fbo);
152
153 glBindFramebuffer(GL_FRAMEBUFFER, m_id);
154 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colour, 0);
155 glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
156 }
157
159 {
160 if (m_renderbuffer != 0)
161 {
162 glDeleteRenderbuffers(1, &m_renderbuffer);
163 }
164
165 static auto s_fbo = 0;
166 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_fbo);
167
168 glBindFramebuffer(GL_FRAMEBUFFER, m_id);
169
170 glGenRenderbuffers(1, &m_renderbuffer);
171 glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
172 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_width, m_height);
173 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderbuffer);
174
175 glBindRenderbuffer(GL_RENDERBUFFER, 0);
176 glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
177 }
178
180 {
181 if (m_storageattach != 0)
182 {
183 glDeleteTextures(1, &m_storageattach);
184 }
185
186 glCreateTextures(GL_TEXTURE_2D, 1, &m_storageattach);
187 glTextureStorage2D(m_storageattach, 1, GL_R32I, m_width, m_height);
188 // glTextureSubImage2D(m_storageattach, 0, 0, 0, m_width, m_height, GL_RED_INTEGER, GL_INT, nullptr);
189 glTextureParameteri(m_storageattach, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
190 glTextureParameteri(m_storageattach, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
191 glTextureParameteri(m_storageattach, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
192 glTextureParameteri(m_storageattach, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
193 glTextureParameteri(m_storageattach, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
194 glTextureParameterf(m_storageattach, GL_TEXTURE_MAX_ANISOTROPY, 1.0f);
195
196 static auto s_fbo = 0;
197 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_fbo);
198
199 glBindFramebuffer(GL_FRAMEBUFFER, m_id);
200 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_storageattach, 0);
201 glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
202 }
203
205 {
206 meta::vector<unsigned int> used;
207
208 if (m_colour > 0)
209 {
210 used.push_back(GL_COLOR_ATTACHMENT0);
211 }
212
213 if (m_storageattach > 0)
214 {
215 used.push_back(GL_COLOR_ATTACHMENT1);
216 }
217
218 glNamedFramebufferDrawBuffers(m_id, static_cast<GLsizei>(used.size()), used.data());
219
220 const auto status = glCheckNamedFramebufferStatus(m_id, GL_FRAMEBUFFER);
221 if (status != GL_FRAMEBUFFER_COMPLETE)
222 {
223 std::string reason;
224 switch (status)
225 {
226 case GL_FRAMEBUFFER_UNDEFINED:
227 reason = "GL_FRAMEBUFFER_UNDEFINED";
228 break;
229 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
230 reason = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
231 break;
232 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
233 reason = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
234 break;
235 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
236 reason = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
237 break;
238 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
239 reason = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
240 break;
241 case GL_FRAMEBUFFER_UNSUPPORTED:
242 reason = "GL_FRAMEBUFFER_UNSUPPORTED";
243 break;
244 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
245 reason = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
246 break;
247 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
248 reason = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
249 break;
250 default:
251 reason = "UNKNOWN";
252 break;
253 }
254
255 GALAXY_LOG(GALAXY_FATAL, "Failed to complete framebuffer: {0}.", reason);
256 }
257 }
258
259 int Framebuffer::read_storagebuffer(const int x, const int y)
260 {
261 static auto s_fbo = 0;
262 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_fbo);
263
264 glBindFramebuffer(GL_FRAMEBUFFER, m_id);
265 glReadBuffer(1);
266
267 int data = -1;
268 glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, &data);
269
270 glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
271 return data;
272 }
273
275 {
276 glClearNamedFramebufferiv(m_id, GL_COLOR, 1, &val);
277 }
278
280 {
281 const auto& vec = col.vec4();
282
283 m_clear_colour[0] = vec.x;
284 m_clear_colour[1] = vec.y;
285 m_clear_colour[2] = vec.z;
286 m_clear_colour[3] = vec.w;
287 }
288
289 void Framebuffer::begin(const bool clear)
290 {
291 glBindFramebuffer(GL_FRAMEBUFFER, m_id);
292 glViewport(0, 0, m_width, m_height);
293
294 if (clear)
295 {
296 glClearColor(m_clear_colour[0], m_clear_colour[1], m_clear_colour[2], m_clear_colour[3]);
297 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
298 }
299 }
300
302 {
303 glBindFramebuffer(GL_FRAMEBUFFER, 0);
304 }
305
307 {
308 if (m_colour != 0)
309 {
310 clear(0);
311 }
312
313 if (m_renderbuffer != 0)
314 {
315 constexpr const auto CLEAR_DEPTH = 1.0f;
316 glClearNamedFramebufferfv(m_renderbuffer, GL_DEPTH, 0, &CLEAR_DEPTH);
317 }
318
319 if (m_storageattach > 0)
320 {
321 clear(1);
322 }
323 }
324
325 void Framebuffer::clear(const unsigned int index)
326 {
327 glClearNamedFramebufferfv(m_id, GL_COLOR, index, m_clear_colour.data());
328 }
329
331 {
332 glDeleteFramebuffers(1, &m_id);
333
334 if (m_colour != 0)
335 {
336 glDeleteTextures(1, &m_colour);
337 }
338
339 if (m_renderbuffer != 0)
340 {
341 glDeleteRenderbuffers(1, &m_renderbuffer);
342 }
343
344 if (m_storageattach != 0)
345 {
346 glDeleteTextures(1, &m_storageattach);
347 }
348
349 glCreateFramebuffers(1, &m_id);
350 }
351
353 {
354 return m_width;
355 }
356
358 {
359 return m_height;
360 }
361
362 unsigned int Framebuffer::texture() const
363 {
364 return m_colour;
365 }
366
367 unsigned int Framebuffer::id() const
368 {
369 return m_id;
370 }
371 } // namespace graphics
372} // namespace galaxy
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:28
#define GALAXY_FATAL
Definition Log.hpp:25
Represents an RGBA colour.
Definition Colour.hpp:27
glm::vec4 & vec4()
Get vec4.
Definition Colour.cpp:160
OpenGL framebuffer to render to.
std::array< float, 4 > m_clear_colour
Clear colour.
unsigned int m_renderbuffer
Renderbuffer attachment.
unsigned int m_id
OpenGL handle.
void clear_storagebuffer(const int val)
Clear storagebuffer.
unsigned int m_storageattach
Storage attachment id.
void add_colour_attachment(const int width, const int height)
Add a colour attachment to the framebuffer.
void add_depth_stencil_renderbuffer()
Adds a depth and stencil supported renderbuffer to the framebuffer.
void reset()
Completely delete objects.
int width() const
Get width.
int height() const
Get height.
unsigned int id() const
Get OpenGL framebuffer object.
unsigned int texture() const
Get colour attachment texture id.
void create()
Construct framebuffer from attachments and renderbuffers.
Framebuffer & operator=(Framebuffer &&)
Move assignment operator.
int read_storagebuffer(const int x, const int y)
Read storage buffer.
unsigned int m_colour
Colour attachment id.
void end()
Unbind framebuffer.
void add_storage_attachment()
Add an attachment to store an integer.
void clear()
Clear framebuffer attachments.
void begin(const bool clear=true)
Bind framebuffer for rendering to.
void set_clear_colour(const graphics::Colour &col)
Set clear colour.
Animated.cpp galaxy.
Definition Animated.cpp:16