From 7c8e88aeb4ff9e1c0acb5aa0a4ba791d06936f26 Mon Sep 17 00:00:00 2001 From: Maaxxaam Date: Sun, 16 Apr 2023 17:07:06 +0300 Subject: [PATCH 1/3] Read resolution.xml config on startup Also writes resolution.xml based of user's current video mode if absent Note: fullscreen scaling for lower resolutions is still wrong, needs fixing --- src/common/platform.cpp | 15 +++++++++++++ src/common/platform.h | 14 ++++++++++++ src/engines/awan/configuration.cpp | 6 +++++ src/engines/awan/engine.cpp | 1 + src/game.cpp | 6 +++++ src/graphics/gfxman.cpp | 4 ++++ src/graphics/gfxman.h | 2 ++ src/graphics/opengl/framebuffer.cpp | 15 ++++++++++--- src/graphics/opengl/renderer.cpp | 34 ++++++++++++++++++++--------- src/graphics/opengl/renderer.h | 2 ++ src/graphics/renderer.cpp | 17 +++++++++++++-- src/graphics/renderer.h | 7 +++++- src/platform/context.h | 5 +++++ src/platform/window.cpp | 16 ++++++++++++++ src/platform/window.h | 3 +++ 15 files changed, 131 insertions(+), 16 deletions(-) diff --git a/src/common/platform.cpp b/src/common/platform.cpp index d38c39e1..342b95db 100644 --- a/src/common/platform.cpp +++ b/src/common/platform.cpp @@ -21,7 +21,10 @@ #include #include +#include + #include "src/common/platform.h" +#include "src/common/exception.h" #include "src/common/types.h" #include "src/common/crc32.h" #include "src/common/strutil.h" @@ -135,4 +138,16 @@ std::string getUserDataDirectory() { return userData; } +VideoMode getPrimaryMonitorVideoMode() { + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + if (!monitor) + throw CreateException("Failed to get primary monitor"); + const GLFWvidmode *mode = glfwGetVideoMode(monitor); + return VideoMode{ + mode->width, + mode->height, + mode->redBits + mode->greenBits + mode->blueBits, + mode->refreshRate}; } + +} // End of namespace Common diff --git a/src/common/platform.h b/src/common/platform.h index ce7a7ea2..384dd421 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -45,6 +45,13 @@ enum Language { kUnrecognized }; +struct VideoMode { + int width; + int height; + int bpp; + int refreshRate; +}; + /*! * Return if the current desktop environment (Not the application itself!) is running on X11 * \return If the current desktop envionment is running on X11 @@ -79,6 +86,13 @@ std::string getHomeDirectory(); */ std::string getUserDataDirectory(); + +/*! + * Get primary monitor's current video mode + * + * \return The primary monitor's current video mode + */ +VideoMode getPrimaryMonitorVideoMode(); } #endif // COMMON_PLATFORM_H diff --git a/src/engines/awan/configuration.cpp b/src/engines/awan/configuration.cpp index a746092b..a0192617 100644 --- a/src/engines/awan/configuration.cpp +++ b/src/engines/awan/configuration.cpp @@ -77,10 +77,16 @@ void Configuration::read() { std::string configFile = fmt::format("{}/config", path); std::string resolutionFile = fmt::format("{}/resolution.xml", path); + spdlog::info("Resolution file: {} ({} {})", resolutionFile, std::filesystem::exists(resolutionFile), std::filesystem::is_regular_file(resolutionFile)); if (std::filesystem::is_regular_file(resolutionFile)) { auto resolutionStream = std::make_unique(resolutionFile); readResolution(*resolutionStream); + } else { + Common::VideoMode videoMode = Common::getPrimaryMonitorVideoMode(); + resolution.width = videoMode.width; + resolution.height = videoMode.height; + resolution.fullscreen = true; } if (std::filesystem::is_regular_file(configFile)) { diff --git a/src/engines/awan/engine.cpp b/src/engines/awan/engine.cpp index f8e90944..102cc6f8 100644 --- a/src/engines/awan/engine.cpp +++ b/src/engines/awan/engine.cpp @@ -37,6 +37,7 @@ Engine::Engine(entt::registry ®istry, const LocaleConfig::Config &config) : ::Engine(registry, config, new Functions(registry, *this)) { _storyModeRound = 1; _configuration.reset(new AlanWakesAmericanNightmare::Configuration()); + _configuration->read(); } void Engine::init() { diff --git a/src/game.cpp b/src/game.cpp index 652a152b..a74b3753 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -270,6 +270,12 @@ void Game::init() { _engine->init(); }); + + // set window resolution and fullscreen mode + bool fullscreen = _engine->getConfiguration().resolution.fullscreen; + _window->setFullscreen(fullscreen); + _window->setSize(_engine->getConfiguration().resolution.width, _engine->getConfiguration().resolution.height); + GfxMan.setScreenSize(_engine->getConfiguration().resolution.width, _engine->getConfiguration().resolution.height); } void Game::start() { diff --git a/src/graphics/gfxman.cpp b/src/graphics/gfxman.cpp index f9b8fef8..95a1fb5a 100644 --- a/src/graphics/gfxman.cpp +++ b/src/graphics/gfxman.cpp @@ -196,6 +196,10 @@ void GraphicsManager::drawFrame() { _renderer->drawFrame(); } +void GraphicsManager::setScreenSize(unsigned int width, unsigned int height) { + _renderer->setRenderPlane(width, height); +} + void GraphicsManager::setAmbianceState(const std::string &id) { if (!_renderer) return; diff --git a/src/graphics/gfxman.h b/src/graphics/gfxman.h index 0021a6b2..459afa4b 100644 --- a/src/graphics/gfxman.h +++ b/src/graphics/gfxman.h @@ -181,6 +181,8 @@ class GraphicsManager : public Common::Singleton { void drawFrame(); + void setScreenSize(unsigned int width, unsigned int height); + private: std::unique_ptr _renderer; }; diff --git a/src/graphics/opengl/framebuffer.cpp b/src/graphics/opengl/framebuffer.cpp index f36ccbc9..70e3db03 100644 --- a/src/graphics/opengl/framebuffer.cpp +++ b/src/graphics/opengl/framebuffer.cpp @@ -19,6 +19,7 @@ */ #include +#include #include "src/common/exception.h" @@ -42,6 +43,17 @@ Framebuffer::~Framebuffer() { } void Framebuffer::attachTexture(const Texture &texture, GLenum attachmentType) { + auto hasAttachment = std::find(_attachments.begin(), _attachments.end(), attachmentType); + if (hasAttachment != _attachments.end()) { + glFramebufferTexture2D( + GL_FRAMEBUFFER, + attachmentType, + texture._type, + 0, + 0 + ); + _attachments.erase(hasAttachment); + } glFramebufferTexture2D( GL_FRAMEBUFFER, attachmentType, @@ -63,9 +75,6 @@ void Framebuffer::attachRenderBuffer(const Renderbuffer &renderbuffer, GLenum at GL_RENDERBUFFER, renderbuffer._id ); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw CreateException("Failed to attach renderbuffer tot exture"); } void Framebuffer::clear() { diff --git a/src/graphics/opengl/renderer.cpp b/src/graphics/opengl/renderer.cpp index 4d41ae17..e6e7480c 100644 --- a/src/graphics/opengl/renderer.cpp +++ b/src/graphics/opengl/renderer.cpp @@ -42,6 +42,8 @@ #include "src/common/strutil.h" #include "src/common/readfile.h" +#include "src/platform/window.h" + #include "src/awe/resman.h" #include "src/awe/objfile.h" #include "src/awe/hg.h" @@ -51,6 +53,7 @@ #include "src/graphics/shaderconverter.h" #include "src/graphics/skeleton.h" #include "src/graphics/images/surface.h" +#include "src/graphics/renderer.h" #include "src/graphics/opengl/renderer.h" #include "src/graphics/opengl/opengl.h" #include "src/graphics/opengl/vbo.h" @@ -64,6 +67,7 @@ static void *loadProcAddress(const char *name) { } Renderer::Renderer(Platform::Window &window, const std::string &shaderDirectory) : + Graphics::Renderer(window.getSize()), _window(window), _shaderDirectory(shaderDirectory) { _window.makeCurrent(); @@ -194,27 +198,36 @@ Renderer::Renderer(Platform::Window &window, const std::string &shaderDirectory) // rebuildShaders(); - // Get width and height of the default framebuffer - unsigned int width, height; - window.getSize(width, height); + _deferredBuffer = std::make_unique(); + setRenderPlane(_window.getSize()); + + // Check for errors + assert(glGetError() == GL_NO_ERROR); +} + +void Renderer::setRenderPlane(unsigned int width, unsigned int height) { + setRenderPlane(glm::vec2(width, height)); +} + +void Renderer::setRenderPlane(const glm::vec2 size) { + Graphics::Renderer::setRenderPlane(size); // Initialize deferred shading // - _depthTexture = std::make_unique(_loadingTasks, width, height, kRGBA16F, "depth_buffer"); - _normalTexture = std::make_unique(_loadingTasks, width, height, kRGBA16F, "normal_buffer"); + _depthTexture = std::make_unique(_loadingTasks, size.x, size.y, kRGBA16F, "depth_buffer"); + _normalTexture = std::make_unique(_loadingTasks, size.x, size.y, kRGBA16F, "normal_buffer"); _depthstencilBuffer = std::make_unique(width, height, GL_DEPTH24_STENCIL8, "depthstencil_renderbuffer"); _deferredBuffer = std::make_unique("Deferred Buffer"); _deferredBuffer->setClearColor({0.0f, 0.0f, 0.0f, 0.0f}); _deferredBuffer->bind(); - _deferredBuffer->attachRenderBuffer(*_depthstencilBuffer, GL_DEPTH_STENCIL_ATTACHMENT); _deferredBuffer->attachTexture(*_depthTexture, GL_COLOR_ATTACHMENT0); _deferredBuffer->attachTexture(*_normalTexture, GL_COLOR_ATTACHMENT1); - _lightBufferTexture = std::make_unique(_loadingTasks, width, height, kRGBA16F, "light_buffer"); + _lightBufferTexture = std::make_unique(_loadingTasks, size.x, size.y, kRGBA16F, "light_buffer"); _lightBuffer = std::make_unique("Light Buffer"); _lightBuffer->setClearColor({0.0f, 0.0f, 0.0f, 0.0f}); @@ -241,6 +254,7 @@ Renderer::Renderer(Platform::Window &window, const std::string &shaderDirectory) // Initialize ImGui ImGui_ImplOpenGL3_Init(); + glViewport(0, 0, size.x, size.y); // Check for errors assert(glGetError() == GL_NO_ERROR); @@ -605,7 +619,7 @@ void Renderer::drawLights() { } void Renderer::drawGUI() { - glm::mat4 vp = glm::ortho(0.0f, 1920.0f, 0.0f, 1080.0f, -1000.0f, 1000.0f); + glm::mat4 vp = glm::ortho(0.0f, _renderPlane.x, 0.0f, _renderPlane.y, -1000.0f, 1000.0f); pushDebug("Draw GUI"); @@ -621,14 +635,14 @@ void Renderer::drawGUI() { for (const auto &element: _guiElements) { glm::mat4 m = glm::translate(glm::vec3( element->getAbsolutePosition() + - element->getRelativePosition() * glm::vec2(1920.0, 1080.0), + element->getRelativePosition() * _renderPlane, 0.0f )); std::static_pointer_cast(element->getVertexAttributes())->bind(); for (const auto &part: element->getParts()) { glm::mat4 m2 = m * - glm::scale(glm::vec3(part.absoluteSize + part.relativeSize * glm::vec2(1920, 1080), 1.0f)) * + glm::scale(glm::vec3(part.absoluteSize + part.relativeSize * _renderPlane, 1.0f)) * glm::translate(glm::vec3(part.position, 1.0f)); std::static_pointer_cast(part.indices)->bind(); diff --git a/src/graphics/opengl/renderer.h b/src/graphics/opengl/renderer.h index 2fdc649e..7d114388 100644 --- a/src/graphics/opengl/renderer.h +++ b/src/graphics/opengl/renderer.h @@ -48,6 +48,8 @@ class Renderer : public Graphics::Renderer { void drawFrame() override; bool isLoading() const override; + void setRenderPlane(unsigned int width, unsigned int height) override; + void setRenderPlane(glm::vec2 size) override; TexturePtr createTexture( TextureType type, diff --git a/src/graphics/renderer.cpp b/src/graphics/renderer.cpp index 66e62e78..b91b2d32 100644 --- a/src/graphics/renderer.cpp +++ b/src/graphics/renderer.cpp @@ -22,9 +22,22 @@ #include "renderer.h" -Graphics::Renderer::Renderer() { +Graphics::Renderer::Renderer(unsigned int width, unsigned int height) { + setRenderPlane(width, height); +} + +Graphics::Renderer::Renderer(glm::vec2 renderPlane) { + setRenderPlane(renderPlane); +} + +void Graphics::Renderer::setRenderPlane(unsigned int width, unsigned int height) { + setRenderPlane(glm::vec2(width, height)); +} + +void Graphics::Renderer::setRenderPlane(glm::vec2 renderPlane) { // Setup initial projection matrix - _projection = glm::perspectiveFov(45.0f, 1920.0f, 1080.0f, 1.0f, 10000.0f); + _renderPlane = renderPlane; + _projection = glm::perspectiveFov(45.0f, _renderPlane.x, _renderPlane.y, 1.0f, 10000.0f); // Initialize frustrum with projection matrix _frustrum.setProjectionMatrix(_projection); diff --git a/src/graphics/renderer.h b/src/graphics/renderer.h index a5382703..b7354f88 100644 --- a/src/graphics/renderer.h +++ b/src/graphics/renderer.h @@ -42,9 +42,13 @@ namespace Graphics { class Renderer { public: - Renderer(); + Renderer(unsigned int width, unsigned int height); + Renderer(glm::vec2 renderPlane); virtual ~Renderer(); + virtual void setRenderPlane(unsigned int width, unsigned int height); + virtual void setRenderPlane(glm::vec2 renderPlane); + void addModel(Model *model); void removeModel(Model *model); void addGUIElement(GUIElement *gui); @@ -141,6 +145,7 @@ class Renderer { glm::mat4 _view; glm::mat4 _projection; + glm::vec2 _renderPlane; SkyPtr _sky; diff --git a/src/platform/context.h b/src/platform/context.h index 0fe67c60..d24d9a38 100644 --- a/src/platform/context.h +++ b/src/platform/context.h @@ -21,11 +21,16 @@ #ifndef AWE_CONTEXT_H #define AWE_CONTEXT_H +#include + namespace Platform { class Context { public: virtual void getSize(unsigned int &width, unsigned int &height) = 0; + virtual glm::vec2 getSize() = 0; + virtual void setSize(unsigned int width, unsigned int height) = 0; + virtual void setFullscreen(bool fullscreen) = 0; }; } diff --git a/src/platform/window.cpp b/src/platform/window.cpp index 01bc811b..f5848273 100644 --- a/src/platform/window.cpp +++ b/src/platform/window.cpp @@ -265,4 +265,20 @@ void Window::getSize(unsigned int &width, unsigned int &height) { glfwGetFramebufferSize(_window, reinterpret_cast(&width), reinterpret_cast(&height)); } +glm::vec2 Window::getSize() { + unsigned int width, height; + glfwGetFramebufferSize(_window, reinterpret_cast(&width), reinterpret_cast(&height)); + return glm::vec2(width, height); +} + +void Window::setSize(unsigned int width, unsigned int height) { + glfwSetWindowSize(_window, width, height); +} + +void Window::setFullscreen(bool fullscreen) { + unsigned int width, height; + getSize(width, height); + glfwSetWindowMonitor(_window, fullscreen ? glfwGetPrimaryMonitor() : NULL, 0, 0, width, height, GLFW_DONT_CARE); +} + } diff --git a/src/platform/window.h b/src/platform/window.h index 898496c2..dcd95eb1 100644 --- a/src/platform/window.h +++ b/src/platform/window.h @@ -57,6 +57,9 @@ class Window : public GLContext, public VulkanContext { void swap() override; void getSize(unsigned int &width, unsigned int &height) override; + glm::vec2 getSize() override; + void setSize(unsigned int width, unsigned int height) override; + void setFullscreen(bool fullscreen) override; bool isMouseCursorVisible(); void setMouseCursorVisible(bool visible); From b3c198f3d134e709c1c6e7b933bcdffcd806c60a Mon Sep 17 00:00:00 2001 From: Maaxxaam Date: Fri, 23 Jun 2023 21:12:07 +0300 Subject: [PATCH 2/3] Fullscreen video mode patch attempt --- src/platform/window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/window.cpp b/src/platform/window.cpp index f5848273..93719c16 100644 --- a/src/platform/window.cpp +++ b/src/platform/window.cpp @@ -279,6 +279,8 @@ void Window::setFullscreen(bool fullscreen) { unsigned int width, height; getSize(width, height); glfwSetWindowMonitor(_window, fullscreen ? glfwGetPrimaryMonitor() : NULL, 0, 0, width, height, GLFW_DONT_CARE); + // set size again (because Wayland...) + glfwSetWindowSize(_window, width, height); } } From 7885ff96f36c7196e286a377390442f073339b41 Mon Sep 17 00:00:00 2001 From: maaxxaam Date: Tue, 12 Sep 2023 21:57:31 +0300 Subject: [PATCH 3/3] More resolution fixes - Add content scaling (because of how Wayland does fullscreen) - Rename _renderPlane to _viewportSize - Move getPrimaryMonitorVideoMode to Platform - Remove setSize/Fullscreen from Context --- src/common/platform.cpp | 12 ------------ src/common/platform.h | 14 -------------- src/configuration.h | 10 ++++++---- src/engines/awan/configuration.cpp | 10 +++++----- src/game.cpp | 25 +++++++++++++++++++++---- src/graphics/gfxman.cpp | 4 ++++ src/graphics/gfxman.h | 1 + src/graphics/opengl/framebuffer.cpp | 22 +++++++++------------- src/graphics/opengl/renderer.cpp | 21 ++++++++++++--------- src/graphics/opengl/renderer.h | 1 + src/graphics/renderer.cpp | 8 ++++++-- src/graphics/renderer.h | 4 +++- src/platform/context.h | 2 -- src/platform/platform.cpp | 14 ++++++++++++++ src/platform/platform.h | 14 ++++++++++++++ src/platform/window.cpp | 15 +++++++++++++-- src/platform/window.h | 7 +++++-- 17 files changed, 114 insertions(+), 70 deletions(-) diff --git a/src/common/platform.cpp b/src/common/platform.cpp index 342b95db..784492f0 100644 --- a/src/common/platform.cpp +++ b/src/common/platform.cpp @@ -138,16 +138,4 @@ std::string getUserDataDirectory() { return userData; } -VideoMode getPrimaryMonitorVideoMode() { - GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - if (!monitor) - throw CreateException("Failed to get primary monitor"); - const GLFWvidmode *mode = glfwGetVideoMode(monitor); - return VideoMode{ - mode->width, - mode->height, - mode->redBits + mode->greenBits + mode->blueBits, - mode->refreshRate}; -} - } // End of namespace Common diff --git a/src/common/platform.h b/src/common/platform.h index 384dd421..ce7a7ea2 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -45,13 +45,6 @@ enum Language { kUnrecognized }; -struct VideoMode { - int width; - int height; - int bpp; - int refreshRate; -}; - /*! * Return if the current desktop environment (Not the application itself!) is running on X11 * \return If the current desktop envionment is running on X11 @@ -86,13 +79,6 @@ std::string getHomeDirectory(); */ std::string getUserDataDirectory(); - -/*! - * Get primary monitor's current video mode - * - * \return The primary monitor's current video mode - */ -VideoMode getPrimaryMonitorVideoMode(); } #endif // COMMON_PLATFORM_H diff --git a/src/configuration.h b/src/configuration.h index 2ae3d3b9..50709944 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -21,6 +21,11 @@ #ifndef OPENAWE_CONFIGURATION_H #define OPENAWE_CONFIGURATION_H +struct ResolutionData { + unsigned int width, height; + bool fullscreen; +}; + /*! * \brief Class representing the global configuration of the engine * @@ -32,10 +37,7 @@ class Configuration { public: virtual ~Configuration() = default; - struct { - unsigned int width, height; - bool fullscreen; - } resolution; + ResolutionData resolution; /*! * Write the configuration diff --git a/src/engines/awan/configuration.cpp b/src/engines/awan/configuration.cpp index a0192617..1e2e98f7 100644 --- a/src/engines/awan/configuration.cpp +++ b/src/engines/awan/configuration.cpp @@ -77,16 +77,16 @@ void Configuration::read() { std::string configFile = fmt::format("{}/config", path); std::string resolutionFile = fmt::format("{}/resolution.xml", path); - spdlog::info("Resolution file: {} ({} {})", resolutionFile, std::filesystem::exists(resolutionFile), std::filesystem::is_regular_file(resolutionFile)); if (std::filesystem::is_regular_file(resolutionFile)) { auto resolutionStream = std::make_unique(resolutionFile); readResolution(*resolutionStream); } else { - Common::VideoMode videoMode = Common::getPrimaryMonitorVideoMode(); - resolution.width = videoMode.width; - resolution.height = videoMode.height; - resolution.fullscreen = true; + resolution = { + 0, + 0, + false + }; } if (std::filesystem::is_regular_file(configFile)) { diff --git a/src/game.cpp b/src/game.cpp index a74b3753..0b59cf7e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -23,6 +23,11 @@ #include +#include +#include "src/configuration.h" +#include "src/graphics/gfxman.h" +#include "src/graphics/text.h" + #include "src/common/crc32.h" #include "src/common/threadpool.h" #include "src/common/strutil.h" @@ -38,6 +43,7 @@ #include "src/platform/keyconversion.h" #include "src/platform/gamepadconversion.h" #include "src/platform/gamepadman.h" +#include "src/platform/platform.h" #include "src/graphics/fontman.h" #include "src/graphics/text.h" @@ -272,10 +278,21 @@ void Game::init() { }); // set window resolution and fullscreen mode - bool fullscreen = _engine->getConfiguration().resolution.fullscreen; - _window->setFullscreen(fullscreen); - _window->setSize(_engine->getConfiguration().resolution.width, _engine->getConfiguration().resolution.height); - GfxMan.setScreenSize(_engine->getConfiguration().resolution.width, _engine->getConfiguration().resolution.height); + Configuration & config = _engine->getConfiguration(); + + if (config.resolution.width == 0 || config.resolution.height == 0) { + Platform::VideoMode videoMode = _platform.getPrimaryMonitorVideoMode(); + config.resolution.width = videoMode.width; + config.resolution.height = videoMode.height; + config.resolution.fullscreen = true; + } + + _window->setFullscreen(config.resolution.fullscreen); + _window->setSize(config.resolution.width, config.resolution.height); + spdlog::error("Window size: {} x {}", _window->getSize().x, _window->getSize().y); + spdlog::error("Content scale: {} x {}", _window->getContentScale().x, _window->getContentScale().y); + GfxMan.setScreenSize(config.resolution.width, config.resolution.height); + GfxMan.setContentScale(_window->getContentScale()); } void Game::start() { diff --git a/src/graphics/gfxman.cpp b/src/graphics/gfxman.cpp index 95a1fb5a..c4dbc393 100644 --- a/src/graphics/gfxman.cpp +++ b/src/graphics/gfxman.cpp @@ -200,6 +200,10 @@ void GraphicsManager::setScreenSize(unsigned int width, unsigned int height) { _renderer->setRenderPlane(width, height); } +void GraphicsManager::setContentScale(glm::vec2 scale) { + _renderer->setContentScale(scale); +} + void GraphicsManager::setAmbianceState(const std::string &id) { if (!_renderer) return; diff --git a/src/graphics/gfxman.h b/src/graphics/gfxman.h index 459afa4b..6b2175b3 100644 --- a/src/graphics/gfxman.h +++ b/src/graphics/gfxman.h @@ -182,6 +182,7 @@ class GraphicsManager : public Common::Singleton { void drawFrame(); void setScreenSize(unsigned int width, unsigned int height); + void setContentScale(glm::vec2 scale); private: std::unique_ptr _renderer; diff --git a/src/graphics/opengl/framebuffer.cpp b/src/graphics/opengl/framebuffer.cpp index 70e3db03..fa7b273a 100644 --- a/src/graphics/opengl/framebuffer.cpp +++ b/src/graphics/opengl/framebuffer.cpp @@ -30,8 +30,10 @@ namespace Graphics::OpenGL { Framebuffer::Framebuffer(const std::string &label) { glGenFramebuffers(1, &_id); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw CreateException("Failed to initialize framebuffer"); + const GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) + throw CreateException("Failed to initialize framebuffer: {}", framebufferStatus); bind(); if (GLAD_GL_KHR_debug && !label.empty()) @@ -43,17 +45,6 @@ Framebuffer::~Framebuffer() { } void Framebuffer::attachTexture(const Texture &texture, GLenum attachmentType) { - auto hasAttachment = std::find(_attachments.begin(), _attachments.end(), attachmentType); - if (hasAttachment != _attachments.end()) { - glFramebufferTexture2D( - GL_FRAMEBUFFER, - attachmentType, - texture._type, - 0, - 0 - ); - _attachments.erase(hasAttachment); - } glFramebufferTexture2D( GL_FRAMEBUFFER, attachmentType, @@ -75,6 +66,11 @@ void Framebuffer::attachRenderBuffer(const Renderbuffer &renderbuffer, GLenum at GL_RENDERBUFFER, renderbuffer._id ); + + const GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) + throw CreateException("Failed to render buffer to texture: {}", framebufferStatus); } void Framebuffer::clear() { diff --git a/src/graphics/opengl/renderer.cpp b/src/graphics/opengl/renderer.cpp index e6e7480c..ccbc8e34 100644 --- a/src/graphics/opengl/renderer.cpp +++ b/src/graphics/opengl/renderer.cpp @@ -198,7 +198,6 @@ Renderer::Renderer(Platform::Window &window, const std::string &shaderDirectory) // rebuildShaders(); - _deferredBuffer = std::make_unique(); setRenderPlane(_window.getSize()); // Check for errors @@ -216,7 +215,7 @@ void Renderer::setRenderPlane(const glm::vec2 size) { // _depthTexture = std::make_unique(_loadingTasks, size.x, size.y, kRGBA16F, "depth_buffer"); _normalTexture = std::make_unique(_loadingTasks, size.x, size.y, kRGBA16F, "normal_buffer"); - _depthstencilBuffer = std::make_unique(width, height, GL_DEPTH24_STENCIL8, + _depthstencilBuffer = std::make_unique(size.x, size.y, GL_DEPTH24_STENCIL8, "depthstencil_renderbuffer"); _deferredBuffer = std::make_unique("Deferred Buffer"); @@ -260,6 +259,12 @@ void Renderer::setRenderPlane(const glm::vec2 size) { assert(glGetError() == GL_NO_ERROR); } +void Renderer::setContentScale(glm::vec2 scale) { + Graphics::Renderer::setContentScale(scale); + glm::vec2 scaledResolution = _viewportSize * _contentScale; + glViewport(0, 0, scaledResolution.x, scaledResolution.y); +} + Renderer::~Renderer() { ImGui_ImplOpenGL3_Shutdown(); } @@ -311,8 +316,6 @@ void Renderer::drawWorld(const std::string &stage) { const auto &defaultShader = getProgram("standardmaterial", stage, 0); static const glm::mat4 mirrorZ = glm::scale(glm::vec3(1, 1, -1)); - const auto screenResolution = glm::vec2(1920, 1080); - bool wireframe = false; Material::CullMode cullMode = Material::kNone; @@ -343,7 +346,7 @@ void Renderer::drawWorld(const std::string &stage) { const std::optional skinningMatrices = currentShader->getUniformLocation("GPU_skinning_matrices"); if (screenRes) - currentShader->setUniform2f(*screenRes, screenResolution); + currentShader->setUniform2f(*screenRes, _viewportSize); GLuint textureSlotShader = 0; if (lightBuffer) { @@ -594,7 +597,7 @@ void Renderer::drawLights() { const auto cameraLightPositionView = _view * mirrorZ * light->getTransform()[3]; - pointlightProgram->setUniform2f(screenResIndex, glm::vec2(1920, 1080)); + pointlightProgram->setUniform2f(screenResIndex, _viewportSize); pointlightProgram->setUniformMatrix4f(localToClipIndex, vp * mirrorZ * light->getTransform()); pointlightProgram->setUniformMatrix4f(clipToViewIndex, clipToView); pointlightProgram->setUniform3f(lightPositionIndex, cameraLightPositionView); @@ -619,7 +622,7 @@ void Renderer::drawLights() { } void Renderer::drawGUI() { - glm::mat4 vp = glm::ortho(0.0f, _renderPlane.x, 0.0f, _renderPlane.y, -1000.0f, 1000.0f); + glm::mat4 vp = glm::ortho(0.0f, _viewportSize.x, 0.0f, _viewportSize.y, -1000.0f, 1000.0f); pushDebug("Draw GUI"); @@ -635,14 +638,14 @@ void Renderer::drawGUI() { for (const auto &element: _guiElements) { glm::mat4 m = glm::translate(glm::vec3( element->getAbsolutePosition() + - element->getRelativePosition() * _renderPlane, + element->getRelativePosition() * _viewportSize, 0.0f )); std::static_pointer_cast(element->getVertexAttributes())->bind(); for (const auto &part: element->getParts()) { glm::mat4 m2 = m * - glm::scale(glm::vec3(part.absoluteSize + part.relativeSize * _renderPlane, 1.0f)) * + glm::scale(glm::vec3(part.absoluteSize + part.relativeSize * _viewportSize, 1.0f)) * glm::translate(glm::vec3(part.position, 1.0f)); std::static_pointer_cast(part.indices)->bind(); diff --git a/src/graphics/opengl/renderer.h b/src/graphics/opengl/renderer.h index 7d114388..856d5723 100644 --- a/src/graphics/opengl/renderer.h +++ b/src/graphics/opengl/renderer.h @@ -50,6 +50,7 @@ class Renderer : public Graphics::Renderer { bool isLoading() const override; void setRenderPlane(unsigned int width, unsigned int height) override; void setRenderPlane(glm::vec2 size) override; + void setContentScale(glm::vec2 scale) override; TexturePtr createTexture( TextureType type, diff --git a/src/graphics/renderer.cpp b/src/graphics/renderer.cpp index b91b2d32..b859193c 100644 --- a/src/graphics/renderer.cpp +++ b/src/graphics/renderer.cpp @@ -36,13 +36,17 @@ void Graphics::Renderer::setRenderPlane(unsigned int width, unsigned int height) void Graphics::Renderer::setRenderPlane(glm::vec2 renderPlane) { // Setup initial projection matrix - _renderPlane = renderPlane; - _projection = glm::perspectiveFov(45.0f, _renderPlane.x, _renderPlane.y, 1.0f, 10000.0f); + _viewportSize = renderPlane; + _projection = glm::perspectiveFov(45.0f, _viewportSize.x, _viewportSize.y, 1.0f, 10000.0f); // Initialize frustrum with projection matrix _frustrum.setProjectionMatrix(_projection); } +void Graphics::Renderer::setContentScale(glm::vec2 scale) { + _contentScale = scale; +} + Graphics::Renderer::~Renderer() { } diff --git a/src/graphics/renderer.h b/src/graphics/renderer.h index b7354f88..ba47a2e6 100644 --- a/src/graphics/renderer.h +++ b/src/graphics/renderer.h @@ -48,6 +48,7 @@ class Renderer { virtual void setRenderPlane(unsigned int width, unsigned int height); virtual void setRenderPlane(glm::vec2 renderPlane); + virtual void setContentScale(glm::vec2 scale); void addModel(Model *model); void removeModel(Model *model); @@ -145,7 +146,8 @@ class Renderer { glm::mat4 _view; glm::mat4 _projection; - glm::vec2 _renderPlane; + glm::vec2 _viewportSize; + glm::vec2 _contentScale; SkyPtr _sky; diff --git a/src/platform/context.h b/src/platform/context.h index d24d9a38..5f81a628 100644 --- a/src/platform/context.h +++ b/src/platform/context.h @@ -29,8 +29,6 @@ class Context { public: virtual void getSize(unsigned int &width, unsigned int &height) = 0; virtual glm::vec2 getSize() = 0; - virtual void setSize(unsigned int width, unsigned int height) = 0; - virtual void setFullscreen(bool fullscreen) = 0; }; } diff --git a/src/platform/platform.cpp b/src/platform/platform.cpp index 25404d85..e968bb2f 100644 --- a/src/platform/platform.cpp +++ b/src/platform/platform.cpp @@ -22,6 +22,8 @@ #include #include +#include "src/common/exception.h" + #include "platform.h" namespace Platform { @@ -56,6 +58,18 @@ void Platform::monitorCallback(GLFWmonitor *monitor, int event) { ImGui_ImplGlfw_MonitorCallback(monitor, event); } +VideoMode Platform::getPrimaryMonitorVideoMode() { + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + if (!monitor) + throw CreateException("Failed to get primary monitor"); + const GLFWvidmode *mode = glfwGetVideoMode(monitor); + return VideoMode{ + mode->width, + mode->height, + mode->redBits + mode->greenBits + mode->blueBits, + mode->refreshRate}; +} + void Platform::errorCallback(int code, const char *description) { spdlog::error("GLFW Error {}: {}", code, description); } diff --git a/src/platform/platform.h b/src/platform/platform.h index d82c856e..c7adcc97 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -25,6 +25,13 @@ namespace Platform { +struct VideoMode { + int width; + int height; + int bpp; + int refreshRate; +}; + /*! * \brief class for handling platform specific stuff * @@ -42,6 +49,13 @@ class Platform { void update(); + /*! + * Get primary monitor's current video mode + * + * \return The primary monitor's current video mode + */ + VideoMode getPrimaryMonitorVideoMode(); + private: static void monitorCallback(GLFWmonitor* monitor, int event); static void errorCallback(int code, const char *description); diff --git a/src/platform/window.cpp b/src/platform/window.cpp index 93719c16..82e7a5af 100644 --- a/src/platform/window.cpp +++ b/src/platform/window.cpp @@ -63,6 +63,8 @@ Window::Window(ContextType type) { glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); _window = glfwCreateWindow(1920, 1080, "", nullptr, nullptr); + _contentScale = glm::vec2(1, 1); + _desiredResolution = glm::vec2(1920, 1080); glfwSetInputMode(_window, GLFW_STICKY_KEYS, GLFW_TRUE); @@ -272,15 +274,24 @@ glm::vec2 Window::getSize() { } void Window::setSize(unsigned int width, unsigned int height) { + _desiredResolution = glm::vec2(width, height); + glm::vec2 oldResolution = getSize(); glfwSetWindowSize(_window, width, height); + // On Wayland, when window is fullscreen, the line above does nothing. + // That means we have to scale the content ourselves... + if (getSize() == oldResolution) { + _contentScale = oldResolution / _desiredResolution; + } +} + +glm::vec2 Window::getContentScale() { + return _contentScale; } void Window::setFullscreen(bool fullscreen) { unsigned int width, height; getSize(width, height); glfwSetWindowMonitor(_window, fullscreen ? glfwGetPrimaryMonitor() : NULL, 0, 0, width, height, GLFW_DONT_CARE); - // set size again (because Wayland...) - glfwSetWindowSize(_window, width, height); } } diff --git a/src/platform/window.h b/src/platform/window.h index dcd95eb1..af57280f 100644 --- a/src/platform/window.h +++ b/src/platform/window.h @@ -58,8 +58,9 @@ class Window : public GLContext, public VulkanContext { void getSize(unsigned int &width, unsigned int &height) override; glm::vec2 getSize() override; - void setSize(unsigned int width, unsigned int height) override; - void setFullscreen(bool fullscreen) override; + void setSize(unsigned int width, unsigned int height); + void setFullscreen(bool fullscreen); + glm::vec2 getContentScale(); bool isMouseCursorVisible(); void setMouseCursorVisible(bool visible); @@ -95,6 +96,8 @@ class Window : public GLContext, public VulkanContext { GLFWwindow *_window; void *_imguiCtx; + glm::vec2 _desiredResolution; + glm::vec2 _contentScale; KeyCallback _keyCallback; MouseButtonCallback _mouseButtonCallback;