init
This commit is contained in:
@@ -0,0 +1,486 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Graphical Effects module.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtGraphicalEffects.private 1.12
|
||||
|
||||
/*!
|
||||
\qmltype Blend
|
||||
\inqmlmodule QtGraphicalEffects
|
||||
\since QtGraphicalEffects 1.0
|
||||
\inherits QtQuick2::Item
|
||||
\ingroup qtgraphicaleffects-blend
|
||||
\brief Merges two source items by using a blend mode.
|
||||
|
||||
Blend mode can be selected with the \l{Blend::mode}{mode} property.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li source
|
||||
\li foregroundSource
|
||||
\li Effect applied
|
||||
\row
|
||||
\li \image Original_bug.png
|
||||
\li \image Original_butterfly.png
|
||||
\li \image Blend_bug_and_butterfly.png
|
||||
\endtable
|
||||
|
||||
\note This effect is available when running with OpenGL.
|
||||
|
||||
\section1 Example
|
||||
|
||||
The following example shows how to apply the effect.
|
||||
\snippet Blend-example.qml example
|
||||
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
|
||||
/*!
|
||||
This property defines the source item that is going to be the base when
|
||||
\l{Blend::foregroundSource}{foregroundSource} is blended over it.
|
||||
|
||||
\note It is not supported to let the effect include itself, for
|
||||
instance by setting source to the effect's parent.
|
||||
*/
|
||||
property variant source
|
||||
|
||||
/*!
|
||||
This property defines the item that is going to be blended over the
|
||||
\l{Blend::source}{source}.
|
||||
|
||||
\note It is not supported to let the effect include itself, for
|
||||
instance by setting foregroundSource to the effect's parent.
|
||||
*/
|
||||
property variant foregroundSource
|
||||
|
||||
/*!
|
||||
This property defines the mode which is used when foregroundSource is
|
||||
blended over source. Values are case insensitive.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li mode
|
||||
\li description
|
||||
\row
|
||||
\li normal
|
||||
\li The pixel component values from foregroundSource are written
|
||||
over source by using alpha blending.
|
||||
\row
|
||||
\li addition
|
||||
\li The pixel component values from source and foregroundSource are
|
||||
added together and written.
|
||||
\row
|
||||
\li average
|
||||
\li The pixel component values from source and foregroundSource are
|
||||
averaged and written.
|
||||
\row
|
||||
\li color
|
||||
\li The lightness value from source is combined with hue and
|
||||
saturation from foregroundSource and written.
|
||||
\row
|
||||
\li colorBurn
|
||||
\li The darker pixels from source are darkened more, if both source
|
||||
and foregroundSource pixels are light the result is light.
|
||||
\row
|
||||
\li colorDodge
|
||||
\li The lighter pixels from source are lightened more, if both
|
||||
source and foregroundSource pixels are dark the result is dark.
|
||||
\row
|
||||
\li darken
|
||||
\li The darker pixel component value from source and
|
||||
foregroundSource is written.
|
||||
\row
|
||||
\li darkerColor
|
||||
\li The lower luminance pixel rgb-value from source and
|
||||
foregroundSource is written.
|
||||
\row
|
||||
\li difference
|
||||
\li The absolute pixel component value difference between source and
|
||||
foregroundSource is written.
|
||||
\row
|
||||
\li divide
|
||||
\li The pixel component values from source is divided by the value
|
||||
from foregroundSource and written.
|
||||
\row
|
||||
\li exclusion
|
||||
\li The pixel component value difference with reduced contrast
|
||||
between source and foregroundSource is written.
|
||||
\row
|
||||
\li hardLight
|
||||
\li The pixel component values from source are lightened or darkened
|
||||
according to foregroundSource values and written.
|
||||
\row
|
||||
\li hue
|
||||
\li The hue value from foregroundSource is combined with saturation
|
||||
and lightness from source and written.
|
||||
\row
|
||||
\li lighten
|
||||
\li The lightest pixel component value from source and
|
||||
foregroundSource is written.
|
||||
\row
|
||||
\li lighterColor
|
||||
\li The higher luminance pixel rgb-value from source and
|
||||
foregroundSource is written.
|
||||
\row
|
||||
\li lightness
|
||||
\li The lightness value from foregroundSource is combined with hue
|
||||
and saturation from source and written.
|
||||
\row
|
||||
\li multiply
|
||||
\li The pixel component values from source and foregroundSource are
|
||||
multiplied together and written.
|
||||
\row
|
||||
\li negation
|
||||
\li The inverted absolute pixel component value difference between
|
||||
source and foregroundSource is written.
|
||||
\row
|
||||
\li saturation
|
||||
\li The saturation value from foregroundSource is combined with hue
|
||||
and lightness from source and written.
|
||||
\row
|
||||
\li screen
|
||||
\li The pixel values from source and foregroundSource are negated,
|
||||
then multiplied, negated again, and written.
|
||||
\row
|
||||
\li subtract
|
||||
\li Pixel value from foregroundSource is subracted from source and
|
||||
written.
|
||||
\row
|
||||
\li softLight
|
||||
\li The pixel component values from source are lightened or darkened
|
||||
slightly according to foregroundSource values and written.
|
||||
|
||||
\endtable
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Example source
|
||||
\li Example foregroundSource
|
||||
\row
|
||||
\li \image Original_bug.png
|
||||
\li \image Original_butterfly.png
|
||||
\endtable
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Output examples with different mode values
|
||||
\li
|
||||
\li
|
||||
\row
|
||||
\li \image Blend_mode1.png
|
||||
\li \image Blend_mode2.png
|
||||
\li \image Blend_mode3.png
|
||||
\row
|
||||
\li \b { mode: normal }
|
||||
\li \b { mode: addition }
|
||||
\li \b { mode: average }
|
||||
\row
|
||||
\li \image Blend_mode4.png
|
||||
\li \image Blend_mode5.png
|
||||
\li \image Blend_mode6.png
|
||||
\row
|
||||
\li \b { mode: color }
|
||||
\li \b { mode: colorBurn }
|
||||
\li \b { mode: colorDodge }
|
||||
\row
|
||||
\li \image Blend_mode7.png
|
||||
\li \image Blend_mode8.png
|
||||
\li \image Blend_mode9.png
|
||||
\row
|
||||
\li \b { mode: darken }
|
||||
\li \b { mode: darkerColor }
|
||||
\li \b { mode: difference }
|
||||
\row
|
||||
\li \image Blend_mode10.png
|
||||
\li \image Blend_mode11.png
|
||||
\li \image Blend_mode12.png
|
||||
\row
|
||||
\li \b { mode: divide }
|
||||
\li \b { mode: exclusion }
|
||||
\li \b { mode: hardlight }
|
||||
\row
|
||||
\li \image Blend_mode13.png
|
||||
\li \image Blend_mode14.png
|
||||
\li \image Blend_mode15.png
|
||||
\row
|
||||
\li \b { mode: hue }
|
||||
\li \b { mode: lighten }
|
||||
\li \b { mode: lighterColor }
|
||||
\row
|
||||
\li \image Blend_mode16.png
|
||||
\li \image Blend_mode17.png
|
||||
\li \image Blend_mode18.png
|
||||
\row
|
||||
\li \b { mode: lightness }
|
||||
\li \b { mode: negation }
|
||||
\li \b { mode: multiply }
|
||||
\row
|
||||
\li \image Blend_mode19.png
|
||||
\li \image Blend_mode20.png
|
||||
\li \image Blend_mode21.png
|
||||
\row
|
||||
\li \b { mode: saturation }
|
||||
\li \b { mode: screen }
|
||||
\li \b { mode: subtract }
|
||||
\row
|
||||
\li \image Blend_mode22.png
|
||||
\row
|
||||
\li \b { mode: softLight }
|
||||
\endtable
|
||||
*/
|
||||
property string mode: "normal"
|
||||
|
||||
/*!
|
||||
This property allows the effect output pixels to be cached in order to
|
||||
improve the rendering performance.
|
||||
|
||||
Every time the source or effect properties are changed, the pixels in the
|
||||
cache must be updated. Memory consumption is increased, because an extra
|
||||
buffer of memory is required for storing the effect output.
|
||||
|
||||
It is recommended to disable the cache when the source or the effect
|
||||
properties are animated.
|
||||
|
||||
By default, the property is set to false.
|
||||
|
||||
*/
|
||||
property bool cached: false
|
||||
|
||||
SourceProxy {
|
||||
id: backgroundSourceProxy
|
||||
input: rootItem.source
|
||||
}
|
||||
|
||||
SourceProxy {
|
||||
id: foregroundSourceProxy
|
||||
input: rootItem.foregroundSource
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: cacheItem
|
||||
anchors.fill: parent
|
||||
visible: rootItem.cached
|
||||
smooth: true
|
||||
sourceItem: shaderItem
|
||||
live: true
|
||||
hideSource: visible
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: shaderItem
|
||||
property variant backgroundSource: backgroundSourceProxy.output
|
||||
property variant foregroundSource: foregroundSourceProxy.output
|
||||
property string mode: rootItem.mode
|
||||
anchors.fill: parent
|
||||
|
||||
fragmentShader: fragmentShaderBegin + blendModeNormal + fragmentShaderEnd
|
||||
|
||||
function buildFragmentShader() {
|
||||
var shader = fragmentShaderBegin
|
||||
|
||||
switch (mode.toLowerCase()) {
|
||||
case "addition" : shader += blendModeAddition; break;
|
||||
case "average" : shader += blendModeAverage; break;
|
||||
case "color" : shader += blendModeColor; break;
|
||||
case "colorburn" : shader += blendModeColorBurn; break;
|
||||
case "colordodge" : shader += blendModeColorDodge; break;
|
||||
case "darken" : shader += blendModeDarken; break;
|
||||
case "darkercolor" : shader += blendModeDarkerColor; break;
|
||||
case "difference" : shader += blendModeDifference; break;
|
||||
case "divide" : shader += blendModeDivide; break;
|
||||
case "exclusion" : shader += blendModeExclusion; break;
|
||||
case "hardlight" : shader += blendModeHardLight; break;
|
||||
case "hue" : shader += blendModeHue; break;
|
||||
case "lighten" : shader += blendModeLighten; break;
|
||||
case "lightercolor" : shader += blendModeLighterColor; break;
|
||||
case "lightness" : shader += blendModeLightness; break;
|
||||
case "negation" : shader += blendModeNegation; break;
|
||||
case "normal" : shader += blendModeNormal; break;
|
||||
case "multiply" : shader += blendModeMultiply; break;
|
||||
case "saturation" : shader += blendModeSaturation; break;
|
||||
case "screen" : shader += blendModeScreen; break;
|
||||
case "subtract" : shader += blendModeSubtract; break;
|
||||
case "softlight" : shader += blendModeSoftLight; break;
|
||||
default: shader += "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"; break;
|
||||
}
|
||||
|
||||
shader += fragmentShaderEnd
|
||||
fragmentShader = shader
|
||||
|
||||
// Workaraound for a bug just to make sure display gets updated when the mode changes.
|
||||
backgroundSourceChanged()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
buildFragmentShader()
|
||||
}
|
||||
|
||||
onModeChanged: {
|
||||
buildFragmentShader()
|
||||
}
|
||||
|
||||
property string blendModeAddition: "result.rgb = min(rgb1 + rgb2, 1.0);"
|
||||
property string blendModeAverage: "result.rgb = 0.5 * (rgb1 + rgb2);"
|
||||
property string blendModeColor: "result.rgb = HSLtoRGB(vec3(RGBtoHSL(rgb2).xy, RGBtoL(rgb1)));"
|
||||
property string blendModeColorBurn: "result.rgb = clamp(1.0 - ((1.0 - rgb1) / max(vec3(1.0 / 256.0), rgb2)), vec3(0.0), vec3(1.0));"
|
||||
property string blendModeColorDodge: "result.rgb = clamp(rgb1 / max(vec3(1.0 / 256.0), (1.0 - rgb2)), vec3(0.0), vec3(1.0));"
|
||||
property string blendModeDarken: "result.rgb = min(rgb1, rgb2);"
|
||||
property string blendModeDarkerColor: "result.rgb = 0.3 * rgb1.r + 0.59 * rgb1.g + 0.11 * rgb1.b > 0.3 * rgb2.r + 0.59 * rgb2.g + 0.11 * rgb2.b ? rgb2 : rgb1;"
|
||||
property string blendModeDifference: "result.rgb = abs(rgb1 - rgb2);"
|
||||
property string blendModeDivide: "result.rgb = clamp(rgb1 / rgb2, 0.0, 1.0);"
|
||||
property string blendModeExclusion: "result.rgb = rgb1 + rgb2 - 2.0 * rgb1 * rgb2;"
|
||||
property string blendModeHardLight: "result.rgb = vec3(channelBlendHardLight(rgb1.r, rgb2.r), channelBlendHardLight(rgb1.g, rgb2.g), channelBlendHardLight(rgb1.b, rgb2.b));"
|
||||
property string blendModeHue: "result.rgb = HSLtoRGB(vec3(RGBtoHSL(rgb2).x, RGBtoHSL(rgb1).yz));"
|
||||
property string blendModeLighten: "result.rgb = max(rgb1, rgb2);"
|
||||
property string blendModeLighterColor: "result.rgb = 0.3 * rgb1.r + 0.59 * rgb1.g + 0.11 * rgb1.b > 0.3 * rgb2.r + 0.59 * rgb2.g + 0.11 * rgb2.b ? rgb1 : rgb2;"
|
||||
property string blendModeLightness: "result.rgb = HSLtoRGB(vec3(RGBtoHSL(rgb1).xy, RGBtoL(rgb2)));"
|
||||
property string blendModeMultiply: "result.rgb = rgb1 * rgb2;"
|
||||
property string blendModeNegation: "result.rgb = 1.0 - abs(1.0 - rgb1 - rgb2);"
|
||||
property string blendModeNormal: "result.rgb = rgb2; a = max(color1.a, color2.a);"
|
||||
property string blendModeSaturation: "lowp vec3 hsl1 = RGBtoHSL(rgb1); result.rgb = HSLtoRGB(vec3(hsl1.x, RGBtoHSL(rgb2).y, hsl1.z));"
|
||||
property string blendModeScreen: "result.rgb = 1.0 - (vec3(1.0) - rgb1) * (vec3(1.0) - rgb2);"
|
||||
property string blendModeSubtract: "result.rgb = max(rgb1 - rgb2, vec3(0.0));"
|
||||
property string blendModeSoftLight: "result.rgb = rgb1 * ((1.0 - rgb1) * rgb2 + (1.0 - (1.0 - rgb1) * (1.0 - rgb2)));"
|
||||
|
||||
property string fragmentCoreShaderWorkaround: (GraphicsInfo.profile === GraphicsInfo.OpenGLCoreProfile ? "#version 150 core
|
||||
#define varying in
|
||||
#define texture2D texture
|
||||
out vec4 fragColor;
|
||||
#define gl_FragColor fragColor
|
||||
" : "")
|
||||
|
||||
property string fragmentShaderBegin: fragmentCoreShaderWorkaround + "
|
||||
varying mediump vec2 qt_TexCoord0;
|
||||
uniform highp float qt_Opacity;
|
||||
uniform lowp sampler2D backgroundSource;
|
||||
uniform lowp sampler2D foregroundSource;
|
||||
|
||||
highp float RGBtoL(highp vec3 color) {
|
||||
highp float cmin = min(color.r, min(color.g, color.b));
|
||||
highp float cmax = max(color.r, max(color.g, color.b));
|
||||
highp float l = (cmin + cmax) / 2.0;
|
||||
return l;
|
||||
}
|
||||
|
||||
highp vec3 RGBtoHSL(highp vec3 color) {
|
||||
highp float cmin = min(color.r, min(color.g, color.b));
|
||||
highp float cmax = max(color.r, max(color.g, color.b));
|
||||
highp float h = 0.0;
|
||||
highp float s = 0.0;
|
||||
highp float l = (cmin + cmax) / 2.0;
|
||||
highp float diff = cmax - cmin;
|
||||
|
||||
if (diff > 1.0 / 256.0) {
|
||||
if (l < 0.5)
|
||||
s = diff / (cmin + cmax);
|
||||
else
|
||||
s = diff / (2.0 - (cmin + cmax));
|
||||
|
||||
if (color.r == cmax)
|
||||
h = (color.g - color.b) / diff;
|
||||
else if (color.g == cmax)
|
||||
h = 2.0 + (color.b - color.r) / diff;
|
||||
else
|
||||
h = 4.0 + (color.r - color.g) / diff;
|
||||
|
||||
h /= 6.0;
|
||||
}
|
||||
return vec3(h, s, l);
|
||||
}
|
||||
|
||||
highp float hueToIntensity(highp float v1, highp float v2, highp float h) {
|
||||
h = fract(h);
|
||||
if (h < 1.0 / 6.0)
|
||||
return v1 + (v2 - v1) * 6.0 * h;
|
||||
else if (h < 1.0 / 2.0)
|
||||
return v2;
|
||||
else if (h < 2.0 / 3.0)
|
||||
return v1 + (v2 - v1) * 6.0 * (2.0 / 3.0 - h);
|
||||
|
||||
return v1;
|
||||
}
|
||||
|
||||
highp vec3 HSLtoRGB(highp vec3 color) {
|
||||
highp float h = color.x;
|
||||
highp float l = color.z;
|
||||
highp float s = color.y;
|
||||
|
||||
if (s < 1.0 / 256.0)
|
||||
return vec3(l, l, l);
|
||||
|
||||
highp float v1;
|
||||
highp float v2;
|
||||
if (l < 0.5)
|
||||
v2 = l * (1.0 + s);
|
||||
else
|
||||
v2 = (l + s) - (s * l);
|
||||
|
||||
v1 = 2.0 * l - v2;
|
||||
|
||||
highp float d = 1.0 / 3.0;
|
||||
highp float r = hueToIntensity(v1, v2, h + d);
|
||||
highp float g = hueToIntensity(v1, v2, h);
|
||||
highp float b = hueToIntensity(v1, v2, h - d);
|
||||
return vec3(r, g, b);
|
||||
}
|
||||
|
||||
lowp float channelBlendHardLight(lowp float c1, lowp float c2) {
|
||||
return c2 > 0.5 ? (1.0 - (1.0 - 2.0 * (c2 - 0.5)) * (1.0 - c1)) : (2.0 * c1 * c2);
|
||||
}
|
||||
|
||||
void main() {
|
||||
lowp vec4 result = vec4(0.0);
|
||||
lowp vec4 color1 = texture2D(backgroundSource, qt_TexCoord0);
|
||||
lowp vec4 color2 = texture2D(foregroundSource, qt_TexCoord0);
|
||||
lowp vec3 rgb1 = color1.rgb / max(1.0/256.0, color1.a);
|
||||
lowp vec3 rgb2 = color2.rgb / max(1.0/256.0, color2.a);
|
||||
highp float a = max(color1.a, color1.a * color2.a);
|
||||
"
|
||||
|
||||
property string fragmentShaderEnd: "
|
||||
gl_FragColor.rgb = mix(rgb1, result.rgb, color2.a);
|
||||
gl_FragColor.rbg *= a;
|
||||
gl_FragColor.a = a;
|
||||
gl_FragColor *= qt_Opacity;
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user