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; +}