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"
14#include "CameraBase.h"
15#include "../../Component/CameraComponent.h"
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
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) {
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;
250 BlitCopiedFrameBuffer();
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;
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();
265 cameraStruct.projection, mat4::Identity());
266 if (uniforms.SourceBufferSize >= 0)
267 glUniform2fv(uniforms.SourceBufferSize, 1, sizeRaw);
269 ShaderUtil::BindAttributeToPlane();
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();
279 unsigned int copy_fbo;
280 glGenFramebuffers(1, ©_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);
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;
292int SFrameBuffer::GetWidth()
const {
296int SFrameBuffer::GetHeight()
const {
300int SFrameBuffer::GenerateAttachmentType(SFrameBuffer::BufferType type,
bool isIncreaseAttachment)
const {
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;
308 return GL_COLOR_ATTACHMENT0 + m_colorAttachmentSize;
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;
315 return GL_COLOR_ATTACHMENT0;
319int SFrameBuffer::GenerateInternalFormat(
int channel)
const {
323 case GL_DEPTH_COMPONENT:
324 return CSE_GL_DEPTH_COMPONENT;
333int SFrameBuffer::GenerateInternalType(
int channel)
const {
335 case GL_DEPTH_COMPONENT:
336#if defined(__CSE_DESKTOP__)
338#elif defined(__CSE_ES__)
339 return GL_UNSIGNED_INT;
342#if defined(__CSE_DESKTOP__)
344#elif defined(__CSE_ES__)
345 return GL_UNSIGNED_BYTE;
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);
359SFrameBuffer::BufferStatus SFrameBuffer::GetBufferStatus()
const {
360 return m_bufferStatus;
364 if (index < 0 || index > m_buffers.size() - 1)
return nullptr;
366 auto texture = m_buffers[index]->texture;
371 for (
const auto& buffer: m_buffers) {
372 const auto& texture = buffer->texture;
373 if (texture ==
nullptr)
continue;
375 std::string bufferId = texture->GetHash();
376 if (bufferId ==
id)
return texture;
382 if (index < 0 || index > m_buffers.size() - 1)
return 0;
384 auto id = m_buffers[index]->renderbufferId;
391std::string SFrameBuffer::PrintValue()
const {
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 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.