From ed1efdcd668c6fd7824cd533406961ada596a84e Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Date: Fri, 4 Nov 2022 10:16:13 +0100 Subject: [PATCH] Added parsing for text properties Simplified how passes rendering works and separated it into a two stages process Setup (prepares shaders, uniforms, attributes, etc) Render (only performs the actual rendering) Signed-off-by: Alexis Maiquez --- CMakeLists.txt | 2 + src/WallpaperEngine/Core/CProject.cpp | 7 +- .../Core/Projects/CProperty.cpp | 19 ++- .../Core/Projects/CPropertyText.cpp | 21 +++ .../Core/Projects/CPropertyText.h | 19 +++ src/WallpaperEngine/Render/Objects/CImage.cpp | 126 +++++++++------- src/WallpaperEngine/Render/Objects/CImage.h | 13 +- .../Render/Objects/Effects/CPass.cpp | 142 ++++++++++++++++-- .../Render/Objects/Effects/CPass.h | 36 ++++- 9 files changed, 292 insertions(+), 93 deletions(-) create mode 100644 src/WallpaperEngine/Core/Projects/CPropertyText.cpp create mode 100644 src/WallpaperEngine/Core/Projects/CPropertyText.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a51237..16215e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,8 @@ add_executable( src/WallpaperEngine/Core/Projects/CPropertySlider.cpp src/WallpaperEngine/Core/Projects/CPropertyCombo.h src/WallpaperEngine/Core/Projects/CPropertyCombo.cpp + src/WallpaperEngine/Core/Projects/CPropertyText.h + src/WallpaperEngine/Core/Projects/CPropertyText.cpp src/WallpaperEngine/Core/Scenes/CCamera.cpp src/WallpaperEngine/Core/Scenes/CCamera.h diff --git a/src/WallpaperEngine/Core/CProject.cpp b/src/WallpaperEngine/Core/CProject.cpp index ba22b3b..41593b7 100644 --- a/src/WallpaperEngine/Core/CProject.cpp +++ b/src/WallpaperEngine/Core/CProject.cpp @@ -60,9 +60,10 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container for (; cur != end; cur ++) { - project->insertProperty ( - Projects::CProperty::fromJSON (*cur, cur.key ()) - ); + Projects::CProperty* property = Projects::CProperty::fromJSON (*cur, cur.key ()); + + if (property != nullptr) + project->insertProperty (property); } } } diff --git a/src/WallpaperEngine/Core/Projects/CProperty.cpp b/src/WallpaperEngine/Core/Projects/CProperty.cpp index a78da12..ae83fd3 100644 --- a/src/WallpaperEngine/Core/Projects/CProperty.cpp +++ b/src/WallpaperEngine/Core/Projects/CProperty.cpp @@ -1,34 +1,33 @@ -#include +#include #include "CProperty.h" #include "CPropertyColor.h" #include "CPropertyCombo.h" #include "CPropertySlider.h" #include "CPropertyBoolean.h" +#include "CPropertyText.h" using namespace WallpaperEngine::Core::Projects; CProperty* CProperty::fromJSON (json data, const std::string& name) { auto type = jsonFindRequired (data, "type", "Project properties must have the type field"); - auto value = jsonFindRequired (data, "value", "Project properties must have the value field"); - auto text = data.find ("text"); if (*type == CPropertyColor::Type) return CPropertyColor::fromJSON (data, name); - if (*type == CPropertyBoolean::Type) return CPropertyBoolean::fromJSON (data, name); - if (*type == CPropertySlider::Type) return CPropertySlider::fromJSON (data, name); - if (*type == CPropertyCombo::Type) return CPropertyCombo::fromJSON (data, name); + if (*type == CPropertyText::Type) + return CPropertyText::fromJSON (data, name); - std::stringstream buffer; - buffer << "Unexpected type for property:" << *type << std::endl << data; - // throw an exception - throw std::runtime_error (buffer.str()); + + // show the error and ignore this property + std::cout << "Unexpected type for property:" << *type << std::endl << data << std::endl; + + return nullptr; } CProperty::CProperty (std::string name, std::string type, std::string text) : diff --git a/src/WallpaperEngine/Core/Projects/CPropertyText.cpp b/src/WallpaperEngine/Core/Projects/CPropertyText.cpp new file mode 100644 index 0000000..9affcae --- /dev/null +++ b/src/WallpaperEngine/Core/Projects/CPropertyText.cpp @@ -0,0 +1,21 @@ +#include "CPropertyText.h" +#include "WallpaperEngine/Core/Core.h" + +using namespace WallpaperEngine::Core::Projects; + +CPropertyText* CPropertyText::fromJSON (json data, const std::string& name) +{ + json::const_iterator text = data.find ("type"); + + return new CPropertyText ( + name, + *text + ); +} + +CPropertyText::CPropertyText (const std::string& name, const std::string& text) : + CProperty (name, Type, text) +{ +} + +const std::string CPropertyText::Type = "text"; \ No newline at end of file diff --git a/src/WallpaperEngine/Core/Projects/CPropertyText.h b/src/WallpaperEngine/Core/Projects/CPropertyText.h new file mode 100644 index 0000000..2a6e0a3 --- /dev/null +++ b/src/WallpaperEngine/Core/Projects/CPropertyText.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CProperty.h" + +namespace WallpaperEngine::Core::Projects +{ + using json = nlohmann::json; + + class CPropertyText : public CProperty + { + public: + static CPropertyText* fromJSON (json data, const std::string& name); + + static const std::string Type; + + private: + CPropertyText (const std::string& name, const std::string& text); + }; +}; diff --git a/src/WallpaperEngine/Render/Objects/CImage.cpp b/src/WallpaperEngine/Render/Objects/CImage.cpp index 56057e7..d3d7f51 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.cpp +++ b/src/WallpaperEngine/Render/Objects/CImage.cpp @@ -312,9 +312,63 @@ void CImage::setup () this->m_animationTime += (*cur)->frametime; } + this->setupPasses (); this->m_initialized = true; } +void CImage::setupPasses () +{ + // do a pass on everything and setup proper inputs and values + const CFBO* drawTo = this->m_currentMainFBO; + const ITexture* asInput = this->getTexture (); + GLuint texcoord = this->getTexCoordCopy (); + + auto cur = this->m_passes.begin (); + auto end = this->m_passes.end (); + + for (; cur != end; cur ++) + { + Effects::CPass* pass = *cur; + const CFBO* prevDrawTo = drawTo; + GLuint spacePosition = this->getCopySpacePosition (); + glm::mat4* projection = &this->m_modelViewProjectionPass; + + // set viewport and target texture if needed + if (pass->getMaterial ()->getMaterial ()->hasTarget () == true) + { + // setup target texture + std::string target = pass->getMaterial ()->getMaterial ()->getTarget (); + drawTo = pass->getMaterial ()->getEffect ()->findFBO (target); + spacePosition = this->getPassSpacePosition (); + + // not a local fbo, try to find a scene fbo with the same name + if (drawTo == nullptr) + // this one throws if no fbo was found + drawTo = this->getScene ()->findFBO (target); + } + + // 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) + { + spacePosition = this->getSceneSpacePosition (); + drawTo = this->getScene ()->getFBO (); + projection = &this->m_modelViewProjectionScreen; + } + + pass->setDestination (drawTo); + pass->setInput (asInput); + pass->setPosition (spacePosition); + pass->setTexCoord (texcoord); + pass->setModelViewProjectionMatrix (projection); + + texcoord = this->getTexCoordPass (); + drawTo = prevDrawTo; + + if (pass->getMaterial ()->getMaterial ()->hasTarget () == false) + this->pinpongFramebuffer (&drawTo, &asInput); + } +} + void CImage::pinpongFramebuffer (const CFBO** drawTo, const ITexture** asInput) { // temporarily store FBOs used @@ -337,63 +391,21 @@ void CImage::render () if (this->m_initialized == false) return; - // reset the framebuffers so the drawing always happens on the same order - this->m_currentMainFBO = this->m_mainFBO; - this->m_currentSubFBO = this->m_subFBO; - glColorMask (true, true, true, true); - // start drawing to the main framebuffer - const CFBO* drawTo = this->m_currentMainFBO; - const ITexture* asInput = this->getTexture (); - GLuint texcoord = *this->getTexCoordCopy (); + // update the position if required + if (this->getScene ()->getScene ()->isCameraParallax () == true) + this->updateScreenSpacePosition (); auto cur = this->m_passes.begin (); auto end = this->m_passes.end (); for (; cur != end; cur ++) { - Effects::CPass* pass = *cur; - const CFBO* prevDrawTo = drawTo; - GLuint spacePosition = *this->getCopySpacePosition (); - glm::mat4 projection = this->m_modelViewProjectionPass; - - // set viewport and target texture if needed - if (pass->getMaterial ()->getMaterial ()->hasTarget () == true) - { - // setup target texture - std::string target = pass->getMaterial ()->getMaterial ()->getTarget (); - drawTo = pass->getMaterial ()->getEffect ()->findFBO (target); - spacePosition = *this->getPassSpacePosition (); - - // not a local fbo, try to find a scene fbo with the same name - if (drawTo == nullptr) - // this one throws if no fbo was found - drawTo = this->getScene ()->findFBO (target); - } - - // 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; - + if (std::next (cur) == end) glColorMask (true, true, true, false); - } - pass->render (drawTo, asInput, spacePosition, texcoord, projection); - - texcoord = *this->getTexCoordPass (); - drawTo = prevDrawTo; - - if (pass->getMaterial ()->getMaterial ()->hasTarget () == false) - this->pinpongFramebuffer (&drawTo, &asInput); + (*cur)->render (); } } @@ -445,29 +457,29 @@ const glm::vec2 CImage::getSize() const return {this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()}; } -const GLuint* CImage::getSceneSpacePosition () const +const GLuint CImage::getSceneSpacePosition () const { - return &this->m_sceneSpacePosition; + return this->m_sceneSpacePosition; } -const GLuint* CImage::getCopySpacePosition () const +const GLuint CImage::getCopySpacePosition () const { - return &this->m_copySpacePosition; + return this->m_copySpacePosition; } -const GLuint* CImage::getPassSpacePosition () const +const GLuint CImage::getPassSpacePosition () const { - return &this->m_passSpacePosition; + return this->m_passSpacePosition; } -const GLuint* CImage::getTexCoordCopy () const +const GLuint CImage::getTexCoordCopy () const { - return &this->m_texcoordCopy; + return this->m_texcoordCopy; } -const GLuint* CImage::getTexCoordPass () const +const GLuint CImage::getTexCoordPass () const { - return &this->m_texcoordPass; + return this->m_texcoordPass; } const std::string CImage::Type = "image"; \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Objects/CImage.h b/src/WallpaperEngine/Render/Objects/CImage.h index 4e968f4..68d4d09 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.h +++ b/src/WallpaperEngine/Render/Objects/CImage.h @@ -40,12 +40,11 @@ namespace WallpaperEngine::Render::Objects const std::vector& getEffects () const; const glm::vec2 getSize() const; - const GLfloat* getVertex () const; - const GLuint* getSceneSpacePosition () const; - const GLuint* getCopySpacePosition () const; - const GLuint* getPassSpacePosition () const; - const GLuint* getTexCoordCopy () const; - const GLuint* getTexCoordPass () const; + const GLuint getSceneSpacePosition () const; + const GLuint getCopySpacePosition () const; + const GLuint getPassSpacePosition () const; + const GLuint getTexCoordCopy () const; + const GLuint getTexCoordPass () const; const ITexture* getTexture () const; const double getAnimationTime () const; @@ -60,6 +59,8 @@ namespace WallpaperEngine::Render::Objects protected: static const std::string Type; + void setupPasses (); + void updateScreenSpacePosition (); private: const ITexture* m_texture; diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp index d1e6f6f..1d09f4b 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp @@ -63,13 +63,13 @@ const ITexture* CPass::resolveTexture (const ITexture* expected, int index, cons return fbo; } -void CPass::render (const CFBO* drawTo, const ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection) +void CPass::render () { // set the framebuffer we're drawing to - glBindFramebuffer (GL_FRAMEBUFFER, drawTo->getFramebuffer ()); + glBindFramebuffer (GL_FRAMEBUFFER, this->m_drawTo->getFramebuffer ()); // set proper viewport based on what we're drawing to - glViewport (0, 0, drawTo->getRealWidth (), drawTo->getRealHeight ()); + glViewport (0, 0, this->m_drawTo->getRealWidth (), this->m_drawTo->getRealHeight ()); // set texture blending if (this->m_pass->getBlendingMode () == "translucent") @@ -120,19 +120,11 @@ void CPass::render (const CFBO* drawTo, const ITexture* input, GLuint position, glDepthMask (true); } - // update variables used in the render process (like g_ModelViewProjectionMatrix) - this->m_modelViewProjectionMatrix = projection; - - // update a_TexCoord and a_Position based on what to draw to - // this should not be required once we do some prediction on rendering things - // but for now should be enough - this->a_TexCoord = texcoord; - this->a_Position = position; - // use the shader we have registered glUseProgram (this->m_programID); - const ITexture* texture = this->resolveTexture (input, 0, input); + // maybe we can do this when setting the texture? + const ITexture* texture = this->resolveTexture (this->m_input, 0, this->m_input); uint32_t currentTexture = 0; glm::vec2 translation = {0.0f, 0.0f}; @@ -180,7 +172,7 @@ void CPass::render (const CFBO* drawTo, const ITexture* input, GLuint position, for (; cur != end; cur ++) { - texture = this->resolveTexture ((*cur).second, (*cur).first, input); + texture = this->resolveTexture ((*cur).second, (*cur).first, this->m_input); glActiveTexture (GL_TEXTURE0 + (*cur).first); glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0)); @@ -222,6 +214,41 @@ void CPass::render (const CFBO* drawTo, const ITexture* input, GLuint position, } } } + // add reference uniforms + { + auto cur = this->m_referenceUniforms.begin (); + auto end = this->m_referenceUniforms.end (); + + for (; cur != end; cur ++) + { + ReferenceUniformEntry* entry = (*cur).second; + + switch (entry->type) + { + case Double: + glUniform1d (entry->id, *reinterpret_cast (*entry->value)); + break; + case Float: + glUniform1f (entry->id, *reinterpret_cast (*entry->value)); + break; + case Integer: + glUniform1i (entry->id, *reinterpret_cast (*entry->value)); + break; + case Vector4: + glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast (*entry->value))); + break; + case Vector3: + glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast (*entry->value))); + break; + case Vector2: + glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast (*entry->value))); + break; + case Matrix4: + glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast (*entry->value))); + break; + } + } + } if (this->g_Texture0Rotation != -1) { @@ -255,7 +282,7 @@ void CPass::render (const CFBO* drawTo, const ITexture* input, GLuint position, } // start actual rendering now - glBindBuffer (GL_ARRAY_BUFFER, position); + glBindBuffer (GL_ARRAY_BUFFER, this->a_Position); glDrawArrays (GL_TRIANGLES, 0, 6); // disable vertex attribs array and textures @@ -290,6 +317,36 @@ const CMaterial* CPass::getMaterial () const return this->m_material; } +void CPass::setDestination (const CFBO* drawTo) +{ + this->m_drawTo = drawTo; +} + +void CPass::setInput (const ITexture* input) +{ + this->m_input = input; +} + +void CPass::setModelViewProjectionMatrix (const glm::mat4* projection) +{ + this->m_modelViewProjectionMatrix = projection; +} + +void CPass::setModelMatrix (glm::mat4 model) +{ + this->m_modelMatrix = model; +} + +void CPass::setTexCoord (GLuint texcoord) +{ + this->a_TexCoord = texcoord; +} + +void CPass::setPosition (GLuint position) +{ + this->a_Position = position; +} + Core::Objects::Images::Materials::CPass* CPass::getPass () { return this->m_pass; @@ -623,6 +680,23 @@ void CPass::addUniform (const std::string& name, UniformType type, T* value) ); } +template +void CPass::addUniform (const std::string& name, UniformType type, T** value) +{ + // this version is used to reference to system variables so things like g_Time works fine + GLint id = glGetUniformLocation (this->m_programID, name.c_str ()); + + // parameter not found, can be ignored + if (id == -1) + return; + + // uniform found, add it to the list + this->m_referenceUniforms.insert ( + std::make_pair (name, new ReferenceUniformEntry (id, name, type, reinterpret_cast (value))) + ); +} + + void CPass::setupTextures () { auto cur = this->m_pass->getTextures ().begin (); @@ -798,6 +872,11 @@ void CPass::addUniform (const std::string& name, const int* value) this->addUniform (name, UniformType::Integer, value); } +void CPass::addUniform (const std::string& name, const int** value) +{ + this->addUniform (name, UniformType::Integer, value); +} + void CPass::addUniform (const std::string& name, double value) { this->addUniform (name, UniformType::Double, value); @@ -808,6 +887,11 @@ void CPass::addUniform (const std::string& name, const double* value) this->addUniform (name, UniformType::Double, value); } +void CPass::addUniform (const std::string& name, const double** value) +{ + this->addUniform (name, UniformType::Double, value); +} + void CPass::addUniform (const std::string& name, float value) { this->addUniform (name, UniformType::Float, value); @@ -818,6 +902,12 @@ void CPass::addUniform (const std::string& name, const float* value) this->addUniform (name, UniformType::Float, value); } +void CPass::addUniform (const std::string& name, const float** value) +{ + this->addUniform (name, UniformType::Float, value); +} + + void CPass::addUniform (const std::string& name, glm::vec2 value) { this->addUniform (name, UniformType::Vector2, value); @@ -828,6 +918,12 @@ void CPass::addUniform (const std::string& name, const glm::vec2* value) this->addUniform (name, UniformType::Vector2, value); } +void CPass::addUniform (const std::string& name, const glm::vec2** value) +{ + this->addUniform (name, UniformType::Vector2, value); +} + + void CPass::addUniform (const std::string& name, glm::vec3 value) { this->addUniform (name, UniformType::Vector3, value); @@ -838,6 +934,12 @@ void CPass::addUniform (const std::string& name, const glm::vec3* value) this->addUniform (name, UniformType::Vector3, value); } +void CPass::addUniform (const std::string& name, const glm::vec3** value) +{ + this->addUniform (name, UniformType::Vector3, value); +} + + void CPass::addUniform (const std::string& name, glm::vec4 value) { this->addUniform (name, UniformType::Vector4, value); @@ -848,6 +950,11 @@ void CPass::addUniform (const std::string& name, const glm::vec4* value) this->addUniform (name, UniformType::Vector4, value); } +void CPass::addUniform (const std::string& name, const glm::vec4** value) +{ + this->addUniform (name, UniformType::Vector4, value); +} + void CPass::addUniform (const std::string& name, glm::mat4 value) { this->addUniform (name, UniformType::Matrix4, value); @@ -857,3 +964,8 @@ void CPass::addUniform (const std::string& name, const glm::mat4* value) { this->addUniform (name, UniformType::Matrix4, value); } + +void CPass::addUniform (const std::string& name, const glm::mat4** value) +{ + this->addUniform (name, UniformType::Matrix4, value); +} diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.h b/src/WallpaperEngine/Render/Objects/Effects/CPass.h index 1b8f52d..1ada477 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.h +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.h @@ -21,7 +21,14 @@ namespace WallpaperEngine::Render::Objects::Effects public: CPass (CMaterial* material, Core::Objects::Images::Materials::CPass* pass); - void render (const CFBO* drawTo, const ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection); + void render (); + + void setDestination (const CFBO* drawTo); + void setInput (const ITexture* input); + void setTexCoord (GLuint texcoord); + void setPosition (GLuint position); + void setModelViewProjectionMatrix (const glm::mat4* projection); + void setModelMatrix (glm::mat4 model); const CMaterial* getMaterial () const; Core::Objects::Images::Materials::CPass* getPass (); @@ -50,6 +57,18 @@ namespace WallpaperEngine::Render::Objects::Effects const void* value; }; + class ReferenceUniformEntry + { + public: + ReferenceUniformEntry (GLint id, std::string name, UniformType type, const void** value) : + id (id), name (std::move (name)), type (type), value (value) { } + + GLint id; + std::string name; + UniformType type; + const void** value; + }; + class AttribEntry { public: @@ -84,8 +103,16 @@ namespace WallpaperEngine::Render::Objects::Effects void addUniform (const std::string& name, const glm::vec3* value); void addUniform (const std::string& name, const glm::vec4* value); void addUniform (const std::string& name, const glm::mat4* value); + void addUniform (const std::string& name, const int** value); + void addUniform (const std::string& name, const double** value); + void addUniform (const std::string& name, const float** value); + void addUniform (const std::string& name, const glm::vec2** value); + void addUniform (const std::string& name, const glm::vec3** value); + void addUniform (const std::string& name, const glm::vec4** value); + void addUniform (const std::string& name, const glm::mat4** value); template void addUniform (const std::string& name, UniformType type, T value); template void addUniform (const std::string& name, UniformType type, T* value); + template void addUniform (const std::string& name, UniformType type, T** value); const ITexture* resolveTexture (const ITexture* expected, int index, const ITexture* previous = nullptr); @@ -96,7 +123,9 @@ namespace WallpaperEngine::Render::Objects::Effects std::map m_foundCombos; std::vector m_attribs; std::map m_uniforms; - glm::mat4 m_modelViewProjectionMatrix; + std::map m_referenceUniforms; + const glm::mat4* m_modelViewProjectionMatrix; + glm::mat4 m_modelMatrix; /** * Contains the final map of textures to be used @@ -106,6 +135,9 @@ namespace WallpaperEngine::Render::Objects::Effects Render::Shaders::Compiler* m_fragShader; Render::Shaders::Compiler* m_vertShader; + const CFBO* m_drawTo; + const ITexture* m_input; + GLuint m_programID; // shader variables used temporary