Переглянути джерело

Ignore composelayers for now
Added support for color blend mode
Main pass' blendmode should be normal
Last pass' blendmode should be the first's
Fixed order of glClear's so _rt_FullFrameBuffer is the right color at the right time
Simplified effect and pass creation code a bit more
Non-visible images should render the full chain into the pingpong framebuffers instead of to screen
Fixed an integer division not producing float numbers

Signed-off-by: Alexis Maiquez <almamu@almamu.com>

Alexis Maiquez 3 роки тому
батько
коміт
5521e90155

+ 4 - 0
src/WallpaperEngine/Core/CObject.cpp

@@ -68,6 +68,10 @@ CObject* CObject::fromJSON (json data, CContainer* container)
 
     if (image_it != data.end () && (*image_it).is_null () == false)
     {
+        // composelayer should be ignored for now, or artifacts will appear
+        if (*image_it == "models/util/composelayer.json")
+            return nullptr;
+
         object = Objects::CImage::fromJSON (
                 data,
                 container,

+ 12 - 3
src/WallpaperEngine/Core/Objects/CImage.cpp

@@ -19,14 +19,16 @@ CImage::CImage (
         std::string alignment,
         const glm::vec3& color,
         float alpha,
-        float brightness) :
+        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_brightness (brightness),
+        m_colorBlendMode (colorBlendMode)
 {
 }
 
@@ -46,6 +48,7 @@ WallpaperEngine::Core::CObject* CImage::fromJSON (
     auto alpha = jsonFindDefault <float> (data, "alpha", 1.0);
     auto color_val = jsonFindDefault <std::string> (data, "color", "1.0 1.0 1.0");
     auto brightness_val = jsonFindDefault <float> (data, "brightness", 1.0);
+    auto colorBlendMode_val = jsonFindDefault <uint32_t> (data, "colorBlendMode", 0);
 
     json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*image_it).get <std::string> (), container));
 
@@ -63,7 +66,8 @@ WallpaperEngine::Core::CObject* CImage::fromJSON (
         alignment,
         WallpaperEngine::Core::aToVector3 (color_val),
         alpha,
-        brightness_val
+        brightness_val,
+        colorBlendMode_val
     );
 }
 
@@ -97,4 +101,9 @@ const float CImage::getBrightness () const
     return this->m_brightness;
 }
 
+const uint32_t CImage::getColorBlendMode () const
+{
+    return this->m_colorBlendMode;
+}
+
 const std::string CImage::Type = "image";

+ 4 - 1
src/WallpaperEngine/Core/Objects/CImage.h

@@ -34,6 +34,7 @@ namespace WallpaperEngine::Core::Objects
         const float getAlpha () const;
         const glm::vec3& getColor () const;
         const float getBrightness () const;
+        const uint32_t getColorBlendMode () const;
 
     protected:
         CImage (
@@ -48,7 +49,8 @@ namespace WallpaperEngine::Core::Objects
                 std::string alignment,
                 const glm::vec3& color,
                 float alpha,
-                float brightness
+                float brightness,
+                uint32_t colorBlendMode
         );
 
         static const std::string Type;
@@ -60,5 +62,6 @@ namespace WallpaperEngine::Core::Objects
         float m_alpha;
         float m_brightness;
         glm::vec3 m_color;
+        uint32_t m_colorBlendMode;
     };
 };

+ 5 - 0
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.cpp

@@ -139,6 +139,11 @@ const std::string& CPass::getDepthWrite ()const
     return this->m_depthwrite;
 }
 
+void CPass::setBlendingMode (std::string mode)
+{
+    this->m_blending = mode;
+}
+
 void CPass::insertConstant (const std::string& name, CShaderConstant* constant)
 {
     this->m_constants.insert (std::pair <std::string, CShaderConstant*> (name, constant));

+ 1 - 0
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.h

@@ -28,6 +28,7 @@ namespace WallpaperEngine::Core::Objects::Images::Materials
         const std::string& getCullingMode () const;
         const std::string& getDepthTest () const;
         const std::string& getDepthWrite () const;
+        void setBlendingMode (std::string mode);
 
         void insertCombo (const std::string& name, int value);
         void insertConstant (const std::string& name, Effects::Constants::CShaderConstant* constant);

+ 7 - 8
src/WallpaperEngine/Render/CScene.cpp

@@ -39,6 +39,11 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
         scene->getOrthogonalProjection ()->getHeight ()
     );
 
+    // set clear color
+    FloatColor clearColor = this->getScene ()->getClearColor ();
+
+    glClearColor (clearColor.r, clearColor.g, clearColor.b, 1.0f);
+
     // setup framebuffers
     this->setupFramebuffers ();
 
@@ -136,21 +141,15 @@ void CScene::renderFrame (glm::ivec4 viewport)
     // ensure the virtual mouse position is up to date
     this->updateMouse (viewport);
 
-    // clear screen
-    FloatColor clearColor = this->getScene ()->getClearColor ();
-
-    glClearColor (clearColor.r, clearColor.g, clearColor.b, 0.0f);
-
     // use the scene's framebuffer by default
     glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer());
     // ensure we render over the whole screen
     glViewport (0, 0, projection->getWidth (), projection->getHeight ());
 
+    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
     for (; cur != end; cur ++)
         (*cur)->render ();
-
-    // ensure we render over the whole screen
-    glViewport (0, 0, projection->getWidth (), projection->getHeight ());
 }
 
 void CScene::updateMouse (glm::ivec4 viewport)

+ 59 - 35
src/WallpaperEngine/Render/Objects/CImage.cpp

@@ -94,8 +94,8 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
         this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()
     );
 
-    GLfloat realWidth = this->m_texture->getRealWidth () / 2;
-    GLfloat realHeight = this->m_texture->getRealHeight () / 2;
+    GLfloat realWidth = this->m_texture->getRealWidth () / 2.0f;
+    GLfloat realHeight = this->m_texture->getRealHeight () / 2.0f;
 
     // build a list of vertices, these might need some change later (or maybe invert the camera)
     GLfloat sceneSpacePosition [] = {
@@ -216,32 +216,35 @@ void CImage::setup ()
     if (this->m_initialized)
         return;
 
-    // generate the main material used to render the image
-    this->m_material = new Effects::CMaterial (
-        new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
-        this->m_image->getMaterial ()
-    );
+    // TODO: SUPPORT PASSTHROUGH (IT'S A SHADER)
 
-    if (this->getImage ()->getEffects ().empty () == false)
     {
-        // generate the effects used by this material
-        auto cur = this->getImage ()->getEffects ().begin ();
-        auto end = this->getImage ()->getEffects ().end ();
+        // generate the main material used to render the image
+        this->m_material = new Effects::CMaterial (
+            new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
+            this->m_image->getMaterial ()
+        );
+
+        // add blendmode to the combos
+        auto cur = this->m_material->getPasses ().begin ();
+        auto end = this->m_material->getPasses ().end ();
 
         for (; cur != end; cur ++)
-            this->m_effects.emplace_back (new CEffect (this, *cur));
+            this->m_passes.push_back (*cur);
     }
 
     // prepare the passes list
-    if (this->getEffects ().empty () == false)
+    if (this->getImage ()->getEffects ().empty () == false)
     {
-        auto effectCur = this->getEffects ().begin ();
-        auto effectEnd = this->getEffects ().end ();
+        // generate the effects used by this material
+        auto cur = this->getImage ()->getEffects ().begin ();
+        auto end = this->getImage ()->getEffects ().end ();
 
-        for (; effectCur != effectEnd; effectCur ++)
+        for (; cur != end; cur ++)
         {
-            auto materialCur = (*effectCur)->getMaterials ().begin ();
-            auto materialEnd = (*effectCur)->getMaterials ().end ();
+            auto effect = new CEffect (this, *cur);
+            auto materialCur = effect->getMaterials ().begin ();
+            auto materialEnd = effect->getMaterials ().end ();
 
             for (; materialCur != materialEnd; materialCur ++)
             {
@@ -251,27 +254,52 @@ void CImage::setup ()
                 for (; passCur != passEnd; passCur ++)
                     this->m_passes.push_back (*passCur);
             }
+
+            this->m_effects.push_back (effect);
         }
     }
 
-    // add the final passes too
-    if (this->m_material->getPasses ().empty () == false)
+    if (this->m_image->getColorBlendMode () > 0)
     {
-        auto cur = this->m_material->getPasses ().begin ();
-        auto end = this->m_material->getPasses ().end ();
+        auto material = Core::Objects::Images::CMaterial::fromFile ("materials/util/effectpassthrough.json", this->getContainer ());
+
+        // effectpasshthrough only has one pass
+        (*material->getPasses ().begin ())->insertCombo ("BLENDMODE", this->m_image->getColorBlendMode ());
+
+        // generate the main material used to render the image
+        this->m_colorBlendMaterial = new Effects::CMaterial(
+            new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
+            material
+        );
+
+        // add blendmode to the combos
+        auto cur = this->m_colorBlendMaterial->getPasses ().begin ();
+        auto end = this->m_colorBlendMaterial->getPasses ().end ();
 
         for (; cur != end; cur ++)
             this->m_passes.push_back (*cur);
     }
 
-    // calculate full animation time (if any)
-    this->m_animationTime = 0.0f;
+    // if there's more than one pass the blendmode has to be moved from the beginning to the end
+    if (this->m_passes.size () > 1)
+    {
+        auto first = this->m_passes.begin ();
+        auto last = this->m_passes.rbegin ();
 
-    auto cur = this->getTexture ()->getFrames ().begin ();
-    auto end = this->getTexture ()->getFrames ().end ();
+        (*last)->getPass ()->setBlendingMode ((*first)->getPass ()->getBlendingMode ());
+        (*first)->getPass ()->setBlendingMode ("normal");
+    }
 
-    for (; cur != end; cur ++)
-        this->m_animationTime += (*cur)->frametime;
+    {
+        // calculate full animation time (if any)
+        this->m_animationTime = 0.0f;
+
+        auto cur = this->getTexture ()->getFrames ().begin ();
+        auto end = this->getTexture ()->getFrames ().end ();
+
+        for (; cur != end; cur++)
+            this->m_animationTime += (*cur)->frametime;
+    }
 
     this->m_initialized = true;
 }
@@ -299,8 +327,8 @@ void CImage::render ()
         return;
 
     // reset the framebuffers so the drawing always happens on the same order
-    this->m_currentMainFBO = this->m_subFBO;
-    this->m_currentSubFBO = this->m_mainFBO;
+    this->m_currentMainFBO = this->m_mainFBO;
+    this->m_currentSubFBO = this->m_subFBO;
 
     glColorMask (true, true, true, true);
 
@@ -334,12 +362,8 @@ 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)
+        else if (std::next (cur) == end && this->getImage ()->isVisible () == true)
         {
-            // do not draw to screen if the image is not visible
-            if (this->getImage ()->isVisible () == false)
-                return;
-
             spacePosition = *this->getSceneSpacePosition ();
             drawTo = this->getScene ()->getFBO ();
             projection = this->m_modelViewProjectionScreen;

+ 1 - 0
src/WallpaperEngine/Render/Objects/CImage.h

@@ -79,6 +79,7 @@ namespace WallpaperEngine::Render::Objects
 
         std::vector<CEffect*> m_effects;
         Effects::CMaterial* m_material;
+        Effects::CMaterial* m_colorBlendMaterial;
         std::vector <Effects::CPass*> m_passes;
 
         double m_animationTime;

+ 58 - 12
src/WallpaperEngine/Render/Objects/Effects/CPass.cpp

@@ -289,6 +289,11 @@ const CMaterial* CPass::getMaterial () const
     return this->m_material;
 }
 
+Core::Objects::Images::Materials::CPass* CPass::getPass ()
+{
+    return this->m_pass;
+}
+
 GLuint CPass::compileShader (Render::Shaders::Compiler* shader, GLuint type)
 {
     // reserve shaders in OpenGL
@@ -464,6 +469,7 @@ void CPass::setupUniforms ()
             if (bindCur != bindEnd)
             {
                 this->m_finalTextures.insert (std::make_pair ((*bindCur).first, nullptr));
+                bindCur ++;
             }
 
             if (cur != end)
@@ -472,26 +478,66 @@ void CPass::setupUniforms ()
                     this->m_finalTextures.insert (std::make_pair (index, *cur));
 
                 index ++;
+                cur ++;
             }
 
-            if (fragCur != fragEnd && (*fragCur).second != nullptr)
+            if (fragCur != fragEnd)
             {
-                this->m_finalTextures.insert (std::make_pair ((*fragCur).first, (*fragCur).second));
-            }
+                std::string textureName = (*fragCur).second;
 
-            if (vertCur != vertEnd && (*vertCur).second != nullptr)
-            {
-                this->m_finalTextures.insert (std::make_pair ((*vertCur).first, (*vertCur).second));
-            }
+                try
+                {
+                    // resolve the texture first
+                    ITexture* textureRef = nullptr;
+
+                    if (textureName.find ("_rt_") == 0)
+                    {
+                        textureRef = this->getMaterial ()->getEffect ()->findFBO (textureName);
+
+                        if (textureRef == nullptr)
+                            textureRef = this->getMaterial ()->getImage ()->getScene ()->findFBO (textureName);
+                    }
+                    else
+                        textureRef = this->getMaterial ()->getImage ()->getContainer ()->readTexture (textureName);
+
+                    this->m_finalTextures.insert (std::make_pair ((*fragCur).first, textureRef));
+                }
+                catch (std::runtime_error& ex)
+                {
+                    std::cerr << "Cannot resolve texture " << textureName << " for fragment shader: " << ex.what () << std::endl;
+                }
 
-            if (bindCur != bindEnd)
-                bindCur ++;
-            if (cur != end)
-                cur ++;
-            if (fragCur != fragEnd)
                 fragCur ++;
+            }
+
             if (vertCur != vertEnd)
+            {
+                std::string textureName = (*vertCur).second;
+
+                try
+                {
+                    // resolve the texture first
+                    ITexture* textureRef = nullptr;
+
+                    if (textureName.find ("_rt_") == 0)
+                    {
+                        textureRef = this->getMaterial ()->getEffect ()->findFBO (textureName);
+
+                        if (textureRef == nullptr)
+                            textureRef = this->getMaterial ()->getImage ()->getScene ()->findFBO (textureName);
+                    }
+                    else
+                        textureRef = this->getMaterial ()->getImage ()->getContainer ()->readTexture (textureName);
+
+                    this->m_finalTextures.insert (std::make_pair ((*vertCur).first, textureRef));
+                }
+                catch (std::runtime_error& ex)
+                {
+                    std::cerr << "Cannot resolve texture " << textureName << " for vertex shader: " << ex.what () << std::endl;
+                }
+
                 vertCur ++;
+            }
         }
     }
 

+ 1 - 0
src/WallpaperEngine/Render/Objects/Effects/CPass.h

@@ -24,6 +24,7 @@ namespace WallpaperEngine::Render::Objects::Effects
         void render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection);
 
         const CMaterial* getMaterial () const;
+        Core::Objects::Images::Materials::CPass* getPass ();
 
     private:
         enum UniformType

+ 3 - 40
src/WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -711,47 +711,10 @@ namespace WallpaperEngine::Render::Shaders
                         this->m_foundCombos->insert (std::make_pair <std::string, bool> (*combo, true));
                 }
 
-                if (textureName != data.end ())
-                {
-                    // also ensure that the textureName is loaded and we know about it
-                    ITexture* texture = this->m_container->readTexture ((*textureName).get <std::string> ());
-
-                    this->m_textures.insert (
-                            std::make_pair (index, texture)
-                    );
-                }
             }
-            else
-            {
-                // check for texture name too
-                if (textureName != data.end ())
-                {
-                    try
-                    {
-                        // also ensure that the textureName is loaded and we know about it
-                        ITexture* texture = this->m_container->readTexture ((*textureName).get <std::string> ());
-
-                        this->m_textures.insert (
-                            std::make_pair (index, texture)
-                        );
-                    }
-                    catch (CAssetLoadException& ex)
-                    {
-                        // cannot resolve texture
-                        // TODO: TAKE CARE OF FBOS
-                        this->m_textures.insert (
-                            std::make_pair (index, nullptr)
-                        );
-                    }
-                }
-                else
-                {
-                    this->m_textures.insert (
-                        std::make_pair (index, nullptr)
-                    );
-                }
 
-            }
+            if (textureName != data.end ())
+                this->m_textures.insert (std::make_pair (index, *textureName));
 
             // samplers are not saved, we can ignore them for now
             return;
@@ -798,7 +761,7 @@ namespace WallpaperEngine::Render::Shaders
         return this->m_combos;
     }
 
-    const std::map <int, ITexture*>& Compiler::getTextures () const
+    const std::map <int, std::string>& Compiler::getTextures () const
     {
         return this->m_textures;
     }

+ 2 - 2
src/WallpaperEngine/Render/Shaders/Compiler.h

@@ -91,7 +91,7 @@ namespace WallpaperEngine::Render::Shaders
         /**
          * @return The list of textures inferred from the shader's code
          */
-        const std::map <int, ITexture*>& getTextures () const;
+        const std::map <int, std::string>& getTextures () const;
 
     private:
         /**
@@ -263,7 +263,7 @@ namespace WallpaperEngine::Render::Shaders
          /**
           * List of textures that the shader expects (inferred from sampler2D and it's JSON data)
           */
-         std::map<int, ITexture*> m_textures;
+         std::map<int, std::string> m_textures;
          bool m_includesProcessed = false;
     };
 }