kwin: Replace brightness and opacity with a modulation constant

This makes it possible to adjust both brightness and opacity
at the same time with one multiplication in the fragment shader.
This commit is contained in:
Fredrik Höglund 2011-02-12 01:36:21 +01:00
parent 175b45c5de
commit 73be6657ea
7 changed files with 89 additions and 43 deletions

View file

@ -1,8 +1,7 @@
uniform sampler2D sample;
uniform vec4 modulation;
uniform float textureWidth;
uniform float textureHeight;
uniform float opacity;
uniform float brightness;
uniform float saturation;
uniform int u_forceAlpha;
@ -11,17 +10,19 @@ varying vec2 varyingTexCoords;
void main()
{
vec4 tex = texture2D(sample, varyingTexCoords);
if (u_forceAlpha > 0) {
tex.a = 1.0;
}
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3( dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation );
}
tex.rgb = tex.rgb * opacity * vec3( brightness );
tex *= modulation;
tex.rgb = vec3(1.0) - tex.rgb;
tex.a = tex.a * opacity;
gl_FragColor = tex;
}

View file

@ -324,9 +324,10 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region
m_windowData[w].iconFrame->setPosition(point);
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if (effects->compositingType() == KWin::OpenGLCompositing && data.shader) {
const float a = 0.9 * data.opacity * m_decalOpacity * 0.75;
data.shader->setUniform(GLShader::TextureWidth, 1.0f);
data.shader->setUniform(GLShader::TextureHeight, 1.0f);
data.shader->setUniform(GLShader::Opacity, 0.9 * data.opacity * m_decalOpacity * 0.75);
data.shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#endif
m_windowData[w].iconFrame->render(region, 0.9 * data.opacity * m_decalOpacity, 0.75);
@ -337,9 +338,10 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region
m_windowData[w].textFrame->setPosition(point);
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if (effects->compositingType() == KWin::OpenGLCompositing && data.shader) {
const float a = 0.9 * data.opacity * m_decalOpacity * 0.75;
data.shader->setUniform(GLShader::TextureWidth, 1.0f);
data.shader->setUniform(GLShader::TextureHeight, 1.0f);
data.shader->setUniform(GLShader::Opacity, 0.9 * data.opacity * m_decalOpacity * 0.75);
data.shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#endif
m_windowData[w].textFrame->render(region, 0.9 * data.opacity * m_decalOpacity, 0.75);

View file

@ -207,6 +207,7 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region,
int sw = width;
int sh = height;
GLTexture *cachedTexture = static_cast< GLTexture*>(w->data(LanczosCacheRole).value<void*>());
if (cachedTexture) {
if (cachedTexture->width() == tw && cachedTexture->height() == th) {
@ -214,13 +215,18 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region,
if (ShaderManager::instance()->isValid()) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float rgb = data.brightness * data.opacity;
const float a = data.opacity;
GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
shader->setUniform(GLShader::Opacity, data.opacity);
shader->setUniform(GLShader::Brightness, data.brightness);
shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a));
shader->setUniform(GLShader::Saturation, data.saturation);
shader->setUniform(GLShader::AlphaToOne, 0);
cachedTexture->render(textureRect, textureRect);
ShaderManager::instance()->popShader();
glDisable(GL_BLEND);
} else {
@ -336,16 +342,22 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region,
cache->bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - th, tw, th);
effects->popRenderTarget();
if (ShaderManager::instance()->isValid()) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float rgb = data.brightness * data.opacity;
const float a = data.opacity;
GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
shader->setUniform(GLShader::Opacity, data.opacity);
shader->setUniform(GLShader::Brightness, data.brightness);
shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a));
shader->setUniform(GLShader::Saturation, data.saturation);
shader->setUniform(GLShader::AlphaToOne, 0);
cache->render(textureRect, textureRect);
ShaderManager::instance()->popShader();
glDisable(GL_BLEND);
} else {
@ -353,6 +365,7 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region,
cache->render(textureRect, textureRect);
restoreRenderStates(cache, data.opacity, data.brightness, data.saturation);
}
cache->unbind();
w->setData(LanczosCacheRole, QVariant::fromValue(static_cast<void*>(cache)));

View file

@ -870,8 +870,8 @@ void GLShader::resolveLocations()
mVec2Location[Offset] = uniformLocation("offset");
mFloatLocation[Opacity] = uniformLocation("opacity");
mFloatLocation[Brightness] = uniformLocation("brightness");
mVec4Location[ModulationConstant] = uniformLocation("modulation");
mFloatLocation[Saturation] = uniformLocation("saturation");
mFloatLocation[TextureWidth] = uniformLocation("textureWidth");
mFloatLocation[TextureHeight] = uniformLocation("textureHeight");
@ -899,6 +899,12 @@ bool GLShader::setUniform(GLShader::Vec2Uniform uniform, const QVector2D &value)
return setUniform(mVec2Location[uniform], value);
}
bool GLShader::setUniform(GLShader::Vec4Uniform uniform, const QVector4D &value)
{
resolveLocations();
return setUniform(mVec4Location[uniform], value);
}
bool GLShader::setUniform(GLShader::FloatUniform uniform, float value)
{
resolveLocations();
@ -1329,9 +1335,8 @@ void ShaderManager::resetShader(ShaderType type)
shader->setUniform(GLShader::WindowTransformation, identity);
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0));
shader->setUniform(GLShader::Opacity, 1.0f);
shader->setUniform(GLShader::Brightness, 1.0f);
shader->setUniform(GLShader::Saturation, 1.0f);
shader->setUniform(GLShader::AlphaToOne, 0);

View file

@ -297,9 +297,12 @@ public:
Vec2UniformCount
};
enum Vec4Uniform {
ModulationConstant,
Vec4UniformCount
};
enum FloatUniform {
Opacity,
Brightness,
Saturation,
TextureWidth,
TextureHeight,
@ -313,6 +316,7 @@ public:
bool setUniform(MatrixUniform uniform, const QMatrix4x4 &matrix);
bool setUniform(Vec2Uniform uniform, const QVector2D &value);
bool setUniform(Vec4Uniform uniform, const QVector4D &value);
bool setUniform(FloatUniform uniform, float value);
bool setUniform(IntUniform uniform, int value);
@ -340,6 +344,7 @@ private:
bool mLocationsResolved:1;
int mMatrixLocation[MatrixCount];
int mVec2Location[Vec2UniformCount];
int mVec4Location[Vec4UniformCount];
int mFloatLocation[FloatUniformCount];
int mIntLocation[IntUniformCount];
float mTextureWidth;

View file

@ -1,6 +1,5 @@
uniform sampler2D sample;
uniform float opacity;
uniform float brightness;
uniform vec4 modulation;
uniform float saturation;
uniform int debug;
uniform int u_forceAlpha;
@ -11,19 +10,22 @@ varying vec2 varyingTexCoords;
void main() {
vec4 tex = texture2D(sample, varyingTexCoords);
if (u_forceAlpha > 0) {
tex.a = 1.0;
}
if( saturation != 1.0 ) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3( dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation );
}
tex.rgb = tex.rgb * opacity * brightness;
tex.a = tex.a * opacity;
tex *= modulation;
/*if (debug != 0) {
tex.g += 0.5;
}*/
gl_FragColor = tex;
}

View file

@ -729,10 +729,13 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa
glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA);
}
}
shader->setUniform(GLShader::Opacity, opacity);
shader->setUniform(GLShader::Saturation, saturation);
shader->setUniform(GLShader::Brightness, brightness);
shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0);
const float rgb = brightness * opacity;
const float a = opacity;
shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a));
shader->setUniform(GLShader::Saturation, saturation);
shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0);
const float texw = shader->textureWidth();
const float texh = shader->textureHeight();
@ -1081,8 +1084,8 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
if (sceneShader)
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0));
shader->setUniform(GLShader::Saturation, 1.0f);
shader->setUniform(GLShader::Brightness, 1.0f);
shader->setUniform(GLShader::AlphaToOne, 0);
shader->setUniform(GLShader::TextureWidth, 1.0f);
@ -1210,8 +1213,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
m_unstyledVBO->setData(verts.count() / 2, 2, verts.data(), texCoords.data());
}
if (shader)
shader->setUniform(GLShader::Opacity, opacity * frameOpacity);
if (shader) {
const float a = opacity * frameOpacity;
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(0.0, 0.0, 0.0, opacity * frameOpacity);
@ -1243,8 +1248,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
if (!m_texture) // Lazy creation
updateTexture();
if (shader)
shader->setUniform(GLShader::Opacity, opacity * frameOpacity);
if (shader) {
const float a = opacity * frameOpacity;
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
@ -1275,9 +1282,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2);
if (m_effectFrame->isCrossFade() && m_oldIconTexture) {
if (shader)
shader->setUniform(GLShader::Opacity,
opacity * (1.0f - m_effectFrame->crossFadeProgress()));
if (shader) {
const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress()));
@ -1286,15 +1294,19 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
m_oldIconTexture->bind();
m_oldIconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
m_oldIconTexture->unbind();
if (shader)
shader->setUniform(GLShader::Opacity, opacity * m_effectFrame->crossFadeProgress());
if (shader) {
const float a = opacity * m_effectFrame->crossFadeProgress();
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
#endif
} else {
if (shader)
shader->setUniform(GLShader::Opacity, opacity);
if (shader) {
const QVector4D constant(opacity, opacity, opacity, opacity);
shader->setUniform(GLShader::ModulationConstant, constant);
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity);
@ -1315,8 +1327,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
// Render text
if (!m_effectFrame->text().isEmpty()) {
if (m_effectFrame->isCrossFade() && m_oldTextTexture) {
if (shader)
shader->setUniform(GLShader::Opacity, opacity * (1.0f - m_effectFrame->crossFadeProgress()));
if (shader) {
const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity *(1.0 - m_effectFrame->crossFadeProgress()));
@ -1325,15 +1339,19 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
m_oldTextTexture->bind();
m_oldTextTexture->render(region, m_effectFrame->geometry());
m_oldTextTexture->unbind();
if (shader)
shader->setUniform(GLShader::Opacity, opacity * m_effectFrame->crossFadeProgress());
if (shader) {
const float a = opacity * m_effectFrame->crossFadeProgress();
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
#endif
} else {
if (shader)
shader->setUniform(GLShader::Opacity, opacity);
if (shader) {
const QVector4D constant(opacity, opacity, opacity, opacity);
shader->setUniform(GLShader::ModulationConstant, constant);
}
#ifndef KWIN_HAVE_OPENGLES
else
glColor4f(1.0, 1.0, 1.0, opacity);