Upgraded to shader version 330

Added support for shader patches
Removed useless DEBUG define in favour of NDEBUG

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2023-02-11 03:11:27 +01:00
parent 4e0f02f64d
commit 37631e9c40
14 changed files with 204 additions and 51 deletions

View File

@ -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()

View File

@ -0,0 +1,13 @@
{
"patches": [
{
"matches": [
"uniform float g_Chromatic;",
"g_AudioSpectrum16Left[g_Chromatic]"
],
"replacements": {
"g_AudioSpectrum16Left[g_Chromatic]": "g_AudioSpectrum16Left[int(g_Chromatic)]"
}
}
]
}

View File

@ -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 ();

View File

@ -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&)
{
}
}
}

View File

@ -64,7 +64,6 @@ namespace WallpaperEngine::Assets
*/
std::string readIncludeShader (const std::string& filename) const;
private:
/**
* Reads a file as string
*

View File

@ -35,7 +35,7 @@ namespace WallpaperEngine::Logging
template<typename... Data>
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<typename... Data>
void debugerror (Data... data)
{
#if DEBUG && ERRORONLY
#if (!NDEBUG) && (ERRORONLY)
// buffer the string first
std::stringbuf buffer;
std::ostream bufferStream (&buffer);

View File

@ -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)

View File

@ -23,7 +23,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
{
auto context = static_cast <CRenderContext*> (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 <CVideo> ();
#if DEBUG
#if !NDEBUG
glPopDebugGroup ();
#endif /* DEBUG */
}

View File

@ -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);

View File

@ -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 */

View File

@ -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 */
}

View File

@ -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 ());

View File

@ -12,6 +12,8 @@
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h>
#include <regex>
#include <filesystem>
#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 <std::string, bool> 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);

View File

@ -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
*/