From b837000b88e34cf297380c99ea608a1517fdf26d Mon Sep 17 00:00:00 2001 From: LaG1924 Date: Sat, 20 Nov 2021 00:09:45 +0500 Subject: Added framebuffer to Gal --- src/Gal.hpp | 5 ++ src/GalOgl.cpp | 128 +++++++++++++++++++++++++++++++++++++------------- src/Render.cpp | 121 ++++++++++++++++++++++++++++++++++------------- src/Render.hpp | 25 ++++++---- src/RendererWorld.cpp | 12 ++--- src/RendererWorld.hpp | 4 +- 6 files changed, 212 insertions(+), 83 deletions(-) diff --git a/src/Gal.hpp b/src/Gal.hpp index 82ede78..f448c89 100644 --- a/src/Gal.hpp +++ b/src/Gal.hpp @@ -60,6 +60,7 @@ namespace Gal { }; enum class Format { + D24S8, R8G8B8, R8G8B8A8, }; @@ -241,6 +242,10 @@ namespace Gal { struct FramebufferConfig { virtual ~FramebufferConfig() = default; + + virtual void SetDepthStencil(std::shared_ptr texture) = 0; + + virtual void SetTexture(size_t location, std::shared_ptr texture) = 0; }; struct ShaderParameters { diff --git a/src/GalOgl.cpp b/src/GalOgl.cpp index 7ee6cf3..74e1f33 100644 --- a/src/GalOgl.cpp +++ b/src/GalOgl.cpp @@ -10,11 +10,11 @@ using namespace Gal; class ImplOgl; -class FramebufferDefaultOgl; class ShaderOgl; +class FramebufferOgl; std::unique_ptr impl; -std::shared_ptr fbDefault; +std::shared_ptr fbDefault; size_t GalTypeGetComponents(Gal::Type type) { switch (type) { @@ -171,6 +171,8 @@ size_t GalFormatGetSize(Format format) { GLenum GalFormatGetGlInternalFormat(Format format) { switch (format) { + case Format::D24S8: + return GL_DEPTH24_STENCIL8; case Format::R8G8B8: return GL_RGB8; case Format::R8G8B8A8: @@ -183,6 +185,8 @@ GLenum GalFormatGetGlInternalFormat(Format format) { GLenum GalFormatGetGlFormat(Format format) { switch (format) { + case Format::D24S8: + return GL_DEPTH_STENCIL; case Format::R8G8B8: return GL_RGB; case Format::R8G8B8A8: @@ -195,6 +199,8 @@ GLenum GalFormatGetGlFormat(Format format) { GLenum GalFormatGetGlType(Format format) { switch (format) { + case Format::D24S8: + return GL_UNSIGNED_INT_24_8; case Format::R8G8B8: return GL_UNSIGNED_BYTE; case Format::R8G8B8A8: @@ -334,7 +340,7 @@ public: virtual void SetData(std::vector&& data, size_t mipLevel = 0) override { size_t expectedSize = width * height * depth * GalFormatGetSize(format); - if (data.size() != expectedSize) + if (data.size() != expectedSize && !data.empty()) throw std::logic_error("Size of data is not valid for this texture"); glBindTexture(type, texture); @@ -354,13 +360,13 @@ public: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_PROXY_TEXTURE_CUBE_MAP: - glTexImage2D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.data()); + glTexImage2D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); break; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: - glTexImage3D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, depth, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.data()); + glTexImage3D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, depth, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); break; default: throw std::runtime_error("Unknown texture type"); @@ -412,12 +418,53 @@ public: }; +class FramebufferOgl : public Framebuffer { +public: + size_t vpX = 0, vpY = 0, vpW = 1, vpH = 1; + std::shared_ptr depthStencil; + std::vector> colors; + + GLuint fbo = 0; + + virtual void Clear() override { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLbitfield clearBits = 0; + clearBits |= GL_COLOR_BUFFER_BIT; + clearBits |= GL_DEPTH_BUFFER_BIT; + clearBits |= GL_STENCIL_BUFFER_BIT; + glClear(clearBits); + } + + virtual void SetViewport(size_t x, size_t y, size_t w, size_t h) override { + vpX = x; + vpY = y; + vpW = w; + vpH = h; + } +}; + +class FramebufferConfigOgl : public FramebufferConfig { +public: + std::shared_ptr depthStencil; + std::map> colors; + + virtual void SetDepthStencil(std::shared_ptr texture) override { + auto tex = std::static_pointer_cast(texture); + depthStencil = tex; + } + + virtual void SetTexture(size_t location, std::shared_ptr texture) override { + auto tex = std::static_pointer_cast(texture); + colors.emplace(location, tex); + } +}; + class PipelineConfigOgl : public PipelineConfig { public: std::shared_ptr vertexShader, pixelShader; std::map> textures; std::map shaderParameters; - std::shared_ptr targetFb; + std::shared_ptr targetFb; std::vector> vertexBuffers; Primitive vertexPrimitive = Primitive::Triangle; public: @@ -439,7 +486,8 @@ public: } virtual void SetTarget(std::shared_ptr target) override { - targetFb = target; + auto fb = std::static_pointer_cast(target); + targetFb = fb; } virtual void SetPrimitive(Primitive primitive) override { @@ -531,10 +579,14 @@ public: }; std::vector vertexBindCmds; Primitive primitive; + std::shared_ptr target; virtual void Activate() override { glUseProgram(program); + glBindFramebuffer(GL_FRAMEBUFFER, target->fbo); + glViewport(target->vpX, target->vpY, target->vpW, target->vpH); + for (size_t i = 0; i < staticTextures.size(); i++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(staticTextures[i]->type, staticTextures[i]->texture); @@ -815,6 +867,10 @@ public: pipeline->primitive = config->vertexPrimitive; + pipeline->target = config->targetFb; + if (!pipeline->target) + pipeline->target = std::static_pointer_cast(GetDefaultFramebuffer()); + //Shader compilation bool vertexFailed = false, pixelFailed = false, linkFailed = false; @@ -900,6 +956,8 @@ public: pipeline->staticTextures.push_back(texture); } + glCheckError(); + //Vertex attributes size_t bufferId = 0; @@ -946,17 +1004,44 @@ public: } virtual std::shared_ptr CreateFramebufferConfig() override { - return nullptr; + auto config = std::make_shared(); + return std::static_pointer_cast(config); } virtual std::shared_ptr BuildFramebuffer(std::shared_ptr config) override { - return nullptr; + auto conf = std::static_pointer_cast(config); + auto fb = std::make_shared(); + + glGenFramebuffers(1, &fb->fbo); + + glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); + + if (conf->depthStencil) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, conf->depthStencil->type, conf->depthStencil->texture, 0); + fb->depthStencil = std::move(conf->depthStencil); + } + + for (auto&& [location, texture] : conf->colors) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + location, texture->type, texture->texture, 0); + fb->colors.emplace_back(std::move(texture)); + } + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR) << "Framebuffer not completed: " << glCheckFramebufferStatus(GL_FRAMEBUFFER); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glCheckError(); + + return std::static_pointer_cast(fb); } virtual std::shared_ptr GetDefaultFramebuffer() override { if (!fbDefault) - fbDefault = std::make_shared(); - return std::static_pointer_cast(fbDefault); + fbDefault = std::make_shared(); + fbDefault->fbo = 0; + return std::static_pointer_cast(fbDefault); } @@ -979,27 +1064,6 @@ public: } }; -class FramebufferDefaultOgl : public Framebuffer { - size_t vpX, vpY, vpW, vpH; -public: - - virtual void Clear() override { - GLbitfield clearBits = 0; - clearBits |= GL_COLOR_BUFFER_BIT; - clearBits |= GL_DEPTH_BUFFER_BIT; - clearBits |= GL_STENCIL_BUFFER_BIT; - glClear(clearBits); - } - - virtual void SetViewport(size_t x, size_t y, size_t w, size_t h) override { - vpX = x; - vpY = y; - vpW = w; - vpH = h; - glViewport(x, y, w, h); - } -}; - Impl* Gal::GetImplementation() { if (!impl) diff --git a/src/Render.cpp b/src/Render.cpp index 74582a1..e6eb673 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -6,7 +6,6 @@ #include #include -#include "Shader.hpp" #include "AssetManager.hpp" #include "Event.hpp" #include "DebugInfo.hpp" @@ -15,7 +14,6 @@ #include "GameState.hpp" #include "RendererWorld.hpp" #include "Settings.hpp" -#include "Framebuffer.hpp" #include "Plugin.hpp" #include "Rml.hpp" #include "Gal.hpp" @@ -93,7 +91,7 @@ void Render::InitSdl(unsigned int WinWidth, unsigned int WinHeight, std::string if (SDL_Init(SDL_INIT_VIDEO) < 0) throw std::runtime_error("SDL initalization failed: " + std::string(SDL_GetError())); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -124,14 +122,76 @@ void Render::InitGlew() { int width, height; SDL_GL_GetDrawableSize(window, &width, &height); gal->GetDefaultFramebuffer()->SetViewport(0, 0, width, height); + gal->GetDefaultFramebuffer()->Clear(); } void Render::PrepareToRendering() { int width, height; - SDL_GL_GetDrawableSize(window, &width, &height); - framebuffer = std::make_unique(width, height, true); - Framebuffer::GetDefault().Activate(); - Framebuffer::GetDefault().Resize(width, height); + SDL_GL_GetDrawableSize(window, &width, &height); + + float resolutionScale = Settings::ReadDouble("resolutionScale", 1.0f); + size_t scaledW = width * resolutionScale, scaledH = height * resolutionScale; + + auto gal = Gal::GetImplementation(); + gal->GetDefaultFramebuffer()->SetViewport(0, 0, width, height); + + + auto dsTexConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::D24S8); + dsTexConf->SetMinFilter(Gal::Filtering::Nearest); + dsTexConf->SetMaxFilter(Gal::Filtering::Nearest); + fbDepthStencil = gal->BuildTexture(dsTexConf); + + auto texConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::R8G8B8A8); + texConf->SetMinFilter(Gal::Filtering::Nearest); + texConf->SetMaxFilter(Gal::Filtering::Nearest); + fbColor = gal->BuildTexture(texConf); + + auto fbConf = gal->CreateFramebufferConfig(); + fbConf->SetTexture(0, fbColor); + fbConf->SetDepthStencil(fbDepthStencil); + + framebuffer = gal->BuildFramebuffer(fbConf); + framebuffer->SetViewport(0, 0, scaledW, scaledH); + framebuffer->Clear(); + + std::string vertexSource, pixelSource; + { + auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/fbo"); + vertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); + + auto pixelAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fbo"); + pixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); + } + + constexpr float quadVertices[] = { + // positions // texCoords + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + fbBuffer = gal->CreateBuffer(); + fbBuffer->SetData({ reinterpret_cast(quadVertices), reinterpret_cast(quadVertices) + sizeof(quadVertices) }); + auto fbPPC = gal->CreatePipelineConfig(); + fbPPC->SetTarget(gal->GetDefaultFramebuffer()); + fbPPC->SetVertexShader(gal->LoadVertexShader(vertexSource)); + fbPPC->SetPixelShader(gal->LoadPixelShader(pixelSource)); + fbPPC->AddStaticTexture("inputTexture", fbColor); + auto fbColorBB = fbPPC->BindVertexBuffer({ + {"Pos", Gal::Type::Vec2}, + {"TextureCoords", Gal::Type::Vec2} + }); + + fbPipeline = gal->BuildPipeline(fbPPC); + fbPipelineInstance = fbPipeline->CreateInstance({ + {fbColorBB, fbBuffer} + }); + + if (world) + world->PrepareRender(framebuffer); } void Render::UpdateKeyboard() { @@ -153,30 +213,30 @@ void Render::UpdateKeyboard() { } void Render::RenderFrame() { - OPTICK_EVENT(); - //framebuffer->Clear(); - Framebuffer::GetDefault().Clear(); + OPTICK_EVENT(); + + Gal::GetImplementation()->GetDefaultFramebuffer()->Clear(); + framebuffer->Clear(); - //if (renderWorld) - // framebuffer->Activate(); - if (isWireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //if (isWireframe) + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); if (renderWorld) world->Render(renderState); - if (isWireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - //if (renderWorld) - // framebuffer->RenderTo(Framebuffer::GetDefault()); + //if (isWireframe) + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - RenderGui(); + fbPipeline->Activate(); + fbPipelineInstance->Activate(); + fbPipelineInstance->Render(0, 6); - if (world) { - world->Update(GetTime()->RemainTimeMs()); - } + RenderGui(); + + if (world) { + world->Update(GetTime()->RemainTimeMs()); + } - - OPTICK_EVENT("VSYNC"); - SDL_GL_SwapWindow(window); + OPTICK_EVENT("VSYNC"); + SDL_GL_SwapWindow(window); } void Render::HandleEvents() { @@ -201,9 +261,7 @@ void Render::HandleEvents() { renderState.WindowHeight = height; rmlRender->Update(width, height); rmlContext->SetDimensions(Rml::Vector2i(width, height)); - double resolutionScale = Settings::ReadDouble("resolutionScale", 1.0f); - framebuffer->Resize(width * resolutionScale, height * resolutionScale); - Framebuffer::GetDefault().Resize(width, height); + PrepareToRendering(); break; } @@ -424,7 +482,7 @@ void Render::InitEvents() { listener.RegisterHandler("PlayerConnected", [this](const Event&) { stateString = "Loading terrain..."; - world = std::make_unique(); + world = std::make_unique(framebuffer); world->MaxRenderingDistance = Settings::ReadDouble("renderDistance", 2.0f); PUSH_EVENT("UpdateSectionsRender", 0); }); @@ -534,10 +592,7 @@ void Render::InitEvents() { float brightness = Settings::ReadDouble("brightness", 0.2f); PUSH_EVENT("SetMinLightLevel", brightness); - float resolutionScale = Settings::ReadDouble("resolutionScale", 1.0f); - int width, height; - SDL_GL_GetDrawableSize(window, &width, &height); - framebuffer->Resize(width * resolutionScale, height * resolutionScale); + PrepareToRendering(); }); } diff --git a/src/Render.hpp b/src/Render.hpp index 9a9feee..cf9b9f9 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -10,9 +10,9 @@ #include "Utility.hpp" #include "Renderer.hpp" #include "Event.hpp" +#include "Gal.hpp" class RendererWorld; -class Framebuffer; class RmlRenderInterface; class RmlSystemInterface; class RmlFileInterface; @@ -35,16 +35,21 @@ class Render { std::map isKeyPressed; bool HasFocus=true; float sensetivity = 0.1f; - bool isWireframe = false; - std::unique_ptr framebuffer; - EventListener listener; + bool isWireframe = false; + std::shared_ptr framebuffer; + std::shared_ptr fbDepthStencil; + std::shared_ptr fbColor; + std::shared_ptr fbPipeline; + std::shared_ptr fbPipelineInstance; + std::shared_ptr fbBuffer; + EventListener listener; std::string stateString; - std::unique_ptr rmlRender; - std::unique_ptr rmlSystem; - std::unique_ptr rmlFile; - Rml::Context* rmlContext; - unsigned short sdlKeyMods = 0; - bool hideRml = false; + std::unique_ptr rmlRender; + std::unique_ptr rmlSystem; + std::unique_ptr rmlFile; + Rml::Context* rmlContext; + unsigned short sdlKeyMods = 0; + bool hideRml = false; void SetMouseCapture(bool IsCaptured); diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 5970160..e4a1589 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -153,7 +153,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) { } } -RendererWorld::RendererWorld() { +RendererWorld::RendererWorld(std::shared_ptr target) { OPTICK_EVENT(); MaxRenderingDistance = 2; numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2); @@ -162,7 +162,7 @@ RendererWorld::RendererWorld() { globalTimeStart = std::chrono::high_resolution_clock::now(); - PrepareRender(); + PrepareRender(target); listener->RegisterHandler("DeleteSectionRender", [this](const Event& eventData) { OPTICK_EVENT("EV_DeleteSectionRender"); @@ -411,7 +411,7 @@ void RendererWorld::Render(RenderState & renderState) { DebugInfo::renderFaces = renderedFaces; } -void RendererWorld::PrepareRender() { +void RendererWorld::PrepareRender(std::shared_ptr target) { std::string sectionVertexSource, sectionPixelSource; { auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/face"); @@ -442,7 +442,7 @@ void RendererWorld::PrepareRender() { auto gal = Gal::GetImplementation(); { auto sectionsPLC = gal->CreatePipelineConfig(); - sectionsPLC->SetTarget(gal->GetDefaultFramebuffer()); + sectionsPLC->SetTarget(target); sectionsPLC->AddShaderParameter("projView", Gal::Type::Mat4); sectionsPLC->AddShaderParameter("DayTime", Gal::Type::Float); sectionsPLC->AddShaderParameter("GlobalTime", Gal::Type::Float); @@ -466,7 +466,7 @@ void RendererWorld::PrepareRender() { { auto entitiesPLC = gal->CreatePipelineConfig(); - entitiesPLC->SetTarget(gal->GetDefaultFramebuffer()); + entitiesPLC->SetTarget(target); entitiesPLC->AddShaderParameter("projView", Gal::Type::Mat4); entitiesPLC->AddShaderParameter("model", Gal::Type::Mat4); entitiesPLC->AddShaderParameter("color", Gal::Type::Vec3); @@ -630,7 +630,7 @@ void RendererWorld::PrepareRender() { { auto skyPPC = gal->CreatePipelineConfig(); - skyPPC->SetTarget(gal->GetDefaultFramebuffer()); + skyPPC->SetTarget(target); skyPPC->AddShaderParameter("sunTexture", Gal::Type::Vec4); skyPPC->AddShaderParameter("sunTextureLayer", Gal::Type::Float); skyPPC->AddShaderParameter("moonTexture", Gal::Type::Vec4); diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index 706af68..91910a0 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -55,11 +55,11 @@ class RendererWorld { std::shared_ptr skyPipelineInstance; std::shared_ptr skyBuffer; public: - RendererWorld(); + RendererWorld(std::shared_ptr target); ~RendererWorld(); void Render(RenderState& renderState); - void PrepareRender(); + void PrepareRender(std::shared_ptr target); double MaxRenderingDistance; -- cgit v1.2.3