From c7ba0a2567357619fa9df0c80b96048256c9619f Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 15 Jun 2022 18:45:15 +0300 Subject: [PATCH] effects/blur: Make shader code readable At the moment, blur shader code is barely readable because the code is constructed at runtime. Since ShaderManager handles opengl context profiles when loading shaders from files, we can improve code readability by splitting shader code in the corresponding files. Note that ShaderManager adds "precision highp float;" for convenience (whether using "highp" is okay is up for debate). --- src/effects/blur/CMakeLists.txt | 1 + src/effects/blur/blur.qrc | 14 ++ src/effects/blur/blurshader.cpp | 156 +++--------------- src/effects/blur/shaders/copy.frag | 9 + src/effects/blur/shaders/copy_core.frag | 13 ++ src/effects/blur/shaders/downsample.frag | 17 ++ src/effects/blur/shaders/downsample_core.frag | 21 +++ src/effects/blur/shaders/noise.frag | 14 ++ src/effects/blur/shaders/noise_core.frag | 18 ++ src/effects/blur/shaders/upsample.frag | 20 +++ src/effects/blur/shaders/upsample_core.frag | 24 +++ src/effects/blur/shaders/vertex.vert | 7 + src/effects/blur/shaders/vertex_core.vert | 9 + 13 files changed, 189 insertions(+), 134 deletions(-) create mode 100644 src/effects/blur/blur.qrc create mode 100644 src/effects/blur/shaders/copy.frag create mode 100644 src/effects/blur/shaders/copy_core.frag create mode 100644 src/effects/blur/shaders/downsample.frag create mode 100644 src/effects/blur/shaders/downsample_core.frag create mode 100644 src/effects/blur/shaders/noise.frag create mode 100644 src/effects/blur/shaders/noise_core.frag create mode 100644 src/effects/blur/shaders/upsample.frag create mode 100644 src/effects/blur/shaders/upsample_core.frag create mode 100644 src/effects/blur/shaders/vertex.vert create mode 100644 src/effects/blur/shaders/vertex_core.vert diff --git a/src/effects/blur/CMakeLists.txt b/src/effects/blur/CMakeLists.txt index 4bbcdb3ff6..a69b15355b 100644 --- a/src/effects/blur/CMakeLists.txt +++ b/src/effects/blur/CMakeLists.txt @@ -3,6 +3,7 @@ set(blur_SOURCES blur.cpp + blur.qrc blurshader.cpp main.cpp ) diff --git a/src/effects/blur/blur.qrc b/src/effects/blur/blur.qrc new file mode 100644 index 0000000000..3e09aa9c99 --- /dev/null +++ b/src/effects/blur/blur.qrc @@ -0,0 +1,14 @@ + + + shaders/copy.frag + shaders/copy_core.frag + shaders/downsample.frag + shaders/downsample_core.frag + shaders/noise.frag + shaders/noise_core.frag + shaders/upsample.frag + shaders/upsample_core.frag + shaders/vertex.vert + shaders/vertex_core.vert + + diff --git a/src/effects/blur/blurshader.cpp b/src/effects/blur/blurshader.cpp index 8bad250c9e..e609c1e0f4 100644 --- a/src/effects/blur/blurshader.cpp +++ b/src/effects/blur/blurshader.cpp @@ -8,10 +8,12 @@ #include "blurshader.h" #include -#include -#include -#include +static void ensureResources() +{ + // Must initialize resources manually because the effect is a static lib. + Q_INIT_RESOURCE(blur); +} namespace KWin { @@ -19,141 +21,27 @@ namespace KWin BlurShader::BlurShader(QObject *parent) : QObject(parent) { - const bool gles = GLPlatform::instance()->isGLES(); - const bool glsl_140 = !gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(1, 40); - const bool core = glsl_140 || (gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(3, 0)); + ensureResources(); - QByteArray vertexSource; - QByteArray fragmentDownSource; - QByteArray fragmentUpSource; - QByteArray fragmentCopySource; - QByteArray fragmentNoiseSource; + m_shaderDownsample.reset(ShaderManager::instance()->generateShaderFromFile( + ShaderTrait::MapTexture, + QStringLiteral(":/effects/blur/shaders/vertex.vert"), + QStringLiteral(":/effects/blur/shaders/downsample.frag"))); - const QByteArray attribute = core ? "in" : "attribute"; - const QByteArray texture2D = core ? "texture" : "texture2D"; - const QByteArray fragColor = core ? "fragColor" : "gl_FragColor"; + m_shaderUpsample.reset(ShaderManager::instance()->generateShaderFromFile( + ShaderTrait::MapTexture, + QStringLiteral(":/effects/blur/shaders/vertex.vert"), + QStringLiteral(":/effects/blur/shaders/upsample.frag"))); - QString glHeaderString; + m_shaderCopysample.reset(ShaderManager::instance()->generateShaderFromFile( + ShaderTrait::MapTexture, + QStringLiteral(":/effects/blur/shaders/vertex.vert"), + QStringLiteral(":/effects/blur/shaders/copy.frag"))); - if (gles) { - if (core) { - glHeaderString += "#version 300 es\n\n"; - } - - glHeaderString += "precision highp float;\n"; - } else if (glsl_140) { - glHeaderString += "#version 140\n\n"; - } - - QString glUniformString = "uniform sampler2D texUnit;\n" - "uniform float offset;\n" - "uniform vec2 renderTextureSize;\n" - "uniform vec2 halfpixel;\n"; - - if (core) { - glUniformString += "out vec4 fragColor;\n\n"; - } - - // Vertex shader - QTextStream streamVert(&vertexSource); - - streamVert << glHeaderString; - - streamVert << "uniform mat4 modelViewProjectionMatrix;\n"; - streamVert << attribute << " vec4 vertex;\n\n"; - streamVert << "\n"; - streamVert << "void main(void)\n"; - streamVert << "{\n"; - streamVert << " gl_Position = modelViewProjectionMatrix * vertex;\n"; - streamVert << "}\n"; - - streamVert.flush(); - - // Fragment shader (Dual Kawase Blur) - Downsample - QTextStream streamFragDown(&fragmentDownSource); - - streamFragDown << glHeaderString << glUniformString; - - streamFragDown << "void main(void)\n"; - streamFragDown << "{\n"; - streamFragDown << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; - streamFragDown << " \n"; - streamFragDown << " vec4 sum = " << texture2D << "(texUnit, uv) * 4.0;\n"; - streamFragDown << " sum += " << texture2D << "(texUnit, uv - halfpixel.xy * offset);\n"; - streamFragDown << " sum += " << texture2D << "(texUnit, uv + halfpixel.xy * offset);\n"; - streamFragDown << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset);\n"; - streamFragDown << " sum += " << texture2D << "(texUnit, uv - vec2(halfpixel.x, -halfpixel.y) * offset);\n"; - streamFragDown << " \n"; - streamFragDown << " " << fragColor << " = sum / 8.0;\n"; - streamFragDown << "}\n"; - - streamFragDown.flush(); - - // Fragment shader (Dual Kawase Blur) - Upsample - QTextStream streamFragUp(&fragmentUpSource); - - streamFragUp << glHeaderString << glUniformString; - - streamFragUp << "void main(void)\n"; - streamFragUp << "{\n"; - streamFragUp << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; - streamFragUp << " \n"; - streamFragUp << " vec4 sum = " << texture2D << "(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset);\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset);\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset);\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n"; - streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; - streamFragUp << " \n"; - streamFragUp << " " << fragColor << " = sum / 12.0;\n"; - streamFragUp << "}\n"; - - streamFragUp.flush(); - - // Fragment shader - Copy texture - QTextStream streamFragCopy(&fragmentCopySource); - - streamFragCopy << glHeaderString; - - streamFragCopy << "uniform sampler2D texUnit;\n"; - streamFragCopy << "uniform vec2 renderTextureSize;\n"; - streamFragCopy << "uniform vec4 blurRect;\n"; - - if (core) { - streamFragCopy << "out vec4 fragColor;\n\n"; - } - - streamFragCopy << "void main(void)\n"; - streamFragCopy << "{\n"; - streamFragCopy << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; - streamFragCopy << " " << fragColor << " = " << texture2D << "(texUnit, clamp(uv, blurRect.xy, blurRect.zw));\n"; - streamFragCopy << "}\n"; - - streamFragCopy.flush(); - - // Fragment shader - Noise tiling - QTextStream streamFragNoise(&fragmentNoiseSource); - - streamFragNoise << glHeaderString << glUniformString; - - streamFragNoise << "uniform vec2 noiseTextureSize;\n"; - streamFragNoise << "uniform vec2 texStartPos;\n"; - - streamFragNoise << "void main(void)\n"; - streamFragNoise << "{\n"; - streamFragNoise << " vec2 uvNoise = vec2((texStartPos.xy + gl_FragCoord.xy) / noiseTextureSize);\n"; - streamFragNoise << " \n"; - streamFragNoise << " " << fragColor << " = vec4(" << texture2D << "(texUnit, uvNoise).rrr, 0);\n"; - streamFragNoise << "}\n"; - - streamFragNoise.flush(); - - m_shaderDownsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource)); - m_shaderUpsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource)); - m_shaderCopysample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource)); - m_shaderNoisesample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource)); + m_shaderNoisesample.reset(ShaderManager::instance()->generateShaderFromFile( + ShaderTrait::MapTexture, + QStringLiteral(":/effects/blur/shaders/vertex.vert"), + QStringLiteral(":/effects/blur/shaders/noise.frag"))); m_valid = m_shaderDownsample->isValid() && m_shaderUpsample->isValid() && m_shaderCopysample->isValid() && m_shaderNoisesample->isValid(); diff --git a/src/effects/blur/shaders/copy.frag b/src/effects/blur/shaders/copy.frag new file mode 100644 index 0000000000..d2859063c3 --- /dev/null +++ b/src/effects/blur/shaders/copy.frag @@ -0,0 +1,9 @@ +uniform sampler2D texUnit; +uniform vec2 renderTextureSize; +uniform vec4 blurRect; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + gl_FragColor = texture2D(texUnit, clamp(uv, blurRect.xy, blurRect.zw)); +} diff --git a/src/effects/blur/shaders/copy_core.frag b/src/effects/blur/shaders/copy_core.frag new file mode 100644 index 0000000000..9bcca7c672 --- /dev/null +++ b/src/effects/blur/shaders/copy_core.frag @@ -0,0 +1,13 @@ +#version 140 + +uniform sampler2D texUnit; +uniform vec2 renderTextureSize; +uniform vec4 blurRect; + +out vec4 fragColor; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + fragColor = texture(texUnit, clamp(uv, blurRect.xy, blurRect.zw)); +} diff --git a/src/effects/blur/shaders/downsample.frag b/src/effects/blur/shaders/downsample.frag new file mode 100644 index 0000000000..a17851be1f --- /dev/null +++ b/src/effects/blur/shaders/downsample.frag @@ -0,0 +1,17 @@ +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + + vec4 sum = texture2D(texUnit, uv) * 4.0; + sum += texture2D(texUnit, uv - halfpixel.xy * offset); + sum += texture2D(texUnit, uv + halfpixel.xy * offset); + sum += texture2D(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset); + sum += texture2D(texUnit, uv - vec2(halfpixel.x, -halfpixel.y) * offset); + + gl_FragColor = sum / 8.0; +} diff --git a/src/effects/blur/shaders/downsample_core.frag b/src/effects/blur/shaders/downsample_core.frag new file mode 100644 index 0000000000..39dd38a8dc --- /dev/null +++ b/src/effects/blur/shaders/downsample_core.frag @@ -0,0 +1,21 @@ +#version 140 + +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +out vec4 fragColor; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + + vec4 sum = texture(texUnit, uv) * 4.0; + sum += texture(texUnit, uv - halfpixel.xy * offset); + sum += texture(texUnit, uv + halfpixel.xy * offset); + sum += texture(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset); + sum += texture(texUnit, uv - vec2(halfpixel.x, -halfpixel.y) * offset); + + fragColor = sum / 8.0; +} diff --git a/src/effects/blur/shaders/noise.frag b/src/effects/blur/shaders/noise.frag new file mode 100644 index 0000000000..ed89e61d51 --- /dev/null +++ b/src/effects/blur/shaders/noise.frag @@ -0,0 +1,14 @@ +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +uniform vec2 noiseTextureSize; +uniform vec2 texStartPos; + +void main(void) +{ + vec2 uvNoise = vec2((texStartPos.xy + gl_FragCoord.xy) / noiseTextureSize); + + gl_FragColor = vec4(texture2D(texUnit, uvNoise).rrr, 0); +} diff --git a/src/effects/blur/shaders/noise_core.frag b/src/effects/blur/shaders/noise_core.frag new file mode 100644 index 0000000000..63a6ede78e --- /dev/null +++ b/src/effects/blur/shaders/noise_core.frag @@ -0,0 +1,18 @@ +#version 140 + +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +uniform vec2 noiseTextureSize; +uniform vec2 texStartPos; + +out vec4 fragColor; + +void main(void) +{ + vec2 uvNoise = vec2((texStartPos.xy + gl_FragCoord.xy) / noiseTextureSize); + + fragColor = vec4(texture(texUnit, uvNoise).rrr, 0); +} diff --git a/src/effects/blur/shaders/upsample.frag b/src/effects/blur/shaders/upsample.frag new file mode 100644 index 0000000000..2fc6da176c --- /dev/null +++ b/src/effects/blur/shaders/upsample.frag @@ -0,0 +1,20 @@ +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + + vec4 sum = texture2D(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset); + sum += texture2D(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0; + sum += texture2D(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset); + sum += texture2D(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0; + sum += texture2D(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset); + sum += texture2D(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0; + sum += texture2D(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset); + sum += texture2D(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0; + + gl_FragColor = sum / 12.0; +} diff --git a/src/effects/blur/shaders/upsample_core.frag b/src/effects/blur/shaders/upsample_core.frag new file mode 100644 index 0000000000..0494141a3f --- /dev/null +++ b/src/effects/blur/shaders/upsample_core.frag @@ -0,0 +1,24 @@ +#version 140 + +uniform sampler2D texUnit; +uniform float offset; +uniform vec2 renderTextureSize; +uniform vec2 halfpixel; + +out vec4 fragColor; + +void main(void) +{ + vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize); + + vec4 sum = texture(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset); + sum += texture(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0; + sum += texture(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset); + sum += texture(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0; + sum += texture(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset); + sum += texture(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0; + sum += texture(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset); + sum += texture(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0; + + fragColor = sum / 12.0; +} diff --git a/src/effects/blur/shaders/vertex.vert b/src/effects/blur/shaders/vertex.vert new file mode 100644 index 0000000000..cdee50bc04 --- /dev/null +++ b/src/effects/blur/shaders/vertex.vert @@ -0,0 +1,7 @@ +uniform mat4 modelViewProjectionMatrix; +attribute vec4 vertex; + +void main(void) +{ + gl_Position = modelViewProjectionMatrix * vertex; +} diff --git a/src/effects/blur/shaders/vertex_core.vert b/src/effects/blur/shaders/vertex_core.vert new file mode 100644 index 0000000000..0a7de7ef3e --- /dev/null +++ b/src/effects/blur/shaders/vertex_core.vert @@ -0,0 +1,9 @@ +#version 140 + +uniform mat4 modelViewProjectionMatrix; +in vec4 vertex; + +void main(void) +{ + gl_Position = modelViewProjectionMatrix * vertex; +}