diff --git a/src/libkwineffects/kwinglutils.cpp b/src/libkwineffects/kwinglutils.cpp index 86d0c5a4d7..55a3116f90 100644 --- a/src/libkwineffects/kwinglutils.cpp +++ b/src/libkwineffects/kwinglutils.cpp @@ -430,6 +430,8 @@ void GLShader::resolveLocations() mVec2Location[Offset] = uniformLocation("offset"); + m_vec3Locations[Vec3Uniform::PrimaryBrightness] = uniformLocation("primaryBrightness"); + mVec4Location[ModulationConstant] = uniformLocation("modulation"); mFloatLocation[Saturation] = uniformLocation("saturation"); @@ -470,6 +472,12 @@ bool GLShader::setUniform(GLShader::Vec2Uniform uniform, const QVector2D &value) return setUniform(mVec2Location[uniform], value); } +bool GLShader::setUniform(Vec3Uniform uniform, const QVector3D &value) +{ + resolveLocations(); + return setUniform(m_vec3Locations[uniform], value); +} + bool GLShader::setUniform(GLShader::Vec4Uniform uniform, const QVector4D &value) { resolveLocations(); @@ -783,6 +791,7 @@ QByteArray ShaderManager::generateFragmentSource(ShaderTraits traits) const } if (traits & ShaderTrait::AdjustSaturation) { stream << "uniform float saturation;\n"; + stream << "uniform vec3 primaryBrightness;\n"; } stream << "\n" @@ -841,9 +850,6 @@ QByteArray ShaderManager::generateFragmentSource(ShaderTraits traits) const } else if (traits & ShaderTrait::UniformColor) { stream << " result = geometryColor;\n"; } - if (traits & ShaderTrait::AdjustSaturation) { - stream << " result.rgb = mix(vec3(dot(result.rgb, vec3(0.2126, 0.7152, 0.0722))), result.rgb, saturation);\n"; - } if (traits & ShaderTrait::TransformColorspace) { // sRGB -> output colorspace & linear stream << " if (sourceNamedTransferFunction == 0) {\n"; @@ -851,6 +857,12 @@ QByteArray ShaderManager::generateFragmentSource(ShaderTraits traits) const stream << " }\n"; stream << " result.rgb = doTonemapping(colorimetryTransform * result.rgb, maxHdrBrightness);\n"; } + if (traits & ShaderTrait::AdjustSaturation) { + // this calculates the Y component of the XYZ color representation for the color, + // which roughly corresponds to the brightness of the RGB tuple + stream << " float Y = dot(result.rgb, primaryBrightness);\n"; + stream << " result.rgb = mix(vec3(Y), result.rgb, saturation);\n"; + } if (traits & ShaderTrait::Modulate) { stream << " result *= modulation;\n"; } diff --git a/src/libkwineffects/kwinglutils.h b/src/libkwineffects/kwinglutils.h index ccd8c39ca2..7daaeb2321 100644 --- a/src/libkwineffects/kwinglutils.h +++ b/src/libkwineffects/kwinglutils.h @@ -121,6 +121,10 @@ public: Vec2UniformCount }; + enum class Vec3Uniform { + PrimaryBrightness = 0 + }; + enum Vec4Uniform { ModulationConstant, Vec4UniformCount @@ -150,6 +154,7 @@ public: bool setUniform(MatrixUniform uniform, const QMatrix3x3 &value); bool setUniform(MatrixUniform uniform, const QMatrix4x4 &matrix); bool setUniform(Vec2Uniform uniform, const QVector2D &value); + bool setUniform(Vec3Uniform uniform, const QVector3D &value); bool setUniform(Vec4Uniform uniform, const QVector4D &value); bool setUniform(FloatUniform uniform, float value); bool setUniform(IntUniform uniform, int value); @@ -177,6 +182,7 @@ private: bool mExplicitLinking : 1; int mMatrixLocation[MatrixCount]; int mVec2Location[Vec2UniformCount]; + QHash m_vec3Locations; int mVec4Location[Vec4UniformCount]; int mFloatLocation[FloatUniformCount]; int mIntLocation[IntUniformCount]; diff --git a/src/libkwineffects/kwinoffscreeneffect.cpp b/src/libkwineffects/kwinoffscreeneffect.cpp index 8a2c150716..060a4dcb3c 100644 --- a/src/libkwineffects/kwinoffscreeneffect.cpp +++ b/src/libkwineffects/kwinoffscreeneffect.cpp @@ -155,7 +155,6 @@ void OffscreenData::paint(const RenderTarget &renderTarget, const RenderViewport { GLShader *shader = m_shader ? m_shader : ShaderManager::instance()->shader(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::AdjustSaturation | ShaderTrait::TransformColorspace); ShaderBinder binder(shader); - shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); const double scale = viewport.scale(); @@ -185,11 +184,14 @@ void OffscreenData::paint(const RenderTarget &renderTarget, const RenderViewport QMatrix4x4 mvp = data.projectionMatrix(); mvp.translate(window->x() * scale, window->y() * scale); + const auto toXYZ = renderTarget.colorDescription().colorimetry().toXYZ(); shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp * data.toMatrix(scale)); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); + shader->setUniform(GLShader::Vec3Uniform::PrimaryBrightness, QVector3D(toXYZ(1, 0), toXYZ(1, 1), toXYZ(1, 2))); shader->setUniform(GLShader::TextureWidth, m_texture->width()); shader->setUniform(GLShader::TextureHeight, m_texture->height()); + shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); const bool clipping = region != infiniteRegion(); const QRegion clipRegion = clipping ? viewport.mapToRenderTarget(region) : infiniteRegion(); diff --git a/src/scene/itemrenderer_opengl.cpp b/src/scene/itemrenderer_opengl.cpp index eeb7fd8902..e36bf05ae8 100644 --- a/src/scene/itemrenderer_opengl.cpp +++ b/src/scene/itemrenderer_opengl.cpp @@ -322,7 +322,11 @@ void ItemRendererOpenGL::renderItem(const RenderTarget &renderTarget, const Rend vbo->bindArrays(); GLShader *shader = ShaderManager::instance()->pushShader(shaderTraits); - shader->setUniform(GLShader::Saturation, data.saturation()); + if (shaderTraits & ShaderTrait::AdjustSaturation) { + const auto toXYZ = renderTarget.colorDescription().colorimetry().toXYZ(); + shader->setUniform(GLShader::Saturation, data.saturation()); + shader->setUniform(GLShader::Vec3Uniform::PrimaryBrightness, QVector3D(toXYZ(1, 0), toXYZ(1, 1), toXYZ(1, 2))); + } shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); if (renderContext.hardwareClipping) {