From 625397ea0ced171dbaa978a0b8199406ba486995 Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Date: Thu, 3 Nov 2022 18:43:05 +0100 Subject: [PATCH] Added a basic (and somewhat convincing) parallax effect for the camera Signed-off-by: Alexis Maiquez --- src/WallpaperEngine/Core/Objects/CImage.cpp | 55 +++++++++++-------- src/WallpaperEngine/Core/Objects/CImage.h | 45 ++++++++------- src/WallpaperEngine/Render/CScene.cpp | 23 ++++++-- src/WallpaperEngine/Render/CScene.h | 2 + src/WallpaperEngine/Render/Objects/CImage.cpp | 50 ++++++++++++----- src/WallpaperEngine/Render/Objects/CImage.h | 4 ++ 6 files changed, 117 insertions(+), 62 deletions(-) diff --git a/src/WallpaperEngine/Core/Objects/CImage.cpp b/src/WallpaperEngine/Core/Objects/CImage.cpp index ec1a041..1515974 100644 --- a/src/WallpaperEngine/Core/Objects/CImage.cpp +++ b/src/WallpaperEngine/Core/Objects/CImage.cpp @@ -8,27 +8,30 @@ using namespace WallpaperEngine::Core::Objects; CImage::CImage ( - Images::CMaterial* material, - bool visible, - uint32_t id, - std::string name, - const glm::vec3& origin, - const glm::vec3& scale, - const glm::vec3& angles, - const glm::vec2& size, - std::string alignment, - const glm::vec3& color, - float alpha, - float brightness, - uint32_t colorBlendMode) : - CObject (visible, id, std::move(name), Type, origin, scale, angles), - m_size (size), - m_material (material), - m_alignment (std::move(alignment)), - m_color (color), - m_alpha (alpha), - m_brightness (brightness), - m_colorBlendMode (colorBlendMode) + Images::CMaterial* material, + bool visible, + uint32_t id, + std::string name, + const glm::vec3& origin, + const glm::vec3& scale, + const glm::vec3& angles, + const glm::vec2& size, + std::string alignment, + const glm::vec3& color, + float alpha, + float brightness, + uint32_t colorBlendMode, + const glm::vec2& parallaxDepth +) : + CObject (visible, id, std::move(name), Type, origin, scale, angles), + m_size (size), + m_material (material), + m_alignment (std::move(alignment)), + m_color (color), + m_alpha (alpha), + m_brightness (brightness), + m_colorBlendMode (colorBlendMode), + m_parallaxDepth(parallaxDepth) { } @@ -49,6 +52,7 @@ WallpaperEngine::Core::CObject* CImage::fromJSON ( auto color_val = jsonFindDefault (data, "color", "1.0 1.0 1.0"); auto brightness_val = jsonFindDefault (data, "brightness", 1.0); auto colorBlendMode_val = jsonFindDefault (data, "colorBlendMode", 0); + auto parallaxDepth_val = jsonFindDefault (data, "parallaxDepth", "0 0"); json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*image_it).get (), container)); @@ -67,7 +71,8 @@ WallpaperEngine::Core::CObject* CImage::fromJSON ( WallpaperEngine::Core::aToVector3 (color_val), alpha, brightness_val, - colorBlendMode_val + colorBlendMode_val, + WallpaperEngine::Core::aToVector2 (parallaxDepth_val) ); } @@ -106,4 +111,10 @@ const uint32_t CImage::getColorBlendMode () const return this->m_colorBlendMode; } + +const glm::vec2& CImage::getParallaxDepth () const +{ + return this->m_parallaxDepth; +} + const std::string CImage::Type = "image"; \ No newline at end of file diff --git a/src/WallpaperEngine/Core/Objects/CImage.h b/src/WallpaperEngine/Core/Objects/CImage.h index 8e719d3..22b96df 100644 --- a/src/WallpaperEngine/Core/Objects/CImage.h +++ b/src/WallpaperEngine/Core/Objects/CImage.h @@ -18,14 +18,14 @@ namespace WallpaperEngine::Core::Objects public: static CObject* fromJSON ( - json data, - CContainer* container, - bool visible, - uint32_t id, - std::string name, - const glm::vec3& origin, - const glm::vec3& scale, - const glm::vec3& angles + json data, + CContainer* container, + bool visible, + uint32_t id, + std::string name, + const glm::vec3& origin, + const glm::vec3& scale, + const glm::vec3& angles ); const Images::CMaterial* getMaterial () const; @@ -35,28 +35,31 @@ namespace WallpaperEngine::Core::Objects const glm::vec3& getColor () const; const float getBrightness () const; const uint32_t getColorBlendMode () const; + const glm::vec2& getParallaxDepth () const; protected: CImage ( - Images::CMaterial* material, - bool visible, - uint32_t id, - std::string name, - const glm::vec3& origin, - const glm::vec3& scale, - const glm::vec3& angles, - const glm::vec2& size, - std::string alignment, - const glm::vec3& color, - float alpha, - float brightness, - uint32_t colorBlendMode + Images::CMaterial* material, + bool visible, + uint32_t id, + std::string name, + const glm::vec3& origin, + const glm::vec3& scale, + const glm::vec3& angles, + const glm::vec2& size, + std::string alignment, + const glm::vec3& color, + float alpha, + float brightness, + uint32_t colorBlendMode, + const glm::vec2& parallaxDepth ); static const std::string Type; private: glm::vec2 m_size; + const glm::vec2 m_parallaxDepth; Images::CMaterial* m_material; std::string m_alignment; float m_alpha; diff --git a/src/WallpaperEngine/Render/CScene.cpp b/src/WallpaperEngine/Render/CScene.cpp index 4ffee40..9879c32 100644 --- a/src/WallpaperEngine/Render/CScene.cpp +++ b/src/WallpaperEngine/Render/CScene.cpp @@ -34,6 +34,8 @@ CScene::CScene (Core::CScene* scene, CContext* context) : } } + this->m_parallaxDisplacement = {0, 0}; + this->m_camera->setOrthogonalProjection ( scene->getOrthogonalProjection ()->getWidth (), scene->getOrthogonalProjection ()->getHeight () @@ -49,7 +51,6 @@ CScene::CScene (Core::CScene* scene, CContext* context) : // create all objects based off their dependencies { - auto cur = scene->getObjects ().begin (); auto end = scene->getObjects ().end (); @@ -71,7 +72,6 @@ CScene::CScene (Core::CScene* scene, CContext* context) : this->m_objectsByRenderOrder.emplace_back ((*obj).second); } - } Render::CObject* CScene::createObject (Core::CObject* object) @@ -141,6 +141,17 @@ void CScene::renderFrame (glm::ivec4 viewport) // ensure the virtual mouse position is up to date this->updateMouse (viewport); + // update the parallax position if required + if (this->getScene ()->isCameraParallax () == true) + { + float influence = this->getScene ()->getCameraParallaxMouseInfluence (); + float amount = this->getScene ()->getCameraParallaxAmount (); + float delay = this->getScene ()->getCameraParallaxDelay (); + + this->m_parallaxDisplacement.x = glm::mix (this->m_parallaxDisplacement.x, (this->m_mousePosition.x * amount) * influence, delay); + this->m_parallaxDisplacement.y = glm::mix (this->m_parallaxDisplacement.y, (this->m_mousePosition.y * amount) * influence, delay); + } + // use the scene's framebuffer by default glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer()); // ensure we render over the whole screen @@ -154,8 +165,6 @@ void CScene::renderFrame (glm::ivec4 viewport) void CScene::updateMouse (glm::ivec4 viewport) { - // projection also affects the mouse position - auto projection = this->getScene ()->getOrthogonalProjection (); // update virtual mouse position first CMouseInput* mouse = this->getContext ()->getMouse (); // TODO: PROPERLY TRANSLATE THESE TO WHAT'S VISIBLE ON SCREEN (FOR BACKGROUNDS THAT DO NOT EXACTLY FIT ON SCREEN) @@ -176,4 +185,10 @@ glm::vec2* CScene::getMousePosition () return &this->m_mousePosition; } + +glm::vec2* CScene::getParallaxDisplacement () +{ + return &this->m_parallaxDisplacement; +} + const std::string CScene::Type = "scene"; diff --git a/src/WallpaperEngine/Render/CScene.h b/src/WallpaperEngine/Render/CScene.h index 5a30da7..fbc49a6 100644 --- a/src/WallpaperEngine/Render/CScene.h +++ b/src/WallpaperEngine/Render/CScene.h @@ -22,6 +22,7 @@ namespace WallpaperEngine::Render Core::CScene* getScene (); glm::vec2* getMousePosition (); + glm::vec2* getParallaxDisplacement (); protected: void renderFrame (glm::ivec4 viewport) override; @@ -38,5 +39,6 @@ namespace WallpaperEngine::Render std::map m_objects; std::vector m_objectsByRenderOrder; glm::vec2 m_mousePosition; + glm::vec2 m_parallaxDisplacement; }; } diff --git a/src/WallpaperEngine/Render/Objects/CImage.cpp b/src/WallpaperEngine/Render/Objects/CImage.cpp index c149b4d..cdeaa00 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.cpp +++ b/src/WallpaperEngine/Render/Objects/CImage.cpp @@ -20,19 +20,14 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : glm::vec2 size = this->getSize (); glm::vec3 scale = this->getImage ()->getScale (); - float xleft = 0.0f; - float ytop = 0.0f; - float xright = 0.0f; - float ybottom = 0.0f; - // depending on the alignment these values might change, for now just support center if (this->getImage ()->getAlignment () == "center") { // calculate the real position of the image - xleft = (-scene_width / 2) + (origin.x - (size.x * scale.x / 2)); - xright = (-scene_width / 2) + (origin.x + (size.x * scale.x / 2)); - ytop = (-scene_height / 2) + origin.y + (size.y * scale.y / 2); - ybottom = (-scene_height / 2) + (origin.y - (size.y * scale.y / 2)); + this->m_pos.x = (-scene_width / 2) + (origin.x - (size.x * scale.x / 2)); + this->m_pos.z = (-scene_width / 2) + (origin.x + (size.x * scale.x / 2)); + this->m_pos.y = (-scene_height / 2) + origin.y + (size.y * scale.y / 2); + this->m_pos.w = (-scene_height / 2) + (origin.y - (size.y * scale.y / 2)); } else { @@ -99,12 +94,12 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : // build a list of vertices, these might need some change later (or maybe invert the camera) GLfloat sceneSpacePosition [] = { - xleft, ytop, 0.0f, - xright, ytop, 0.0f, - xleft, ybottom, 0.0f, - xleft, ybottom, 0.0f, - xright, ytop, 0.0f, - xright, ybottom, 0.0f + this->m_pos.x, this->m_pos.y, 0.0f, + this->m_pos.z, this->m_pos.y, 0.0f, + this->m_pos.x, this->m_pos.w, 0.0f, + this->m_pos.x, this->m_pos.w, 0.0f, + this->m_pos.z, this->m_pos.y, 0.0f, + this->m_pos.z, this->m_pos.w, 0.0f }; GLfloat copySpacePosition [] = { @@ -364,6 +359,11 @@ void CImage::render () // determine if it's the last element in the list as this is a screen-copy-like process else if (std::next (cur) == end && this->getImage ()->isVisible () == true) { + if (this->getScene ()->getScene ()->isCameraParallax () == true) + { + this->updateScreenSpacePosition (); + } + spacePosition = *this->getSceneSpacePosition (); drawTo = this->getScene ()->getFBO (); projection = this->m_modelViewProjectionScreen; @@ -381,6 +381,26 @@ void CImage::render () } } +void CImage::updateScreenSpacePosition () +{ + double parallaxAmount = this->getScene ()->getScene ()->getCameraParallaxAmount (); + glm::vec2 depth = this->getImage ()->getParallaxDepth (); + glm::vec2* displacement = this->getScene ()->getParallaxDisplacement (); + + // no need to update if the depth is 0 + if (depth.x == 0.0 && depth.y == 0.0) + return; + + float x = (depth.x + parallaxAmount) * displacement->x * this->getSize ().x; + float y = (depth.y + parallaxAmount) * displacement->y * this->getSize ().x; + this->m_modelViewProjectionScreen = + glm::translate ( + this->getScene ()->getCamera ()->getProjection () * + this->getScene ()->getCamera ()->getLookAt (), + {x, y, 0.0f} + ); +} + const ITexture* CImage::getTexture () const { return this->m_texture; diff --git a/src/WallpaperEngine/Render/Objects/CImage.h b/src/WallpaperEngine/Render/Objects/CImage.h index 229478b..4e968f4 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.h +++ b/src/WallpaperEngine/Render/Objects/CImage.h @@ -59,6 +59,8 @@ namespace WallpaperEngine::Render::Objects protected: static const std::string Type; + + void updateScreenSpacePosition (); private: const ITexture* m_texture; GLuint m_sceneSpacePosition; @@ -82,6 +84,8 @@ namespace WallpaperEngine::Render::Objects Effects::CMaterial* m_colorBlendMaterial; std::vector m_passes; + glm::vec4 m_pos; + double m_animationTime; bool m_initialized;