From 537acb97bdc37b41b80c585614ec1b0eca4e6523 Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Date: Sun, 8 Aug 2021 08:41:03 +0200 Subject: [PATCH] ~ shader precompilation should be done in order to ensure that the vertex shader has information discovered by the fragment shader (like new combos) should fix some effects on backgrounds + added partial support for shader constant values from the scene.json Signed-off-by: Alexis Maiquez --- .../Render/Objects/Effects/CPass.cpp | 14 ++-- .../Render/Shaders/Compiler.cpp | 71 +++++++++++++++---- src/WallpaperEngine/Render/Shaders/Compiler.h | 24 +++++-- 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp index a27c041..ccc9ff8 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp @@ -42,12 +42,18 @@ CPass::CPass (Irrlicht::CContext* context, CMaterial* material, Core::Objects::I irr::io::path fragPath = this->m_context->resolveFragmentShader (pass->getShader ()); // register fragment shader this->m_fragShader = new Render::Shaders::Compiler ( - this->m_context, fragPath, Render::Shaders::Compiler::Type::Type_Pixel, pass->getCombos (), false + this->m_context, fragPath, Render::Shaders::Compiler::Type::Type_Pixel, + pass->getCombos (), pass->getConstants (), false ); + // compile fragment shader + this->m_fragShader->precompile (); // register vertex shader, combos come from the fragment as it can sometimes define them this->m_vertShader = new Render::Shaders::Compiler ( - this->m_context, vertPath, Render::Shaders::Compiler::Type::Type_Vertex, this->m_fragShader->getCombos (), false + this->m_context, vertPath, Render::Shaders::Compiler::Type::Type_Vertex, + this->m_fragShader->getCombos (), pass->getConstants (), false ); + // compile vertex shader + this->m_vertShader->precompile (); this->setupTextures (); // initialize material data and compile shader used for this pass this->m_irrlichtMaterial.Wireframe = false; @@ -56,8 +62,8 @@ CPass::CPass (Irrlicht::CContext* context, CMaterial* material, Core::Objects::I this->m_irrlichtMaterial.setFlag (irr::video::EMF_BLEND_OPERATION, true); this->m_irrlichtMaterial.MaterialType = (irr::video::E_MATERIAL_TYPE) this->m_context->getDevice ()->getVideoDriver ()->getGPUProgrammingServices ()->addHighLevelShaderMaterial ( - 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->m_vertShader->getCompiled ().c_str (), "main", irr::video::EVST_VS_2_0, + this->m_fragShader->getCompiled ().c_str (), "main", irr::video::EPST_PS_2_0, this, irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0, irr::video::EGSL_DEFAULT ); diff --git a/src/WallpaperEngine/Render/Shaders/Compiler.cpp b/src/WallpaperEngine/Render/Shaders/Compiler.cpp index d89a9c4..af424eb 100644 --- a/src/WallpaperEngine/Render/Shaders/Compiler.cpp +++ b/src/WallpaperEngine/Render/Shaders/Compiler.cpp @@ -9,6 +9,9 @@ // shader compiler #include +#include +#include +#include #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h" @@ -21,14 +24,21 @@ using namespace WallpaperEngine::Core; namespace WallpaperEngine::Render::Shaders { - Compiler::Compiler (Irrlicht::CContext* context, irr::io::path& file, Type type, std::map combos, bool recursive) : - m_combos (std::move(combos)), + Compiler::Compiler ( + Irrlicht::CContext* context, + irr::io::path& file, + Type type, + std::map combos, + const std::map& constants, + bool recursive) : + m_combos (combos), m_recursive (recursive), m_type (type), m_file (file), m_error (""), m_errorInfo (""), - m_context (context) + m_context (context), + m_constants (constants) { this->m_content =WallpaperEngine::FileSystem::loadFullFile (file); } @@ -209,9 +219,11 @@ namespace WallpaperEngine::Render::Shaders // now compile the new shader // do not include the default header (as it's already included in the parent) - Compiler loader (this->m_context, shader, this->m_type, this->m_combos, true); + Compiler loader (this->m_context, shader, this->m_type, this->m_combos, this->m_constants, true); - return loader.precompile (); + loader.precompile (); + + return loader.getCompiled (); } std::string Compiler::lookupReplaceSymbol (std::string symbol) @@ -233,7 +245,12 @@ namespace WallpaperEngine::Render::Shaders return symbol; } - std::string Compiler::precompile() + std::string& Compiler::getCompiled () + { + return this->m_compiledContent; + } + + void Compiler::precompile() { #define BREAK_IF_ERROR if (this->m_error == true) { throw std::runtime_error ("ERROR PRE-COMPILING SHADER" + this->m_errorInfo); } // parse the shader and find #includes and such things and translate them to the correct name @@ -475,10 +492,11 @@ namespace WallpaperEngine::Render::Shaders if (this->m_recursive == false) { std::cout << "======================== COMPILED SHADER " << this->m_file.c_str () << " ========================" << std::endl; - std::cout << this->m_compiledContent << std::endl; + std::cout << finalCode << std::endl; } - return finalCode; + // store the final final code here + this->m_compiledContent = finalCode; #undef BREAK_IF_ERROR } @@ -526,16 +544,19 @@ namespace WallpaperEngine::Render::Shaders auto range = data.find ("range"); // this is not a real parameter - if (material == data.end () || defvalue == data.end ()) + if (material == data.end ()) + return; + auto constant = this->m_constants.find (*material); + + if (constant == this->m_constants.end () && defvalue == data.end ()) { if (type != "sampler2D") - throw std::runtime_error ("cannot parse parameter info for " + name); - - return; + throw std::runtime_error ("cannot parse parameter data"); } Variables::CShaderVariable* parameter = nullptr; + // TODO: SUPPORT VALUES FOR ALL THESE TYPES if (type == "vec4") { parameter = new Variables::CShaderVariableVector4 ( @@ -545,7 +566,9 @@ namespace WallpaperEngine::Render::Shaders else if (type == "vec3") { parameter = new Variables::CShaderVariableVector3 ( - WallpaperEngine::Core::ato3vf (*defvalue) + constant == this->m_constants.end () + ? WallpaperEngine::Core::ato3vf (*defvalue) + : *(*constant).second->as ()->getValue () ); } else if (type == "vec2") @@ -556,11 +579,29 @@ namespace WallpaperEngine::Render::Shaders } else if (type == "float") { - parameter = new Variables::CShaderVariableFloat ((*defvalue).get ()); + irr::f32 value = 0; + + if (constant == this->m_constants.end ()) + value = (*defvalue).get (); + else if ((*constant).second->is () == true) + value = *(*constant).second->as ()->getValue (); + else if ((*constant).second->is () == true) + value = *(*constant).second->as ()->getValue (); + + parameter = new Variables::CShaderVariableFloat (value); } else if (type == "int") { - parameter = new Variables::CShaderVariableInteger ((*defvalue).get ()); + irr::s32 value = 0; + + if (constant == this->m_constants.end ()) + value = (*defvalue).get (); + else if ((*constant).second->is () == true) + value = *(*constant).second->as ()->getValue (); + else if ((*constant).second->is () == true) + value = *(*constant).second->as ()->getValue (); + + parameter = new Variables::CShaderVariableInteger (value); } else if (type == "sampler2D") { diff --git a/src/WallpaperEngine/Render/Shaders/Compiler.h b/src/WallpaperEngine/Render/Shaders/Compiler.h index 03b16e5..fe5d970 100644 --- a/src/WallpaperEngine/Render/Shaders/Compiler.h +++ b/src/WallpaperEngine/Render/Shaders/Compiler.h @@ -16,6 +16,7 @@ namespace WallpaperEngine::Render::Shaders { using json = nlohmann::json; + using namespace WallpaperEngine::Core::Objects::Effects::Constants; /** * A basic shader loader that adds basic function definitions to every loaded shader @@ -50,18 +51,29 @@ namespace WallpaperEngine::Render::Shaders * @param file The file to load * @param type The type of shader * @param combos Settings for the shader + * @param constants Default values for shader variables * @param recursive Whether the compiler should add base definitions or not */ - Compiler (Irrlicht::CContext* context, irr::io::path& file, Type type, std::map combos, bool recursive = false); + Compiler ( + Irrlicht::CContext* context, + irr::io::path& file, + Type type, + std::map combos, + const std::map& constants, + 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 (); + void precompile (); + /** + * @return The compiled shader's text (if available) + */ + std::string& getCompiled (); + /** * Searches the list of parameters available for the parameter with the given value * @@ -225,6 +237,10 @@ namespace WallpaperEngine::Render::Shaders * The combos the shader should be generated with */ std::map m_combos; + /** + * The shader constants with values for variables inside the shader + */ + const std::map& m_constants; /** * Whether this compilation is a recursive one or not */