ソースを参照

~ Moved Shader compiler to the proper, new namespace

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
Alexis Maiquez 7 年 前
親
コミット
5c56e0860b

+ 2 - 2
CMakeLists.txt

@@ -20,8 +20,8 @@ include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR
 add_executable(
         wallengine
         main.cpp
-        WallpaperEngine/shaders/compiler.h
-        WallpaperEngine/shaders/compiler.cpp
+        WallpaperEngine/Render/Shaders/Compiler.h
+        WallpaperEngine/Render/Shaders/Compiler.cpp
         WallpaperEngine/project.cpp
         WallpaperEngine/project.h
         WallpaperEngine/scene.cpp

+ 635 - 0
WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -0,0 +1,635 @@
+#include <irrlicht/irrlicht.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+// filesystem
+#include <WallpaperEngine/FileSystem/utils.h>
+
+// video engine
+#include <WallpaperEngine/Irrlicht/Irrlicht.h>
+
+// shader compiler
+#include <WallpaperEngine/Render/Shaders/Compiler.h>
+#include <WallpaperEngine/Core/Core.h>
+
+namespace WallpaperEngine::Render::Shaders
+{
+    Compiler::Compiler (irr::io::path& file, Type type, std::map<std::string, int>* combos, bool recursive)
+    {
+        this->m_recursive = recursive;
+        this->m_combos = combos;
+
+        // begin with an space so it gets ignored properly on parse
+        if (recursive == false)
+        {
+            // compatibility layer for OpenGL shaders
+            this->m_content =   "#version 120\n"
+                                "#define highp\n"
+                                "#define mediump\n"
+                                "#define lowp\n"
+                                "#define mul(x, y) (y * x)\n"
+                                "#define frac fract\n"
+                                "#define CAST2(x) (vec2(x))\n"
+                                "#define CAST3(x) (vec3(x))\n"
+                                "#define CAST4(x) (vec4(x))\n"
+                                "#define CAST3X3(x) (mat3(x))\n"
+                                "#define saturate(x) (clamp(x, 0.0, 1.0))\n"
+                                "#define texSample2D texture2D\n"
+                                "#define texSample2DLod texture2DLod\n"
+                                "#define texture2DLod texture2D\n"
+                                "#define atan2 atan\n"
+                                "#define ddx dFdx\n"
+                                "#define ddy(x) dFdy(-(x))\n"
+                                "#define GLSL 1\n\n";
+
+            std::map<std::string, int>::const_iterator cur = this->m_combos->begin ();
+            std::map<std::string, int>::const_iterator end = this->m_combos->end ();
+
+            for (; cur != end; cur ++)
+            {
+                this->m_content += "#define " + (*cur).first + " " + std::to_string ((*cur).second) + "\n";
+            }
+        }
+        else
+        {
+            this->m_content = "";
+        }
+
+        this->m_content.append (WallpaperEngine::FileSystem::loadFullFile (file));
+
+        // append file content
+        this->m_type = type;
+
+        this->m_file = file;
+    }
+
+    bool Compiler::peekString(std::string str, std::string::const_iterator& it)
+    {
+        std::string::const_iterator check = str.begin();
+        std::string::const_iterator cur = it;
+
+        while (cur != this->m_content.end () && check != str.end ())
+        {
+            if (*cur != *check) return false;
+
+            cur ++; check ++;
+        }
+
+        if (cur == this->m_content.end ())
+        {
+            return false;
+        }
+
+        if (check != str.end ())
+        {
+            return false;
+        }
+
+        it = cur;
+
+        return true;
+    }
+
+    bool Compiler::expectSemicolon (std::string::const_iterator& it)
+    {
+        if (*it != ';')
+        {
+            this->m_error = true;
+            this->m_errorInfo = "Expected semicolon but got " + *it;
+            return false;
+        }
+
+        it ++;
+
+        return true;
+    }
+
+    void Compiler::ignoreSpaces(std::string::const_iterator &it)
+    {
+        while (it != this->m_content.end() && (*it == ' ' || *it == '\t')) it ++;
+    }
+
+    void Compiler::ignoreUpToNextLineFeed (std::string::const_iterator& it)
+    {
+        while (it != this->m_content.end() && *it != '\n') it ++;
+    }
+
+    void Compiler::ignoreUpToBlockCommentEnd (std::string::const_iterator& it)
+    {
+        while (it != this->m_content.end() && this->peekString ("*/", it) == false) it ++;
+    }
+
+    std::string Compiler::extractType (std::string::const_iterator& it)
+    {
+        std::vector<std::string>::const_iterator cur = sTypes.begin ();
+        std::vector<std::string>::const_iterator end = sTypes.end ();
+
+        while (cur != end)
+        {
+            if (this->peekString (*cur, it) == true)
+            {
+                return *cur;
+            }
+
+            cur ++;
+        }
+
+        this->m_error = true;
+        this->m_errorInfo = "Expected type";
+        return "";
+    }
+
+    std::string Compiler::extractName (std::string::const_iterator& it)
+    {
+        std::string::const_iterator cur = it;
+        std::string::const_iterator begin = cur;
+
+        // first character has to be a valid alphabetic characer
+        if (this->isChar (cur) == false && *cur != '_')
+        {
+            this->m_error = true;
+            this->m_errorInfo = "Expected name doesn't start with a valid character";
+            return "";
+        }
+
+        cur ++;
+
+        while (cur != this->m_content.end () && (this->isChar (cur) == true || *cur == '_' || this->isNumeric (cur) == true)) cur ++;
+
+        it = cur;
+
+        return std::string (begin, cur);
+    }
+
+    bool Compiler::isChar (std::string::const_iterator& it)
+    {
+        return ((*it) >= 'A' && (*it) <= 'Z') || ((*it) >= 'a' && (*it) <= 'z');
+    }
+
+    bool Compiler::isNumeric (std::string::const_iterator& it)
+    {
+        return (*it) >= '0' && (*it) <= '9';
+    }
+
+    std::string Compiler::extractQuotedValue(std::string::const_iterator& it)
+    {
+        std::string::const_iterator cur = it;
+
+        if (*cur != '"')
+        {
+            m_error = true;
+            m_errorInfo = "Expected opening \" but got " + (*cur);
+            return "";
+        }
+
+        cur ++;
+
+        while (cur != this->m_content.end () && *cur != '\n' && *cur != '"') cur ++;
+
+        if (cur == this->m_content.end ())
+        {
+            m_error = true;
+            m_errorInfo = "Expected closing \" not found";
+            it = cur;
+            return "";
+        }
+
+        std::string filename = std::string (++it, cur);
+
+        it = ++cur;
+
+        return filename;
+    }
+
+    std::string Compiler::lookupShaderFile (std::string filename)
+    {
+        // get file information
+        irr::io::path shader = ("shaders/" + filename).c_str ();
+
+        if (shader == "")
+        {
+            this->m_error = true;
+            this->m_errorInfo = "Cannot find file " + filename + " to include";
+            return "";
+        }
+
+        // now compile the new shader
+        // do not include the default header (as it's already included in the parent)
+        Compiler loader (shader, this->m_type, this->m_combos, true);
+
+        return loader.precompile ();
+    }
+
+    std::string Compiler::lookupReplaceSymbol (std::string symbol)
+    {
+        std::map<std::string, std::string>::const_iterator cur = sVariableReplacement.begin ();
+        std::map<std::string, std::string>::const_iterator end = sVariableReplacement.end ();
+
+        while (cur != end)
+        {
+            if (cur->first == symbol)
+            {
+                return cur->second;
+            }
+
+            cur ++;
+        }
+
+        // if there is no replacement, return the original
+        return symbol;
+    }
+
+    std::string Compiler::precompile()
+    {
+    #define BREAK_IF_ERROR if (this->m_error == true) { WallpaperEngine::Irrlicht::device->getLogger ()->log ("ERROR PRE-COMPILING SHADER", irr::ELL_ERROR); WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_errorInfo.c_str (), irr::ELL_ERROR); return ""; }
+        // parse the shader and find #includes and such things and translate them to the correct name
+        // also remove any #version definition to prevent errors
+        std::string::const_iterator it = this->m_content.begin ();
+
+        // reset error indicator
+        this->m_error = false;
+        this->m_errorInfo = "";
+
+        // search preprocessor macros and parse them
+        while (it != this->m_content.end () && this->m_error == false)
+        {
+            if (*it == ' ' || *it == '\t' || *it == '\n' || *it == '\r' || *it == '\0' || *it == '{' || *it == '}' || *it == '[' || *it == ']' || *it == '.')
+            {
+                this->m_compiledContent += *it;
+                it ++;
+            }
+            else if (*it == '#')
+            {
+                if (this->peekString ("#include", it) == true)
+                {
+                    std::string filename = "";
+
+                    // ignore whitespaces
+                    this->ignoreSpaces (it); BREAK_IF_ERROR
+                    // extract value between quotes
+                    filename = this->extractQuotedValue (it); BREAK_IF_ERROR
+
+                    // try to find the file first
+                    this->m_compiledContent += "// begin of included from file " + filename + "\r\n";
+                    this->m_compiledContent += this->lookupShaderFile (filename);
+                    this->m_compiledContent += "\r\n// end of included from file " + filename + "\r\n";
+                }
+                else
+                {
+                    this->m_compiledContent += '#';
+                    it ++;
+                }
+            }
+            else if (*it == 'u')
+            {
+                // uniforms might have extra information for their values
+                if (this->peekString ("uniform", it) == true)
+                {
+                    this->ignoreSpaces (it);
+                    std::string type = this->extractType (it); BREAK_IF_ERROR
+                    this->ignoreSpaces (it);
+                    std::string name = this->extractName (it); BREAK_IF_ERROR
+                    this->ignoreSpaces (it);
+                    this->expectSemicolon (it); BREAK_IF_ERROR
+                    this->ignoreSpaces (it);
+
+                    // check if there is any actual extra information and parse it
+                    if (this->peekString ("//", it) == true)
+                    {
+                        this->ignoreSpaces (it);
+                        std::string::const_iterator begin = it;
+                        this->ignoreUpToNextLineFeed (it);
+
+                        std::string configuration; configuration.append (begin, it);
+
+                        // parse the parameter information
+                        this->parseParameterConfiguration (type, name, configuration); BREAK_IF_ERROR
+                        this->m_compiledContent += "uniform " + type + " " + name + "; // " + configuration;
+                    }
+                    else
+                    {
+                        this->m_compiledContent += "uniform " + type + " " + name + ";";
+                    }
+                }
+            }
+            else if (*it == 'a')
+            {
+                // find attribute definitions
+                if (this->peekString ("attribute", it) == true)
+                {
+                    this->ignoreSpaces (it);
+                    std::string type = this->extractType (it); BREAK_IF_ERROR
+                    this->ignoreSpaces (it);
+                    std::string name = this->extractName (it); BREAK_IF_ERROR
+                    this->ignoreSpaces (it);
+                    this->expectSemicolon (it); BREAK_IF_ERROR
+
+                    this->m_compiledContent += "// attribute";
+                    this->m_compiledContent += " " + type + " ";
+                    this->m_compiledContent += name;
+                    this->m_compiledContent += "; /* replaced by " + this->lookupReplaceSymbol (name) + " */";
+                }
+                else
+                {
+                    // check for types first
+                    std::string type = this->extractType (it);
+
+                    // types not found, try names
+                    if (this->m_error == false)
+                    {
+                        this->m_compiledContent += type;
+                    }
+                    else
+                    {
+                        this->m_error = false;
+                        std::string name = this->extractName (it);
+
+                        if (this->m_error == false)
+                        {
+                            // check if the name is a translated one or not
+                            this->m_compiledContent += this->lookupReplaceSymbol (name);
+                        }
+                        else
+                        {
+                            this->m_error = false;
+                            this->m_compiledContent += *it;
+                            it ++;
+                        }
+                    }
+                }
+            }
+            else if (*it == '/')
+            {
+                if (this->peekString ("//", it) == true)
+                {
+                    std::string::const_iterator begin = it - 2;
+                    // is there a COMBO mark to take care of?
+                    this->ignoreSpaces (it);
+
+                    if (this->peekString ("[COMBO]", it) == true)
+                    {
+                        // parse combo json data to define the proper variables
+                        this->ignoreSpaces (it);
+                        begin = it;
+                        this->ignoreUpToNextLineFeed (it);
+
+                        std::string configuration; configuration.append (begin, it);
+
+                        this->m_compiledContent += "// [COMBO] " + configuration;
+
+                        this->parseComboConfiguration (configuration); BREAK_IF_ERROR;
+                    }
+                    else if (this->peekString ("[COMBO_OFF]", it) == true)
+                    {
+                        // parse combo json data to define the proper variables
+                        this->ignoreSpaces (it);
+                        begin = it;
+                        this->ignoreUpToNextLineFeed (it);
+
+                        std::string configuration; configuration.append (begin, it);
+
+                        this->m_compiledContent += "// [COMBO_OFF] " + configuration;
+
+                        this->parseComboConfiguration (configuration); BREAK_IF_ERROR;
+                    }
+                    else
+                    {
+                        this->ignoreUpToNextLineFeed (it);
+                        this->m_compiledContent.append (begin, it);
+                    }
+                }
+                else if (this->peekString ("/*", it) == true)
+                {
+                    std::string::const_iterator begin = it - 2;
+                    this->ignoreUpToBlockCommentEnd (it);
+                    this->m_compiledContent.append (begin, it);
+                }
+                else
+                {
+                    this->m_compiledContent += *it;
+                    it ++;
+                }
+            }
+            else
+            {
+                // check for types first
+                std::string type = this->extractType (it);
+
+                // types not found, try names
+                if (this->m_error == false)
+                {
+                    this->m_compiledContent += type;
+                }
+                else
+                {
+                    this->m_error = false;
+                    std::string name = this->extractName (it);
+
+                    if (this->m_error == false)
+                    {
+                        // check if the name is a translated one or not
+                        this->m_compiledContent += this->lookupReplaceSymbol (name);
+                    }
+                    else
+                    {
+                        this->m_error = false;
+                        this->m_compiledContent += *it;
+                        it ++;
+                    }
+                }
+            }
+        }
+
+        if (this->m_recursive == false)
+        {
+            WallpaperEngine::Irrlicht::device->getLogger ()->log ("Compiled shader output for", this->m_file.c_str ());
+            WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_compiledContent.c_str ());
+        }
+
+        return this->m_compiledContent;
+    #undef BREAK_IF_ERROR
+    }
+
+    void Compiler::parseComboConfiguration (const std::string& content)
+    {
+        json data = json::parse (content);
+        json::const_iterator combo = data.find ("combo");
+        json::const_iterator defvalue = data.find ("default");
+
+        // add line feed just in case
+        this->m_compiledContent += "\n";
+
+        if (combo == data.end () || defvalue == data.end ())
+        {
+            WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information", irr::ELL_ERROR);
+            return;
+        }
+
+        // check the combos
+        std::map<std::string, int>::const_iterator entry = this->m_combos->find ((*combo).get <std::string> ());
+
+        // if the combo was not found in the predefined values this means that the default value in the JSON data can be used
+        // so only define the ones that are not already defined
+        if (entry == this->m_combos->end ())
+        {
+            // if no combo is defined just load the default settings
+            if ((*defvalue).is_number_float ())
+            {
+                this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + std::to_string ((*defvalue).get <irr::f32> ()) + "\n";
+            }
+            else if ((*defvalue).is_number_integer ())
+            {
+                this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + std::to_string ((*defvalue).get <irr::s32> ()) + "\n";
+            }
+            else if ((*defvalue).is_string ())
+            {
+                this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + (*defvalue).get <std::string> () + "\n";
+            }
+            else
+            {
+                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information, unknown type", irr::ELL_ERROR);
+            }
+        }
+    }
+
+    void Compiler::parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content)
+    {
+        json data = json::parse (content);
+        json::const_iterator material = data.find ("material");
+        json::const_iterator defvalue = data.find ("default");
+        json::const_iterator range = data.find ("range");
+
+        // this is not a real parameter
+        if (material == data.end () || defvalue == data.end ())
+        {
+            if (type != "sampler2D")
+                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse parameter info for ", name.c_str (), irr::ELL_ERROR);
+
+            return;
+        }
+
+        ShaderParameter* param = new ShaderParameter;
+
+        param->identifierName = (*material).get <std::string> ();
+        param->variableName = name;
+        param->type = type;
+
+        if (type == "vec4" || type == "vec3")
+        {
+            if ((*defvalue).is_string () == false)
+            {
+                irr::core::vector3df* vector = new irr::core::vector3df;
+
+                vector->X = 0.0f;
+                vector->Y = 0.0f;
+                vector->Z = 0.0f;
+
+                param->defaultValue = vector;
+            }
+            else
+            {
+                irr::core::vector3df tmp = WallpaperEngine::Core::ato3vf ((*defvalue).get <std::string> ().c_str ());
+                irr::core::vector3df* vector = new irr::core::vector3df;
+
+                vector->X = tmp.X;
+                vector->Y = tmp.Y;
+                vector->Z = tmp.Z;
+
+                param->defaultValue = vector;
+            }
+        }
+        else if (type == "vec2")
+        {
+            if ((*defvalue).is_string () == false)
+            {
+                irr::core::vector2df* vector = new irr::core::vector2df;
+
+                vector->X = 0.0f;
+                vector->Y = 0.0f;
+
+                param->defaultValue = vector;
+            }
+            else
+            {
+                irr::core::vector2df* vector = new irr::core::vector2df;
+                irr::core::vector2df tmp = WallpaperEngine::Core::ato2vf ((*defvalue).get <std::string> ().c_str ());
+
+                vector->X = tmp.X;
+                vector->Y = tmp.Y;
+
+                param->defaultValue = vector;
+            }
+        }
+        else if (type == "float")
+        {
+            if ((*defvalue).is_number () == false)
+            {
+                irr::f32* val = new irr::f32;
+
+                *val = 0.0f;
+
+                param->defaultValue = val;
+
+            }
+            else
+            {
+                irr::f32* val = new irr::f32;
+
+                *val = (*defvalue).get <irr::f32> ();
+
+                param->defaultValue = val;
+            }
+        }
+        else if (type == "sampler2D")
+        {
+            // samplers are not saved, we can ignore them for now
+            delete param;
+            return;
+        }
+        else
+        {
+            this->m_error = true;
+            this->m_errorInfo = "Unknown parameter type: " + type + " for " + param->identifierName + " (" + param->variableName + ")";
+            return;
+        }
+
+        this->m_parameters.push_back (param);
+    }
+
+    Compiler::ShaderParameter* Compiler::findParameter (std::string identifier)
+    {
+        std::vector<ShaderParameter*>::const_iterator cur = this->m_parameters.begin ();
+        std::vector<ShaderParameter*>::const_iterator end = this->m_parameters.end ();
+
+        for (; cur != end; cur ++)
+        {
+            if ((*cur)->identifierName == identifier)
+            {
+                return (*cur);
+            }
+        }
+
+        return nullptr;
+    }
+
+    std::vector <Compiler::ShaderParameter*>& Compiler::getParameters ()
+    {
+        return this->m_parameters;
+    }
+
+    std::map<std::string, std::string>  Compiler::sVariableReplacement =
+    {
+        // attribute vec3 a_position
+        {"a_Position", "gl_Vertex.xyz"},
+        // attribute vec2 a_TexCoord
+        {"a_TexCoord", "gl_MultiTexCoord0.xy"},
+        // attribute vec3 a_Normal
+        {"a_Normal", "gl_Normal.xyz"}
+    };
+
+    std::vector<std::string> Compiler::sTypes =
+    {
+        "vec4", "vec3", "vec2", "float", "sampler2D", "mat4"
+    };
+}

+ 240 - 0
WallpaperEngine/Render/Shaders/Compiler.h

@@ -0,0 +1,240 @@
+#pragma once
+
+#include <irrlicht/irrlicht.h>
+#include <iostream>
+#include <vector>
+#include <map>
+#include <nlohmann/json.hpp>
+
+#include <WallpaperEngine/FileSystem/utils.h>
+
+namespace WallpaperEngine::Render::Shaders
+{
+    using json = nlohmann::json;
+
+    /**
+     * A basic shader loader that adds basic function definitions to every loaded shader
+     */
+    class Compiler
+    {
+    public:
+        /**
+         * Basic struct used to define all the shader variables
+         * the compiler will replace in pre-processing time
+         * to make sure the shaders compile under OpenGL
+         */
+        struct VariableReplacement
+        {
+            const char* original;
+            const char* replacement;
+        };
+
+        struct TypeName
+        {
+            const char* name;
+            int size;
+        };
+
+        struct ShaderParameter
+        {
+            std::string type;
+            std::string variableName;
+            std::string identifierName;
+            void* defaultValue;
+            void* range [2];
+        };
+
+        /**
+         * Types of shaders
+         */
+        enum Type
+        {
+            Type_Vertex = 0,
+            Type_Pixel = 1,
+        };
+
+        /**
+         * List of variables to replace when pre-process is performed
+         */
+        static std::map<std::string, std::string> sVariableReplacement;
+        /**
+         * Types of variables the pre-processor understands
+         */
+        static std::vector<std::string> sTypes;
+
+        /**
+         * Compiler constructor, loads the given shader file and prepares
+         * the pre-processing and compilation of the shader, adding
+         * required definitions if needed
+         *
+         * @param file The file to load
+         * @param type The type of shader
+         * @param recursive Whether the compiler should add base definitions or not
+         */
+        Compiler (irr::io::path& file, Type type, std::map<std::string, int>* combos, bool recursive = false);
+        /**
+         * Performs the actual pre-compilation/pre-processing over the shader files
+         * This step is kinda big, replaces variables names on sVariableReplacement,
+         * ensures #include directives are correctly handled
+         * and takes care of attribute comments for the wallpaper engine specifics
+         *
+         * @return The shader contents ready to be used by OpenGL
+         */
+        std::string precompile ();
+        /**
+         * Searches the list of parameters available for the parameter with the given value
+         *
+         * @param identifier The identifier to search for
+         * @return The shader information
+         */
+        ShaderParameter* findParameter (std::string identifier);
+
+        /**
+         * @return The list of parameters available for this shader with their default values
+         */
+        std::vector <ShaderParameter*>& getParameters ();
+
+    private:
+        /**
+         * Checks if there is "str" in the current position without advancing the
+         * iterator in use
+         *
+         * @param str The string to check for
+         * @param it  The position to start checking at
+         *
+         * @return
+         */
+        bool peekString (std::string str, std::string::const_iterator& it);
+        /**
+         * Checks for a semicolon as current character, advancing the iterator
+         * after finding it, otherwise returns an error
+         *
+         * @param it The position where to expect the semicolon
+         *
+         * @return
+         */
+        bool expectSemicolon (std::string::const_iterator& it);
+        /**
+         * Ignores contiguous space characters in the string advancing the iterator
+         * until the first non-space character
+         *
+         * @param it The iterator to increase
+         */
+        void ignoreSpaces (std::string::const_iterator& it);
+        /**
+         * Ignores all characters until next line-fee (\n) advancing the interator
+         *
+         * @param it The iterator to increase
+         */
+        void ignoreUpToNextLineFeed (std::string::const_iterator& it);
+        /**
+         * Ignores all characters until a block comment end is found, advancing the iterator
+         *
+         * @param it The iterator to increase
+         */
+        void ignoreUpToBlockCommentEnd (std::string::const_iterator& it);
+        /**
+         * Parses the current position as a variable type, extracts it and compares it
+         * to the registered types in the pre-processor, returning it's name if valid
+         * increasing the iterator at the same time
+         *
+         * @param it The position to extract it from
+         *
+         * @return The type name
+         */
+        std::string extractType (std::string::const_iterator& it);
+        /**
+         * Parses the current position as a variable name, extractig it's name and
+         * increasing the iterator as the name is extracted
+         *
+         * @param it The position to start extracting the variable name from
+         *
+         * @return The variable name
+         */
+        std::string extractName (std::string::const_iterator& it);
+        /**
+         * Parses the current position as a quoted value, extracting it's value
+         * and increasing the iterator at the same time
+         *
+         * @param it The position to start extracting the value from
+         *
+         * @return The value
+         */
+        std::string extractQuotedValue (std::string::const_iterator& it);
+        /**
+         * Tries to find the given shader file and compile it
+         *
+         * @param filename The shader's filename
+         *
+         * @return The compiled contents
+         */
+        std::string lookupShaderFile (std::string filename);
+        /**
+         * Searches for the given symbol in the replace table
+         *
+         * @param symbol The symbol to look for
+         *
+         * @return The symbol it should be replaced with
+         */
+        std::string lookupReplaceSymbol (std::string symbol);
+
+        /**
+         * @return Whether the character in the current position is a character or not
+         */
+        bool isChar (std::string::const_iterator& it);
+        /**
+         * @return Whether the character in the current position is a number or not
+         */
+        bool isNumeric (std::string::const_iterator& it);
+        /**
+         * Parses a COMBO value to add the proper define to the code
+         *
+         * @param content The parameter configuration
+         */
+        void parseComboConfiguration (const std::string& content);
+        /**
+         * Parses a parameter extra metadata created by wallpaper engine
+         *
+         * @param type The type of variable to parse
+         * @param name The name of the variable in the shader (for actual variable declaration)
+         * @param content The parameter configuration
+         */
+        void parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content);
+        /**
+         * The shader file this instance is loading
+         */
+        irr::io::path m_file;
+        /**
+         * The original file content
+         */
+        std::string m_content;
+        /**
+         * The final, compiled content ready to be used by OpenGL
+         */
+        std::string m_compiledContent;
+        /**
+         * Whether there was any kind of error in the compilation or not
+         */
+        bool m_error;
+        /**
+         * Extra information about the error (if any)
+         */
+        std::string m_errorInfo;
+        /**
+         * The type of shader
+         */
+        Type m_type;
+        /**
+         * The parameters the shader needs
+         */
+        std::vector <ShaderParameter*> m_parameters;
+        /**
+         * The combos the shader should be generated with
+         */
+         std::map <std::string, int>* m_combos;
+         /**
+          * Whether this compilation is a recursive one or not
+          */
+         bool m_recursive;
+    };
+}

+ 7 - 7
WallpaperEngine/effect.cpp

@@ -1,6 +1,6 @@
 #include <WallpaperEngine/FileSystem/utils.h>
 
-#include "shaders/compiler.h"
+#include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "effect.h"
 #include "WallpaperEngine/Irrlicht/Irrlicht.h"
 #include "WallpaperEngine/Core/Core.h"
@@ -94,8 +94,8 @@ namespace WallpaperEngine
             irr::io::path fragpath = shaderpath + ".frag";
             irr::io::path vertpath = shaderpath + ".vert";
 
-            this->m_fragShader = new WallpaperEngine::shaders::compiler (fragpath, WallpaperEngine::shaders::compiler::Type::Type_Pixel, &this->m_combos, false);
-            this->m_vertShader = new WallpaperEngine::shaders::compiler (vertpath, WallpaperEngine::shaders::compiler::Type::Type_Vertex, &this->m_combos, false);
+            this->m_fragShader = new WallpaperEngine::Render::Shaders::Compiler (fragpath, WallpaperEngine::Render::Shaders::Compiler::Type::Type_Pixel, &this->m_combos, false);
+            this->m_vertShader = new WallpaperEngine::Render::Shaders::Compiler (vertpath, WallpaperEngine::Render::Shaders::Compiler::Type::Type_Vertex, &this->m_combos, false);
 
             this->m_materialType = WallpaperEngine::Irrlicht::driver->getGPUProgrammingServices ()
                 ->addHighLevelShaderMaterial (
@@ -111,8 +111,8 @@ namespace WallpaperEngine
             this->parseConstantValues ((*constantvalues));
 
         // last step is creating the actual variables for the shaders
-        std::vector <shaders::compiler::ShaderParameter*>::const_iterator cur;
-        std::vector <shaders::compiler::ShaderParameter*>::const_iterator end;
+        std::vector <Render::Shaders::Compiler::ShaderParameter*>::const_iterator cur;
+        std::vector <Render::Shaders::Compiler::ShaderParameter*>::const_iterator end;
 
         cur = this->m_fragShader->getParameters ().begin ();
         end = this->m_fragShader->getParameters ().end ();
@@ -120,7 +120,7 @@ namespace WallpaperEngine
         // first do fragment shaders
         for (; cur != end; cur ++)
         {
-            WallpaperEngine::shaders::compiler::ShaderParameter* param = (*cur);
+            WallpaperEngine::Render::Shaders::Compiler::ShaderParameter* param = (*cur);
             ShaderParameter* parameter = new ShaderParameter;
             void* defaultValue = param->defaultValue;
 
@@ -203,7 +203,7 @@ namespace WallpaperEngine
         // second do vertex shaders
         for (;cur != end; cur ++)
         {
-            WallpaperEngine::shaders::compiler::ShaderParameter* param = (*cur);
+            WallpaperEngine::Render::Shaders::Compiler::ShaderParameter* param = (*cur);
 
             if (param == nullptr)
                 continue;

+ 3 - 3
WallpaperEngine/effect.h

@@ -6,7 +6,7 @@
 
 #include "texture.h"
 #include "object.h"
-#include "shaders/compiler.h"
+#include "WallpaperEngine/Render/Shaders/Compiler.h"
 
 namespace WallpaperEngine
 {
@@ -42,8 +42,8 @@ namespace WallpaperEngine
         void parseConstantValues (json data);
         void parseCombos (json data);
 
-        WallpaperEngine::shaders::compiler* m_fragShader;
-        WallpaperEngine::shaders::compiler* m_vertShader;
+        WallpaperEngine::Render::Shaders::Compiler* m_fragShader;
+        WallpaperEngine::Render::Shaders::Compiler* m_vertShader;
 
         std::map <std::string, ShaderParameter*> m_vertexVariables;
         std::map <std::string, ShaderParameter*> m_pixelVariables;

+ 0 - 638
WallpaperEngine/shaders/compiler.cpp

@@ -1,638 +0,0 @@
-#include <irrlicht/irrlicht.h>
-#include <iostream>
-#include <fstream>
-#include <string>
-
-// filesystem
-#include <WallpaperEngine/FileSystem/utils.h>
-
-// video engine
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
-
-// shader compiler
-#include <WallpaperEngine/shaders/compiler.h>
-#include <WallpaperEngine/Core/Core.h>
-
-namespace WallpaperEngine
-{
-    namespace shaders
-    {
-        compiler::compiler (irr::io::path& file, Type type, std::map<std::string, int>* combos, bool recursive)
-        {
-            this->m_recursive = recursive;
-            this->m_combos = combos;
-
-            // begin with an space so it gets ignored properly on parse
-            if (recursive == false)
-            {
-                // compatibility layer for OpenGL shaders
-                this->m_content =   "#version 120\n"
-                                    "#define highp\n"
-                                    "#define mediump\n"
-                                    "#define lowp\n"
-                                    "#define mul(x, y) (y * x)\n"
-                                    "#define frac fract\n"
-                                    "#define CAST2(x) (vec2(x))\n"
-                                    "#define CAST3(x) (vec3(x))\n"
-                                    "#define CAST4(x) (vec4(x))\n"
-                                    "#define CAST3X3(x) (mat3(x))\n"
-                                    "#define saturate(x) (clamp(x, 0.0, 1.0))\n"
-                                    "#define texSample2D texture2D\n"
-                                    "#define texSample2DLod texture2DLod\n"
-                                    "#define texture2DLod texture2D\n"
-                                    "#define atan2 atan\n"
-                                    "#define ddx dFdx\n"
-                                    "#define ddy(x) dFdy(-(x))\n"
-                                    "#define GLSL 1\n\n";
-
-                std::map<std::string, int>::const_iterator cur = this->m_combos->begin ();
-                std::map<std::string, int>::const_iterator end = this->m_combos->end ();
-
-                for (; cur != end; cur ++)
-                {
-                    this->m_content += "#define " + (*cur).first + " " + std::to_string ((*cur).second) + "\n";
-                }
-            }
-            else
-            {
-                this->m_content = "";
-            }
-
-            this->m_content.append (WallpaperEngine::FileSystem::loadFullFile (file));
-
-            // append file content
-            this->m_type = type;
-
-            this->m_file = file;
-        }
-
-        bool compiler::peekString(std::string str, std::string::const_iterator& it)
-        {
-            std::string::const_iterator check = str.begin();
-            std::string::const_iterator cur = it;
-
-            while (cur != this->m_content.end () && check != str.end ())
-            {
-                if (*cur != *check) return false;
-
-                cur ++; check ++;
-            }
-
-            if (cur == this->m_content.end ())
-            {
-                return false;
-            }
-
-            if (check != str.end ())
-            {
-                return false;
-            }
-
-            it = cur;
-
-            return true;
-        }
-
-        bool compiler::expectSemicolon (std::string::const_iterator& it)
-        {
-            if (*it != ';')
-            {
-                this->m_error = true;
-                this->m_errorInfo = "Expected semicolon but got " + *it;
-                return false;
-            }
-
-            it ++;
-
-            return true;
-        }
-
-        void compiler::ignoreSpaces(std::string::const_iterator &it)
-        {
-            while (it != this->m_content.end() && (*it == ' ' || *it == '\t')) it ++;
-        }
-
-        void compiler::ignoreUpToNextLineFeed (std::string::const_iterator& it)
-        {
-            while (it != this->m_content.end() && *it != '\n') it ++;
-        }
-
-        void compiler::ignoreUpToBlockCommentEnd (std::string::const_iterator& it)
-        {
-            while (it != this->m_content.end() && this->peekString ("*/", it) == false) it ++;
-        }
-
-        std::string compiler::extractType (std::string::const_iterator& it)
-        {
-            std::vector<std::string>::const_iterator cur = sTypes.begin ();
-            std::vector<std::string>::const_iterator end = sTypes.end ();
-
-            while (cur != end)
-            {
-                if (this->peekString (*cur, it) == true)
-                {
-                    return *cur;
-                }
-
-                cur ++;
-            }
-
-            this->m_error = true;
-            this->m_errorInfo = "Expected type";
-            return "";
-        }
-
-        std::string compiler::extractName (std::string::const_iterator& it)
-        {
-            std::string::const_iterator cur = it;
-            std::string::const_iterator begin = cur;
-
-            // first character has to be a valid alphabetic characer
-            if (this->isChar (cur) == false && *cur != '_')
-            {
-                this->m_error = true;
-                this->m_errorInfo = "Expected name doesn't start with a valid character";
-                return "";
-            }
-
-            cur ++;
-
-            while (cur != this->m_content.end () && (this->isChar (cur) == true || *cur == '_' || this->isNumeric (cur) == true)) cur ++;
-
-            it = cur;
-
-            return std::string (begin, cur);
-        }
-
-        bool compiler::isChar (std::string::const_iterator& it)
-        {
-            return ((*it) >= 'A' && (*it) <= 'Z') || ((*it) >= 'a' && (*it) <= 'z');
-        }
-
-        bool compiler::isNumeric (std::string::const_iterator& it)
-        {
-            return (*it) >= '0' && (*it) <= '9';
-        }
-
-        std::string compiler::extractQuotedValue(std::string::const_iterator& it)
-        {
-            std::string::const_iterator cur = it;
-
-            if (*cur != '"')
-            {
-                m_error = true;
-                m_errorInfo = "Expected opening \" but got " + (*cur);
-                return "";
-            }
-
-            cur ++;
-
-            while (cur != this->m_content.end () && *cur != '\n' && *cur != '"') cur ++;
-
-            if (cur == this->m_content.end ())
-            {
-                m_error = true;
-                m_errorInfo = "Expected closing \" not found";
-                it = cur;
-                return "";
-            }
-
-            std::string filename = std::string (++it, cur);
-
-            it = ++cur;
-
-            return filename;
-        }
-
-        std::string compiler::lookupShaderFile (std::string filename)
-        {
-            // get file information
-            irr::io::path shader = ("shaders/" + filename).c_str ();
-
-            if (shader == "")
-            {
-                this->m_error = true;
-                this->m_errorInfo = "Cannot find file " + filename + " to include";
-                return "";
-            }
-
-            // now compile the new shader
-            // do not include the default header (as it's already included in the parent)
-            compiler loader (shader, this->m_type, this->m_combos, true);
-
-            return loader.precompile ();
-        }
-
-        std::string compiler::lookupReplaceSymbol (std::string symbol)
-        {
-            std::map<std::string, std::string>::const_iterator cur = sVariableReplacement.begin ();
-            std::map<std::string, std::string>::const_iterator end = sVariableReplacement.end ();
-
-            while (cur != end)
-            {
-                if (cur->first == symbol)
-                {
-                    return cur->second;
-                }
-
-                cur ++;
-            }
-
-            // if there is no replacement, return the original
-            return symbol;
-        }
-
-        std::string compiler::precompile()
-        {
-        #define BREAK_IF_ERROR if (this->m_error == true) { WallpaperEngine::Irrlicht::device->getLogger ()->log ("ERROR PRE-COMPILING SHADER", irr::ELL_ERROR); WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_errorInfo.c_str (), irr::ELL_ERROR); return ""; }
-            // parse the shader and find #includes and such things and translate them to the correct name
-            // also remove any #version definition to prevent errors
-            std::string::const_iterator it = this->m_content.begin ();
-
-            // reset error indicator
-            this->m_error = false;
-            this->m_errorInfo = "";
-
-            // search preprocessor macros and parse them
-            while (it != this->m_content.end () && this->m_error == false)
-            {
-                if (*it == ' ' || *it == '\t' || *it == '\n' || *it == '\r' || *it == '\0' || *it == '{' || *it == '}' || *it == '[' || *it == ']' || *it == '.')
-                {
-                    this->m_compiledContent += *it;
-                    it ++;
-                }
-                else if (*it == '#')
-                {
-                    if (this->peekString ("#include", it) == true)
-                    {
-                        std::string filename = "";
-
-                        // ignore whitespaces
-                        this->ignoreSpaces (it); BREAK_IF_ERROR
-                        // extract value between quotes
-                        filename = this->extractQuotedValue (it); BREAK_IF_ERROR
-
-                        // try to find the file first
-                        this->m_compiledContent += "// begin of included from file " + filename + "\r\n";
-                        this->m_compiledContent += this->lookupShaderFile (filename);
-                        this->m_compiledContent += "\r\n// end of included from file " + filename + "\r\n";
-                    }
-                    else
-                    {
-                        this->m_compiledContent += '#';
-                        it ++;
-                    }
-                }
-                else if (*it == 'u')
-                {
-                    // uniforms might have extra information for their values
-                    if (this->peekString ("uniform", it) == true)
-                    {
-                        this->ignoreSpaces (it);
-                        std::string type = this->extractType (it); BREAK_IF_ERROR
-                        this->ignoreSpaces (it);
-                        std::string name = this->extractName (it); BREAK_IF_ERROR
-                        this->ignoreSpaces (it);
-                        this->expectSemicolon (it); BREAK_IF_ERROR
-                        this->ignoreSpaces (it);
-
-                        // check if there is any actual extra information and parse it
-                        if (this->peekString ("//", it) == true)
-                        {
-                            this->ignoreSpaces (it);
-                            std::string::const_iterator begin = it;
-                            this->ignoreUpToNextLineFeed (it);
-
-                            std::string configuration; configuration.append (begin, it);
-
-                            // parse the parameter information
-                            this->parseParameterConfiguration (type, name, configuration); BREAK_IF_ERROR
-                            this->m_compiledContent += "uniform " + type + " " + name + "; // " + configuration;
-                        }
-                        else
-                        {
-                            this->m_compiledContent += "uniform " + type + " " + name + ";";
-                        }
-                    }
-                }
-                else if (*it == 'a')
-                {
-                    // find attribute definitions
-                    if (this->peekString ("attribute", it) == true)
-                    {
-                        this->ignoreSpaces (it);
-                        std::string type = this->extractType (it); BREAK_IF_ERROR
-                        this->ignoreSpaces (it);
-                        std::string name = this->extractName (it); BREAK_IF_ERROR
-                        this->ignoreSpaces (it);
-                        this->expectSemicolon (it); BREAK_IF_ERROR
-
-                        this->m_compiledContent += "// attribute";
-                        this->m_compiledContent += " " + type + " ";
-                        this->m_compiledContent += name;
-                        this->m_compiledContent += "; /* replaced by " + this->lookupReplaceSymbol (name) + " */";
-                    }
-                    else
-                    {
-                        // check for types first
-                        std::string type = this->extractType (it);
-
-                        // types not found, try names
-                        if (this->m_error == false)
-                        {
-                            this->m_compiledContent += type;
-                        }
-                        else
-                        {
-                            this->m_error = false;
-                            std::string name = this->extractName (it);
-
-                            if (this->m_error == false)
-                            {
-                                // check if the name is a translated one or not
-                                this->m_compiledContent += this->lookupReplaceSymbol (name);
-                            }
-                            else
-                            {
-                                this->m_error = false;
-                                this->m_compiledContent += *it;
-                                it ++;
-                            }
-                        }
-                    }
-                }
-                else if (*it == '/')
-                {
-                    if (this->peekString ("//", it) == true)
-                    {
-                        std::string::const_iterator begin = it - 2;
-                        // is there a COMBO mark to take care of?
-                        this->ignoreSpaces (it);
-
-                        if (this->peekString ("[COMBO]", it) == true)
-                        {
-                            // parse combo json data to define the proper variables
-                            this->ignoreSpaces (it);
-                            begin = it;
-                            this->ignoreUpToNextLineFeed (it);
-
-                            std::string configuration; configuration.append (begin, it);
-
-                            this->m_compiledContent += "// [COMBO] " + configuration;
-
-                            this->parseComboConfiguration (configuration); BREAK_IF_ERROR;
-                        }
-                        else if (this->peekString ("[COMBO_OFF]", it) == true)
-                        {
-                            // parse combo json data to define the proper variables
-                            this->ignoreSpaces (it);
-                            begin = it;
-                            this->ignoreUpToNextLineFeed (it);
-
-                            std::string configuration; configuration.append (begin, it);
-
-                            this->m_compiledContent += "// [COMBO_OFF] " + configuration;
-
-                            this->parseComboConfiguration (configuration); BREAK_IF_ERROR;
-                        }
-                        else
-                        {
-                            this->ignoreUpToNextLineFeed (it);
-                            this->m_compiledContent.append (begin, it);
-                        }
-                    }
-                    else if (this->peekString ("/*", it) == true)
-                    {
-                        std::string::const_iterator begin = it - 2;
-                        this->ignoreUpToBlockCommentEnd (it);
-                        this->m_compiledContent.append (begin, it);
-                    }
-                    else
-                    {
-                        this->m_compiledContent += *it;
-                        it ++;
-                    }
-                }
-                else
-                {
-                    // check for types first
-                    std::string type = this->extractType (it);
-
-                    // types not found, try names
-                    if (this->m_error == false)
-                    {
-                        this->m_compiledContent += type;
-                    }
-                    else
-                    {
-                        this->m_error = false;
-                        std::string name = this->extractName (it);
-
-                        if (this->m_error == false)
-                        {
-                            // check if the name is a translated one or not
-                            this->m_compiledContent += this->lookupReplaceSymbol (name);
-                        }
-                        else
-                        {
-                            this->m_error = false;
-                            this->m_compiledContent += *it;
-                            it ++;
-                        }
-                    }
-                }
-            }
-
-            if (this->m_recursive == false)
-            {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Compiled shader output for", this->m_file.c_str ());
-                WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_compiledContent.c_str ());
-            }
-
-            return this->m_compiledContent;
-        #undef BREAK_IF_ERROR
-        }
-
-        void compiler::parseComboConfiguration (const std::string& content)
-        {
-            json data = json::parse (content);
-            json::const_iterator combo = data.find ("combo");
-            json::const_iterator defvalue = data.find ("default");
-
-            // add line feed just in case
-            this->m_compiledContent += "\n";
-
-            if (combo == data.end () || defvalue == data.end ())
-            {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information", irr::ELL_ERROR);
-                return;
-            }
-
-            // check the combos
-            std::map<std::string, int>::const_iterator entry = this->m_combos->find ((*combo).get <std::string> ());
-
-            // if the combo was not found in the predefined values this means that the default value in the JSON data can be used
-            // so only define the ones that are not already defined
-            if (entry == this->m_combos->end ())
-            {
-                // if no combo is defined just load the default settings
-                if ((*defvalue).is_number_float ())
-                {
-                    this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + std::to_string ((*defvalue).get <irr::f32> ()) + "\n";
-                }
-                else if ((*defvalue).is_number_integer ())
-                {
-                    this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + std::to_string ((*defvalue).get <irr::s32> ()) + "\n";
-                }
-                else if ((*defvalue).is_string ())
-                {
-                    this->m_compiledContent += "#define " + (*combo).get <std::string> () + " " + (*defvalue).get <std::string> () + "\n";
-                }
-                else
-                {
-                    WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information, unknown type", irr::ELL_ERROR);
-                }
-            }
-        }
-
-        void compiler::parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content)
-        {
-            json data = json::parse (content);
-            json::const_iterator material = data.find ("material");
-            json::const_iterator defvalue = data.find ("default");
-            json::const_iterator range = data.find ("range");
-
-            // this is not a real parameter
-            if (material == data.end () || defvalue == data.end ())
-            {
-                if (type != "sampler2D")
-                    WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse parameter info for ", name.c_str (), irr::ELL_ERROR);
-
-                return;
-            }
-
-            ShaderParameter* param = new ShaderParameter;
-
-            param->identifierName = (*material).get <std::string> ();
-            param->variableName = name;
-            param->type = type;
-
-            if (type == "vec4" || type == "vec3")
-            {
-                if ((*defvalue).is_string () == false)
-                {
-                    irr::core::vector3df* vector = new irr::core::vector3df;
-
-                    vector->X = 0.0f;
-                    vector->Y = 0.0f;
-                    vector->Z = 0.0f;
-
-                    param->defaultValue = vector;
-                }
-                else
-                {
-                    irr::core::vector3df tmp = WallpaperEngine::Core::ato3vf ((*defvalue).get <std::string> ().c_str ());
-                    irr::core::vector3df* vector = new irr::core::vector3df;
-
-                    vector->X = tmp.X;
-                    vector->Y = tmp.Y;
-                    vector->Z = tmp.Z;
-
-                    param->defaultValue = vector;
-                }
-            }
-            else if (type == "vec2")
-            {
-                if ((*defvalue).is_string () == false)
-                {
-                    irr::core::vector2df* vector = new irr::core::vector2df;
-
-                    vector->X = 0.0f;
-                    vector->Y = 0.0f;
-
-                    param->defaultValue = vector;
-                }
-                else
-                {
-                    irr::core::vector2df* vector = new irr::core::vector2df;
-                    irr::core::vector2df tmp = WallpaperEngine::Core::ato2vf ((*defvalue).get <std::string> ().c_str ());
-
-                    vector->X = tmp.X;
-                    vector->Y = tmp.Y;
-
-                    param->defaultValue = vector;
-                }
-            }
-            else if (type == "float")
-            {
-                if ((*defvalue).is_number () == false)
-                {
-                    irr::f32* val = new irr::f32;
-
-                    *val = 0.0f;
-
-                    param->defaultValue = val;
-
-                }
-                else
-                {
-                    irr::f32* val = new irr::f32;
-
-                    *val = (*defvalue).get <irr::f32> ();
-
-                    param->defaultValue = val;
-                }
-            }
-            else if (type == "sampler2D")
-            {
-                // samplers are not saved, we can ignore them for now
-                delete param;
-                return;
-            }
-            else
-            {
-                this->m_error = true;
-                this->m_errorInfo = "Unknown parameter type: " + type + " for " + param->identifierName + " (" + param->variableName + ")";
-                return;
-            }
-
-            this->m_parameters.push_back (param);
-        }
-
-        compiler::ShaderParameter* compiler::findParameter (std::string identifier)
-        {
-            std::vector<ShaderParameter*>::const_iterator cur = this->m_parameters.begin ();
-            std::vector<ShaderParameter*>::const_iterator end = this->m_parameters.end ();
-
-            for (; cur != end; cur ++)
-            {
-                if ((*cur)->identifierName == identifier)
-                {
-                    return (*cur);
-                }
-            }
-
-            return nullptr;
-        }
-
-        std::vector <compiler::ShaderParameter*>& compiler::getParameters ()
-        {
-            return this->m_parameters;
-        }
-
-        std::map<std::string, std::string>  compiler::sVariableReplacement =
-        {
-            // attribute vec3 a_position
-            {"a_Position", "gl_Vertex.xyz"},
-            // attribute vec2 a_TexCoord
-            {"a_TexCoord", "gl_MultiTexCoord0.xy"},
-            // attribute vec3 a_Normal
-            {"a_Normal", "gl_Normal.xyz"}
-        };
-
-        std::vector<std::string> compiler::sTypes =
-        {
-            "vec4", "vec3", "vec2", "float", "sampler2D", "mat4"
-        };
-    }
-}

+ 0 - 246
WallpaperEngine/shaders/compiler.h

@@ -1,246 +0,0 @@
-#ifndef __BASIC_SHADER_LOADER_H__
-#define __BASIC_SHADER_LOADER_H__
-
-#include <irrlicht/irrlicht.h>
-#include <iostream>
-#include <vector>
-#include <map>
-#include <nlohmann/json.hpp>
-
-#include <WallpaperEngine/FileSystem/utils.h>
-
-namespace WallpaperEngine
-{
-    namespace shaders
-    {
-        using json = nlohmann::json;
-
-        /**
-         * A basic shader loader that adds basic function definitions to every loaded shader
-         */
-        class compiler
-        {
-        public:
-            /**
-             * Basic struct used to define all the shader variables
-             * the compiler will replace in pre-processing time
-             * to make sure the shaders compile under OpenGL
-             */
-            struct VariableReplacement
-            {
-                const char* original;
-                const char* replacement;
-            };
-
-            struct TypeName
-            {
-                const char* name;
-                int size;
-            };
-
-            struct ShaderParameter
-            {
-                std::string type;
-                std::string variableName;
-                std::string identifierName;
-                void* defaultValue;
-                void* range [2];
-            };
-
-            /**
-             * Types of shaders
-             */
-            enum Type
-            {
-                Type_Vertex = 0,
-                Type_Pixel = 1,
-            };
-
-            /**
-             * List of variables to replace when pre-process is performed
-             */
-            static std::map<std::string, std::string> sVariableReplacement;
-            /**
-             * Types of variables the pre-processor understands
-             */
-            static std::vector<std::string> sTypes;
-
-            /**
-             * Compiler constructor, loads the given shader file and prepares
-             * the pre-processing and compilation of the shader, adding
-             * required definitions if needed
-             *
-             * @param file The file to load
-             * @param type The type of shader
-             * @param recursive Whether the compiler should add base definitions or not
-             */
-            compiler (irr::io::path& file, Type type, std::map<std::string, int>* combos, bool recursive = false);
-            /**
-             * Performs the actual pre-compilation/pre-processing over the shader files
-             * This step is kinda big, replaces variables names on sVariableReplacement,
-             * ensures #include directives are correctly handled
-             * and takes care of attribute comments for the wallpaper engine specifics
-             *
-             * @return The shader contents ready to be used by OpenGL
-             */
-            std::string precompile ();
-            /**
-             * Searches the list of parameters available for the parameter with the given value
-             *
-             * @param identifier The identifier to search for
-             * @return The shader information
-             */
-            ShaderParameter* findParameter (std::string identifier);
-
-            /**
-             * @return The list of parameters available for this shader with their default values
-             */
-            std::vector <ShaderParameter*>& getParameters ();
-
-        private:
-            /**
-             * Checks if there is "str" in the current position without advancing the
-             * iterator in use
-             *
-             * @param str The string to check for
-             * @param it  The position to start checking at
-             *
-             * @return
-             */
-            bool peekString (std::string str, std::string::const_iterator& it);
-            /**
-             * Checks for a semicolon as current character, advancing the iterator
-             * after finding it, otherwise returns an error
-             *
-             * @param it The position where to expect the semicolon
-             *
-             * @return
-             */
-            bool expectSemicolon (std::string::const_iterator& it);
-            /**
-             * Ignores contiguous space characters in the string advancing the iterator
-             * until the first non-space character
-             *
-             * @param it The iterator to increase
-             */
-            void ignoreSpaces (std::string::const_iterator& it);
-            /**
-             * Ignores all characters until next line-fee (\n) advancing the interator
-             *
-             * @param it The iterator to increase
-             */
-            void ignoreUpToNextLineFeed (std::string::const_iterator& it);
-            /**
-             * Ignores all characters until a block comment end is found, advancing the iterator
-             *
-             * @param it The iterator to increase
-             */
-            void ignoreUpToBlockCommentEnd (std::string::const_iterator& it);
-            /**
-             * Parses the current position as a variable type, extracts it and compares it
-             * to the registered types in the pre-processor, returning it's name if valid
-             * increasing the iterator at the same time
-             *
-             * @param it The position to extract it from
-             *
-             * @return The type name
-             */
-            std::string extractType (std::string::const_iterator& it);
-            /**
-             * Parses the current position as a variable name, extractig it's name and
-             * increasing the iterator as the name is extracted
-             *
-             * @param it The position to start extracting the variable name from
-             *
-             * @return The variable name
-             */
-            std::string extractName (std::string::const_iterator& it);
-            /**
-             * Parses the current position as a quoted value, extracting it's value
-             * and increasing the iterator at the same time
-             *
-             * @param it The position to start extracting the value from
-             *
-             * @return The value
-             */
-            std::string extractQuotedValue (std::string::const_iterator& it);
-            /**
-             * Tries to find the given shader file and compile it
-             *
-             * @param filename The shader's filename
-             *
-             * @return The compiled contents
-             */
-            std::string lookupShaderFile (std::string filename);
-            /**
-             * Searches for the given symbol in the replace table
-             *
-             * @param symbol The symbol to look for
-             *
-             * @return The symbol it should be replaced with
-             */
-            std::string lookupReplaceSymbol (std::string symbol);
-
-            /**
-             * @return Whether the character in the current position is a character or not
-             */
-            bool isChar (std::string::const_iterator& it);
-            /**
-             * @return Whether the character in the current position is a number or not
-             */
-            bool isNumeric (std::string::const_iterator& it);
-            /**
-             * Parses a COMBO value to add the proper define to the code
-             *
-             * @param content The parameter configuration
-             */
-            void parseComboConfiguration (const std::string& content);
-            /**
-             * Parses a parameter extra metadata created by wallpaper engine
-             *
-             * @param type The type of variable to parse
-             * @param name The name of the variable in the shader (for actual variable declaration)
-             * @param content The parameter configuration
-             */
-            void parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content);
-            /**
-             * The shader file this instance is loading
-             */
-            irr::io::path m_file;
-            /**
-             * The original file content
-             */
-            std::string m_content;
-            /**
-             * The final, compiled content ready to be used by OpenGL
-             */
-            std::string m_compiledContent;
-            /**
-             * Whether there was any kind of error in the compilation or not
-             */
-            bool m_error;
-            /**
-             * Extra information about the error (if any)
-             */
-            std::string m_errorInfo;
-            /**
-             * The type of shader
-             */
-            Type m_type;
-            /**
-             * The parameters the shader needs
-             */
-            std::vector <ShaderParameter*> m_parameters;
-            /**
-             * The combos the shader should be generated with
-             */
-             std::map <std::string, int>* m_combos;
-             /**
-              * Whether this compilation is a recursive one or not
-              */
-             bool m_recursive;
-        };
-    }
-}
-
-#endif /* !__BASIC_SHADER_LOADER_H__ */

+ 1 - 1
main.cpp

@@ -8,7 +8,7 @@
 #include <SDL_mixer.h>
 #include <SDL.h>
 
-#include "WallpaperEngine/shaders/compiler.h"
+#include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "WallpaperEngine/project.h"
 #include "WallpaperEngine/Irrlicht/Irrlicht.h"
 #include "WallpaperEngine/Irrlicht/CImageLoaderTEX.h"