Commit c7ba0a25 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

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).
parent a4b41c84
Pipeline #191867 passed with stage
in 29 minutes and 44 seconds
......@@ -3,6 +3,7 @@
set(blur_SOURCES
blur.cpp
blur.qrc
blurshader.cpp
main.cpp
)
......
<!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>
......@@ -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));
QByteArray vertexSource;
QByteArray fragmentDownSource;
QByteArray fragmentUpSource;
QByteArray fragmentCopySource;
QByteArray fragmentNoiseSource;
const QByteArray attribute = core ? "in" : "attribute";
const QByteArray texture2D = core ? "texture" : "texture2D";
const QByteArray fragColor = core ? "fragColor" : "gl_FragColor";
QString glHeaderString;
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));
ensureResources();
m_shaderDownsample.reset(ShaderManager::instance()->generateShaderFromFile(
ShaderTrait::MapTexture,
QStringLiteral(":/effects/blur/shaders/vertex.vert"),
QStringLiteral(":/effects/blur/shaders/downsample.frag")));
m_shaderUpsample.reset(ShaderManager::instance()->generateShaderFromFile(
ShaderTrait::MapTexture,
QStringLiteral(":/effects/blur/shaders/vertex.vert"),
QStringLiteral(":/effects/blur/shaders/upsample.frag")));
m_shaderCopysample.reset(ShaderManager::instance()->generateShaderFromFile(
ShaderTrait::MapTexture,
QStringLiteral(":/effects/blur/shaders/vertex.vert"),
QStringLiteral(":/effects/blur/shaders/copy.frag")));
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();
......
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));
}
#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));
}
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;
}
#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;
}
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);
}
#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);
}
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;
}
#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;
}
uniform mat4 modelViewProjectionMatrix;
attribute vec4 vertex;
void main(void)
{
gl_Position = modelViewProjectionMatrix * vertex;
}
#version 140
uniform mat4 modelViewProjectionMatrix;
in vec4 vertex;
void main(void)
{
gl_Position = modelViewProjectionMatrix * vertex;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment