diff --git a/CMakeLists.txt b/CMakeLists.txt index 8423797..3fca169 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,6 @@ find_package(LZ4 REQUIRED) 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/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/utils.cpp wallpaperengine/fs/utils.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp wallpaperengine/irr/CPkgReader.h wallpaperengine/irr/CPkgReader.cpp wallpaperengine/irr/CFileList.h wallpaperengine/irr/CFileList.cpp) +add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/utils.cpp wallpaperengine/fs/utils.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp wallpaperengine/irr/CPkgReader.h wallpaperengine/irr/CPkgReader.cpp wallpaperengine/irr/CFileList.h wallpaperengine/irr/CFileList.cpp wallpaperengine/irr/vector4d.h) target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY}) \ No newline at end of file diff --git a/wallpaperengine/core.h b/wallpaperengine/core.h index ea8488a..43384b2 100644 --- a/wallpaperengine/core.h +++ b/wallpaperengine/core.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace wp { diff --git a/wallpaperengine/effect.cpp b/wallpaperengine/effect.cpp index 85f9eae..a01dbee 100644 --- a/wallpaperengine/effect.cpp +++ b/wallpaperengine/effect.cpp @@ -3,6 +3,7 @@ #include "shaders/compiler.h" #include "effect.h" #include "irrlicht.h" +#include "core.h" extern irr::f32 g_Time; @@ -87,18 +88,211 @@ namespace wp irr::io::path fragpath = shaderpath + ".frag"; irr::io::path vertpath = shaderpath + ".vert"; - wp::shaders::compiler* fragcompiler = new wp::shaders::compiler (fragpath, wp::shaders::compiler::Type::Type_Pixel, false); - wp::shaders::compiler* vertcompiler = new wp::shaders::compiler (vertpath, wp::shaders::compiler::Type::Type_Vertex, false); + this->m_fragShader = new wp::shaders::compiler (fragpath, wp::shaders::compiler::Type::Type_Pixel, false); + this->m_vertShader = new wp::shaders::compiler (vertpath, wp::shaders::compiler::Type::Type_Vertex, false); this->m_materialType = wp::irrlicht::driver->getGPUProgrammingServices () ->addHighLevelShaderMaterial ( - vertcompiler->precompile ().c_str (), "main", irr::video::EVST_VS_2_0, - fragcompiler->precompile ().c_str (), "main", irr::video::EPST_PS_2_0, + this->m_vertShader->precompile ().c_str (), "main", irr::video::EVST_VS_2_0, + this->m_fragShader->precompile ().c_str (), "main", irr::video::EPST_PS_2_0, this, irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0, irr::video::EGSL_DEFAULT ); + } - delete fragcompiler; - delete vertcompiler; + json::const_iterator constantvalues = (*curpass).find ("constantshadervalues"); + + if (constantvalues != (*curpass).end () && (*constantvalues).is_object () == true) + this->parseConstantValues ((*constantvalues)); + + // last step is creating the actual variables for the shaders + std::vector ::const_iterator cur; + std::vector ::const_iterator end; + + cur = this->m_fragShader->getParameters ().begin (); + end = this->m_fragShader->getParameters ().end (); + + // first do fragment shaders + for (; cur != end; cur ++) + { + wp::shaders::compiler::ShaderParameter* param = (*cur); + ShaderParameter* parameter = new ShaderParameter; + + parameter->value = nullptr; + + if (param->type == "vec4") + { + irr::core::vector3df* vec = (irr::core::vector3df*) param->defaultValue; + irr::f32* val = new irr::f32 [4]; + + val [0] = vec->X; + val [1] = vec->Y; + val [2] = vec->Z; + val [3] = 0.0f; + + parameter->value = val; + parameter->type = ParameterType::TYPE_VEC4; + } + else if (param->type == "vec3") + { + irr::core::vector3df* vec = (irr::core::vector3df*) param->defaultValue; + irr::f32* val = new irr::f32 [3]; + + val [0] = vec->X; + val [1] = vec->Y; + val [2] = vec->Z; + + parameter->value = val; + parameter->type = ParameterType::TYPE_VEC3; + } + else if (param->type == "vec2") + { + irr::core::vector2df* vec = (irr::core::vector2df*) param->defaultValue; + irr::f32* val = new irr::f32 [2]; + + val [0] = vec->X; + val [1] = vec->Y; + + parameter->value = val; + parameter->type = ParameterType::TYPE_VEC2; + } + else if (param->type == "float") + { + irr::f32* org = (irr::f32*) param->defaultValue; + irr::f32* val = new irr::f32; + + *val = *org; + + parameter->value = val; + parameter->type = ParameterType::TYPE_FLOAT; + } + else if (param->type == "int") + { + irr::s32* org = (irr::s32*) param->defaultValue; + irr::s32* val = new irr::s32; + + *val = *org; + + parameter->value = val; + parameter->type = ParameterType::TYPE_INT; + } + else if (param->type == "sampler2D") + { + // sampler2D are textures from wallpaper engine + // so these can be ignored as they are later on defined + continue; + } + + this->m_pixelVariables.insert (std::pair (param->variableName, parameter)); + } + + cur = this->m_vertShader->getParameters ().begin (); + end = this->m_vertShader->getParameters ().end (); + + // second do vertex shaders + for (;cur != end; cur ++) + { + wp::shaders::compiler::ShaderParameter* param = (*cur); + + if (param == nullptr) + continue; + + ShaderParameter* parameter = new ShaderParameter; + + parameter->value = nullptr; + + if (param->type == "vec4") + { + irr::core::vector3df* vec = (irr::core::vector3df*) param->defaultValue; + + parameter->value = new irr::f32 [4]; + + (*(irr::f32**) parameter->value) [0] = vec->X; + (*(irr::f32**) parameter->value) [1] = vec->Y; + (*(irr::f32**) parameter->value) [2] = vec->Z; + (*(irr::f32**) parameter->value) [3] = 0.0f; + + parameter->type = ParameterType::TYPE_VEC4; + } + else if (param->type == "vec3") + { + irr::core::vector3df* vec = (irr::core::vector3df*) param->defaultValue; + + parameter->value = new irr::f32 [3]; + + (*(irr::f32**) parameter->value) [0] = vec->X; + (*(irr::f32**) parameter->value) [1] = vec->Y; + (*(irr::f32**) parameter->value) [2] = vec->Z; + + parameter->type = ParameterType::TYPE_VEC3; + } + else if (param->type == "vec2") + { + irr::core::vector2df* vec = (irr::core::vector2df*) param->defaultValue; + + parameter->value = new irr::f32 [2]; + + (*(irr::f32**) parameter->value) [0] = vec->X; + (*(irr::f32**) parameter->value) [1] = vec->Y; + + parameter->type = ParameterType::TYPE_VEC2; + } + else if (param->type == "float") + { + parameter->value = new irr::f32; + *(irr::f32*) parameter->value = *(irr::f32*) param->defaultValue; + + parameter->type = ParameterType::TYPE_FLOAT; + } + else if (param->type == "int") + { + parameter->value = new irr::s32; + *(irr::s32*) parameter->value = *(irr::s32*) param->defaultValue; + + parameter->type = ParameterType::TYPE_INT; + } + else if (param->type == "sampler2D") + { + // sampler2D are textures from wallpaper engine + // so these can be ignored as they are later on defined + continue; + } + + this->m_vertexVariables.insert (std::pair (param->variableName, parameter)); + } + } + + void effect::parseConstantValues (json data) + { +/* + "ui_editor_properties_animation_speed" : 0.10000000149011612, + "ui_editor_properties_ripple_scale" : 2.5, + "ui_editor_properties_ripple_strength" : 0.070000000298023224 +*/ + json::const_iterator cur = data.begin (); + json::const_iterator end = data.end (); + + for (; cur != end; cur ++) + { + std::string name = cur.key (); + void* value = nullptr; + + if ((*cur).is_number_float () == true) + { + value = new irr::f32; + *(irr::f32*) value = (*cur).get (); + } + else if ((*cur).is_number_integer () == true) + { + value = new irr::s32; + *(irr::s32*) value = (*cur).get (); + } + else if ((*cur).is_string () == true) + { + value = new irr::core::vector3df; + *(irr::core::vector3df*) value = core::ato3vf ((*cur).get ().c_str ()); + } + + this->m_constants.insert (std::pair (name, value)); } } @@ -135,21 +329,150 @@ namespace wp worldViewProj *= driver->getTransform(irr::video::ETS_VIEW); worldViewProj *= driver->getTransform(irr::video::ETS_WORLD); - services->setVertexShaderConstant ("g_AnimationSpeed", &g_AnimationSpeed, 1); + /* + THESE ARE THE VARIABLES AVAILABLE ON SHADERS + + uniform float g_Alpha; + + uniform vec3 g_Color; + + // Application time, starts with 0 + uniform float g_Time; + + // Maps 24 hrs to [0, 1] + uniform float g_Daytime; + + uniform vec2 g_TexelSize; + uniform vec2 g_TexelSizeHalf; + + uniform mat4 g_ModelMatrix; + uniform mat4 g_ViewProjectionMatrix; + uniform mat4 g_ModelViewProjectionMatrix; + uniform mat4 g_ModelViewProjectionMatrixInverse; + + uniform vec3 g_EyePosition; + uniform vec3 g_ViewUp; + uniform vec3 g_ViewRight; + + // Samplers that map to the textures[] array in the material + uniform sampler2D g_Texture0; + uniform sampler2D g_Texture1; + uniform sampler2D g_Texture2; + uniform sampler2D g_Texture3; + uniform sampler2D g_Texture4; + uniform sampler2D g_Texture5; + uniform sampler2D g_Texture6; + uniform sampler2D g_Texture7; + + // For sprite sheets (GIFs) + uniform vec4 g_Texture0Rotation; + uniform vec4 g_Texture1Rotation; + uniform vec4 g_Texture2Rotation; + uniform vec4 g_Texture3Rotation; + uniform vec4 g_Texture4Rotation; + uniform vec4 g_Texture5Rotation; + uniform vec4 g_Texture6Rotation; + uniform vec4 g_Texture7Rotation; + + uniform vec2 g_Texture0Translation; + uniform vec2 g_Texture1Translation; + uniform vec2 g_Texture2Translation; + uniform vec2 g_Texture3Translation; + uniform vec2 g_Texture4Translation; + uniform vec2 g_Texture5Translation; + uniform vec2 g_Texture6Translation; + uniform vec2 g_Texture7Translation; + + uniform vec4 g_LightsColorRadius[4]; // color in XYZ, radius in W + uniform vec3 g_LightsPosition[4]; + + uniform vec3 g_LightAmbientColor; + uniform vec3 g_LightSkylightColor; + + // lower frequencies at lower indices + uniform float g_AudioSpectrum16Left[16]; + uniform float g_AudioSpectrum16Right[16]; + uniform float g_AudioSpectrum32Left[32]; + uniform float g_AudioSpectrum32Right[32]; + uniform float g_AudioSpectrum64Left[64]; + uniform float g_AudioSpectrum64Right[64]; + + // Normalized in UV space [0, 1] + uniform vec2 g_PointerPosition; + + */ + + services->setVertexShaderConstant ("g_Time", &g_Time, 1); + services->setPixelShaderConstant ("g_Time", &g_Time, 1); + + std::map::const_iterator vertcur = this->m_vertexVariables.begin (); + std::map::const_iterator vertend = this->m_vertexVariables.end (); + + for (; vertcur != vertend; vertcur ++) + { + switch ((*vertcur).second->type) + { + case ParameterType::TYPE_FLOAT: + services->setVertexShaderConstant ((*vertcur).first.c_str (), (irr::f32*) (*vertcur).second, 1); + break; + case ParameterType::TYPE_VEC2: + services->setVertexShaderConstant ((*vertcur).first.c_str (), (irr::f32*) (*vertcur).second, 2); + break; + case ParameterType::TYPE_VEC3: + services->setVertexShaderConstant ((*vertcur).first.c_str (), (irr::f32*) (*vertcur).second, 3); + break; + case ParameterType::TYPE_VEC4: + services->setVertexShaderConstant ((*vertcur).first.c_str (), (irr::f32*) (*vertcur).second, 4); + break; + case ParameterType::TYPE_INT: + services->setVertexShaderConstant ((*vertcur).first.c_str (), (irr::s32*) (*vertcur).second, 1); + break; + + } + } + + std::map::const_iterator pixelcur = this->m_pixelVariables.begin (); + std::map::const_iterator pixelend = this->m_pixelVariables.end (); + + for (; pixelcur != pixelend; pixelcur ++) + { + switch ((*pixelcur).second->type) + { + case ParameterType::TYPE_FLOAT: + services->setPixelShaderConstant ((*pixelcur).first.c_str (), (irr::f32*) (*pixelcur).second, 1); + break; + case ParameterType::TYPE_VEC2: + services->setPixelShaderConstant ((*pixelcur).first.c_str (), (irr::f32*) (*pixelcur).second, 2); + break; + case ParameterType::TYPE_VEC3: + services->setPixelShaderConstant ((*pixelcur).first.c_str (), (irr::f32*) (*pixelcur).second, 3); + break; + case ParameterType::TYPE_VEC4: + services->setPixelShaderConstant ((*pixelcur).first.c_str (), (irr::f32*) (*pixelcur).second, 4); + break; + case ParameterType::TYPE_INT: + services->setPixelShaderConstant ((*pixelcur).first.c_str (), (irr::s32*) (*pixelcur).second, 1); + break; + + } + } + + /*services->setVertexShaderConstant ("g_AnimationSpeed", &g_AnimationSpeed, 1); services->setVertexShaderConstant ("g_Scale", &g_Scale, 1); services->setVertexShaderConstant ("g_ScrollSpeed", &g_ScrollSpeed, 1); - services->setVertexShaderConstant ("g_Direction", &g_Direction, 1); - services->setVertexShaderConstant ("g_Time", &g_Time, 1); + services->setVertexShaderConstant ("g_Direction", &g_Direction, 1);*/ services->setVertexShaderConstant ("g_ModelViewProjectionMatrix", worldViewProj.pointer(), 16); + + services->setVertexShaderConstant ("g_Texture0Resolution", g_Texture1Resolution, 4); services->setVertexShaderConstant ("g_Texture1Resolution", g_Texture1Resolution, 4); services->setVertexShaderConstant ("g_Texture2Resolution", g_Texture1Resolution, 4); // TODO: Support up to 7 materials (as wallpaper engine) - services->setPixelShaderConstant ("g_Strength", &g_Strength, 1); + /*services->setPixelShaderConstant ("g_Strength", &g_Strength, 1); services->setPixelShaderConstant ("g_SpecularPower", &g_SpecularPower, 1); services->setPixelShaderConstant ("g_SpecularStrength", &g_SpecularStrength, 1); - services->setPixelShaderConstant ("g_SpecularColor", g_SpecularColor, 3); + services->setPixelShaderConstant ("g_SpecularColor", g_SpecularColor, 3);*/ services->setPixelShaderConstant ("g_Texture0", &g_Texture0, 1); services->setPixelShaderConstant ("g_Texture1", &g_Texture1, 1); services->setPixelShaderConstant ("g_Texture2", &g_Texture2, 1); diff --git a/wallpaperengine/effect.h b/wallpaperengine/effect.h index bcbc270..e99cb46 100644 --- a/wallpaperengine/effect.h +++ b/wallpaperengine/effect.h @@ -5,6 +5,7 @@ #include #include "texture.h" +#include "shaders/compiler.h" namespace wp { @@ -20,6 +21,30 @@ namespace wp std::vector & getTextureList (); irr::s32 getMaterialType (); private: + enum ParameterType + { + TYPE_VEC4, + TYPE_VEC3, + TYPE_VEC2, + TYPE_FLOAT, + TYPE_INT + }; + + struct ShaderParameter + { + void* value; + ParameterType type; + }; + + void parseConstantValues (json data); + + wp::shaders::compiler* m_fragShader; + wp::shaders::compiler* m_vertShader; + + std::map m_vertexVariables; + std::map m_pixelVariables; + + std::map m_constants; std::vector m_textures; std::string m_content; json m_json; diff --git a/wallpaperengine/shaders/compiler.cpp b/wallpaperengine/shaders/compiler.cpp index 6257922..72027b8 100644 --- a/wallpaperengine/shaders/compiler.cpp +++ b/wallpaperengine/shaders/compiler.cpp @@ -11,6 +11,7 @@ // shader compiler #include +#include namespace wp { @@ -270,6 +271,38 @@ namespace wp 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 @@ -373,6 +406,126 @@ namespace wp #undef BREAK_IF_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 ()) + { + return; + } + + ShaderParameter* param = new ShaderParameter; + + param->identifierName = (*material).get (); + 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 = wp::core::ato3vf ((*defvalue).get ().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 = wp::core::ato2vf ((*defvalue).get ().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 (); + + param->defaultValue = val; + } + } + else if (type == "sampler2D") + { + param->defaultValue = nullptr; + } + 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::const_iterator cur = this->m_parameters.begin (); + std::vector::const_iterator end = this->m_parameters.end (); + + for (; cur != end; cur ++) + { + if ((*cur)->identifierName == identifier) + { + return (*cur); + } + } + + return nullptr; + } + + std::vector & compiler::getParameters () + { + return this->m_parameters; + } + std::map compiler::sVariableReplacement = { // attribute vec3 a_position @@ -385,7 +538,7 @@ namespace wp std::vector compiler::sTypes = { - "vec4", "vec3", "vec2", "float" + "vec4", "vec3", "vec2", "float", "sampler2D", "mat4" }; } } diff --git a/wallpaperengine/shaders/compiler.h b/wallpaperengine/shaders/compiler.h index e14d90e..32fcf92 100644 --- a/wallpaperengine/shaders/compiler.h +++ b/wallpaperengine/shaders/compiler.h @@ -35,12 +35,13 @@ namespace wp int size; }; - struct ShaderParameters + struct ShaderParameter { - char* variableName; + std::string type; + std::string variableName; + std::string identifierName; void* defaultValue; void* range [2]; - char* type; }; /** @@ -79,7 +80,19 @@ namespace wp * * @return The shader contents ready to be used by OpenGL */ - std::string precompile(); + 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 & getParameters (); private: /** @@ -173,7 +186,14 @@ namespace wp * @return Whether the character in the current position is a number or not */ bool isNumeric (std::string::const_iterator& it); - + /** + * 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 */ @@ -201,7 +221,7 @@ namespace wp /** * Tha parameters the shader needs */ - std::vector m_parameters; + std::vector m_parameters; }; } }