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).
This commit is contained in:
Vlad Zahorodnii 2022-06-15 18:45:15 +03:00
parent a4b41c84e1
commit c7ba0a2567
13 changed files with 189 additions and 134 deletions

View file

@ -3,6 +3,7 @@
set(blur_SOURCES
blur.cpp
blur.qrc
blurshader.cpp
main.cpp
)

14
src/effects/blur/blur.qrc Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effects/blur/">
<file>shaders/copy.frag</file>
<file>shaders/copy_core.frag</file>
<file>shaders/downsample.frag</file>
<file>shaders/downsample_core.frag</file>
<file>shaders/noise.frag</file>
<file>shaders/noise_core.frag</file>
<file>shaders/upsample.frag</file>
<file>shaders/upsample_core.frag</file>
<file>shaders/vertex.vert</file>
<file>shaders/vertex_core.vert</file>
</qresource>
</RCC>

View file

@ -8,10 +8,12 @@
#include "blurshader.h"
#include <kwineffects.h>
#include <kwinglplatform.h>
#include <QByteArray>
#include <QTextStream>
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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
uniform mat4 modelViewProjectionMatrix;
attribute vec4 vertex;
void main(void)
{
gl_Position = modelViewProjectionMatrix * vertex;
}

View file

@ -0,0 +1,9 @@
#version 140
uniform mat4 modelViewProjectionMatrix;
in vec4 vertex;
void main(void)
{
gl_Position = modelViewProjectionMatrix * vertex;
}