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#include "CameraBase.h"
15#include "../../Component/CameraComponent.h"
16
17#if defined(__CSE_DESKTOP__)
18#define CSE_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT32F
19#define CSE_GL_RG GL_RG16F
20#define CSE_GL_RGB GL_RGB16F
21#define CSE_GL_RGBA GL_RGBA16F
22#elif defined(__CSE_ES__)
23#define CSE_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16
24#define CSE_GL_RG GL_RG8
25#define CSE_GL_RGB GL_RGB8
26#define CSE_GL_RGBA GL_RGBA8
27#endif
28
29using namespace CSE;
30
31RESOURCE_CONSTRUCTOR(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::PostFrameBuffer(GLProgramHandle* handle, const CameraBase& camera) {
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 if (m_postObject.handle == nullptr) {
244 m_postObject.handle = handle;
245 m_postObject.color = m_postObject.handle->UniformLocation("post.color")->id;
246 m_postObject.depth = m_postObject.handle->UniformLocation("post.depth")->id;
247 }
248
249 // Blit for copy buffer
250 BlitCopiedFrameBuffer();
251
252 const auto& colorTexture = m_postObject.copyBuffer;
253 const auto& depthTexture = m_depthBuffer->texture;
254 const float sizeRaw[2] = { static_cast<float>(m_size->x), static_cast<float>(m_size->y) };
255 const auto& uniforms = m_postObject.handle->Uniforms;
256
257 AttachFrameBuffer();
258 glClear(GL_COLOR_BUFFER_BIT);
259 glViewport(0, 0, m_size->x, m_size->y);
260 glUseProgram(m_postObject.handle->Program);
261 colorTexture->Bind(m_postObject.color, 0);
262 depthTexture->Bind(m_postObject.depth, 1);
263 const auto& cameraStruct = camera.GetCameraMatrixStruct();
264 ShaderUtil::BindCameraToShader(*m_postObject.handle, cameraStruct.camera, cameraStruct.cameraPosition,
265 cameraStruct.projection, mat4::Identity());
266 if (uniforms.SourceBufferSize >= 0)
267 glUniform2fv(uniforms.SourceBufferSize, 1, sizeRaw);
268
269 ShaderUtil::BindAttributeToPlane();
270}
271
272STexture* SFrameBuffer::BlitCopiedFrameBuffer() const {
273 if (m_postObject.copyFbo < 0) {
274 m_postObject.copyBuffer = new STexture(static_cast<STexture::Type>(m_dimension));
275 m_postObject.copyBuffer->InitTexture(m_size->x, m_size->y, GL_RGB, GenerateInternalFormat(GL_RGB),
276 GenerateInternalType(GL_RGB));
277 m_postObject.copyTexId = m_postObject.copyBuffer->GetTextureID();
278
279 unsigned int copy_fbo;
280 glGenFramebuffers(1, &copy_fbo);
281 glBindFramebuffer(GL_FRAMEBUFFER, copy_fbo);
282 m_postObject.copyFbo = copy_fbo;
283 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_postObject.copyTexId, 0);
284 }
285
286 AttachFrameBuffer(GL_READ_FRAMEBUFFER);
287 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_postObject.copyFbo);
288 glBlitFramebuffer(0, 0, m_size->x, m_size->y, 0, 0, m_size->x, m_size->y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
289 return m_postObject.copyBuffer;
290}
291
292int SFrameBuffer::GetWidth() const {
293 return m_size->x;
294}
295
296int SFrameBuffer::GetHeight() const {
297 return m_size->y;
298}
299
300int SFrameBuffer::GenerateAttachmentType(SFrameBuffer::BufferType type, bool isIncreaseAttachment) const {
301 switch (type) {
302 case RENDER:
303 if (m_bufferStatus == BufferStatus::NONE) m_bufferStatus = COLOR_ONLY;
304 if (m_bufferStatus == BufferStatus::DEPTH_ONLY) m_bufferStatus = MULTI;
305 if (isIncreaseAttachment)
306 return GL_COLOR_ATTACHMENT0 + (++m_colorAttachmentSize) - 1;
307 else
308 return GL_COLOR_ATTACHMENT0 + m_colorAttachmentSize;
309 case DEPTH:
310 if (m_bufferStatus == BufferStatus::NONE) m_bufferStatus = DEPTH_ONLY;
311 if (m_bufferStatus == BufferStatus::COLOR_ONLY) m_bufferStatus = MULTI;
312 return GL_DEPTH_ATTACHMENT;
313 case STENCIL:
314 default:
315 return GL_COLOR_ATTACHMENT0;
316 }
317}
318
319int SFrameBuffer::GenerateInternalFormat(int channel) const {
320 switch (channel) {
321 case GL_RG:
322 return CSE_GL_RG;
323 case GL_DEPTH_COMPONENT:
324 return CSE_GL_DEPTH_COMPONENT;
325 case GL_RGBA:
326 return CSE_GL_RGBA;
327 case GL_RGB:
328 default:
329 return CSE_GL_RGB;
330 }
331}
332
333int SFrameBuffer::GenerateInternalType(int channel) const {
334 switch (channel) {
335 case GL_DEPTH_COMPONENT:
336#if defined(__CSE_DESKTOP__)
337 return GL_FLOAT;
338#elif defined(__CSE_ES__)
339 return GL_UNSIGNED_INT;
340#endif
341 default:
342#if defined(__CSE_DESKTOP__)
343 return GL_FLOAT;
344#elif defined(__CSE_ES__)
345 return GL_UNSIGNED_BYTE;
346#endif
347 }
348}
349
350void SFrameBuffer::ReleaseBufferObject(const SFrameBuffer::BufferObject* bufferObject) {
351 if (bufferObject->renderbufferId > 0) glDeleteRenderbuffers(1, &bufferObject->renderbufferId);
352 if (bufferObject->texture != nullptr) {
353 auto resMgr = CORE->GetCore(ResMgr);
354 resMgr->Remove(bufferObject->texture);
355 }
356 delete bufferObject;
357}
358
359SFrameBuffer::BufferStatus SFrameBuffer::GetBufferStatus() const {
360 return m_bufferStatus;
361}
362
364 if (index < 0 || index > m_buffers.size() - 1) return nullptr;
365
366 auto texture = m_buffers[index]->texture;
367 return texture;
368}
369
370STexture* SFrameBuffer::GetTexture(const char* id) const {
371 for (const auto& buffer: m_buffers) {
372 const auto& texture = buffer->texture;
373 if (texture == nullptr) continue;
374
375 std::string bufferId = texture->GetHash();
376 if (bufferId == id) return texture;
377 }
378 return nullptr;
379}
380
381unsigned int SFrameBuffer::GetRenderbufferID(int index) const {
382 if (index < 0 || index > m_buffers.size() - 1) return 0;
383
384 auto id = m_buffers[index]->renderbufferId;
385 return id;
386}
387
388void SFrameBuffer::SetValue(std::string name_str, VariableBinder::Arguments value) {
389}
390
391std::string SFrameBuffer::PrintValue() const {
392 return {};
393}
unsigned int GetRenderbufferID(int index) const
STexture * GenerateTexturebuffer(BufferType type, int channel, int level=0)
unsigned int GenerateRenderbuffer(BufferType type, int internalFormat)
void SetValue(std::string name_str, Arguments value) override
void GenerateFramebuffer(BufferDimension dimension, int width, int height)
STexture * GetTexture(int index) const
static void BindCameraToShader(const GLProgramHandle &handle, const mat4 &camera, const vec3 &cameraPosition, const mat4 &projection, const mat4 &transform)
Binds the camera data to the shader.
Definition XML.h:77
Definition XML.h:43