1/**************************************************************************** 2** 3** Copyright (C) 2017 The Qt Company Ltd. 4** Contact: https://www.qt.io/licensing/ 5** 6** This file is part of the Qt Graphical Effects module. 7** 8** $QT_BEGIN_LICENSE:LGPL$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see https://www.qt.io/terms-conditions. For further 15** information use the contact form at https://www.qt.io/contact-us. 16** 17** GNU Lesser General Public License Usage 18** Alternatively, this file may be used under the terms of the GNU Lesser 19** General Public License version 3 as published by the Free Software 20** Foundation and appearing in the file LICENSE.LGPL3 included in the 21** packaging of this file. Please review the following information to 22** ensure the GNU Lesser General Public License version 3 requirements 23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24** 25** GNU General Public License Usage 26** Alternatively, this file may be used under the terms of the GNU 27** General Public License version 2.0 or (at your option) the GNU General 28** Public license version 3 or any later version approved by the KDE Free 29** Qt Foundation. The licenses are as published by the Free Software 30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31** included in the packaging of this file. Please review the following 32** information to ensure the GNU General Public License requirements will 33** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34** https://www.gnu.org/licenses/gpl-3.0.html. 35** 36** $QT_END_LICENSE$ 37** 38****************************************************************************/ 39 40import QtQuick 2.12 41import QtGraphicalEffects.private 1.12 42 43/*! 44 \qmltype FastBlur 45 \inqmlmodule QtGraphicalEffects 46 \since QtGraphicalEffects 1.0 47 \inherits QtQuick2::Item 48 \ingroup qtgraphicaleffects-blur 49 \brief Applies a fast blur effect to one or more source items. 50 51 FastBlur offers lower blur quality than 52 \l{QtGraphicalEffects::GaussianBlur}{GaussianBlur}, but it is faster to 53 render. The FastBlur effect softens the source content by blurring it with 54 algorithm which uses the source content downscaling and bilinear filtering. 55 Use this effect in situations where the source content is rapidly changing 56 and the highest possible blur quality is not 57 needed. 58 59 \table 60 \header 61 \li Source 62 \li Effect applied 63 \row 64 \li \image Original_bug.png 65 \li \image FastBlur_bug.png 66 \endtable 67 68 \note This effect is available when running with OpenGL. 69 s 70 \section1 Example 71 72 The following example shows how to apply the effect. 73 \snippet FastBlur-example.qml example 74 75*/ 76Item { 77 id: rootItem 78 79 /*! 80 This property defines the source item that is going to be blurred. 81 82 \note It is not supported to let the effect include itself, for 83 instance by setting source to the effect's parent. 84 */ 85 property variant source 86 87 /*! 88 This property defines the distance of the neighboring pixels which affect 89 the blurring of an individual pixel. A larger radius increases the blur 90 effect. FastBlur algorithm may internally reduce the accuracy of the radius in order to 91 provide good rendering performance. 92 93 The value ranges from 0.0 (no blur) to inf. Visual quality of the blur is reduced when 94 radius exceeds value 64. By default, the property is set to \c 0.0 (no blur). 95 96 \table 97 \header 98 \li Output examples with different blur values 99 \li 100 \li 101 \row 102 \li \image FastBlur_radius1.png 103 \li \image FastBlur_radius2.png 104 \li \image FastBlur_radius3.png 105 \row 106 \li \b { radius: 0 } 107 \li \b { radius: 32 } 108 \li \b { radius: 64 } 109 \endtable 110 */ 111 property real radius: 0.0 112 113 /*! 114 This property defines the blur behavior near the edges of the item, 115 where the pixel blurring is affected by the pixels outside the source 116 edges. 117 118 If the property is set to \c true, the pixels outside the source are 119 interpreted to be transparent, which is similar to OpenGL 120 clamp-to-border extension. The blur is expanded slightly outside the 121 effect item area. 122 123 If the property is set to \c false, the pixels outside the source are 124 interpreted to contain the same color as the pixels at the edge of the 125 item, which is similar to OpenGL clamp-to-edge behavior. The blur does 126 not expand outside the effect item area. 127 128 By default, the property is set to \c false. 129 130 \table 131 \header 132 \li Output examples with different transparentBorder values 133 \li 134 \li 135 \row 136 \li \image FastBlur_transparentBorder1.png 137 \li \image FastBlur_transparentBorder2.png 138 \row 139 \li \b { transparentBorder: false } 140 \li \b { transparentBorder: true } 141 \row 142 \li \l radius: 64 143 \li \l radius: 64 144 \endtable 145 */ 146 property bool transparentBorder: false 147 148 /*! 149 This property allows the effect output pixels to be cached in order to 150 improve the rendering performance. 151 152 Every time the source or effect properties are changed, the pixels in 153 the cache must be updated. Memory consumption is increased, because an 154 extra buffer of memory is required for storing the effect output. 155 156 It is recommended to disable the cache when the source or the effect 157 properties are animated. 158 159 By default, the property is set to \c false. 160 161 */ 162 property bool cached: false 163 164 SourceProxy { 165 id: sourceProxy 166 input: rootItem.source 167 } 168 169 ShaderEffectSource { 170 id: cacheItem 171 anchors.fill: shaderItem 172 visible: rootItem.cached 173 sourceItem: shaderItem 174 live: true 175 hideSource: visible 176 smooth: rootItem.radius > 0 177 } 178 179 /*! \internal */ 180 property string __internalBlurVertexShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/fastblur_internal.vert" 181 182 /*! \internal */ 183 property string __internalBlurFragmentShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/fastblur_internal.frag" 184 185 ShaderEffect { 186 id: level0 187 property variant source: sourceProxy.output 188 anchors.fill: parent 189 visible: false 190 smooth: true 191 } 192 193 ShaderEffectSource { 194 id: level1 195 width: Math.ceil(shaderItem.width / 32) * 32 196 height: Math.ceil(shaderItem.height / 32) * 32 197 sourceItem: level0 198 hideSource: rootItem.visible 199 sourceRect: transparentBorder ? Qt.rect(-64, -64, shaderItem.width, shaderItem.height) : Qt.rect(0, 0, 0, 0) 200 visible: false 201 smooth: rootItem.radius > 0 202 } 203 204 ShaderEffect { 205 id: effect1 206 property variant source: level1 207 property real yStep: 1/height 208 property real xStep: 1/width 209 anchors.fill: level2 210 visible: false 211 smooth: true 212 vertexShader: __internalBlurVertexShader 213 fragmentShader: __internalBlurFragmentShader 214 } 215 216 ShaderEffectSource { 217 id: level2 218 width: level1.width / 2 219 height: level1.height / 2 220 sourceItem: effect1 221 hideSource: rootItem.visible 222 visible: false 223 smooth: true 224 } 225 226 ShaderEffect { 227 id: effect2 228 property variant source: level2 229 property real yStep: 1/height 230 property real xStep: 1/width 231 anchors.fill: level3 232 visible: false 233 smooth: true 234 vertexShader: __internalBlurVertexShader 235 fragmentShader: __internalBlurFragmentShader 236 } 237 238 ShaderEffectSource { 239 id: level3 240 width: level2.width / 2 241 height: level2.height / 2 242 sourceItem: effect2 243 hideSource: rootItem.visible 244 visible: false 245 smooth: true 246 } 247 248 ShaderEffect { 249 id: effect3 250 property variant source: level3 251 property real yStep: 1/height 252 property real xStep: 1/width 253 anchors.fill: level4 254 visible: false 255 smooth: true 256 vertexShader: __internalBlurVertexShader 257 fragmentShader: __internalBlurFragmentShader 258 } 259 260 ShaderEffectSource { 261 id: level4 262 width: level3.width / 2 263 height: level3.height / 2 264 sourceItem: effect3 265 hideSource: rootItem.visible 266 visible: false 267 smooth: true 268 } 269 270 ShaderEffect { 271 id: effect4 272 property variant source: level4 273 property real yStep: 1/height 274 property real xStep: 1/width 275 anchors.fill: level5 276 visible: false 277 smooth: true 278 vertexShader: __internalBlurVertexShader 279 fragmentShader: __internalBlurFragmentShader 280 } 281 282 ShaderEffectSource { 283 id: level5 284 width: level4.width / 2 285 height: level4.height / 2 286 sourceItem: effect4 287 hideSource: rootItem.visible 288 visible: false 289 smooth: true 290 } 291 292 ShaderEffect { 293 id: effect5 294 property variant source: level5 295 property real yStep: 1/height 296 property real xStep: 1/width 297 anchors.fill: level6 298 visible: false 299 smooth: true 300 vertexShader: __internalBlurVertexShader 301 fragmentShader: __internalBlurFragmentShader 302 } 303 304 ShaderEffectSource { 305 id: level6 306 width: level5.width / 2 307 height: level5.height / 2 308 sourceItem: effect5 309 hideSource: rootItem.visible 310 visible: false 311 smooth: true 312 } 313 314 Item { 315 id: dummysource 316 width: 1 317 height: 1 318 visible: false 319 } 320 321 ShaderEffectSource { 322 id: dummy 323 width: 1 324 height: 1 325 sourceItem: dummysource 326 visible: false 327 smooth: false 328 live: false 329 } 330 331 ShaderEffect { 332 id: shaderItem 333 334 property variant source1: level1 335 property variant source2: level2 336 property variant source3: level3 337 property variant source4: level4 338 property variant source5: level5 339 property variant source6: level6 340 property real lod: Math.sqrt(rootItem.radius / 64.0) * 1.2 - 0.2 341 property real weight1 342 property real weight2 343 property real weight3 344 property real weight4 345 property real weight5 346 property real weight6 347 348 x: transparentBorder ? -64 : 0 349 y: transparentBorder ? -64 : 0 350 width: transparentBorder ? parent.width + 128 : parent.width 351 height: transparentBorder ? parent.height + 128 : parent.height 352 353 function weight(v) { 354 if (v <= 0.0) 355 return 1.0 356 if (v >= 0.5) 357 return 0.0 358 359 return 1.0 - v * 2.0 360 } 361 362 function calculateWeights() { 363 364 var w1 = weight(Math.abs(lod - 0.100)) 365 var w2 = weight(Math.abs(lod - 0.300)) 366 var w3 = weight(Math.abs(lod - 0.500)) 367 var w4 = weight(Math.abs(lod - 0.700)) 368 var w5 = weight(Math.abs(lod - 0.900)) 369 var w6 = weight(Math.abs(lod - 1.100)) 370 371 var sum = w1 + w2 + w3 + w4 + w5 + w6; 372 weight1 = w1 / sum; 373 weight2 = w2 / sum; 374 weight3 = w3 / sum; 375 weight4 = w4 / sum; 376 weight5 = w5 / sum; 377 weight6 = w6 / sum; 378 379 upateSources() 380 } 381 382 function upateSources() { 383 var sources = new Array(); 384 var weights = new Array(); 385 386 if (weight1 > 0) { 387 sources.push(level1) 388 weights.push(weight1) 389 } 390 391 if (weight2 > 0) { 392 sources.push(level2) 393 weights.push(weight2) 394 } 395 396 if (weight3 > 0) { 397 sources.push(level3) 398 weights.push(weight3) 399 } 400 401 if (weight4 > 0) { 402 sources.push(level4) 403 weights.push(weight4) 404 } 405 406 if (weight5 > 0) { 407 sources.push(level5) 408 weights.push(weight5) 409 } 410 411 if (weight6 > 0) { 412 sources.push(level6) 413 weights.push(weight6) 414 } 415 416 for (var j = sources.length; j < 6; j++) { 417 sources.push(dummy) 418 weights.push(0.0) 419 } 420 421 source1 = sources[0] 422 source2 = sources[1] 423 source3 = sources[2] 424 source4 = sources[3] 425 source5 = sources[4] 426 source6 = sources[5] 427 428 weight1 = weights[0] 429 weight2 = weights[1] 430 weight3 = weights[2] 431 weight4 = weights[3] 432 weight5 = weights[4] 433 weight6 = weights[5] 434 } 435 436 Component.onCompleted: calculateWeights() 437 438 onLodChanged: calculateWeights() 439 440 fragmentShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/fastblur.frag" 441 } 442} 443