ソースを参照

Implemented proper dependency detection for images
Simplified texture decision graph and preload it so render is quicker
Improved material detecion on shaders

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

Alexis Maiquez 3 年 前
親
コミット
7b7d699371

+ 9 - 2
src/WallpaperEngine/Core/CScene.cpp

@@ -113,16 +113,23 @@ CScene* CScene::fromFile (const std::string& filename, CContainer* container)
     return scene;
 }
 
-const std::vector<CObject*>& CScene::getObjects () const
+const std::map<uint32_t, CObject*>& CScene::getObjects () const
 {
     return this->m_objects;
 }
+const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const
+{
+    return this->m_objectsByRenderOrder;
+}
 
 void CScene::insertObject (CObject* object)
 {
     /// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED
     if (object != nullptr)
-        this->m_objects.push_back (object);
+    {
+        this->m_objects.insert (std::make_pair (object->getId (), object));
+        this->m_objectsByRenderOrder.emplace_back (object);
+    }
 }
 
 CContainer* CScene::getContainer ()

+ 4 - 2
src/WallpaperEngine/Core/CScene.h

@@ -21,7 +21,8 @@ namespace WallpaperEngine::Core
     public:
         static CScene* fromFile (const std::string& filename, CContainer* container);
 
-        const std::vector<CObject*>& getObjects () const;
+        const std::map<uint32_t, CObject*>& getObjects () const;
+        const std::vector<CObject*>& getObjectsByRenderOrder () const;
 
         const FloatColor& getAmbientColor() const;
         const bool isBloom() const;
@@ -95,6 +96,7 @@ namespace WallpaperEngine::Core
         Scenes::CProjection* m_orthogonalProjection;
         FloatColor m_skylightColor;
 
-        std::vector<CObject*> m_objects;
+        std::map<uint32_t, CObject*> m_objects;
+        std::vector<CObject*> m_objectsByRenderOrder;
     };
 };

+ 8 - 6
src/WallpaperEngine/Core/Objects/CEffect.cpp

@@ -91,14 +91,16 @@ CEffect* CEffect::fromJSON (json data, Core::CObject* object, CContainer* contai
 
                         if ((*texturesCur).is_null () == true)
                         {
-                            if (object->is <CImage> () == false)
+                            if (textureNumber == 0)
                             {
-                                throw std::runtime_error ("unexpected null texture for non-image object");
-                            }
-
-                            CImage* image = object->as <CImage> ();
+                                CImage* image = object->as <CImage> ();
 
-                            texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ());
+                                texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ());
+                            }
+                            else
+                            {
+                                texture = "";
+                            }
                         }
                         else
                         {

+ 5 - 0
src/WallpaperEngine/Render/CObject.cpp

@@ -24,4 +24,9 @@ CScene* CObject::getScene () const
 CContainer* CObject::getContainer () const
 {
     return this->getScene ()->getContainer ();
+}
+
+const int CObject::getId () const
+{
+    return this->m_object->getId ();
 }

+ 1 - 0
src/WallpaperEngine/Render/CObject.h

@@ -22,6 +22,7 @@ namespace WallpaperEngine::Render
 
         CScene* getScene () const;
         CContainer* getContainer () const;
+        const int getId () const;
 
     protected:
         CObject (CScene* scene, std::string type, Core::CObject *object);

+ 64 - 22
src/WallpaperEngine/Render/CScene.cpp

@@ -24,10 +24,10 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
 
         for (; cur != end; cur ++)
         {
-            if ((*cur)->is<Core::Objects::CImage> () == false)
+            if ((*cur).second->is<Core::Objects::CImage> () == false)
                 continue;
 
-            glm::vec2 size = (*cur)->as <Core::Objects::CImage> ()->getSize ();
+            glm::vec2 size = (*cur).second->as <Core::Objects::CImage> ()->getSize ();
 
             scene->getOrthogonalProjection ()->setWidth (size.x);
             scene->getOrthogonalProjection ()->setHeight (size.y);
@@ -42,42 +42,84 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
     // setup framebuffers
     this->setupFramebuffers ();
 
-    auto cur = scene->getObjects ().begin ();
-    auto end = scene->getObjects ().end ();
+    // create all objects based off their dependencies
+    {
+
+        auto cur = scene->getObjects ().begin ();
+        auto end = scene->getObjects ().end ();
+
+        for (; cur != end; cur++)
+            this->createObject ((*cur).second);
+    }
+
+    // now setup the render order
+    auto cur = scene->getObjectsByRenderOrder ().begin ();
+    auto end = scene->getObjectsByRenderOrder ().end ();
 
     for (; cur != end; cur ++)
     {
-        CObject* object = nullptr;
+        auto obj = this->m_objects.find ((*cur)->getId ());
 
-        if ((*cur)->is<Core::Objects::CImage>() == true)
-        {
-            object = new Objects::CImage (this, (*cur)->as<Core::Objects::CImage>());
-        }
-        else if ((*cur)->is<Core::Objects::CSound>() == true)
-        {
-            object = new Objects::CSound (this, (*cur)->as<Core::Objects::CSound>());
-        }
+        // ignores not created objects like particle systems
+        if (obj == this->m_objects.end ())
+            continue;
 
-        if (object != nullptr)
-            this->m_objects.emplace_back (object);
+        this->m_objectsByRenderOrder.emplace_back ((*obj).second);
     }
 
-    auto objectsCur = this->m_objects.begin ();
-    auto objectsEnd = this->m_objects.end ();
+}
+
+Render::CObject* CScene::createObject (Core::CObject* object)
+{
+    Render::CObject* renderObject = nullptr;
+
+    // ensure the item is not loaded already
+    auto current = this->m_objects.find (object->getId ());
+
+    if (current != this->m_objects.end ())
+        return (*current).second;
+
+    // check dependencies too!
+    auto depCur = object->getDependencies ().begin ();
+    auto depEnd = object->getDependencies ().end ();
+
+    for (; depCur != depEnd; depCur ++)
+    {
+        // self-dependency is a possibility...
+        if ((*depCur) == object->getId ())
+            continue;
+
+        auto dep = this->getScene ()->getObjects ().find (*depCur);
+
+        if (dep != this->getScene ()->getObjects ().end ())
+            this->createObject ((*dep).second);
+    }
 
-    for (; objectsCur != objectsEnd; objectsCur ++)
+    if (object->is<Core::Objects::CImage>() == true)
     {
+        Objects::CImage* image = new Objects::CImage (this, object->as<Core::Objects::CImage>());
+
         try
         {
-            if ((*objectsCur)->is <Objects::CImage> () == true)
-                (*objectsCur)->as <Objects::CImage> ()->setup ();
+            image->setup ();
         }
         catch (std::runtime_error ex)
         {
             std::cerr << "Cannot setup image resource: " << std::endl;
             std::cerr << ex.what () << std::endl;
         }
+
+        renderObject = image;
     }
+    else if (object->is<Core::Objects::CSound>() == true)
+    {
+        renderObject = new Objects::CSound (this, object->as<Core::Objects::CSound>());
+    }
+
+    if (renderObject != nullptr)
+        this->m_objects.insert (std::make_pair (renderObject->getId (), renderObject));
+
+    return renderObject;
 }
 
 CCamera* CScene::getCamera () const
@@ -88,8 +130,8 @@ CCamera* CScene::getCamera () const
 void CScene::renderFrame (glm::ivec4 viewport)
 {
     auto projection = this->getScene ()->getOrthogonalProjection ();
-    auto cur = this->m_objects.begin ();
-    auto end = this->m_objects.end ();
+    auto cur = this->m_objectsByRenderOrder.begin ();
+    auto end = this->m_objectsByRenderOrder.end ();
 
     // ensure the virtual mouse position is up to date
     this->updateMouse (viewport);

+ 4 - 1
src/WallpaperEngine/Render/CScene.h

@@ -32,8 +32,11 @@ namespace WallpaperEngine::Render
         static const std::string Type;
 
     private:
+        Render::CObject* createObject (Core::CObject* object);
+
         CCamera* m_camera;
-        std::vector<CObject*> m_objects;
+        std::map<int, CObject*> m_objects;
+        std::vector<CObject*> m_objectsByRenderOrder;
         glm::vec2 m_mousePosition;
     };
 }

+ 4 - 0
src/WallpaperEngine/Render/Objects/CImage.cpp

@@ -212,6 +212,10 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
 
 void CImage::setup ()
 {
+    // do not double-init stuff, that's bad!
+    if (this->m_initialized)
+        return;
+
     // generate the main material used to copy the image to the correct texture
     this->m_copyMaterial = new Effects::CMaterial (
         new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),

+ 59 - 91
src/WallpaperEngine/Render/Objects/Effects/CPass.cpp

@@ -170,68 +170,22 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
         }
     }
 
+    // first texture is a bit special as we have to take what comes from the chain first
     glActiveTexture (GL_TEXTURE0);
     glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture));
-    int lastTextureIndex = 0;
 
-    // first bind the textures to their sampler place
+    // continue on the map from the second texture
+    if (this->m_finalTextures.empty () == false)
     {
-        // set texture slots for the shader
-        auto cur = this->m_textures.begin ();
-        auto end = this->m_textures.end ();
-
-        for (int index = 1; cur != end; cur ++, index ++)
-        {
-            texture = this->resolveTexture ((*cur), index, input);
-
-            glActiveTexture (GL_TEXTURE0 + index);
-            glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
-            // increase the number of textures counter
-            lastTextureIndex ++;
-        }
-    }
-
-    {
-        // load the extra textures needed (if any) from the shader
-        auto cur = this->m_fragShader->getTextures ().begin ();
-        auto end = this->m_fragShader->getTextures ().end ();
+        auto cur = this->m_finalTextures.begin ();
+        auto end = this->m_finalTextures.end ();
 
         for (; cur != end; cur ++)
         {
-            if ((*cur).first <= lastTextureIndex)
-                continue;
-
             texture = this->resolveTexture ((*cur).second, (*cur).first, input);
 
-            if (texture == nullptr)
-                continue;
-
-            // set the active texture index
             glActiveTexture (GL_TEXTURE0 + (*cur).first);
-            // bind the correct texture here
-            glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
-        }
-    }
-
-    {
-        // load the extra textures needed (if any) from the shader
-        auto cur = this->m_vertShader->getTextures ().begin ();
-        auto end = this->m_vertShader->getTextures ().end ();
-
-        for (; cur != end; cur ++)
-        {
-            if ((*cur).first <= lastTextureIndex)
-                continue;
-
-            texture = this->resolveTexture ((*cur).second, (*cur).first, input);
-
-            if (texture == nullptr)
-                continue;
-
-            // set the active texture index
-            glActiveTexture (GL_TEXTURE0 + (*cur).first);
-            // bind the correct texture here
-            glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
+            glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
         }
     }
 
@@ -456,62 +410,69 @@ void CPass::setupUniforms ()
     this->addUniform ("g_Texture7", 7);
     this->addUniform ("g_Texture0Resolution", texture->getResolution ());
 
-    int lastTextureIndex = 0;
-    // register the extra texture resolutions
+    // do the real, final texture setup for the whole process
     {
         auto cur = this->m_textures.begin ();
         auto end = this->m_textures.end ();
-
-        for (int index = 1; cur != end; cur ++, index ++)
+        auto fragCur = this->m_fragShader->getTextures ().begin ();
+        auto fragEnd = this->m_fragShader->getTextures ().end ();
+        auto vertCur = this->m_vertShader->getTextures ().begin ();
+        auto vertEnd = this->m_vertShader->getTextures ().end ();
+        auto bindCur = this->m_material->getMaterial ()->getTextureBinds ().begin ();
+        auto bindEnd = this->m_material->getMaterial ()->getTextureBinds ().end ();
+
+        int index = 1;
+
+        // technically m_textures should have the right amount of textures
+        // but better be safe than sorry
+        while (bindCur != bindEnd || cur != end || fragCur != fragEnd || vertCur != vertEnd)
         {
-            std::ostringstream namestream;
-
-            namestream << "g_Texture" << index << "Resolution";
-
-            texture = this->resolveTexture ((*cur), index, texture);
-            this->addUniform (namestream.str (), texture->getResolution ());
-            lastTextureIndex ++;
-        }
-    }
+            if (bindCur != bindEnd)
+            {
+                this->m_finalTextures.insert (std::make_pair ((*bindCur).first, nullptr));
+            }
 
-    // registers the extra texture resolutions from the shader
-    {
-        auto cur = this->m_fragShader->getTextures ().begin ();
-        auto end = this->m_fragShader->getTextures ().end ();
+            if (cur != end)
+            {
+                if ((*cur) != nullptr)
+                    this->m_finalTextures.insert (std::make_pair (index, *cur));
 
-        for (; cur != end; cur ++)
-        {
-            if ((*cur).first <= lastTextureIndex)
-                continue;
+                index ++;
+            }
 
-            std::ostringstream namestream;
+            if (fragCur != fragEnd && (*fragCur).second != nullptr)
+            {
+                this->m_finalTextures.insert (std::make_pair ((*fragCur).first, (*fragCur).second));
+            }
 
-            namestream << "g_Texture" << (*cur).first << "Resolution";
+            if (vertCur != vertEnd && (*vertCur).second != nullptr)
+            {
+                this->m_finalTextures.insert (std::make_pair ((*vertCur).first, (*vertCur).second));
+            }
 
-            texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
-            if (texture != nullptr)
-                this->addUniform (namestream.str (), texture->getResolution ());
+            if (bindCur != bindEnd)
+                bindCur ++;
+            if (cur != end)
+                cur ++;
+            if (fragCur != fragEnd)
+                fragCur ++;
+            if (vertCur != vertEnd)
+                vertCur ++;
         }
     }
 
-    // registers the extra texture resolutions from the shader
     {
-        auto cur = this->m_vertShader->getTextures ().begin ();
-        auto end = this->m_vertShader->getTextures ().end ();
+        auto cur = this->m_finalTextures.begin ();
+        auto end = this->m_finalTextures.end ();
 
         for (; cur != end; cur ++)
         {
-            if ((*cur).first <= lastTextureIndex)
-                continue;
-
             std::ostringstream namestream;
 
             namestream << "g_Texture" << (*cur).first << "Resolution";
 
             texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
-
-            if (texture != nullptr)
-                this->addUniform (namestream.str (), texture->getResolution ());
+            this->addUniform (namestream.str (), texture->getResolution ());
         }
     }
 
@@ -599,16 +560,23 @@ void CPass::setupTextures ()
             {
                 this->m_fbos.insert (std::make_pair (index, fbo));
                 this->m_textures.emplace_back (
-                    nullptr
+                    fbo
                 );
             }
             // _rt_texture
         }
         else
         {
-            this->m_textures.emplace_back (
-                this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
-            );
+            if ((*cur) == "")
+            {
+                this->m_textures.emplace_back (nullptr);
+            }
+            else
+            {
+                this->m_textures.emplace_back (
+                    this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
+                );
+            }
         }
     }
 }

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

@@ -95,6 +95,11 @@ namespace WallpaperEngine::Render::Objects::Effects
         std::map<std::string, UniformEntry*> m_uniforms;
         glm::mat4 m_modelViewProjectionMatrix;
 
+        /**
+         * Contains the final map of textures to be used
+         */
+        std::map <int, ITexture*> m_finalTextures;
+
         Render::Shaders::Compiler* m_fragShader;
         Render::Shaders::Compiler* m_vertShader;
 

+ 31 - 12
src/WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -12,6 +12,7 @@
 #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
 #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h>
 
+#include "WallpaperEngine/Assets/CAssetLoadException.h"
 #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
 #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
 #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
@@ -667,13 +668,13 @@ namespace WallpaperEngine::Render::Shaders
             // if needed
             auto combo = data.find ("combo");
             auto textureName = data.find ("default");
+            // extract the texture number from the name
+            char value = name.at (std::string("g_Texture").length ());
+            // now convert it to integer
+            int index = value - '0';
 
             if (combo != data.end ())
             {
-                // extract the texture number from the name
-                char value = name.at (std::string("g_Texture").length ());
-                // now convert it to integer
-                int index = value - '0';
 
                 // if the texture exists, add the combo
                 if (this->m_passTextures.size () > index)
@@ -698,16 +699,34 @@ namespace WallpaperEngine::Render::Shaders
             }
             else
             {
-                // material name is not resolved on compile time, but passes will do it after
+                // 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> ());
 
-                // extract the texture number from the name
-                char value = name.at (std::string("g_Texture").length ());
-                // now convert it to integer
-                int index = value - '0';
+                        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)
+                    );
+                }
 
-                this->m_textures.insert (
-                    std::make_pair (index, nullptr)
-                );
             }
 
             // samplers are not saved, we can ignore them for now