FastBlur.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // Copyright (C) 2020 The Qt Company Ltd.
  2. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
  3. // Qt-Security score:significant reason:default
  4. import QtQuick
  5. import Qt5Compat.GraphicalEffects.private
  6. /*!
  7. \qmltype FastBlur
  8. \inqmlmodule Qt5Compat.GraphicalEffects
  9. \since QtGraphicalEffects 1.0
  10. \inherits QtQuick2::Item
  11. \ingroup qtgraphicaleffects-blur
  12. \brief Applies a fast blur effect to one or more source items.
  13. The FastBlur effect softens the source content by blurring it with algorithm
  14. which uses the source content downscaling and bilinear filtering.
  15. \table
  16. \header
  17. \li Source
  18. \li Effect applied
  19. \row
  20. \li \image Original_bug.png
  21. \li \image FastBlur_bug.png
  22. \endtable
  23. \section1 Example
  24. The following example shows how to apply the effect.
  25. \snippet FastBlur-example.qml example
  26. */
  27. Item {
  28. id: rootItem
  29. /*!
  30. This property defines the source item that is going to be blurred.
  31. \note It is not supported to let the effect include itself, for
  32. instance by setting source to the effect's parent.
  33. */
  34. property variant source
  35. /*!
  36. This property defines the distance of the neighboring pixels which affect
  37. the blurring of an individual pixel. A larger radius increases the blur
  38. effect. FastBlur algorithm may internally reduce the accuracy of the radius in order to
  39. provide good rendering performance.
  40. The value ranges from 0.0 (no blur) to inf. Visual quality of the blur is reduced when
  41. radius exceeds value 64. By default, the property is set to \c 0.0 (no blur).
  42. \table
  43. \header
  44. \li Output examples with different blur values
  45. \li
  46. \li
  47. \row
  48. \li \image FastBlur_radius1.png
  49. \li \image FastBlur_radius2.png
  50. \li \image FastBlur_radius3.png
  51. \row
  52. \li \b { radius: 0 }
  53. \li \b { radius: 32 }
  54. \li \b { radius: 64 }
  55. \endtable
  56. */
  57. property real radius: 0.0
  58. /*!
  59. This property defines the blur behavior near the edges of the item,
  60. where the pixel blurring is affected by the pixels outside the source
  61. edges.
  62. If the property is set to \c true, the pixels outside the source are
  63. interpreted to be transparent, which is similar to OpenGL
  64. clamp-to-border extension. The blur is expanded slightly outside the
  65. effect item area.
  66. If the property is set to \c false, the pixels outside the source are
  67. interpreted to contain the same color as the pixels at the edge of the
  68. item, which is similar to OpenGL clamp-to-edge behavior. The blur does
  69. not expand outside the effect item area.
  70. By default, the property is set to \c false.
  71. \table
  72. \header
  73. \li Output examples with different transparentBorder values
  74. \li
  75. \li
  76. \row
  77. \li \image FastBlur_transparentBorder1.png
  78. \li \image FastBlur_transparentBorder2.png
  79. \row
  80. \li \b { transparentBorder: false }
  81. \li \b { transparentBorder: true }
  82. \row
  83. \li \l radius: 64
  84. \li \l radius: 64
  85. \endtable
  86. */
  87. property bool transparentBorder: false
  88. /*!
  89. This property allows the effect output pixels to be cached in order to
  90. improve the rendering performance.
  91. Every time the source or effect properties are changed, the pixels in
  92. the cache must be updated. Memory consumption is increased, because an
  93. extra buffer of memory is required for storing the effect output.
  94. It is recommended to disable the cache when the source or the effect
  95. properties are animated.
  96. By default, the property is set to \c false.
  97. */
  98. property bool cached: false
  99. SourceProxy {
  100. id: sourceProxy
  101. input: rootItem.source
  102. }
  103. ShaderEffectSource {
  104. id: cacheItem
  105. anchors.fill: shaderItem
  106. visible: rootItem.cached
  107. sourceItem: shaderItem
  108. live: true
  109. hideSource: visible
  110. smooth: rootItem.radius > 0
  111. }
  112. /*! \internal */
  113. property string __internalBlurVertexShader: "qrc:/qt-project.org/imports/Qt5Compat/GraphicalEffects/shaders_ng/fastblur_internal.vert.qsb"
  114. /*! \internal */
  115. property string __internalBlurFragmentShader: "qrc:/qt-project.org/imports/Qt5Compat/GraphicalEffects/shaders_ng/fastblur_internal.frag.qsb"
  116. ShaderEffect {
  117. id: level0
  118. property variant source: sourceProxy.output
  119. anchors.fill: parent
  120. visible: false
  121. smooth: true
  122. }
  123. ShaderEffectSource {
  124. id: level1
  125. width: Math.ceil(shaderItem.width / 32) * 32
  126. height: Math.ceil(shaderItem.height / 32) * 32
  127. sourceItem: level0
  128. hideSource: rootItem.visible
  129. sourceRect: transparentBorder ? Qt.rect(-64, -64, shaderItem.width, shaderItem.height) : Qt.rect(0, 0, 0, 0)
  130. visible: false
  131. smooth: rootItem.radius > 0
  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. ShaderEffectSource {
  145. id: level2
  146. width: level1.width / 2
  147. height: level1.height / 2
  148. sourceItem: effect1
  149. hideSource: rootItem.visible
  150. visible: false
  151. smooth: true
  152. }
  153. ShaderEffect {
  154. id: effect2
  155. property variant source: level2
  156. property real yStep: 1/height
  157. property real xStep: 1/width
  158. anchors.fill: level3
  159. visible: false
  160. smooth: true
  161. vertexShader: __internalBlurVertexShader
  162. fragmentShader: __internalBlurFragmentShader
  163. }
  164. ShaderEffectSource {
  165. id: level3
  166. width: level2.width / 2
  167. height: level2.height / 2
  168. sourceItem: effect2
  169. hideSource: rootItem.visible
  170. visible: false
  171. smooth: true
  172. }
  173. ShaderEffect {
  174. id: effect3
  175. property variant source: level3
  176. property real yStep: 1/height
  177. property real xStep: 1/width
  178. anchors.fill: level4
  179. visible: false
  180. smooth: true
  181. vertexShader: __internalBlurVertexShader
  182. fragmentShader: __internalBlurFragmentShader
  183. }
  184. ShaderEffectSource {
  185. id: level4
  186. width: level3.width / 2
  187. height: level3.height / 2
  188. sourceItem: effect3
  189. hideSource: rootItem.visible
  190. visible: false
  191. smooth: true
  192. }
  193. ShaderEffect {
  194. id: effect4
  195. property variant source: level4
  196. property real yStep: 1/height
  197. property real xStep: 1/width
  198. anchors.fill: level5
  199. visible: false
  200. smooth: true
  201. vertexShader: __internalBlurVertexShader
  202. fragmentShader: __internalBlurFragmentShader
  203. }
  204. ShaderEffectSource {
  205. id: level5
  206. width: level4.width / 2
  207. height: level4.height / 2
  208. sourceItem: effect4
  209. hideSource: rootItem.visible
  210. visible: false
  211. smooth: true
  212. }
  213. ShaderEffect {
  214. id: effect5
  215. property variant source: level5
  216. property real yStep: 1/height
  217. property real xStep: 1/width
  218. anchors.fill: level6
  219. visible: false
  220. smooth: true
  221. vertexShader: __internalBlurVertexShader
  222. fragmentShader: __internalBlurFragmentShader
  223. }
  224. ShaderEffectSource {
  225. id: level6
  226. width: level5.width / 2
  227. height: level5.height / 2
  228. sourceItem: effect5
  229. hideSource: rootItem.visible
  230. visible: false
  231. smooth: true
  232. }
  233. Item {
  234. id: dummysource
  235. width: 1
  236. height: 1
  237. visible: false
  238. }
  239. ShaderEffectSource {
  240. id: dummy
  241. width: 1
  242. height: 1
  243. sourceItem: dummysource
  244. visible: false
  245. smooth: false
  246. live: false
  247. }
  248. ShaderEffect {
  249. id: shaderItem
  250. property variant source1: level1
  251. property variant source2: level2
  252. property variant source3: level3
  253. property variant source4: level4
  254. property variant source5: level5
  255. property variant source6: level6
  256. property real lod: Math.sqrt(rootItem.radius / 64.0) * 1.2 - 0.2
  257. property real weight1
  258. property real weight2
  259. property real weight3
  260. property real weight4
  261. property real weight5
  262. property real weight6
  263. x: transparentBorder ? -64 : 0
  264. y: transparentBorder ? -64 : 0
  265. width: transparentBorder ? parent.width + 128 : parent.width
  266. height: transparentBorder ? parent.height + 128 : parent.height
  267. function weight(v) {
  268. if (v <= 0.0)
  269. return 1.0
  270. if (v >= 0.5)
  271. return 0.0
  272. return 1.0 - v * 2.0
  273. }
  274. function calculateWeights() {
  275. var w1 = weight(Math.abs(lod - 0.100))
  276. var w2 = weight(Math.abs(lod - 0.300))
  277. var w3 = weight(Math.abs(lod - 0.500))
  278. var w4 = weight(Math.abs(lod - 0.700))
  279. var w5 = weight(Math.abs(lod - 0.900))
  280. var w6 = weight(Math.abs(lod - 1.100))
  281. var sum = w1 + w2 + w3 + w4 + w5 + w6;
  282. weight1 = w1 / sum;
  283. weight2 = w2 / sum;
  284. weight3 = w3 / sum;
  285. weight4 = w4 / sum;
  286. weight5 = w5 / sum;
  287. weight6 = w6 / sum;
  288. upateSources()
  289. }
  290. function upateSources() {
  291. var sources = new Array();
  292. var weights = new Array();
  293. if (weight1 > 0) {
  294. sources.push(level1)
  295. weights.push(weight1)
  296. }
  297. if (weight2 > 0) {
  298. sources.push(level2)
  299. weights.push(weight2)
  300. }
  301. if (weight3 > 0) {
  302. sources.push(level3)
  303. weights.push(weight3)
  304. }
  305. if (weight4 > 0) {
  306. sources.push(level4)
  307. weights.push(weight4)
  308. }
  309. if (weight5 > 0) {
  310. sources.push(level5)
  311. weights.push(weight5)
  312. }
  313. if (weight6 > 0) {
  314. sources.push(level6)
  315. weights.push(weight6)
  316. }
  317. for (var j = sources.length; j < 6; j++) {
  318. sources.push(dummy)
  319. weights.push(0.0)
  320. }
  321. source1 = sources[0]
  322. source2 = sources[1]
  323. source3 = sources[2]
  324. source4 = sources[3]
  325. source5 = sources[4]
  326. source6 = sources[5]
  327. weight1 = weights[0]
  328. weight2 = weights[1]
  329. weight3 = weights[2]
  330. weight4 = weights[3]
  331. weight5 = weights[4]
  332. weight6 = weights[5]
  333. }
  334. Component.onCompleted: calculateWeights()
  335. onLodChanged: calculateWeights()
  336. fragmentShader: "qrc:/qt-project.org/imports/Qt5Compat/GraphicalEffects/shaders_ng/fastblur.frag.qsb"
  337. }
  338. }