diff --git a/compile_linux.sh b/compile_linux.sh index 177f9d6..d39b12f 100755 --- a/compile_linux.sh +++ b/compile_linux.sh @@ -71,6 +71,7 @@ ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/material.cpp -o sfw/re ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/mesh.cpp -o sfw/render_core/mesh.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/mesh_utils.cpp -o sfw/render_core/mesh_utils.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/texture.cpp -o sfw/render_core/texture.o +ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/frame_buffer.cpp -o sfw/render_core/frame_buffer.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/image.cpp -o sfw/render_core/image.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/render_state.cpp -o sfw/render_core/render_state.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/keyboard.cpp -o sfw/render_core/keyboard.o @@ -126,6 +127,7 @@ ccache g++ -Wall -lX11 -D_REENTRANT -g sfw/core/aabb.o sfw/core/basis.o sfw/core sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/app_window.o \ sfw/render_core/shader.o sfw/render_core/material.o sfw/render_core/mesh.o \ sfw/render_core/mesh_utils.o sfw/render_core/texture.o \ + sfw/render_core/frame_buffer.o \ sfw/render_core/input_event.o sfw/render_core/input_map.o \ sfw/render_core/input.o sfw/render_core/shortcut.o \ sfw/render_core/keyboard.o sfw/render_core/font.o \ diff --git a/compile_osx.sh b/compile_osx.sh index 8663b43..ba2794b 100755 --- a/compile_osx.sh +++ b/compile_osx.sh @@ -75,6 +75,7 @@ clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/material.cpp -o sfw/rende clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/mesh.cpp -o sfw/render_core/mesh.o clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/mesh_utils.cpp -o sfw/render_core/mesh_utils.o clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/texture.cpp -o sfw/render_core/texture.o +clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/frame_buffer.cpp -o sfw/render_core/frame_buffer.o clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/image.cpp -o sfw/render_core/image.o clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/render_state.cpp -o sfw/render_core/render_state.o clang++ $args -D_REENTRANT -g -Isfw -c sfw/render_core/keyboard.cpp -o sfw/render_core/keyboard.o @@ -132,6 +133,7 @@ clang++ $args -D_REENTRANT -g sfw/core/aabb.o sfw/core/basis.o sfw/core/color.o sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/app_window.o \ sfw/render_core/shader.o sfw/render_core/material.o sfw/render_core/mesh.o \ sfw/render_core/mesh_utils.o sfw/render_core/texture.o \ + sfw/render_core/frame_buffer.o \ sfw/render_core/input_event.o sfw/render_core/input_map.o \ sfw/render_core/input.o sfw/render_core/shortcut.o \ sfw/render_core/keyboard.o sfw/render_core/font.o \ diff --git a/compile_vs.bat b/compile_vs.bat index 0922e4a..ef7f91f 100644 --- a/compile_vs.bat +++ b/compile_vs.bat @@ -72,6 +72,7 @@ cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/material.cpp /Fo:sfw/render_c cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/mesh.cpp /Fo:sfw/render_core/mesh.obj cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/mesh_utils.cpp /Fo:sfw/render_core/mesh_utils.obj cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/texture.cpp /Fo:sfw/render_core/texture.obj +cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/frame_buffer.cpp /Fo:sfw/render_core/frame_buffer.obj cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/image.cpp /Fo:sfw/render_core/image.obj cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/render_state.cpp /Fo:sfw/render_core/render_state.obj cl /D_REENTRANT /EHsc /Zi /Isfw /c sfw/render_core/keyboard.cpp /Fo:sfw/render_core/keyboard.obj @@ -138,6 +139,7 @@ cl /D_REENTRANT /Zi ^ sfw/render_core/application.obj sfw/render_core/scene.obj sfw/render_core/app_window.obj ^ sfw/render_core/shader.obj sfw/render_core/material.obj sfw/render_core/mesh.obj ^ sfw/render_core/mesh_utils.obj sfw/render_core/texture.obj ^ + sfw/render_core/frame_buffer.obj ^ sfw/render_core/input_event.obj sfw/render_core/input_map.obj ^ sfw/render_core/input.obj sfw/render_core/shortcut.obj ^ sfw/render_core/keyboard.obj sfw/render_core/font.obj ^ diff --git a/compile_windows.sh b/compile_windows.sh index 78b644e..9e05584 100755 --- a/compile_windows.sh +++ b/compile_windows.sh @@ -72,6 +72,7 @@ ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/material.cpp -o sfw/re ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/mesh.cpp -o sfw/render_core/mesh.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/mesh_utils.cpp -o sfw/render_core/mesh_utils.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/texture.cpp -o sfw/render_core/texture.o +ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/frame_buffer.cpp -o sfw/render_core/frame_buffer.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/image.cpp -o sfw/render_core/image.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/render_state.cpp -o sfw/render_core/render_state.o ccache g++ -Wall -D_REENTRANT -g -Isfw -c sfw/render_core/keyboard.cpp -o sfw/render_core/keyboard.o @@ -128,6 +129,7 @@ ccache g++ -Wall \ sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/window.o \ sfw/render_core/shader.o sfw/render_core/material.o sfw/render_core/mesh.o \ sfw/render_core/mesh_utils.o sfw/render_core/texture.o \ + sfw/render_core/frame_buffer.o \ sfw/render_core/input_event.o sfw/render_core/input_map.o \ sfw/render_core/input.o sfw/render_core/shortcut.o \ sfw/render_core/keyboard.o sfw/render_core/font.o \ diff --git a/sfw/render_core/frame_buffer.cpp b/sfw/render_core/frame_buffer.cpp new file mode 100644 index 0000000..cb16250 --- /dev/null +++ b/sfw/render_core/frame_buffer.cpp @@ -0,0 +1,317 @@ +//--STRIP +#include "render_core/frame_buffer.h" + +#include "core/memory.h" +#include + +#include "render_core/app_window.h" +//--STRIP + +int FrameBuffer::get_texture_flags() const { + return _texture_flags; +} + +void FrameBuffer::set_texture_flags(const int p_flags) { + _texture_flags = p_flags; +} + +int FrameBuffer::create(const int p_width, const int p_height, const int p_msaa_count) { + ERR_FAIL_COND_V(p_width <= 0, -1); + ERR_FAIL_COND_V(p_height <= 0, -1); + ERR_FAIL_COND_V(p_msaa_count < 0, -1); + + int max_msaa_levels = 0; + glGetIntegerv(GL_MAX_SAMPLES, &max_msaa_levels); + + int msaa = MIN(max_msaa_levels, p_msaa_count); + + if (msaa % 2 == 0) { + --msaa; + } + + _fbo_width = p_width; + _fbo_height = p_height; + _fbo_msaa_count = msaa; + + destroy(); + + glGenFramebuffers(1, &_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, _fbo); + + glGenTextures(1, &_texture); + glBindTexture(GL_TEXTURE_2D, _texture); + + if ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS)) { + if ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_FILTER)) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + } else { + if ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_FILTER)) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + } + + if ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_FILTER)) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering + } + + if ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_REPEAT) || (_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIRRORED_REPEAT)) { + if (_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIRRORED_REPEAT) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, ((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS) > 0) ? GL_TRUE : GL_FALSE); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _fbo_width, _fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); + + int status = get_status(); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return status; + } + + if (_fbo_msaa_count > 0) { + glGenFramebuffers(1, &_msaa_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, _msaa_fbo); + + glGenRenderbuffers(1, &_msaa_rbo_color); + glBindRenderbuffer(GL_RENDERBUFFER, _msaa_rbo_color); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, _fbo_msaa_count, GL_RGBA8, _fbo_width, _fbo_height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _msaa_rbo_color); + + glGenRenderbuffers(1, &_msaa_rbo_depth); + glBindRenderbuffer(GL_RENDERBUFFER, _msaa_rbo_depth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, _fbo_msaa_count, GL_DEPTH_COMPONENT, _fbo_width, _fbo_height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _msaa_rbo_depth); + + status = get_status(); + } + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return status; +} + +void FrameBuffer::destroy() { + if (!_fbo) { + return; + } + + if (_msaa_rbo_color) { + glDeleteRenderbuffers(1, &_msaa_rbo_color); + _msaa_rbo_color = 0; + } + + if (_msaa_rbo_depth) { + glDeleteRenderbuffers(1, &_msaa_rbo_depth); + _msaa_rbo_depth = 0; + } + + if (_msaa_fbo) { + glDeleteFramebuffers(1, &_msaa_fbo); + _msaa_fbo = 0; + } + + if (_texture) { + glDeleteTextures(1, &_texture); + _texture = 0; + } + + if (_rbo) { + glDeleteRenderbuffers(1, &_rbo); + _rbo = 0; + } + + if (_fbo) { + glDeleteFramebuffers(1, &_fbo); + _fbo = 0; + } +} + +int FrameBuffer::get_status() { + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + return status; +} + +uint32_t FrameBuffer::get_gl_fbo() { + if (!_msaa_fbo) { + return _fbo; + } + + return _msaa_fbo; +} + +uint32_t FrameBuffer::get_gl_texture() { + return _texture; +} + +void FrameBuffer::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, get_gl_fbo()); +} +void FrameBuffer::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} +void FrameBuffer::update() { + if (_fbo_msaa_count > 0) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, _msaa_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); + glBlitFramebuffer(0, 0, _fbo_width, _fbo_height, 0, 0, _fbo_width, _fbo_height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBlitFramebuffer(0, 0, _fbo_width, _fbo_height, 0, 0, _fbo_width, _fbo_height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + + if (((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS) > 0)) { + glBindTexture(GL_TEXTURE_2D, _texture); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + } +} + +Ref FrameBuffer::get_image_color() { + Ref img; + img.instance(); + + Vector cb = get_color_buffer(); + + img->create(_fbo_width, _fbo_height, false, Image::FORMAT_RGBA8, cb); + + if (((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS) > 0)) { + img->generate_mipmaps(); + } + + return img; +} +Ref FrameBuffer::get_image_depth() { + Ref img; + img.instance(); + + Vector db = get_depth_buffer(); + + img->create(_fbo_width, _fbo_height, false, Image::FORMAT_RF); + + ERR_FAIL_COND_V(db.size() * (int)sizeof(float) != img->get_data_size(), img); + + const float *db_ptr = db.ptr(); + float *ifptr = (float *)img->dataw(); + int db_size = db.size(); + for (int i = 0; i < db_size; ++i) { + ifptr[i] = db_ptr[i]; + } + + if (((_texture_flags & FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS) > 0)) { + img->generate_mipmaps(); + } + + return img; +} +Vector FrameBuffer::get_color_buffer() { + Vector color_buffer; + color_buffer.resize(_fbo_width * _fbo_height * 4); + + if (_fbo_msaa_count > 0) { + blit_color_to(_fbo); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo); + glReadPixels(0, 0, _fbo_width, _fbo_height, GL_RGBA, GL_UNSIGNED_BYTE, color_buffer.ptrw()); + + return color_buffer; +} +Vector FrameBuffer::get_depth_buffer() { + Vector depth_buffer; + depth_buffer.resize(_fbo_width * _fbo_height); + + if (_fbo_msaa_count > 0) { + blit_depth_to(_fbo); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo); + glReadPixels(0, 0, _fbo_width, _fbo_height, GL_DEPTH_COMPONENT, GL_FLOAT, depth_buffer.ptrw()); + + return depth_buffer; +} + +Vector2i FrameBuffer::get_size() const { + return Vector2i(_fbo_width, _fbo_height); +} + +void FrameBuffer::blit_color_to(const uint32_t p_destination_framebuffer, const Rect2i &p_rect) { + ERR_FAIL_COND(!p_destination_framebuffer); + + int width = p_rect.size.width == 0 ? p_rect.size.width : _fbo_width; + int height = p_rect.size.height == 0 ? p_rect.size.height : _fbo_height; + + uint32_t fbo = get_gl_fbo(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p_destination_framebuffer); + glBlitFramebuffer(0, 0, _fbo_width, _fbo_height, p_rect.position.x, p_rect.position.y, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR); +} + +void FrameBuffer::blit_depth_to(const uint32_t p_destination_framebuffer, const Rect2i &p_rect) { + ERR_FAIL_COND(!p_destination_framebuffer); + + int width = p_rect.size.width == 0 ? p_rect.size.width : _fbo_width; + int height = p_rect.size.height == 0 ? p_rect.size.height : _fbo_height; + + uint32_t fbo = get_gl_fbo(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p_destination_framebuffer); + glBlitFramebuffer(0, 0, _fbo_width, _fbo_height, p_rect.position.x, p_rect.position.y, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); +} + +void FrameBuffer::set_as_viewport() { + glViewport(0, 0, _fbo_width, _fbo_height); +} + +void FrameBuffer::reset_as_viewport() { + glViewport(0, 0, AppWindow::get_singleton()->get_width(), AppWindow::get_singleton()->get_height()); +} + +float FrameBuffer::get_aspect() const { + return _fbo_width / (float)_fbo_height; +} + +FrameBuffer::FrameBuffer() { + _texture = 0; + + _msaa_fbo = 0; + _msaa_rbo_color = 0; + _msaa_rbo_depth = 0; + + _fbo_width = 0; + _fbo_height = 0; + _fbo_msaa_count = 0; + + _rbo = 0; + _fbo = 0; + _texture_flags = 0; +} + +FrameBuffer::~FrameBuffer() { + destroy(); +} diff --git a/sfw/render_core/frame_buffer.h b/sfw/render_core/frame_buffer.h new file mode 100644 index 0000000..c4fc8bf --- /dev/null +++ b/sfw/render_core/frame_buffer.h @@ -0,0 +1,78 @@ +//--STRIP +#ifndef FRAME_BUFFER_H +#define FRAME_BUFFER_H +//--STRIP + +//--STRIP +#include "core/vector2i.h" + +#include "object/resource.h" +#include "render_core/3rd_glad.h" +#include "render_core/image.h" +//--STRIP + +class FrameBuffer : public Resource { + SFW_OBJECT(FrameBuffer, Resource); + +public: + enum FrameBufferFlags { + FRAMEBUFFER_TEXTURE_FLAG_FILTER = 1 << 0, + FRAMEBUFFER_TEXTURE_FLAG_REPEAT = 1 << 1, + FRAMEBUFFER_TEXTURE_FLAG_MIRRORED_REPEAT = 1 << 2, + FRAMEBUFFER_TEXTURE_FLAG_MIP_MAPS = 1 << 3, + }; + + int get_texture_flags() const; + void set_texture_flags(const int p_flags); + + int create(const int p_width, const int p_height, const int p_msaa_count = 0); + void destroy(); + + int get_status(); + + uint32_t get_gl_fbo(); + uint32_t get_gl_texture(); + + void bind(); + void unbind(); + void update(); + + Ref get_image_color(); + Ref get_image_depth(); + + Vector get_color_buffer(); + Vector get_depth_buffer(); + + Vector2i get_size() const; + + void blit_color_to(const uint32_t p_destination_framebuffer, const Rect2i &p_rect = Rect2i()); + void blit_depth_to(const uint32_t p_destination_framebuffer, const Rect2i &p_rect = Rect2i()); + + void set_as_viewport(); + void reset_as_viewport(); + + float get_aspect() const; + + FrameBuffer(); + virtual ~FrameBuffer(); + +protected: + uint32_t _texture; + + uint32_t _msaa_fbo; + uint32_t _msaa_rbo_color; + uint32_t _msaa_rbo_depth; + + int _fbo_width; + int _fbo_height; + int _fbo_msaa_count; + + uint32_t _rbo; + uint32_t _fbo; + + int _texture_flags; +}; + +//--STRIP +#endif // TEXTURE_H +//--STRIP diff --git a/tools/merger/sfw_full.cpp.inl b/tools/merger/sfw_full.cpp.inl index 194ac9f..045e13c 100644 --- a/tools/merger/sfw_full.cpp.inl +++ b/tools/merger/sfw_full.cpp.inl @@ -503,12 +503,19 @@ {{FILE:sfw/render_core/font_data_bm_mini.inc.h}} {{FILE:sfw/render_core/font_data_tables.inc.h}} +//--STRIP +//#include "render_core/texture.h" +//#include "core/memory.h" +//#include "render_core/app_window.h" +//--STRIP +{{FILE:sfw/render_core/frame_buffer.cpp}} //--STRIP //#include "render_core/texture.h" //#include "core/memory.h" //#include "render_core/app_window.h" //--STRIP {{FILE:sfw/render_core/texture.cpp}} + //--STRIP //#include "render_core/application.h" //#include "core/math_defs.h" diff --git a/tools/merger/sfw_full.h.inl b/tools/merger/sfw_full.h.inl index bb25bb0..351190c 100644 --- a/tools/merger/sfw_full.h.inl +++ b/tools/merger/sfw_full.h.inl @@ -582,6 +582,13 @@ //#include "render_core/3rd_glad.h" //#include "render_core/image.h" //--STRIP +{{FILE:sfw/render_core/frame_buffer.h}} +//--STRIP +//#include "core/vector2i.h" +//#include "object/resource.h" +//#include "render_core/3rd_glad.h" +//#include "render_core/image.h" +//--STRIP {{FILE:sfw/render_core/texture.h}}