Added noise blur effect
Summary: Added the option to turn on noise behind the blurred area. The lowest strength value disables it completely, so it is optional and is disabled by default. Test Plan: Edit: this new screenshot shows the updated noise generation. Edit2: separated the screenshots so you can flick through them to clearly see the differences {F5694024} {F5694031} {F5694025} {F5694028} Reviewers: #kwin, #vdg, fredrik Reviewed By: #vdg, fredrik Subscribers: davidedmundson, matheusm, romangg, ivan, zzag, ngraham, kwin, #kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D10281
This commit is contained in:
parent
a0aef86a74
commit
cc0325af41
7 changed files with 293 additions and 52 deletions
|
@ -27,12 +27,16 @@
|
|||
|
||||
#include <QMatrix4x4>
|
||||
#include <QLinkedList>
|
||||
#include <QScreen> // for QGuiApplication
|
||||
#include <QTime>
|
||||
#include <cmath> // for ceil()
|
||||
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
#include <KWayland/Server/blur_interface.h>
|
||||
#include <KWayland/Server/shadow_interface.h>
|
||||
#include <KWayland/Server/display.h>
|
||||
#include <KSharedConfig>
|
||||
#include <KConfigGroup>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -143,7 +147,7 @@ void BlurEffect::updateTexture()
|
|||
|
||||
// Prepare the stack for the rendering
|
||||
m_renderTargetStack.clear();
|
||||
m_renderTargets.reserve(m_downSampleIterations * 2 - 1);
|
||||
m_renderTargetStack.reserve(m_downSampleIterations * 2);
|
||||
|
||||
// Upsample
|
||||
for (int i = 1; i < m_downSampleIterations; i++) {
|
||||
|
@ -157,6 +161,9 @@ void BlurEffect::updateTexture()
|
|||
|
||||
// Copysample
|
||||
m_renderTargetStack.push(m_renderTargets[0]);
|
||||
|
||||
// Generate the noise helper texture
|
||||
generateNoiseTexture();
|
||||
}
|
||||
|
||||
void BlurEffect::initBlurStrengthValues()
|
||||
|
@ -227,6 +234,9 @@ void BlurEffect::reconfigure(ReconfigureFlags flags)
|
|||
m_downSampleIterations = blurStrengthValues[blurStrength].iteration;
|
||||
m_offset = blurStrengthValues[blurStrength].offset;
|
||||
m_expandSize = blurOffsets[m_downSampleIterations - 1].expandSize;
|
||||
m_noiseStrength = BlurConfig::noiseStrength();
|
||||
|
||||
m_scalingFactor = QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96.0;
|
||||
|
||||
updateTexture();
|
||||
|
||||
|
@ -550,7 +560,7 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPai
|
|||
}
|
||||
|
||||
if (!shape.isEmpty()) {
|
||||
doBlur(shape, screen, data.opacity(), data.screenProjectionMatrix(), w->isDock());
|
||||
doBlur(shape, screen, data.opacity(), data.screenProjectionMatrix(), w->isDock(), w->geometry());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,12 +576,39 @@ void BlurEffect::paintEffectFrame(EffectFrame *frame, QRegion region, double opa
|
|||
QRegion shape = frame->geometry().adjusted(-borderSize, -borderSize, borderSize, borderSize) & screen;
|
||||
|
||||
if (valid && !shape.isEmpty() && region.intersects(shape.boundingRect()) && frame->style() != EffectFrameNone) {
|
||||
doBlur(shape, screen, opacity * frameOpacity, frame->screenProjectionMatrix(), false);
|
||||
doBlur(shape, screen, opacity * frameOpacity, frame->screenProjectionMatrix(), false, frame->geometry());
|
||||
}
|
||||
effects->paintEffectFrame(frame, region, opacity, frameOpacity);
|
||||
}
|
||||
|
||||
void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock)
|
||||
void BlurEffect::generateNoiseTexture()
|
||||
{
|
||||
if (m_noiseStrength == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Init randomness based on time
|
||||
qsrand((uint)QTime::currentTime().msec());
|
||||
|
||||
QImage noiseImage(QSize(256, 256), QImage::Format_Grayscale8);
|
||||
|
||||
for (int y = 0; y < noiseImage.height(); y++) {
|
||||
uint8_t *noiseImageLine = (uint8_t *) noiseImage.scanLine(y);
|
||||
|
||||
for (int x = 0; x < noiseImage.width(); x++) {
|
||||
noiseImageLine[x] = qrand() % m_noiseStrength + (128 - m_noiseStrength / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// The noise texture looks distorted when not scaled with integer
|
||||
noiseImage = noiseImage.scaled(noiseImage.size() * m_scalingFactor);
|
||||
|
||||
m_noiseTexture = GLTexture(noiseImage);
|
||||
m_noiseTexture.setFilter(GL_NEAREST);
|
||||
m_noiseTexture.setWrapMode(GL_REPEAT);
|
||||
}
|
||||
|
||||
void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock, QRect windowRect)
|
||||
{
|
||||
QRegion expandedBlurRegion = expand(shape) & expand(screen);
|
||||
|
||||
|
@ -628,24 +665,40 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o
|
|||
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
}
|
||||
|
||||
//Final upscale to the screen
|
||||
m_shader->bind(BlurShader::UpSampleType);
|
||||
m_shader->setOffset(m_offset);
|
||||
|
||||
m_shader->setModelViewProjectionMatrix(screenProjection);
|
||||
m_shader->setTargetSize(m_renderTextures[0].size());
|
||||
|
||||
//Copy the image from this texture
|
||||
m_renderTextures[1].bind();
|
||||
|
||||
//Render to the screen
|
||||
vbo->draw(GL_TRIANGLES, blurRectCount * (m_downSampleIterations + 1), shape.rectCount() * 6);
|
||||
upscaleRenderToScreen(vbo, blurRectCount * (m_downSampleIterations + 1), shape.rectCount() * 6, screenProjection, shape.boundingRect(), windowRect.topLeft());
|
||||
|
||||
if (opacity < 1.0) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
vbo->unbindArrays();
|
||||
}
|
||||
|
||||
void BlurEffect::upscaleRenderToScreen(GLVertexBuffer *vbo, int vboStart, int blurRectCount, QMatrix4x4 screenProjection, QRect windowShape, QPoint windowPosition)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_renderTextures[1].bind();
|
||||
|
||||
if (m_noiseStrength > 0) {
|
||||
m_shader->bind(BlurShader::NoiseSampleType);
|
||||
m_shader->setTargetTextureSize(m_renderTextures[0].size());
|
||||
m_shader->setNoiseTextureSize(m_noiseTexture.size());
|
||||
m_shader->setTexturePosition(windowPosition);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_noiseTexture.bind();
|
||||
} else {
|
||||
m_shader->bind(BlurShader::UpSampleType);
|
||||
m_shader->setTargetTextureSize(m_renderTextures[0].size());
|
||||
}
|
||||
|
||||
m_shader->setOffset(m_offset);
|
||||
m_shader->setModelViewProjectionMatrix(screenProjection);
|
||||
|
||||
//Render to the screen
|
||||
vbo->draw(GL_TRIANGLES, vboStart, blurRectCount);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_shader->unbind();
|
||||
}
|
||||
|
||||
|
@ -661,7 +714,7 @@ void BlurEffect::downSampleTexture(GLVertexBuffer *vbo, int blurRectCount)
|
|||
modelViewProjectionMatrix.ortho(0, m_renderTextures[i].width(), m_renderTextures[i].height(), 0 , 0, 65535);
|
||||
|
||||
m_shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);
|
||||
m_shader->setTargetSize(m_renderTextures[i].size());
|
||||
m_shader->setTargetTextureSize(m_renderTextures[i].size());
|
||||
|
||||
//Copy the image from this texture
|
||||
m_renderTextures[i - 1].bind();
|
||||
|
@ -680,12 +733,12 @@ void BlurEffect::upSampleTexture(GLVertexBuffer *vbo, int blurRectCount)
|
|||
m_shader->bind(BlurShader::UpSampleType);
|
||||
m_shader->setOffset(m_offset);
|
||||
|
||||
for (int i = m_downSampleIterations - 1; i > 0; i--) {
|
||||
for (int i = m_downSampleIterations - 1; i >= 1; i--) {
|
||||
modelViewProjectionMatrix.setToIdentity();
|
||||
modelViewProjectionMatrix.ortho(0, m_renderTextures[i].width(), m_renderTextures[i].height(), 0 , 0, 65535);
|
||||
|
||||
m_shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);
|
||||
m_shader->setTargetSize(m_renderTextures[i].size());
|
||||
m_shader->setTargetTextureSize(m_renderTextures[i].size());
|
||||
|
||||
//Copy the image from this texture
|
||||
m_renderTextures[i + 1].bind();
|
||||
|
@ -702,7 +755,7 @@ void BlurEffect::copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount,
|
|||
m_shader->bind(BlurShader::CopySampleType);
|
||||
|
||||
m_shader->setModelViewProjectionMatrix(screenProjection);
|
||||
m_shader->setTargetSize(screenSize);
|
||||
m_shader->setTargetTextureSize(screenSize);
|
||||
|
||||
/*
|
||||
* This '1' sized adjustment is necessary do avoid windows affecting the blur that are
|
||||
|
|
|
@ -83,10 +83,12 @@ private:
|
|||
QRegion blurRegion(const EffectWindow *w) const;
|
||||
bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const;
|
||||
void updateBlurRegion(EffectWindow *w) const;
|
||||
void doBlur(const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock);
|
||||
void doBlur(const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock, QRect windowRect);
|
||||
void uploadRegion(QVector2D *&map, const QRegion ®ion, const int downSampleIterations);
|
||||
void uploadGeometry(GLVertexBuffer *vbo, const QRegion &blurRegion, const QRegion &windowRegion);
|
||||
void generateNoiseTexture();
|
||||
|
||||
void upscaleRenderToScreen(GLVertexBuffer *vbo, int vboStart, int blurRectCount, QMatrix4x4 screenProjection, QRect windowShape, QPoint windowPosition);
|
||||
void downSampleTexture(GLVertexBuffer *vbo, int blurRectCount);
|
||||
void upSampleTexture(GLVertexBuffer *vbo, int blurRectCount);
|
||||
void copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, QSize screenSize, QMatrix4x4 screenProjection);
|
||||
|
@ -96,6 +98,9 @@ private:
|
|||
QVector <GLRenderTarget*> m_renderTargets;
|
||||
QVector <GLTexture> m_renderTextures;
|
||||
QStack <GLRenderTarget*> m_renderTargetStack;
|
||||
|
||||
GLTexture m_noiseTexture;
|
||||
|
||||
bool m_renderTargetsValid;
|
||||
long net_wm_blur_region;
|
||||
QRegion m_damagedArea; // keeps track of the area which has been damaged (from bottom to top)
|
||||
|
@ -105,6 +110,8 @@ private:
|
|||
int m_downSampleIterations; // number of times the texture will be downsized to half size
|
||||
int m_offset;
|
||||
int m_expandSize;
|
||||
int m_noiseStrength;
|
||||
int m_scalingFactor;
|
||||
|
||||
struct OffsetStruct {
|
||||
float minOffset;
|
||||
|
|
|
@ -8,5 +8,8 @@
|
|||
<entry name="BlurStrength" type="Int">
|
||||
<default>10</default>
|
||||
</entry>
|
||||
<entry name="NoiseStrength" type="Int">
|
||||
<default>5</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>95</height>
|
||||
<height>184</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantExplanation">
|
||||
<widget class="QLabel" name="labelConstantBlurDescription">
|
||||
<property name="text">
|
||||
<string>Strength of the effect:</string>
|
||||
<string>Blur strength:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -37,7 +37,7 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantLight">
|
||||
<widget class="QLabel" name="labelConstantBlurLight">
|
||||
<property name="text">
|
||||
<string>Light</string>
|
||||
</property>
|
||||
|
@ -69,7 +69,70 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantStrong">
|
||||
<widget class="QLabel" name="labelConstantBlurStrong">
|
||||
<property name="text">
|
||||
<string>Strong</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantNoiseDescription">
|
||||
<property name="text">
|
||||
<string>Noise strength:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantNoiseLight">
|
||||
<property name="text">
|
||||
<string>Light</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="kcfg_NoiseStrength">
|
||||
<property name="maximum">
|
||||
<number>14</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelConstantNoiseStrong">
|
||||
<property name="text">
|
||||
<string>Strong</string>
|
||||
</property>
|
||||
|
|
|
@ -73,6 +73,9 @@ void GLSLBlurShader::reset()
|
|||
delete m_shaderCopysample;
|
||||
m_shaderCopysample = nullptr;
|
||||
|
||||
delete m_shaderNoisesample;
|
||||
m_shaderNoisesample = nullptr;
|
||||
|
||||
setIsValid(false);
|
||||
}
|
||||
|
||||
|
@ -105,6 +108,14 @@ void GLSLBlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix)
|
|||
m_matrixDownsample = matrix;
|
||||
m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, matrix);
|
||||
break;
|
||||
|
||||
case NoiseSampleType:
|
||||
if (matrix == m_matrixNoisesample)
|
||||
return;
|
||||
|
||||
m_matrixNoisesample = matrix;
|
||||
m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, matrix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,10 +140,18 @@ void GLSLBlurShader::setOffset(float offset)
|
|||
m_offsetDownsample = offset;
|
||||
m_shaderDownsample->setUniform(m_offsetLocationDownsample, offset);
|
||||
break;
|
||||
|
||||
case NoiseSampleType:
|
||||
if (offset == m_offsetNoisesample)
|
||||
return;
|
||||
|
||||
m_offsetNoisesample = offset;
|
||||
m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLBlurShader::setTargetSize(QSize renderTextureSize)
|
||||
void GLSLBlurShader::setTargetTextureSize(QSize renderTextureSize)
|
||||
{
|
||||
if (!isValid())
|
||||
return;
|
||||
|
@ -141,33 +160,41 @@ void GLSLBlurShader::setTargetSize(QSize renderTextureSize)
|
|||
|
||||
switch (m_activeSampleType) {
|
||||
case CopySampleType:
|
||||
if (renderTextureSize == m_renderTextureSizeCopysample)
|
||||
return;
|
||||
|
||||
m_renderTextureSizeCopysample = renderTextureSize;
|
||||
m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, texSize);
|
||||
break;
|
||||
|
||||
case UpSampleType:
|
||||
if (renderTextureSize == m_renderTextureSizeUpsample)
|
||||
return;
|
||||
|
||||
m_renderTextureSizeUpsample = renderTextureSize;
|
||||
m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, texSize);
|
||||
m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y()));
|
||||
break;
|
||||
|
||||
case DownSampleType:
|
||||
if (renderTextureSize == m_renderTextureSizeDownsample)
|
||||
return;
|
||||
|
||||
m_renderTextureSizeDownsample = renderTextureSize;
|
||||
m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, texSize);
|
||||
m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y()));
|
||||
break;
|
||||
|
||||
case NoiseSampleType:
|
||||
m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, texSize);
|
||||
m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLBlurShader::setNoiseTextureSize(QSize noiseTextureSize)
|
||||
{
|
||||
QVector2D noiseTexSize = QVector2D(noiseTextureSize.width(), noiseTextureSize.height());
|
||||
|
||||
if (noiseTexSize != m_noiseTextureSizeNoisesample) {
|
||||
m_noiseTextureSizeNoisesample = noiseTexSize;
|
||||
m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, noiseTexSize);
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLBlurShader::setTexturePosition(QPoint texPos)
|
||||
{
|
||||
m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(-texPos.x(), texPos.y()));
|
||||
}
|
||||
|
||||
void GLSLBlurShader::setBlurRect(QRect blurRect, QSize screenSize)
|
||||
{
|
||||
if (!isValid() || blurRect == m_blurRectCopysample)
|
||||
|
@ -177,9 +204,9 @@ void GLSLBlurShader::setBlurRect(QRect blurRect, QSize screenSize)
|
|||
|
||||
QVector4D rect = QVector4D(
|
||||
blurRect.bottomLeft().x() / float(screenSize.width()),
|
||||
1.0 - blurRect.bottomLeft().y() / float(screenSize.height()),
|
||||
blurRect.topRight().x() / float(screenSize.width()),
|
||||
1.0 - blurRect.topRight().y() / float(screenSize.height())
|
||||
1.0 - blurRect.bottomLeft().y() / float(screenSize.height()),
|
||||
blurRect.topRight().x() / float(screenSize.width()),
|
||||
1.0 - blurRect.topRight().y() / float(screenSize.height())
|
||||
);
|
||||
|
||||
m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect);
|
||||
|
@ -202,6 +229,10 @@ void GLSLBlurShader::bind(SampleType sampleType)
|
|||
case DownSampleType:
|
||||
ShaderManager::instance()->pushShader(m_shaderDownsample);
|
||||
break;
|
||||
|
||||
case NoiseSampleType:
|
||||
ShaderManager::instance()->pushShader(m_shaderNoisesample);
|
||||
break;
|
||||
}
|
||||
|
||||
m_activeSampleType = sampleType;
|
||||
|
@ -222,6 +253,7 @@ void GLSLBlurShader::init()
|
|||
QByteArray fragmentDownSource;
|
||||
QByteArray fragmentUpSource;
|
||||
QByteArray fragmentCopySource;
|
||||
QByteArray fragmentNoiseSource;
|
||||
|
||||
const QByteArray attribute = core ? "in" : "attribute";
|
||||
const QByteArray texture2D = core ? "texture" : "texture2D";
|
||||
|
@ -331,12 +363,46 @@ void GLSLBlurShader::init()
|
|||
|
||||
streamFragCopy.flush();
|
||||
|
||||
// Fragment shader - Noise texture
|
||||
// ===================================================================
|
||||
QTextStream streamFragNoise(&fragmentNoiseSource);
|
||||
|
||||
m_shaderDownsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource);
|
||||
m_shaderUpsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource);
|
||||
m_shaderCopysample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource);
|
||||
streamFragNoise << glHeaderString << glUniformString;
|
||||
|
||||
bool areShadersValid = m_shaderDownsample->isValid() && m_shaderUpsample->isValid() && m_shaderCopysample->isValid();
|
||||
streamFragNoise << "uniform sampler2D noiseTexUnit;\n";
|
||||
streamFragNoise << "uniform vec2 noiseTextureSize;\n";
|
||||
streamFragNoise << "uniform vec2 texStartPos;\n";
|
||||
|
||||
// Upsampling + Noise
|
||||
streamFragNoise << "void main(void)\n";
|
||||
streamFragNoise << "{\n";
|
||||
streamFragNoise << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n";
|
||||
streamFragNoise << " vec2 uvNoise = vec2((texStartPos.xy + gl_FragCoord.xy) / noiseTextureSize);\n";
|
||||
streamFragNoise << " \n";
|
||||
streamFragNoise << " vec4 sum = " << texture2D << "(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset);\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0;\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset);\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0;\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset);\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0;\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n";
|
||||
streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n";
|
||||
streamFragNoise << " \n";
|
||||
streamFragNoise << " " << fragColor << " = sum / 12.0 - (vec4(0.5, 0.5, 0.5, 0) - vec4(" << texture2D << "(noiseTexUnit, uvNoise).rrr, 0));\n";
|
||||
streamFragNoise << "}\n";
|
||||
|
||||
streamFragNoise.flush();
|
||||
|
||||
|
||||
m_shaderDownsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource);
|
||||
m_shaderUpsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource);
|
||||
m_shaderCopysample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource);
|
||||
m_shaderNoisesample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource);
|
||||
|
||||
bool areShadersValid = m_shaderDownsample->isValid() &&
|
||||
m_shaderUpsample->isValid() &&
|
||||
m_shaderCopysample->isValid() &&
|
||||
m_shaderNoisesample->isValid();
|
||||
setIsValid(areShadersValid);
|
||||
|
||||
if (areShadersValid) {
|
||||
|
@ -354,6 +420,13 @@ void GLSLBlurShader::init()
|
|||
m_renderTextureSizeLocationCopysample = m_shaderCopysample->uniformLocation("renderTextureSize");
|
||||
m_blurRectLocationCopysample = m_shaderCopysample->uniformLocation("blurRect");
|
||||
|
||||
m_mvpMatrixLocationNoisesample = m_shaderNoisesample->uniformLocation("modelViewProjectionMatrix");
|
||||
m_offsetLocationNoisesample = m_shaderNoisesample->uniformLocation("offset");
|
||||
m_renderTextureSizeLocationNoisesample = m_shaderNoisesample->uniformLocation("renderTextureSize");
|
||||
m_noiseTextureSizeLocationNoisesample = m_shaderNoisesample->uniformLocation("noiseTextureSize");
|
||||
m_texStartPosLocationNoisesample = m_shaderNoisesample->uniformLocation("texStartPos");
|
||||
m_halfpixelLocationNoisesample = m_shaderNoisesample->uniformLocation("halfpixel");
|
||||
|
||||
QMatrix4x4 modelViewProjection;
|
||||
const QSize screenSize = effects->virtualScreenSize();
|
||||
modelViewProjection.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535);
|
||||
|
@ -379,6 +452,32 @@ void GLSLBlurShader::init()
|
|||
m_shaderCopysample->setUniform(m_blurRectLocationCopysample, QVector4D(1.0, 1.0, 1.0, 1.0));
|
||||
ShaderManager::instance()->popShader();
|
||||
|
||||
ShaderManager::instance()->pushShader(m_shaderNoisesample);
|
||||
m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, modelViewProjection);
|
||||
m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, float(1.0));
|
||||
m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, QVector2D(1.0, 1.0));
|
||||
m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, QVector2D(1.0, 1.0));
|
||||
m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(1.0, 1.0));
|
||||
m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(1.0, 1.0));
|
||||
|
||||
glUniform1i(m_shaderNoisesample->uniformLocation("texUnit"), 0);
|
||||
glUniform1i(m_shaderNoisesample->uniformLocation("noiseTexUnit"), 1);
|
||||
|
||||
ShaderManager::instance()->popShader();
|
||||
|
||||
m_activeSampleType = -1;
|
||||
|
||||
m_offsetDownsample = 0.0;
|
||||
m_matrixDownsample = QMatrix4x4();
|
||||
|
||||
m_offsetUpsample = 0.0;
|
||||
m_matrixUpsample = QMatrix4x4();
|
||||
|
||||
m_matrixCopysample = QMatrix4x4();
|
||||
m_blurRectCopysample = QRect();
|
||||
|
||||
m_offsetNoisesample = 0.0;
|
||||
m_noiseTextureSizeNoisesample = QVector2D();
|
||||
m_matrixNoisesample = QMatrix4x4();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,13 +45,16 @@ public:
|
|||
|
||||
virtual void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) = 0;
|
||||
virtual void setOffset(float offset) = 0;
|
||||
virtual void setTargetSize(QSize renderTextureSize) = 0;
|
||||
virtual void setTargetTextureSize(QSize renderTextureSize) = 0;
|
||||
virtual void setNoiseTextureSize(QSize noiseTextureSize) = 0;
|
||||
virtual void setTexturePosition(QPoint texPos) = 0;
|
||||
virtual void setBlurRect(QRect blurRect, QSize screenSize) = 0;
|
||||
|
||||
enum SampleType {
|
||||
DownSampleType,
|
||||
UpSampleType,
|
||||
CopySampleType
|
||||
CopySampleType,
|
||||
NoiseSampleType
|
||||
};
|
||||
|
||||
virtual void bind(SampleType sampleType) = 0;
|
||||
|
@ -83,7 +86,9 @@ public:
|
|||
void unbind() override final;
|
||||
void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) override final;
|
||||
void setOffset(float offset) override final;
|
||||
void setTargetSize(QSize renderTextureSize) override final;
|
||||
void setTargetTextureSize(QSize renderTextureSize) override final;
|
||||
void setNoiseTextureSize(QSize noiseTextureSize) override final;
|
||||
void setTexturePosition(QPoint texPos) override final;
|
||||
void setBlurRect(QRect blurRect, QSize screenSize) override final;
|
||||
|
||||
protected:
|
||||
|
@ -94,6 +99,7 @@ private:
|
|||
GLShader *m_shaderDownsample = nullptr;
|
||||
GLShader *m_shaderUpsample = nullptr;
|
||||
GLShader *m_shaderCopysample = nullptr;
|
||||
GLShader *m_shaderNoisesample = nullptr;
|
||||
|
||||
int m_mvpMatrixLocationDownsample;
|
||||
int m_offsetLocationDownsample;
|
||||
|
@ -109,22 +115,30 @@ private:
|
|||
int m_renderTextureSizeLocationCopysample;
|
||||
int m_blurRectLocationCopysample;
|
||||
|
||||
int m_mvpMatrixLocationNoisesample;
|
||||
int m_offsetLocationNoisesample;
|
||||
int m_renderTextureSizeLocationNoisesample;
|
||||
int m_noiseTextureSizeLocationNoisesample;
|
||||
int m_texStartPosLocationNoisesample;
|
||||
int m_halfpixelLocationNoisesample;
|
||||
|
||||
|
||||
//Caching uniform values to aviod unnecessary setUniform calls
|
||||
int m_activeSampleType;
|
||||
|
||||
float m_offsetDownsample;
|
||||
QMatrix4x4 m_matrixDownsample;
|
||||
QSize m_renderTextureSizeDownsample;
|
||||
|
||||
float m_offsetUpsample;
|
||||
QMatrix4x4 m_matrixUpsample;
|
||||
QSize m_renderTextureSizeUpsample;
|
||||
|
||||
QMatrix4x4 m_matrixCopysample;
|
||||
QSize m_renderTextureSizeCopysample;
|
||||
QRect m_blurRectCopysample;
|
||||
|
||||
float m_offsetNoisesample;
|
||||
QVector2D m_noiseTextureSizeNoisesample;
|
||||
QMatrix4x4 m_matrixNoisesample;
|
||||
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -125,6 +125,8 @@ GLTexture::GLTexture(const QImage& image, GLenum target)
|
|||
{ GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2BGR30_Premultiplied
|
||||
{ GL_RGB10, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_RGB30
|
||||
{ GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2RGB30_Premultiplied
|
||||
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE }, // QImage::Format_Alpha8
|
||||
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE }, // QImage::Format_Grayscale8
|
||||
};
|
||||
|
||||
QImage im;
|
||||
|
|
Loading…
Reference in a new issue