Initial commit of the blur effect rewrite.
svn path=/trunk/KDE/kdebase/workspace/; revision=1099619
This commit is contained in:
parent
48c3a09119
commit
53391ba944
6 changed files with 544 additions and 0 deletions
14
effects/blur/CMakeLists.txt
Normal file
14
effects/blur/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#######################################
|
||||||
|
# Effect
|
||||||
|
|
||||||
|
# Source files
|
||||||
|
set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
|
||||||
|
blur/blur.cpp
|
||||||
|
blur/blurshader.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# .desktop files
|
||||||
|
install( FILES
|
||||||
|
blur/blur.desktop
|
||||||
|
DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
|
||||||
|
|
200
effects/blur/blur.cpp
Normal file
200
effects/blur/blur.cpp
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. if not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blur.h"
|
||||||
|
#include "blurshader.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
KWIN_EFFECT(blur, BlurEffect)
|
||||||
|
KWIN_EFFECT_SUPPORTED(blur, BlurEffect::supported())
|
||||||
|
|
||||||
|
|
||||||
|
BlurEffect::BlurEffect()
|
||||||
|
: radius(12)
|
||||||
|
{
|
||||||
|
shader = new BlurShader;
|
||||||
|
shader->setRadius(radius);
|
||||||
|
|
||||||
|
// Offscreen texture that's used as the target for the horizontal blur pass
|
||||||
|
// and the source for the vertical pass.
|
||||||
|
tex = new GLTexture(displayWidth(), displayHeight());
|
||||||
|
tex->setFilter(GL_LINEAR);
|
||||||
|
tex->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
target = new GLRenderTarget(tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlurEffect::~BlurEffect()
|
||||||
|
{
|
||||||
|
delete shader;
|
||||||
|
delete target;
|
||||||
|
delete tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlurEffect::supported()
|
||||||
|
{
|
||||||
|
return GLRenderTarget::supported() && GLTexture::NPOTTextureSupported() &&
|
||||||
|
hasGLExtension("GL_ARB_fragment_program");
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect BlurEffect::expand(const QRect &rect) const
|
||||||
|
{
|
||||||
|
return rect.adjusted(-radius, -radius, radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegion BlurEffect::expand(const QRegion ®ion) const
|
||||||
|
{
|
||||||
|
QRegion expanded;
|
||||||
|
|
||||||
|
if (region.rectCount() < 10) {
|
||||||
|
foreach (const QRect &rect, region.rects())
|
||||||
|
expanded += expand(rect);
|
||||||
|
} else
|
||||||
|
expanded += expand(region.boundingRect());
|
||||||
|
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurEffect::paintScreen(int mask, QRegion region, ScreenPaintData &data)
|
||||||
|
{
|
||||||
|
// Force the scene to call paintGenericScreen() so the windows are painted bottom -> top
|
||||||
|
if (!effects->activeFullScreenEffect())
|
||||||
|
mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
|
||||||
|
|
||||||
|
effects->paintScreen(mask, region, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
|
||||||
|
{
|
||||||
|
bool scaled = !qFuzzyCompare(data.xScale, 1.0) && !qFuzzyCompare(data.yScale, 1.0);
|
||||||
|
bool translated = data.xTranslate || data.yTranslate;
|
||||||
|
bool hasAlpha = w->hasAlpha() || (w->hasDecoration() && effects->decorationsHaveAlpha());
|
||||||
|
|
||||||
|
if (!effects->activeFullScreenEffect() && hasAlpha && !w->isDesktop() &&
|
||||||
|
!scaled && !translated /* && region.intersects(w->geometry())*/)
|
||||||
|
{
|
||||||
|
const QRect screen(0, 0, displayWidth(), displayHeight());
|
||||||
|
const QRegion shape = w->shape().translated(w->geometry().topLeft()) & screen;
|
||||||
|
const QRect r = expand(shape.boundingRect()) & screen;
|
||||||
|
const QPoint offset = -shape.boundingRect().topLeft() +
|
||||||
|
(shape.boundingRect().topLeft() - r.topLeft());
|
||||||
|
|
||||||
|
// Create a scratch texture and copy the area in the back buffer that we're
|
||||||
|
// going to blur into it
|
||||||
|
GLTexture scratch(r.width(), r.height());
|
||||||
|
scratch.setFilter(GL_LINEAR);
|
||||||
|
scratch.setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
scratch.bind();
|
||||||
|
|
||||||
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r.x(), displayHeight() - r.y() - r.height(),
|
||||||
|
r.width(), r.height());
|
||||||
|
|
||||||
|
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
|
||||||
|
effects->pushRenderTarget(target);
|
||||||
|
|
||||||
|
shader->bind();
|
||||||
|
shader->setDirection(Qt::Horizontal);
|
||||||
|
shader->setPixelDistance(1.0 / r.width());
|
||||||
|
shader->setOpacity(1.0);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0, 1); glVertex2i(0, 0);
|
||||||
|
glTexCoord2f(1, 1); glVertex2i(r.width(), 0);
|
||||||
|
glTexCoord2f(1, 0); glVertex2i(r.width(), r.height());
|
||||||
|
glTexCoord2f(0, 0); glVertex2i(0, r.height());
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
effects->popRenderTarget();
|
||||||
|
scratch.unbind();
|
||||||
|
scratch.discard();
|
||||||
|
|
||||||
|
// Now draw the horizontally blurred area back to the backbuffer, while
|
||||||
|
// blurring it vertically and clipping it to the window shape.
|
||||||
|
tex->bind();
|
||||||
|
|
||||||
|
shader->setDirection(Qt::Vertical);
|
||||||
|
shader->setPixelDistance(1.0 / tex->height());
|
||||||
|
|
||||||
|
// Modulate the blurred texture with the window opacity if the window isn't opaque
|
||||||
|
const float opacity = data.opacity * data.contents_opacity;
|
||||||
|
if (opacity < 1.0) {
|
||||||
|
shader->setOpacity(opacity);
|
||||||
|
|
||||||
|
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float tw = tex->width();
|
||||||
|
const float th = tex->height();
|
||||||
|
int vertexCount = shape.rectCount() * 4;
|
||||||
|
|
||||||
|
if (vertices.size() < vertexCount) {
|
||||||
|
vertices.resize(vertexCount);
|
||||||
|
texCoords.resize(vertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (const QRect &r, shape.rects()) {
|
||||||
|
vertices[i + 0] = QVector2D(r.x(), r.y());
|
||||||
|
vertices[i + 1] = QVector2D(r.x() + r.width(), r.y());
|
||||||
|
vertices[i + 2] = QVector2D(r.x() + r.width(), r.y() + r.height());
|
||||||
|
vertices[i + 3] = QVector2D(r.x(), r.y() + r.height());
|
||||||
|
|
||||||
|
const QRect sr = r.translated(offset);
|
||||||
|
texCoords[i + 0] = QVector2D(sr.x() / tw, 1 - sr.y() / th);
|
||||||
|
texCoords[i + 1] = QVector2D((sr.x() + sr.width()) / tw, 1 - sr.y() / th);
|
||||||
|
texCoords[i + 2] = QVector2D((sr.x() + sr.width()) / tw, 1 - (sr.y() + sr.height()) / th);
|
||||||
|
texCoords[i + 3] = QVector2D(sr.x() / tw, 1 - (sr.y() + sr.height()) / th);
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertexCount > 1000) {
|
||||||
|
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 0, (float*)texCoords.constData());
|
||||||
|
glVertexPointer(2, GL_FLOAT, 0, (float*)vertices.constData());
|
||||||
|
glDrawArrays(GL_QUADS, 0, vertexCount);
|
||||||
|
glPopClientAttrib();
|
||||||
|
} else {
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
glTexCoord2fv((const float*)&texCoords[i]);
|
||||||
|
glVertex2fv((const float*)&vertices[i]);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opacity < 1.0)
|
||||||
|
glPopAttrib();
|
||||||
|
|
||||||
|
tex->unbind();
|
||||||
|
shader->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the window over the blurred area
|
||||||
|
effects->drawWindow(w, mask, region, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
|
|
18
effects/blur/blur.desktop
Normal file
18
effects/blur/blur.desktop
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Blur
|
||||||
|
Icon=preferences-system-windows-effect-blur
|
||||||
|
Comment=Blurs the background behind semi-transparent windows
|
||||||
|
|
||||||
|
Type=Service
|
||||||
|
X-KDE-ServiceTypes=KWin/Effect
|
||||||
|
X-KDE-PluginInfo-Author=Fredrik Höglund
|
||||||
|
X-KDE-PluginInfo-Email=fredrik@kde.org
|
||||||
|
X-KDE-PluginInfo-Name=kwin4_effect_blur
|
||||||
|
X-KDE-PluginInfo-Version=0.1.0
|
||||||
|
X-KDE-PluginInfo-Category=Appearance
|
||||||
|
X-KDE-PluginInfo-Depends=
|
||||||
|
X-KDE-PluginInfo-License=GPL
|
||||||
|
X-KDE-PluginInfo-EnabledByDefault=false
|
||||||
|
X-KDE-Library=kwin4_effect_builtins
|
||||||
|
X-KDE-Ordering=75
|
||||||
|
|
61
effects/blur/blur.h
Normal file
61
effects/blur/blur.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. if not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLUR_H
|
||||||
|
#define BLUR_H
|
||||||
|
|
||||||
|
#include <kwineffects.h>
|
||||||
|
#include <kwinglutils.h>
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QVector2D>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class BlurShader;
|
||||||
|
|
||||||
|
class BlurEffect : public KWin::Effect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlurEffect();
|
||||||
|
~BlurEffect();
|
||||||
|
|
||||||
|
static bool supported();
|
||||||
|
|
||||||
|
void paintScreen(int mask, QRegion region, ScreenPaintData &data);
|
||||||
|
void drawWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRect expand(const QRect &rect) const;
|
||||||
|
QRegion expand(const QRegion ®ion) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BlurShader *shader;
|
||||||
|
QVector<QVector2D> vertices;
|
||||||
|
QVector<QVector2D> texCoords;
|
||||||
|
GLRenderTarget *target;
|
||||||
|
GLTexture *tex;
|
||||||
|
int radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
188
effects/blur/blurshader.cpp
Normal file
188
effects/blur/blurshader.cpp
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. if not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blurshader.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <KDebug>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
using namespace KWin;
|
||||||
|
|
||||||
|
|
||||||
|
BlurShader::BlurShader()
|
||||||
|
: program(0), radius(12)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BlurShader::~BlurShader()
|
||||||
|
{
|
||||||
|
if (program) {
|
||||||
|
glDeleteProgramsARB(1, &program);
|
||||||
|
program = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::setRadius(int _radius)
|
||||||
|
{
|
||||||
|
int r = qMax(_radius, 2);
|
||||||
|
|
||||||
|
if (radius != r) {
|
||||||
|
radius = r;
|
||||||
|
|
||||||
|
if (program) {
|
||||||
|
glDeleteProgramsARB(1, &program);
|
||||||
|
program = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::setDirection(Qt::Orientation orientation)
|
||||||
|
{
|
||||||
|
direction = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::setPixelDistance(float val)
|
||||||
|
{
|
||||||
|
float firstStep = val * 1.5;
|
||||||
|
float nextStep = val * 2.0;
|
||||||
|
|
||||||
|
if (direction == Qt::Horizontal) {
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, firstStep, 0, 0, 0);
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, nextStep, 0, 0, 0);
|
||||||
|
} else {
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 0, firstStep, 0, 0);
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 0, nextStep, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::setOpacity(float val)
|
||||||
|
{
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, val, val, val, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::bind()
|
||||||
|
{
|
||||||
|
if (!program)
|
||||||
|
init();
|
||||||
|
|
||||||
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::unbind()
|
||||||
|
{
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||||
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
float BlurShader::gaussian(float x, float sigma) const
|
||||||
|
{
|
||||||
|
return (1.0 / std::sqrt(2.0 * M_PI) * sigma)
|
||||||
|
* std::exp(-((x * x) / (2.0 * sigma * sigma)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<float> BlurShader::gaussianKernel() const
|
||||||
|
{
|
||||||
|
const int size = radius | 1;
|
||||||
|
QVector<float> kernel(size);
|
||||||
|
const qreal sigma = radius / 2.5;
|
||||||
|
const int center = size / 2;
|
||||||
|
|
||||||
|
// Generate the gaussian kernel
|
||||||
|
kernel[center] = gaussian(0, sigma) * .5;
|
||||||
|
for (int i = 1; i <= center; i++) {
|
||||||
|
const float val = gaussian(1.5 + (i - 1) * 2.0, sigma);
|
||||||
|
kernel[center + i] = val;
|
||||||
|
kernel[center - i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize the kernel
|
||||||
|
qreal total = 0;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
total += kernel[i];
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
kernel[i] /= total;
|
||||||
|
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlurShader::init()
|
||||||
|
{
|
||||||
|
QVector<float> kernel = gaussianKernel();
|
||||||
|
const int size = kernel.size();
|
||||||
|
const int center = size / 2;
|
||||||
|
|
||||||
|
QByteArray text;
|
||||||
|
QTextStream stream(&text);
|
||||||
|
|
||||||
|
stream << "!!ARBfp1.0\n";
|
||||||
|
|
||||||
|
// The kernel values are hardcoded into the program
|
||||||
|
for (int i = 0; i <= center; i++)
|
||||||
|
stream << "PARAM kernel" << i << " = " << kernel[i] << ";\n";
|
||||||
|
|
||||||
|
stream << "PARAM firstSample = program.local[0];\n"; // Distance from gl_TexCoord[0] to the next sample
|
||||||
|
stream << "PARAM nextSample = program.local[1];\n"; // Distance to the subsequent sample
|
||||||
|
stream << "PARAM opacity = program.local[2];\n"; // The opacity with which to modulate the pixels
|
||||||
|
|
||||||
|
stream << "TEMP coord;\n"; // The coordinate we'll be sampling
|
||||||
|
stream << "TEMP sample;\n"; // The sampled value
|
||||||
|
stream << "TEMP sum;\n"; // The sum of the weighted samples
|
||||||
|
|
||||||
|
// Start by sampling the center coordinate
|
||||||
|
stream << "TEX sample, fragment.texcoord[0], texture[0], 2D;\n"; // sample = texture2D(tex, gl_TexCoord[0])
|
||||||
|
stream << "MUL sum, sample, kernel" << center << ";\n"; // sum = sample * kernel[center]
|
||||||
|
|
||||||
|
for (int i = 1; i <= center; i++) {
|
||||||
|
if (i == 1)
|
||||||
|
stream << "SUB coord, fragment.texcoord[0], firstSample;\n"; // coord = gl_TexCoord[0] - firstSample
|
||||||
|
else
|
||||||
|
stream << "SUB coord, coord, nextSample;\n"; // coord -= nextSample
|
||||||
|
stream << "TEX sample, coord, texture[0], 2D;\n"; // sample = texture2D(tex, coord)
|
||||||
|
stream << "MAD sum, sample, kernel" << center - i << ", sum;\n"; // sum += sample * kernel[center - i]
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= center; i++) {
|
||||||
|
if (i == 1)
|
||||||
|
stream << "ADD coord, fragment.texcoord[0], firstSample;\n"; // coord = gl_TexCoord[0] + firstSample
|
||||||
|
else
|
||||||
|
stream << "ADD coord, coord, nextSample;\n"; // coord += nextSample
|
||||||
|
stream << "TEX sample, coord, texture[0], 2D;\n"; // sample = texture2D(tex, coord)
|
||||||
|
stream << "MAD sum, sample, kernel" << center - i << ", sum;\n"; // sum += sample * kernel[center - i]
|
||||||
|
}
|
||||||
|
stream << "MUL result.color, sum, opacity;\n"; // gl_FragColor = sum * opacity
|
||||||
|
stream << "END\n";
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
glGenProgramsARB(1, &program);
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);
|
||||||
|
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, text.length(), text.constData());
|
||||||
|
|
||||||
|
if (glGetError()) {
|
||||||
|
const char *error = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
||||||
|
kError() << "Error when compiling fragment program:" << error;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||||
|
}
|
||||||
|
|
63
effects/blur/blurshader.h
Normal file
63
effects/blur/blurshader.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2010 Fredrik Höglund <fredrik@kde.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. if not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLURSHADER_H
|
||||||
|
#define BLURSHADER_H
|
||||||
|
|
||||||
|
#include <kwinglutils.h>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class BlurShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlurShader();
|
||||||
|
~BlurShader();
|
||||||
|
|
||||||
|
// Sets the radius in pixels
|
||||||
|
void setRadius(int radius);
|
||||||
|
|
||||||
|
// Sets the blur direction
|
||||||
|
void setDirection(Qt::Orientation orientation);
|
||||||
|
|
||||||
|
// Sets the distance between two pixels
|
||||||
|
void setPixelDistance(float val);
|
||||||
|
|
||||||
|
// The opacity of the resulting pixels is multiplied by this value
|
||||||
|
void setOpacity(float val);
|
||||||
|
|
||||||
|
void bind();
|
||||||
|
void unbind();
|
||||||
|
|
||||||
|
private:
|
||||||
|
float gaussian(float x, float sigma) const;
|
||||||
|
QVector<float> gaussianKernel() const;
|
||||||
|
void init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint program;
|
||||||
|
int radius;
|
||||||
|
Qt::Orientation direction;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue