1/**************************************************************************** 2** 3** Copyright (C) 2016 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:BSD$ 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** BSD License Usage 18** Alternatively, you may use this file under the terms of the BSD license 19** as follows: 20** 21** "Redistribution and use in source and binary forms, with or without 22** modification, are permitted provided that the following conditions are 23** met: 24** * Redistributions of source code must retain the above copyright 25** notice, this list of conditions and the following disclaimer. 26** * Redistributions in binary form must reproduce the above copyright 27** notice, this list of conditions and the following disclaimer in 28** the documentation and/or other materials provided with the 29** distribution. 30** * Neither the name of The Qt Company Ltd nor the names of its 31** contributors may be used to endorse or promote products derived 32** from this software without specific prior written permission. 33** 34** 35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 46** 47** $QT_END_LICENSE$ 48** 49****************************************************************************/ 50 51import QtQuick 2.0 52 53Item { 54 id: rootItem 55 property variant source 56 property real spread: 0.0 57 property real blur: 0.0 58 property color color: "white" 59 property bool transparentBorder: false 60 property bool cached: false 61 62 SourceProxy { 63 id: sourceProxy 64 input: rootItem.source 65 } 66 67 ShaderEffectSource { 68 id: cacheItem 69 anchors.fill: shaderItem 70 visible: rootItem.cached 71 smooth: true 72 sourceItem: shaderItem 73 live: true 74 hideSource: visible 75 } 76 77 property string __internalBlurVertexShader: " 78 attribute highp vec4 qt_Vertex; 79 attribute highp vec2 qt_MultiTexCoord0; 80 uniform highp mat4 qt_Matrix; 81 uniform highp float yStep; 82 uniform highp float xStep; 83 varying highp vec2 qt_TexCoord0; 84 varying highp vec2 qt_TexCoord1; 85 varying highp vec2 qt_TexCoord2; 86 varying highp vec2 qt_TexCoord3; 87 88 void main() { 89 qt_TexCoord0 = vec2(qt_MultiTexCoord0.x + xStep, qt_MultiTexCoord0.y + yStep * 0.36); 90 qt_TexCoord1 = vec2(qt_MultiTexCoord0.x + xStep * 0.36, qt_MultiTexCoord0.y - yStep); 91 qt_TexCoord2 = vec2(qt_MultiTexCoord0.x - xStep * 0.36, qt_MultiTexCoord0.y + yStep); 92 qt_TexCoord3 = vec2(qt_MultiTexCoord0.x - xStep, qt_MultiTexCoord0.y - yStep * 0.36); 93 gl_Position = qt_Matrix * qt_Vertex; 94 } 95 " 96 97 property string __internalBlurFragmentShader: " 98 uniform lowp sampler2D source; 99 uniform lowp float qt_Opacity; 100 varying highp vec2 qt_TexCoord0; 101 varying highp vec2 qt_TexCoord1; 102 varying highp vec2 qt_TexCoord2; 103 varying highp vec2 qt_TexCoord3; 104 105 void main() { 106 highp vec4 sourceColor = (texture2D(source, qt_TexCoord0) + 107 texture2D(source, qt_TexCoord1) + 108 texture2D(source, qt_TexCoord2) + 109 texture2D(source, qt_TexCoord3)) * 0.25; 110 gl_FragColor = sourceColor * qt_Opacity; 111 } 112 " 113 114 ShaderEffect { 115 id: level0 116 property variant source: sourceProxy.output 117 anchors.fill: parent 118 visible: false 119 smooth: true 120 } 121 122 ShaderEffectSource { 123 id: level1 124 width: Math.ceil(shaderItem.width / 32) * 32 125 height: Math.ceil(shaderItem.height / 32) * 32 126 sourceItem: level0 127 hideSource: rootItem.visible 128 sourceRect: transparentBorder ? Qt.rect(-64, -64, shaderItem.width, shaderItem.height) : Qt.rect(0,0,0,0) 129 smooth: true 130 visible: false 131 } 132 133 ShaderEffect { 134 id: effect1 135 property variant source: level1 136 property real yStep: 1/height 137 property real xStep: 1/width 138 anchors.fill: level2 139 visible: false 140 smooth: true 141 vertexShader: __internalBlurVertexShader 142 fragmentShader: __internalBlurFragmentShader 143 } 144 145 ShaderEffectSource { 146 id: level2 147 width: level1.width / 2 148 height: level1.height / 2 149 sourceItem: effect1 150 hideSource: rootItem.visible 151 visible: false 152 smooth: true 153 } 154 155 ShaderEffect { 156 id: effect2 157 property variant source: level2 158 property real yStep: 1/height 159 property real xStep: 1/width 160 anchors.fill: level3 161 visible: false 162 smooth: true 163 vertexShader: __internalBlurVertexShader 164 fragmentShader: __internalBlurFragmentShader 165 } 166 167 ShaderEffectSource { 168 id: level3 169 width: level2.width / 2 170 height: level2.height / 2 171 sourceItem: effect2 172 hideSource: rootItem.visible 173 visible: false 174 smooth: true 175 } 176 177 ShaderEffect { 178 id: effect3 179 property variant source: level3 180 property real yStep: 1/height 181 property real xStep: 1/width 182 anchors.fill: level4 183 visible: false 184 smooth: true 185 vertexShader: __internalBlurVertexShader 186 fragmentShader: __internalBlurFragmentShader 187 } 188 189 ShaderEffectSource { 190 id: level4 191 width: level3.width / 2 192 height: level3.height / 2 193 sourceItem: effect3 194 hideSource: rootItem.visible 195 visible: false 196 smooth: true 197 } 198 199 ShaderEffect { 200 id: effect4 201 property variant source: level4 202 property real yStep: 1/height 203 property real xStep: 1/width 204 anchors.fill: level5 205 visible: false 206 smooth: true 207 vertexShader: __internalBlurVertexShader 208 fragmentShader: __internalBlurFragmentShader 209 } 210 211 ShaderEffectSource { 212 id: level5 213 width: level4.width / 2 214 height: level4.height / 2 215 sourceItem: effect4 216 hideSource: rootItem.visible 217 visible: false 218 smooth: true 219 } 220 221 ShaderEffect { 222 id: effect5 223 property variant source: level5 224 property real yStep: 1/height 225 property real xStep: 1/width 226 anchors.fill: level6 227 visible: false 228 smooth: true 229 vertexShader: __internalBlurVertexShader 230 fragmentShader: __internalBlurFragmentShader 231 } 232 233 ShaderEffectSource { 234 id: level6 235 width: level5.width / 2 236 height: level5.height / 2 237 sourceItem: effect5 238 hideSource: rootItem.visible 239 visible: false 240 smooth: true 241 } 242 243 Item { 244 id: dummysource 245 width: 1 246 height: 1 247 visible: false 248 } 249 250 ShaderEffectSource { 251 id: dummy 252 width: 1 253 height: 1 254 sourceItem: dummysource 255 visible: false 256 smooth: false 257 live: false 258 } 259 260 ShaderEffect { 261 id: shaderItem 262 x: transparentBorder ? -64 : 0 263 y: transparentBorder ? -64 : 0 264 width: transparentBorder ? parent.width + 128 : parent.width 265 height: transparentBorder ? parent.height + 128 : parent.height 266 267 property variant source1: level1 268 property variant source2: level2 269 property variant source3: level3 270 property variant source4: level4 271 property variant source5: level5 272 property variant source6: level6 273 property real lod: rootItem.blur 274 275 property real weight1; 276 property real weight2; 277 property real weight3; 278 property real weight4; 279 property real weight5; 280 property real weight6; 281 282 property real spread: 1.0 - (rootItem.spread * 0.98) 283 property alias color: rootItem.color 284 285 function weight(v) { 286 if (v <= 0.0) 287 return 1 288 if (v >= 0.5) 289 return 0 290 291 return 1.0 - v / 0.5 292 } 293 294 function calculateWeights() { 295 296 var w1 = weight(Math.abs(lod - 0.100)) 297 var w2 = weight(Math.abs(lod - 0.300)) 298 var w3 = weight(Math.abs(lod - 0.500)) 299 var w4 = weight(Math.abs(lod - 0.700)) 300 var w5 = weight(Math.abs(lod - 0.900)) 301 var w6 = weight(Math.abs(lod - 1.100)) 302 303 var sum = w1 + w2 + w3 + w4 + w5 + w6; 304 weight1 = w1 / sum; 305 weight2 = w2 / sum; 306 weight3 = w3 / sum; 307 weight4 = w4 / sum; 308 weight5 = w5 / sum; 309 weight6 = w6 / sum; 310 311 upateSources() 312 } 313 314 function upateSources() { 315 var sources = new Array(); 316 var weights = new Array(); 317 318 if (weight1 > 0) { 319 sources.push(level1) 320 weights.push(weight1) 321 } 322 323 if (weight2 > 0) { 324 sources.push(level2) 325 weights.push(weight2) 326 } 327 328 if (weight3 > 0) { 329 sources.push(level3) 330 weights.push(weight3) 331 } 332 333 if (weight4 > 0) { 334 sources.push(level4) 335 weights.push(weight4) 336 } 337 338 if (weight5 > 0) { 339 sources.push(level5) 340 weights.push(weight5) 341 } 342 343 if (weight6 > 0) { 344 sources.push(level6) 345 weights.push(weight6) 346 } 347 348 for (var j = sources.length; j < 6; j++) { 349 sources.push(dummy) 350 weights.push(0.0) 351 } 352 353 source1 = sources[0] 354 source2 = sources[1] 355 source3 = sources[2] 356 source4 = sources[3] 357 source5 = sources[4] 358 source6 = sources[5] 359 360 weight1 = weights[0] 361 weight2 = weights[1] 362 weight3 = weights[2] 363 weight4 = weights[3] 364 weight5 = weights[4] 365 weight6 = weights[5] 366 } 367 368 Component.onCompleted: calculateWeights() 369 370 onLodChanged: calculateWeights() 371 372 fragmentShader: " 373 uniform lowp sampler2D source1; 374 uniform lowp sampler2D source2; 375 uniform lowp sampler2D source3; 376 uniform lowp sampler2D source4; 377 uniform lowp sampler2D source5; 378 uniform mediump float weight1; 379 uniform mediump float weight2; 380 uniform mediump float weight3; 381 uniform mediump float weight4; 382 uniform mediump float weight5; 383 uniform highp vec4 color; 384 uniform highp float spread; 385 uniform lowp float qt_Opacity; 386 varying mediump vec2 qt_TexCoord0; 387 388 highp float linearstep(highp float e0, highp float e1, highp float x) { 389 return clamp((x - e0) / (e1 - e0), 0.0, 1.0); 390 } 391 392 void main() { 393 lowp vec4 sourceColor = texture2D(source1, qt_TexCoord0) * weight1; 394 sourceColor += texture2D(source2, qt_TexCoord0) * weight2; 395 sourceColor += texture2D(source3, qt_TexCoord0) * weight3; 396 sourceColor += texture2D(source4, qt_TexCoord0) * weight4; 397 sourceColor += texture2D(source5, qt_TexCoord0) * weight5; 398 sourceColor = mix(vec4(0), color, linearstep(0.0, spread, sourceColor.a)); 399 gl_FragColor = sourceColor * qt_Opacity; 400 } 401 " 402 } 403} 404