5#include "SFrameBuffer.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"
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
29SFrameBuffer::BlitObject SFrameBuffer::m_blitObject = SFrameBuffer::BlitObject();
31SFrameBuffer::SFrameBuffer() {
32 SetUndestroyable(
true);
35SFrameBuffer::~SFrameBuffer() =
default;
37void SFrameBuffer::Exterminate() {
38 glDeleteFramebuffers(1, &m_fbo);
40 for (
const auto& buffer : m_buffers) {
41 ReleaseBufferObject(buffer);
44 m_depthBuffer = m_mainColorBuffer =
nullptr;
50 const XNode* root =
nullptr;
53 root =
XFILE(asset->name_path.c_str()).getRoot();
61 const XNode& cse_framebuffer = root->getChild(
"CSEFRAMEBUFFER");
62 const XNode& info = cse_framebuffer.getChild(
"info");
64 auto width_str = info.getAttribute(
"width").value;
65 auto height_str = info.getAttribute(
"height").value;
66 auto dimension_str = info.getAttribute(
"dimension").value;
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));
73 const XNode& buffers = cse_framebuffer.getChild(
"buffers");
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;
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;
86 const auto& textureName =
"?Texture" + std::to_string(index);
87 texture->SetName(GetName() + textureName);
88 texture->SetAbsoluteID(GetHash() + textureName);
98 auto resMgr = CORE->GetCore(
ResMgr);
105 m_dimension = dimension;
109 glGenFramebuffers(1, &m_fbo);
110 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
114 if (m_dimension == CUBE)
return 0;
116 auto buffer =
new BufferObject();
118 buffer->format = internalFormat;
120 glGenRenderbuffers(1, &buffer->renderbufferId);
121 glBindRenderbuffer(GL_RENDERBUFFER, buffer->renderbufferId);
122 glRenderbufferStorage(GL_RENDERBUFFER, GenerateInternalFormat(internalFormat), m_size->x, m_size->y);
124 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
125 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GenerateAttachmentType(type,
false), GL_RENDERBUFFER,
126 buffer->renderbufferId);
128 if (type == RENDER) {
129 if (m_mainColorBuffer ==
nullptr)
130 m_mainColorBuffer = buffer;
131 }
else if (m_depthBuffer ==
nullptr) {
132 m_depthBuffer = buffer;
134 m_buffers.push_back(buffer);
135 return buffer->renderbufferId;
139 auto buffer =
new BufferObject();
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();
149 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
151 if (m_dimension == PLANE) {
152 glFramebufferTexture2D(GL_FRAMEBUFFER, GenerateAttachmentType(type), GL_TEXTURE_2D, texId, level);
155 GenerateAttachmentType(buffer->type,
false);
158 if (type == RENDER) {
159 if (m_mainColorBuffer ==
nullptr)
160 m_mainColorBuffer = buffer;
161 }
else if (m_depthBuffer ==
nullptr) {
162 m_depthBuffer = buffer;
164 m_buffers.push_back(buffer);
165 return buffer->texture;
169 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
170 m_buffers.reserve(m_buffers.size());
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);
179 glDrawBuffers(m_colorAttachmentSize, &attachments[0]);
182 if (m_bufferStatus == COLOR_ONLY) {
184 m_bufferStatus = MULTI;
188void SFrameBuffer::AttachCubeBuffer(
int index,
int level)
const {
189 if (m_dimension != CUBE)
return;
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);
199void SFrameBuffer::AttachFrameBuffer(
int target)
const {
200 glViewport(0, 0, m_size->x, m_size->y);
201 glBindFramebuffer(target, m_fbo);
204void SFrameBuffer::DetachFrameBuffer()
const {
205 glBindFramebuffer(GL_FRAMEBUFFER, 0);
208void SFrameBuffer::ResizeFrameBuffer(
int width,
int height) {
209 std::vector<BufferObject*> origBufferVector(m_buffers);
212 m_buffers.reserve(origBufferVector.size());
213 m_colorAttachmentSize = 0;
214 glDeleteFramebuffers(1, &m_fbo);
216 m_depthBuffer = m_mainColorBuffer =
nullptr;
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;
224 ReleaseBufferObject(buffer);
235 if (m_mainColorBuffer ==
nullptr || m_depthBuffer ==
nullptr) {
245 if (type == REVERSE) {
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;
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;
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);
273 ShaderUtil::BindAttributeToPlane();
276int SFrameBuffer::GetWidth()
const {
280int SFrameBuffer::GetHeight()
const {
284int SFrameBuffer::GenerateAttachmentType(SFrameBuffer::BufferType type,
bool isIncreaseAttachment)
const {
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;
292 return GL_COLOR_ATTACHMENT0 + m_colorAttachmentSize;
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;
299 return GL_COLOR_ATTACHMENT0;
303int SFrameBuffer::GenerateInternalFormat(
int channel)
const {
307 case GL_DEPTH_COMPONENT:
308 return CSE_GL_DEPTH_COMPONENT;
317int SFrameBuffer::GenerateInternalType(
int channel)
const {
319 case GL_DEPTH_COMPONENT:
320#if defined(__CSE_DESKTOP__)
322#elif defined(__CSE_ES__)
323 return GL_UNSIGNED_INT;
326#if defined(__CSE_DESKTOP__)
328#elif defined(__CSE_ES__)
329 return GL_UNSIGNED_BYTE;
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);
343SFrameBuffer::BufferStatus SFrameBuffer::GetBufferStatus()
const {
344 return m_bufferStatus;
348 if (index < 0 || index > m_buffers.size() - 1)
return nullptr;
350 auto texture = m_buffers[index]->texture;
355 for (
const auto& buffer : m_buffers) {
356 const auto& texture = buffer->texture;
357 if (texture ==
nullptr)
continue;
359 std::string bufferId = texture->GetHash();
360 if (bufferId ==
id)
return texture;
366 if (index < 0 || index > m_buffers.size() - 1)
return 0;
368 auto id = m_buffers[index]->renderbufferId;
unsigned int GetRenderbufferID(int index) const
STexture * GenerateTexturebuffer(BufferType type, int channel, int level=0)
unsigned int GenerateRenderbuffer(BufferType type, int internalFormat)
void RasterizeFramebuffer()
void GenerateFramebuffer(BufferDimension dimension, int width, int height)
STexture * GetTexture(int index) const
void BlitFrameBuffer(const SFrameBuffer &dst, BlitType type=IN_ORDER)