From 37631e9c402e44c99adcaec127942b09d92a64ba Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Date: Sat, 11 Feb 2023 03:11:27 +0100 Subject: [PATCH] Upgraded to shader version 330 Added support for shader patches Removed useless DEBUG define in favour of NDEBUG Signed-off-by: Alexis Maiquez --- CMakeLists.txt | 16 +- share/patches/vhstest.vert.json | 13 ++ .../Application/CWallpaperApplication.cpp | 5 + src/WallpaperEngine/Assets/CContainer.cpp | 28 ++-- src/WallpaperEngine/Assets/CContainer.h | 1 - src/WallpaperEngine/Logging/CLog.h | 4 +- src/WallpaperEngine/Render/CFBO.cpp | 4 +- src/WallpaperEngine/Render/CRenderContext.cpp | 12 +- src/WallpaperEngine/Render/CWallpaper.cpp | 17 ++- .../Render/Drivers/COpenGLDriver.cpp | 2 +- src/WallpaperEngine/Render/Objects/CImage.cpp | 7 +- .../Render/Objects/Effects/CPass.cpp | 4 +- .../Render/Shaders/Compiler.cpp | 137 ++++++++++++++++-- src/WallpaperEngine/Render/Shaders/Compiler.h | 5 + 14 files changed, 204 insertions(+), 51 deletions(-) create mode 100644 share/patches/vhstest.vert.json diff --git a/CMakeLists.txt b/CMakeLists.txt index d897adc..e6797e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,16 @@ project(linux-wallpaperengine) set(CMAKE_CXX_STANDARD 17) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") set(OpenGL_GL_PREFERENCE "LEGACY") +set(DATADIR ${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}) +set(PATCHESDIR ${DATADIR}/patches/) + +if(NOT ERRORONLY) + set(ERRORONLY 0) +endif() # if you're developing you might find this debug option useful for shader output, although RenderDoc is encouraged -add_compile_definitions(DEBUG=1) -add_compile_definitions(ERRORONLY=1) +add_compile_definitions(ERRORONLY=${ERRORONLY}) +add_compile_definitions(DATADIR="${DATADIR}") find_package(X11 REQUIRED) find_package(Xrandr REQUIRED) @@ -254,4 +260,10 @@ check_function_exists(XSetIOErrorExitHandler HAVE_XSETIOERROREXITHANDLER) if(HAVE_XSETIOERROREXITHANDLER) add_compile_definitions(HAVE_XSETIOERROREXITHANDLER=1) +endif() + +# set some install parameters if not in debug mode +if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + install(TARGETS linux-wallpaperengine) + install(DIRECTORY share/ DESTINATION share/${PROJECT_NAME}) endif() \ No newline at end of file diff --git a/share/patches/vhstest.vert.json b/share/patches/vhstest.vert.json new file mode 100644 index 0000000..acdaa5c --- /dev/null +++ b/share/patches/vhstest.vert.json @@ -0,0 +1,13 @@ +{ + "patches": [ + { + "matches": [ + "uniform float g_Chromatic;", + "g_AudioSpectrum16Left[g_Chromatic]" + ], + "replacements": { + "g_AudioSpectrum16Left[g_Chromatic]": "g_AudioSpectrum16Left[int(g_Chromatic)]" + } + } + ] +} \ No newline at end of file diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.cpp b/src/WallpaperEngine/Application/CWallpaperApplication.cpp index 860b02d..763bdf2 100644 --- a/src/WallpaperEngine/Application/CWallpaperApplication.cpp +++ b/src/WallpaperEngine/Application/CWallpaperApplication.cpp @@ -34,6 +34,11 @@ void CWallpaperApplication::setupContainer () this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "scene.pkg"); this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "gifscene.pkg"); this->m_vfs.add (new CDirectory (this->m_context.assets)); +#if !NDEBUG + this->m_vfs.add (new CDirectory ("../share/")); +#else + this->m_vfs.add (new CDirectory (DATADIR)); +#endif /* DEBUG */ // TODO: move this somewhere else? CVirtualContainer* container = new CVirtualContainer (); diff --git a/src/WallpaperEngine/Assets/CContainer.cpp b/src/WallpaperEngine/Assets/CContainer.cpp index f525edf..144ac79 100644 --- a/src/WallpaperEngine/Assets/CContainer.cpp +++ b/src/WallpaperEngine/Assets/CContainer.cpp @@ -18,9 +18,9 @@ const ITexture* CContainer::readTexture (std::string filename) const ITexture* result = new CTexture (textureContents); -#if DEBUG +#if !NDEBUG glObjectLabel (GL_TEXTURE, result->getTextureID (), -1, filename.c_str ()); -#endif /* DEBUG */ +#endif /* NDEBUG */ return result; } @@ -33,21 +33,25 @@ std::string CContainer::readShader (const std::string& filename) const if (*it++ == "workshop") { std::filesystem::path workshopId = *it++; - std::filesystem::path shaderfile = *++it; - try + if (++it != shader.end ()) { - shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile; - // replace the old path with the new one - std::string contents = this->readFileAsString (shader); + std::filesystem::path shaderfile = *it; - sLog.out ("Replaced ", filename, " with compat ", shader); + try + { + shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile; + // replace the old path with the new one + std::string contents = this->readFileAsString (shader); - return contents; - } - catch (CAssetLoadException&) - { + sLog.out ("Replaced ", filename, " with compat ", shader); + return contents; + } + catch (CAssetLoadException&) + { + + } } } diff --git a/src/WallpaperEngine/Assets/CContainer.h b/src/WallpaperEngine/Assets/CContainer.h index a58e025..e3d84fe 100644 --- a/src/WallpaperEngine/Assets/CContainer.h +++ b/src/WallpaperEngine/Assets/CContainer.h @@ -64,7 +64,6 @@ namespace WallpaperEngine::Assets */ std::string readIncludeShader (const std::string& filename) const; - private: /** * Reads a file as string * diff --git a/src/WallpaperEngine/Logging/CLog.h b/src/WallpaperEngine/Logging/CLog.h index 933082c..a6146ca 100644 --- a/src/WallpaperEngine/Logging/CLog.h +++ b/src/WallpaperEngine/Logging/CLog.h @@ -35,7 +35,7 @@ namespace WallpaperEngine::Logging template void debug (Data... data) { -#if DEBUG && !ERRORONLY +#if (!NDEBUG) && (!ERRORONLY) // buffer the string first std::stringbuf buffer; std::ostream bufferStream (&buffer); @@ -51,7 +51,7 @@ namespace WallpaperEngine::Logging template void debugerror (Data... data) { -#if DEBUG && ERRORONLY +#if (!NDEBUG) && (ERRORONLY) // buffer the string first std::stringbuf buffer; std::ostream bufferStream (&buffer); diff --git a/src/WallpaperEngine/Render/CFBO.cpp b/src/WallpaperEngine/Render/CFBO.cpp index 066660d..11fa2c6 100644 --- a/src/WallpaperEngine/Render/CFBO.cpp +++ b/src/WallpaperEngine/Render/CFBO.cpp @@ -32,8 +32,8 @@ CFBO::CFBO ( // give OpenGL an empty image glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); // label stuff for debugging -#if DEBUG - glObjectLabel (GL_TEXTURE, this->m_texture, -1, this->m_name.c_str ()); +#if !NDEBUG + glObjectLabel (GL_TEXTURE, this->m_texture, -1, this->m_name.c_str ()); #endif /* DEBUG */ // set filtering parameters, otherwise the texture is not rendered if (flags & TextureFlags::ClampUVs) diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp index cc797a1..4f8439d 100644 --- a/src/WallpaperEngine/Render/CRenderContext.cpp +++ b/src/WallpaperEngine/Render/CRenderContext.cpp @@ -23,7 +23,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata) { auto context = static_cast (userdata); -#ifdef DEBUG +#if !NDEBUG sLog.debugerror ("Critical XServer error detected. Attempting to recover..."); #endif /* DEBUG */ @@ -33,7 +33,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata) int CustomXErrorHandler (Display* dpy, XErrorEvent* event) { -#ifdef DEBUG +#if !NDEBUG sLog.debugerror ("Detected X error"); #endif /* DEBUG */ @@ -45,7 +45,7 @@ int CustomXErrorHandler (Display* dpy, XErrorEvent* event) int CustomXIOErrorHandler (Display* dsp) { -#ifdef DEBUG +#if !NDEBUG sLog.debugerror ("Detected X error"); #endif /* DEBUG */ @@ -188,7 +188,7 @@ void CRenderContext::renderScreens () for (const auto& cur : this->m_viewports) { -#if DEBUG +#if !NDEBUG std::string str = "Rendering to screen " + cur.name; glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ()); @@ -199,9 +199,7 @@ void CRenderContext::renderScreens () // scenes need to render a new frame for each viewport as they produce different results // but videos should only be rendered once per group of viewports firstFrame = false; - renderFrame = !this->m_wallpaper->is (); - -#if DEBUG +#if !NDEBUG glPopDebugGroup (); #endif /* DEBUG */ } diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 3bf1435..4871d99 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -87,10 +87,11 @@ void CWallpaper::setupShaders () GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER); // give shader's source code to OpenGL to be compiled - const char* sourcePointer = "#version 120\n" - "attribute vec3 a_Position;\n" - "attribute vec2 a_TexCoord;\n" - "varying vec2 v_TexCoord;\n" + const char* sourcePointer = "#version 330\n" + "precision highp float;\n" + "in vec3 a_Position;\n" + "in vec2 a_TexCoord;\n" + "out vec2 v_TexCoord;\n" "void main () {\n" "gl_Position = vec4 (a_Position, 1.0);\n" "v_TexCoord = a_TexCoord;\n" @@ -125,11 +126,13 @@ void CWallpaper::setupShaders () GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER); // give shader's source code to OpenGL to be compiled - sourcePointer = "#version 120\n" + sourcePointer = "#version 330\n" + "precision highp float;\n" "uniform sampler2D g_Texture0;\n" - "varying vec2 v_TexCoord;\n" + "in vec2 v_TexCoord;\n" + "out vec4 out_FragColor;\n" "void main () {\n" - "gl_FragColor = texture2D (g_Texture0, v_TexCoord);\n" + "out_FragColor = texture (g_Texture0, v_TexCoord);\n" "}"; glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr); diff --git a/src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp b/src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp index 14190ae..7ebfae6 100644 --- a/src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp +++ b/src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp @@ -18,7 +18,7 @@ COpenGLDriver::COpenGLDriver (const char* windowTitle) : glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint (GLFW_VISIBLE, GLFW_FALSE); -#if DEBUG +#if !NDEBUG glfwWindowHint (GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); #endif /* DEBUG */ diff --git a/src/WallpaperEngine/Render/Objects/CImage.cpp b/src/WallpaperEngine/Render/Objects/CImage.cpp index 0495200..c28c1da 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.cpp +++ b/src/WallpaperEngine/Render/Objects/CImage.cpp @@ -102,6 +102,7 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : // register both FBOs into the scene std::ostringstream nameA, nameB; + // TODO: determine when _rt_imageLayerComposite and _rt_imageLayerAlbedo is used nameA << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_a"; nameB << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_b"; @@ -395,7 +396,7 @@ void CImage::render () if (this->getScene ()->getScene ()->isCameraParallax ()) this->updateScreenSpacePosition (); -#if DEBUG +#if !NDEBUG std::string str = "Rendering "; if (this->getScene ()->getScene ()->isBloom () && this->getId () == 0xFFFFFFFF) @@ -421,8 +422,8 @@ void CImage::render () (*cur)->render (); } -#if DEBUG - glPopDebugGroup (); +#if !NDEBUG + glPopDebugGroup (); #endif /* DEBUG */ } diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp index 936dc5c..5378ccf 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp @@ -246,7 +246,7 @@ void CPass::render () glBindBuffer (GL_ARRAY_BUFFER, *cur->value); glVertexAttribPointer (cur->id, cur->elements, cur->type, GL_FALSE, 0, nullptr); -#if DEBUG +#if !NDEBUG glObjectLabel (GL_BUFFER, *cur->value, -1, ( "Image " + std::to_string (this->getMaterial ()->getImage ()->getId ()) + " Pass " + this->m_pass->getShader() + @@ -429,7 +429,7 @@ void CPass::setupShaders () sLog.exception (message); } -#if DEBUG +#if !NDEBUG glObjectLabel (GL_PROGRAM, this->m_programID, -1, this->m_pass->getShader ().c_str ()); glObjectLabel (GL_SHADER, vertexShaderID, -1, (this->m_pass->getShader () + ".vert").c_str ()); glObjectLabel (GL_SHADER, fragmentShaderID, -1, (this->m_pass->getShader () + ".frag").c_str ()); diff --git a/src/WallpaperEngine/Render/Shaders/Compiler.cpp b/src/WallpaperEngine/Render/Shaders/Compiler.cpp index 06603a2..7b409df 100644 --- a/src/WallpaperEngine/Render/Shaders/Compiler.cpp +++ b/src/WallpaperEngine/Render/Shaders/Compiler.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "WallpaperEngine/Assets/CAssetLoadException.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h" @@ -498,17 +500,14 @@ namespace WallpaperEngine::Render::Shaders if (!this->m_recursive) { // add the opengl compatibility at the top - finalCode = "#version 150\n" + finalCode = "#version 330\n" "// ======================================================\n" "// Processed shader " + this->m_file + "\n" "// ======================================================\n" - "#define highp\n" - "#define mediump\n" - "#define lowp\n" + "precision highp float;\n" "#define mul(x, y) ((y) * (x))\n" - "#define max(x, y) max (y, x)\n" - "#define fmod(x, y) ((x)-(y)*trunc((x)/(y)))\n" - "#define lerp mix\n" + "#define max(x, y) max (y, x)\n" + "#define lerp mix\n" "#define frac fract\n" "#define CAST2(x) (vec2(x))\n" "#define CAST3(x) (vec3(x))\n" @@ -518,13 +517,21 @@ namespace WallpaperEngine::Render::Shaders "#define texSample2D texture\n" "#define texSample2DLod textureLod\n" "#define atan2 atan\n" + "#define fmod(x, y) ((x)-(y)*trunc((x)/(y)))\n" "#define ddx dFdx\n" "#define ddy(x) dFdy(-(x))\n" - "#define GLSL 1\n" - "#define float1 float\n" - "#define float2 vec2\n" - "#define float3 vec3\n" - "#define float4 vec4\n\n"; + "#define GLSL 1\n\n"; + + if (this->m_type == Type_Vertex) + { + finalCode += "#define attribute in\n" + "#define varying out\n"; + } + else + { + finalCode += "out vec4 out_FragColor;\n" + "#define varying in\n"; + } finalCode += "// ======================================================\n" "// Shader combo parameter definitions\n" @@ -551,8 +558,69 @@ namespace WallpaperEngine::Render::Shaders finalCode += "#define " + cur.first + " " + std::to_string (cur.second) + "\n"; } + + // define to 0 everything else found in the code + std::regex ifs ("#if ([A-Za-z0-9_]+)"); + auto words_begin = std::sregex_iterator (this->m_compiledContent.begin (), this->m_compiledContent.end (), ifs); + auto words_end = std::sregex_iterator (); + std::map inserted; + + for (; words_begin != words_end; words_begin ++) + { + std::string define = (*words_begin).str ().substr (4); + + if ( + this->m_foundCombos->find (define) != this->m_foundCombos->end () || + this->m_baseCombos.find (define) != this->m_baseCombos.end () || + inserted.find (define) != inserted.end ()) + continue; + + finalCode += "#define " + define + " 0\n"; + } } + // replace gl_FragColor with the equivalent + std::string from = "gl_FragColor"; + std::string to = "out_FragColor"; + + size_t start_pos = 0; + while((start_pos = this->m_compiledContent.find(from, start_pos)) != std::string::npos) { + this->m_compiledContent.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + + // replace sample occurrences + from = "sample"; + to = "_sample"; + + start_pos = 0; + while((start_pos = this->m_compiledContent.find(from, start_pos)) != std::string::npos) { + // ensure that after it comes something like a space or a ; or a tab + std::string after = this->m_compiledContent.substr (start_pos + from.length (), 1); + + if ( + after != " " && after != ";" && after != "\t" && + after != "=" && after != "+" && after != "-" && + after != "/" && after != "*" && after != "." && + after != "," && after != ")") + { + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + continue; + } + + this->m_compiledContent.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + + try + { + this->applyPatches (); + } + catch (CAssetLoadException&) + { + // nothing important, no patch was found + } + finalCode += this->m_compiledContent; if (!this->m_recursive) @@ -566,6 +634,51 @@ namespace WallpaperEngine::Render::Shaders #undef BREAK_IF_ERROR } + void Compiler::applyPatches () + { + // small patches for things, looks like the official wpengine does the same thing + std::filesystem::path file = this->m_file; + file = "patches" / file.filename (); + + if (this->m_type == Type_Vertex) + file += ".vert"; + else if (this->m_type == Type_Pixel) + file += ".frag"; + + file += ".json"; + + std::string tmp = file; + std::string patchContents = this->m_container.readFileAsString (file); + + json data = json::parse (patchContents); + auto patches = data.find ("patches"); + + for (auto patch : *patches) + { + auto matches = patch.find ("matches"); + + // check for matches first, as these signal whether the patch can be applied or not + for (const auto& match : *matches) + if (this->m_compiledContent.find (match) == std::string::npos) + continue; + + auto replacements = patch.find ("replacements"); + + for (const auto& replacement : (*replacements).items ()) + { + // replace gl_FragColor with the equivalent + std::string from = replacement.key (); + std::string to = replacement.value (); + + size_t start_pos = 0; + while((start_pos = this->m_compiledContent.find(from, start_pos)) != std::string::npos) { + this->m_compiledContent.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + } + } + } + void Compiler::parseComboConfiguration (const std::string& content, int defaultValue) { json data = json::parse (content); diff --git a/src/WallpaperEngine/Render/Shaders/Compiler.h b/src/WallpaperEngine/Render/Shaders/Compiler.h index f7061b3..707cdb2 100644 --- a/src/WallpaperEngine/Render/Shaders/Compiler.h +++ b/src/WallpaperEngine/Render/Shaders/Compiler.h @@ -199,6 +199,11 @@ namespace WallpaperEngine::Render::Shaders * @param content The parameter configuration */ void parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content); + /** + * Applies any available patches for this shader + */ + void applyPatches (); + /** * The shader file this instance is loading */