CSEngine
Loading...
Searching...
No Matches
SFrameBuffer.cpp
1//
2// Created by 나 on 2021-05-26.
3//
4
5#include "SFrameBuffer.h"
6#include "STexture.h"
7#include "../../Manager/EngineCore.h"
8#include "../../Manager/ResMgr.h"
9#include "../Loader/XML/XML.h"
10#include "../../PlatformDef.h"
11#include "../Settings.h"
12#include "../GLProgramHandle.h"
13#include "ShaderUtil.h"
14
15#if defined(__CSE_DESKTOP__)
16#define CSE_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT32F
17#define CSE_GL_RG GL_RG16F
18#define CSE_GL_RGB GL_RGB16F
19#define CSE_GL_RGBA GL_RGBA16F
20#elif defined(__CSE_ES__)
21#define CSE_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16
22#define CSE_GL_RG GL_RG8
23#define CSE_GL_RGB GL_RGB8
24#define CSE_GL_RGBA GL_RGBA8
25#endif
26
27using namespace CSE;
28
29SFrameBuffer::BlitObject SFrameBuffer::m_blitObject = SFrameBuffer::BlitObject();
30
31SFrameBuffer::SFrameBuffer() {
32 SetUndestroyable(true);
33}
34
35SFrameBuffer::~SFrameBuffer() = default;
36
37void SFrameBuffer::Exterminate() {
38 glDeleteFramebuffers(1, &m_fbo);
39
40 for (const auto& buffer : m_buffers) {
41 ReleaseBufferObject(buffer);
42 }
43 m_buffers.clear();
44 m_depthBuffer = m_mainColorBuffer = nullptr;
45 SAFE_DELETE(m_size);
46}
47
48// Init function for asset binding
49void SFrameBuffer::Init(const AssetMgr::AssetReference* asset) {
50 const XNode* root = nullptr;
51
52 try {
53 root = XFILE(asset->name_path.c_str()).getRoot();
54 }
55 catch (int e) {
56 SAFE_DELETE(root);
57 return;
58 }
59
60 try {
61 const XNode& cse_framebuffer = root->getChild("CSEFRAMEBUFFER");
62 const XNode& info = cse_framebuffer.getChild("info");
63
64 auto width_str = info.getAttribute("width").value;
65 auto height_str = info.getAttribute("height").value;
66 auto dimension_str = info.getAttribute("dimension").value;
67
68 m_size->x = std::stoi(width_str);
69 m_size->y = std::stoi(height_str);
70 auto dimension = static_cast<BufferDimension>(std::stoi(dimension_str));
71 GenerateFramebuffer(dimension, m_size->x, m_size->y);
72
73 const XNode& buffers = cse_framebuffer.getChild("buffers");
74 int index = 0;
75 for (const auto& buffer_node : buffers.children) {
76 auto type_str = buffer_node.getAttribute("type").value;
77 auto format_str = buffer_node.getAttribute("format").value;
78 auto isTexture_str = buffer_node.getAttribute("isTexture").value;
79
80 auto type = static_cast<BufferType>(std::stoi(type_str));
81 auto format = std::stoi(format_str);
82 auto isTexture = std::stoi(isTexture_str) == 1;
83
84 if (isTexture) {
85 const auto& texture = GenerateTexturebuffer(type, format);
86 const auto& textureName = "?Texture" + std::to_string(index);
87 texture->SetName(GetName() + textureName);
88 texture->SetAbsoluteID(GetHash() + textureName);
89 } else {
90 GenerateRenderbuffer(type, format);
91 }
92 ++index;
93 }
95 }
96 catch (int e) {
97 SAFE_DELETE(root);
98 auto resMgr = CORE->GetCore(ResMgr);
99 resMgr->Remove(this);
100 }
101 SAFE_DELETE(root);
102}
103
104void SFrameBuffer::GenerateFramebuffer(BufferDimension dimension, int width, int height) {
105 m_dimension = dimension;
106 m_size->x = width;
107 m_size->y = height;
108
109 glGenFramebuffers(1, &m_fbo);
110 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
111}
112
113unsigned int SFrameBuffer::GenerateRenderbuffer(BufferType type, int internalFormat) {
114 if (m_dimension == CUBE) return 0;
115
116 auto buffer = new BufferObject();
117 buffer->type = type;
118 buffer->format = internalFormat;
119
120 glGenRenderbuffers(1, &buffer->renderbufferId);
121 glBindRenderbuffer(GL_RENDERBUFFER, buffer->renderbufferId);
122 glRenderbufferStorage(GL_RENDERBUFFER, GenerateInternalFormat(internalFormat), m_size->x, m_size->y);
123
124 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
125 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GenerateAttachmentType(type, false), GL_RENDERBUFFER,
126 buffer->renderbufferId);
127
128 if (type == RENDER) {
129 if (m_mainColorBuffer == nullptr)
130 m_mainColorBuffer = buffer;
131 } else if (m_depthBuffer == nullptr) {
132 m_depthBuffer = buffer;
133 }
134 m_buffers.push_back(buffer);
135 return buffer->renderbufferId;
136}
137
138STexture* SFrameBuffer::GenerateTexturebuffer(BufferType type, int channel, int level) {
139 auto buffer = new BufferObject();
140 buffer->type = type;
141 buffer->format = channel;
142 buffer->level = (short) level;
143 buffer->texture = new STexture(static_cast<STexture::Type>(m_dimension));
144 buffer->texture->InitTexture(m_size->x, m_size->y, channel, GenerateInternalFormat(channel),
145 GenerateInternalType(channel));
146 unsigned int texId = buffer->texture->GetTextureID();
147// if(level > 0)
148
149 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
150
151 if (m_dimension == PLANE) {
152 glFramebufferTexture2D(GL_FRAMEBUFFER, GenerateAttachmentType(type), GL_TEXTURE_2D, texId, level);
153 } else {
154 // TODO: 큐브맵 텍스쳐 바인딩 설정 필요
155 GenerateAttachmentType(buffer->type, false);
156 }
157
158 if (type == RENDER) {
159 if (m_mainColorBuffer == nullptr)
160 m_mainColorBuffer = buffer;
161 } else if (m_depthBuffer == nullptr) {
162 m_depthBuffer = buffer;
163 }
164 m_buffers.push_back(buffer);
165 return buffer->texture;
166}
167
169 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
170 m_buffers.reserve(m_buffers.size());
171
172 // tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
173 if (m_colorAttachmentSize > 1) {
174 std::vector<unsigned int> attachments;
175 attachments.reserve(m_colorAttachmentSize);
176 for (int i = 0; i < m_colorAttachmentSize; ++i) {
177 attachments.push_back(GL_COLOR_ATTACHMENT0 + i);
178 }
179 glDrawBuffers(m_colorAttachmentSize, &attachments[0]);
180 }
181
182 if (m_bufferStatus == COLOR_ONLY) {
183 GenerateTexturebuffer(SFrameBuffer::DEPTH, GL_DEPTH_COMPONENT);
184 m_bufferStatus = MULTI;
185 }
186}
187
188void SFrameBuffer::AttachCubeBuffer(int index, int level) const {
189 if (m_dimension != CUBE) return;
190
191 for (const auto& buffer : m_buffers) {
192 const auto& texture = buffer->texture;
193 if (texture == nullptr) continue;
194 glFramebufferTexture2D(GL_FRAMEBUFFER, GenerateAttachmentType(buffer->type, false),
195 GL_TEXTURE_CUBE_MAP_POSITIVE_X + index, texture->GetTextureID(), level);
196 }
197}
198
199void SFrameBuffer::AttachFrameBuffer(int target) const {
200 glViewport(0, 0, m_size->x, m_size->y);
201 glBindFramebuffer(target, m_fbo);
202}
203
204void SFrameBuffer::DetachFrameBuffer() const {
205 glBindFramebuffer(GL_FRAMEBUFFER, 0);
206}
207
208void SFrameBuffer::ResizeFrameBuffer(int width, int height) {
209 std::vector<BufferObject*> origBufferVector(m_buffers);
210
211 m_buffers.clear();
212 m_buffers.reserve(origBufferVector.size());
213 m_colorAttachmentSize = 0;
214 glDeleteFramebuffers(1, &m_fbo);
215 GenerateFramebuffer(m_dimension, width, height);
216 m_depthBuffer = m_mainColorBuffer = nullptr;
217
218 for (const auto& buffer : origBufferVector) {
219 auto type = buffer->type;
220 auto format = buffer->format;
221 auto level = buffer->level;
222 auto isTexture = buffer->texture != nullptr;
223
224 ReleaseBufferObject(buffer);
225
226 if (isTexture)
227 GenerateTexturebuffer(type, format, level);
228 else
229 GenerateRenderbuffer(type, format);
230 }
232}
233
234void SFrameBuffer::BlitFrameBuffer(const SFrameBuffer& dst, BlitType type) {
235 if (m_mainColorBuffer == nullptr || m_depthBuffer == nullptr) {
236 Exterminate();
237 GenerateFramebuffer(PLANE, m_size->x, m_size->y);
238 GenerateTexturebuffer(RENDER, GL_RGB);
239 GenerateTexturebuffer(DEPTH, GL_DEPTH_COMPONENT);
241 }
242
243 const SFrameBuffer* a;
244 const SFrameBuffer* b;
245 if (type == REVERSE) {
246 a = this;
247 b = &dst;
248 } else {
249 a = &dst;
250 b = this;
251 }
252 const auto& aColorTexture = a->m_mainColorBuffer->texture;
253 const auto& bColorTexture = b->m_mainColorBuffer->texture;
254 const auto& aDepthTexture = a->m_depthBuffer->texture;
255 const auto& bDepthTexture = b->m_depthBuffer->texture;
256
257 if (m_blitObject.handle == nullptr) {
258 m_blitObject.handle = SResource::Create<GLProgramHandle>(Settings::GetDefaultBlitBufferShaderID());
259 m_blitObject.aColor = m_blitObject.handle->UniformLocation("a.color")->id;
260 m_blitObject.bColor = m_blitObject.handle->UniformLocation("b.color")->id;
261 m_blitObject.aDepth = m_blitObject.handle->UniformLocation("a.depth")->id;
262 m_blitObject.bDepth = m_blitObject.handle->UniformLocation("b.depth")->id;
263 }
264
265 AttachFrameBuffer();
266 glViewport(0, 0, m_size->x, m_size->y);
267 glUseProgram(m_blitObject.handle->Program);
268 aColorTexture->Bind(m_blitObject.aColor, 0);
269 bColorTexture->Bind(m_blitObject.bColor, 1);
270 aDepthTexture->Bind(m_blitObject.aDepth, 2);
271 bDepthTexture->Bind(m_blitObject.bDepth, 3);
272
273 ShaderUtil::BindAttributeToPlane();
274}
275
276int SFrameBuffer::GetWidth() const {
277 return m_size->x;
278}
279
280int SFrameBuffer::GetHeight() const {
281 return m_size->y;
282}
283
284int SFrameBuffer::GenerateAttachmentType(SFrameBuffer::BufferType type, bool isIncreaseAttachment) const {
285 switch (type) {
286 case RENDER:
287 if (m_bufferStatus == BufferStatus::NONE) m_bufferStatus = COLOR_ONLY;
288 if (m_bufferStatus == BufferStatus::DEPTH_ONLY) m_bufferStatus = MULTI;
289 if (isIncreaseAttachment)
290 return GL_COLOR_ATTACHMENT0 + (++m_colorAttachmentSize) - 1;
291 else
292 return GL_COLOR_ATTACHMENT0 + m_colorAttachmentSize;
293 case DEPTH:
294 if (m_bufferStatus == BufferStatus::NONE) m_bufferStatus = DEPTH_ONLY;
295 if (m_bufferStatus == BufferStatus::COLOR_ONLY) m_bufferStatus = MULTI;
296 return GL_DEPTH_ATTACHMENT;
297 case STENCIL:
298 default:
299 return GL_COLOR_ATTACHMENT0;
300 }
301}
302
303int SFrameBuffer::GenerateInternalFormat(int channel) const {
304 switch (channel) {
305 case GL_RG:
306 return CSE_GL_RG;
307 case GL_DEPTH_COMPONENT:
308 return CSE_GL_DEPTH_COMPONENT;
309 case GL_RGBA:
310 return CSE_GL_RGBA;
311 case GL_RGB:
312 default:
313 return CSE_GL_RGB;
314 }
315}
316
317int SFrameBuffer::GenerateInternalType(int channel) const {
318 switch (channel) {
319 case GL_DEPTH_COMPONENT:
320#if defined(__CSE_DESKTOP__)
321 return GL_FLOAT;
322#elif defined(__CSE_ES__)
323 return GL_UNSIGNED_INT;
324#endif
325 default:
326#if defined(__CSE_DESKTOP__)
327 return GL_FLOAT;
328#elif defined(__CSE_ES__)
329 return GL_UNSIGNED_BYTE;
330#endif
331 }
332}
333
334void SFrameBuffer::ReleaseBufferObject(const SFrameBuffer::BufferObject* bufferObject) {
335 if (bufferObject->renderbufferId > 0) glDeleteRenderbuffers(1, &bufferObject->renderbufferId);
336 if (bufferObject->texture != nullptr) {
337 auto resMgr = CORE->GetCore(ResMgr);
338 resMgr->Remove(bufferObject->texture);
339 }
340 delete bufferObject;
341}
342
343SFrameBuffer::BufferStatus SFrameBuffer::GetBufferStatus() const {
344 return m_bufferStatus;
345}
346
348 if (index < 0 || index > m_buffers.size() - 1) return nullptr;
349
350 auto texture = m_buffers[index]->texture;
351 return texture;
352}
353
354STexture* SFrameBuffer::GetTexture(const char* id) const {
355 for (const auto& buffer : m_buffers) {
356 const auto& texture = buffer->texture;
357 if (texture == nullptr) continue;
358
359 std::string bufferId = texture->GetHash();
360 if (bufferId == id) return texture;
361 }
362 return nullptr;
363}
364
365unsigned int SFrameBuffer::GetRenderbufferID(int index) const {
366 if (index < 0 || index > m_buffers.size() - 1) return 0;
367
368 auto id = m_buffers[index]->renderbufferId;
369 return id;
370}
unsigned int GetRenderbufferID(int index) const
STexture * GenerateTexturebuffer(BufferType type, int channel, int level=0)
unsigned int GenerateRenderbuffer(BufferType type, int internalFormat)
void GenerateFramebuffer(BufferDimension dimension, int width, int height)
STexture * GetTexture(int index) const
void BlitFrameBuffer(const SFrameBuffer &dst, BlitType type=IN_ORDER)
Definition XML.h:77
Definition XML.h:43