{"id":4449,"date":"2021-08-05T10:00:00","date_gmt":"2021-08-05T08:00:00","guid":{"rendered":"https:\/\/www.basyskom.de\/?p=4449"},"modified":"2024-01-04T17:19:30","modified_gmt":"2024-01-04T16:19:30","slug":"qt-6-how-to-port-shader-effects-from-qt-5","status":"publish","type":"post","link":"https:\/\/www.basyskom.de\/en\/qt-6-how-to-port-shader-effects-from-qt-5\/","title":{"rendered":"Qt 6: How To port Shader Effects from Qt 5"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"4449\" class=\"elementor elementor-4449\" data-elementor-post-type=\"post\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3dad3c8 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"3dad3c8\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0e9e1ba\" data-id=\"0e9e1ba\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-fbbaf19 elementor-widget elementor-widget-heading\" data-id=\"fbbaf19\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Introduction<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c28f3e6 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"c28f3e6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1ae1404\" data-id=\"1ae1404\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-09cc41a elementor-widget elementor-widget-text-editor\" data-id=\"09cc41a\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;motion_fx_motion_fx_scrolling&quot;:&quot;yes&quot;,&quot;motion_fx_devices&quot;:[&quot;widescreen&quot;,&quot;desktop&quot;,&quot;tablet&quot;,&quot;mobile&quot;]}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Recently, we\u00a0<a href=\"https:\/\/www.basyskom.de\/2021\/porting-a-qt-5-application-to-qt-6\/\">wrote about porting a Qt 5 application to Qt 6<\/a>. The bigger part of the work is due to changes in Qt\u2019s graphics logic &#8211; especially when you have lots of shaders strewn across your QML code.<\/p><p>In this blog post, we introduce a step-by-step guide on how to move the shader code you might have in your Qt 5 application to Qt 6.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d7048bb elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"d7048bb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<i aria-hidden=\"true\" class=\"hm hm-plane\"><\/i>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b09afc9 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"b09afc9\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7d56b0d\" data-id=\"7d56b0d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0c40858 elementor-widget elementor-widget-heading\" data-id=\"0c40858\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Quick Overview<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-32fc368 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"32fc368\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8d01ab6\" data-id=\"8d01ab6\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-8709c47 elementor-widget elementor-widget-text-editor\" data-id=\"8709c47\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>To sum it up, it mostly comes down to the following changes:<\/p><ul><li><span style=\"color: var( --e-global-color-text ); font-family: var( --e-global-typography-text-font-family ), PT+Sans+Narrow; font-weight: var( --e-global-typography-text-font-weight );\">Move embedded shader strings from QML to separate files<\/span><\/li><li>Add a version to the first line in your shader files<\/li><li>The attribute and varying qualifiers got removed, meaning you have to rewrite your variable declarations. All variable declarations should get a layout qualifier. This process is described in detail below<\/li><li>Remove the precision specifiers (highp and lowp)<\/li><li>Fragment shader\u2019s gl_position output becomes an ordinary out variable<\/li><li>Port the deprecated glsl functions to their new counterparts, i.e. change occurrences of texture2D to texture<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-86d59f1 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"86d59f1\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-69d4f2d\" data-id=\"69d4f2d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-af7e8c8 elementor-widget elementor-widget-heading\" data-id=\"af7e8c8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Porting the shaders<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-774630b elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"774630b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a535dae\" data-id=\"a535dae\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6582406 elementor-widget elementor-widget-video\" data-id=\"6582406\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;autoplay&quot;:&quot;yes&quot;,&quot;play_on_mobile&quot;:&quot;yes&quot;,&quot;mute&quot;:&quot;yes&quot;,&quot;loop&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/www.basyskom.de\/wp-content\/uploads\/2021\/02\/PortingExample6-.mp4\" autoplay=\"\" loop=\"\" muted=\"muted\" playsinline=\"\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-76db5c3 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"76db5c3\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4ff75a5\" data-id=\"4ff75a5\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1bf44a4 elementor-widget elementor-widget-text-editor\" data-id=\"1bf44a4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>We have prepared a minimal example to demonstrate the porting process. It has a vertex shader deforming the incoming vertices to generate a wiggling effect and a fragment shader to blend between two <a href=\"https:\/\/pixabay.com\/de\/illustrations\/dreieck-hintergrund-abstrakt-mosaik-2724452\/\" target=\"_blank\" rel=\"noopener\">abstract<\/a> <a href=\"https:\/\/pixabay.com\/de\/illustrations\/textur-abstrakt-struktur-bunte-1909992\/\" target=\"_blank\" rel=\"noopener\">images<\/a> back and forth. Below is the whole <code>main.qml<\/code>:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-09e73d8 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"09e73d8\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-db4ee5d\" data-id=\"db4ee5d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e9ebdc7 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"e9ebdc7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-qml'>import QtQuick 2.15\r\nimport QtQuick.Window 2.12\r\n \r\nWindow {\r\n    id: window\r\n \r\n    width: melting.implicitWidth\r\n    height: melting.implicitHeight\r\n    visible: true\r\n    color: &quot;black&quot;\r\n \r\n    ShaderEffect {\r\n        id: wiggleEffect\r\n \r\n        property real strength: 5.0\r\n        property real time: 50.0\r\n        property real blendingProgress: -1\r\n        property variant source1: firstImageSource\r\n        property variant source2: secondImageSource\r\n \r\n        anchors.centerIn: parent\r\n        width: triangle.width\r\n        height: triangle.height\r\n \r\n        mesh: GridMesh {\r\n            resolution: Qt.size(20, 20)\r\n        }\r\n \r\n        UniformAnimator on time {\r\n            from: 0\r\n            to:  100\r\n            duration: 2000\r\n            loops: -1\r\n            running: true\r\n        }\r\n \r\n        UniformAnimator on blendingProgress {\r\n            from: -1\r\n            to:  1\r\n            duration: 10000\r\n            loops: -1\r\n            running: true\r\n        }\r\n \r\n        vertexShader: &quot;\r\n                float noise(vec2 uv){\r\n                    return fract(sin(dot(uv, vec2(12.9898,78.233))) * 43758.5453123);\r\n                }\r\n \r\n                uniform highp mat4 qt_Matrix;\r\n                uniform lowp float strength;\r\n                uniform lowp float time;\r\n                attribute highp vec4 qt_Vertex;\r\n                attribute highp vec2 qt_MultiTexCoord0;\r\n                varying highp vec2 qt_TexCoord0;\r\n                void main() {\r\n                    qt_TexCoord0 = qt_MultiTexCoord0;\r\n                    highp vec4 pos = qt_Vertex;\r\n                    lowp float angle = 2. * 3.141 * (noise(pos.xy) + time \/ 100.0);\r\n                    lowp float strengthWithVariation = strength * noise(pos.yx);\r\n                    pos.x += cos(angle) * strengthWithVariation;\r\n                    pos.y += sin(angle) * strengthWithVariation;\r\n                    gl_Position = qt_Matrix * pos;\r\n                }&quot;\r\n \r\n        fragmentShader: &quot;\r\n                varying highp vec2 qt_TexCoord0;\r\n                uniform lowp float qt_Opacity;\r\n                uniform lowp float blendingProgress;\r\n                uniform lowp sampler2D source1;\r\n                uniform lowp sampler2D source2;\r\n                void main() {\r\n                    lowp float alpha = abs(blendingProgress);\r\n                    gl_FragColor = ((1. - alpha) * texture2D(source1, qt_TexCoord0)\r\n                                   + alpha * texture2D(source2, qt_TexCoord0))\r\n                                   * qt_Opacity;\r\n                }&quot;\r\n \r\n    }\r\n \r\n    ShaderEffectSource {\r\n        id: firstImageSource\r\n \r\n        live: false\r\n        hideSource: true\r\n        sourceItem: Image {\r\n              id: melting\r\n \r\n              width: implicitWidth\r\n              height: implicitHeight\r\n              source: &quot;qrc:\/melting.jpg&quot;\r\n              fillMode: Image.PreserveAspectFit\r\n        }\r\n    }\r\n \r\n    ShaderEffectSource {\r\n        id: triangle\r\n \r\n        live: false\r\n        hideSource: true\r\n        sourceItem: Image {\r\n              id: triangle\r\n \r\n              width: implicitWidth\r\n              height: implicitHeight\r\n              source: &quot;qrc:\/triangle.jpg&quot;\r\n              fillMode: Image.PreserveAspectFit\r\n        }\r\n    }\r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-0eeb08a elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"0eeb08a\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f5a2d15\" data-id=\"f5a2d15\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a37eccb elementor-widget elementor-widget-text-editor\" data-id=\"a37eccb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tAs you can see, there is one <code>ShaderEffect<\/code> component coming with both, a vertex shader and a fragment shader. The shader code is embedded as strings, as it&#8217;s often the case in Qt 5 applications.\n<br>\n<br>\nTo port the <code>ShaderEffect<\/code>, we first have to outsource the shader strings. Create a directory with the name shader and add two files to the directory: <ul><li> <code>wiggleblender.vert<\/code> <\/li><li><code>wiggleblender.frag<\/code> <\/li><\/ul>\n<br> (or whatever names you give to your shaders; use appropriate file extensions to distinguish between fragment and vertex shaders). <br><br>Copy the shader strings into the corresponding files. Now change the <code>ShaderEffect<\/code> properties <code>fragmentShader<\/code> and <code>vertexShader<\/code> in your <code>main.qml<\/code> accordingly:\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-51494e0 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"51494e0\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ef936e3\" data-id=\"ef936e3\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2a4a672 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"2a4a672\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-qml'>ShaderEffect {\r\n    id: wiggleEffect\r\n \r\n    \/\/ ...\r\n \r\n    vertexShader: &quot;qrc:\/shader\/wiggleblender.vert.qsb&quot;\r\n    fragmentShader: &quot;qrc:\/shader\/wiggleblender.frag.qsb&quot;\r\n \r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-24be57c elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"24be57c\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9b7bbf2\" data-id=\"9b7bbf2\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-23beff3 elementor-widget elementor-widget-text-editor\" data-id=\"23beff3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tNote that the file extension we are using here is <code>qsb<\/code> &#8211; which stands for Qt Shader Baker. Qsb files can contain different shader variants &#8211; one for each of the supported graphics backends like OpenGL, Vulkan, DirectX or Metal. We are going to create <code>qsb<\/code> files later on from the ported shader files.\n<br><br>\nYou can reference the qsb files directly, but in production code it\u2019s often better to access assets via Qt\u00b4s resource system.\n<br><br>\nPorting the shader code is straightforward.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-15fddd5 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"15fddd5\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-82e5ea3\" data-id=\"82e5ea3\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-52d3570 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"52d3570\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-c'>#version 440                                                                       \/\/ 1\r\n \r\nlayout(location = 0) in vec4 position;                                             \/\/ 2\r\nlayout(location = 1) in vec2 texcoord;\r\n \r\nlayout(location = 0) out vec2 coord;                                               \/\/ 3\r\n \r\nlayout(std140, binding = 0) uniform buf {                                          \/\/ 4\r\n    mat4 qt_Matrix;                                                                \/\/ 5\r\n    float qt_Opacity;\r\n \r\n    float strength;\r\n    float time;\r\n    float blendingProgress;\r\n} ubuf;\r\n \r\nout gl_PerVertex { vec4 gl_Position; };                                            \/\/6\r\n \r\nfloat noise(vec2 uv){\r\n    return fract(sin(dot(uv, vec2(12.9898,78.233))) * 43758.5453123);\r\n}\r\n \r\nvoid main() {\r\n    coord = texcoord;\r\n    vec4 pos = position;\r\n    float angle = 2. * 3.141 * (noise(pos.xy) + ubuf.time \/ 100.0);                \/\/ 7\r\n    float strengthWithVariation = ubuf.strength * noise(pos.yx);\r\n    pos.x += cos(angle) * strengthWithVariation;\r\n    pos.y += sin(angle) * strengthWithVariation;\r\n    gl_Position = ubuf.qt_Matrix * pos;\r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6cb2da8 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"6cb2da8\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ee4416a\" data-id=\"ee4416a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b8acdc7 elementor-widget elementor-widget-text-editor\" data-id=\"b8acdc7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tBelow is a step-by-step recipe you can use for your own code:\n<ol>\n \t<li>Add a version string<\/li>\n \t<li>Add these two lines to fetch the vertex data. Qt fills a vertex buffer with vertex positions at location 0 and texture coordinates at location 1. Instead of using the <code>attribute<\/code> qualifier as before, now we declare inputs to the vertex shader by writing modern glsls code using <code>layout<\/code> and <code>in<\/code> qualifiers<\/li>\n \t<li>Declare the outputs you would like to pass to the fragment shader &#8211; these are the <code>varying<\/code> declarations in your non-ported code. For each output variable you have to add a line in the form <code>layout (location = n) out type name<\/code> and increment <code>n<\/code> starting at 0.<\/li>\n \t<li>Declare the uniforms. They are passed directly from QML properties to the shader code by Qt. All uniforms except samplers are provided via a uniform buffer. Qt always binds the buffer at 0 and stores the variables <code>qt_Matrix<\/code> and <code>qt_Opacity<\/code> at the very beginning. Note that you have to add <code>std1440<\/code>, which determines how the uniform buffer is laid out in memory<\/li>\n \t<li>Remove all <code>highp<\/code> and <code>lowp<\/code> specifiers<\/li>\n \t<li>Optional; the vertex shader writes its output to a built-in variable. If you leave this line out, the graphics engine still knows what to do<\/li>\n \t<li>Don\u2019t forget to access the uniform variables via the uniform buffer (easy to miss)<\/li>\n<\/ol>\n<br>Porting the fragment shader works in a similar fashion:\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2aa3fe9 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"2aa3fe9\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-654d4d7\" data-id=\"654d4d7\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ce3e310 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"ce3e310\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-c'>#version 440                                                 # 1\r\n \r\nlayout(location = 0) in vec2 texCoord;                       # 2\r\nlayout(location = 0) out vec4 fragColor;                     # 3\r\n \r\nlayout(std140, binding = 0) uniform buf {                    # 4\r\n    mat4 qt_Matrix;\r\n    float qt_Opacity;\r\n \r\n    float strength;\r\n    float time;\r\n    float blendingProgress;\r\n} ubuf;\r\n \r\nlayout(binding = 1) uniform sampler2D source1;              # 5\r\nlayout(binding = 2) uniform sampler2D source2;\r\n \r\nvoid main() {\r\n    float alpha = abs(ubuf.blendingProgress);\r\n    fragColor = ((1. - alpha) * texture(source1, texCoord)  # 6, 7\r\n                   + alpha * texture(source2, texCoord))\r\n                   * ubuf.qt_Opacity;                       # 8\r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f95838a elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"f95838a\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d6f8abc\" data-id=\"d6f8abc\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d8b519e elementor-widget elementor-widget-text-editor\" data-id=\"d8b519e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<ol><li>Add a version string<\/li><li>Declare the variables coming from the vertex shader, i.e. the\u00a0<code>varying<\/code>\u00a0declarations in the non-ported code. You can just copy all variable declarations with\u00a0<code>out<\/code>\u00a0qualifiers from the vertex shader and replace all\u00a0<code>out<\/code>\u00a0keywords with\u00a0<code>in<\/code>. If you don&#8217;t have a vertex shader, just copy the line as given in the code snippet above &#8211; Qt passes the texture coordinate from the default vertex shader. Note that the layout locations need to match (this does not apply to the variable names, which may differ).<\/li><li>Declare the output &#8211; a <code>vec4<\/code> color. Fragment shader output must be declared explicitly. Output of the color to\u00a0<code>gl_FragColor<\/code>\u00a0does not work anymore.<\/li><li>Add the uniform buffer (the same that we added to the vertex shader)<\/li><li>Declare all samplers. Don&#8217;t forget to assign different bindings. Note that the binding point 0 is reserved for the uniform buffer by Qt.<\/li><li>Port\u00a0<code>gl_FragColor<\/code>\u00a0to whatever name you have used for the out variable<\/li><li>Change all occurrences of\u00a0<code>texture2D<\/code>\u00a0to\u00a0<code>texture<\/code><\/li><li>Again, access uniforms via the uniform buffer<\/li><\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-368883f elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"368883f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<i aria-hidden=\"true\" class=\"hm hm-chef-cap\"><\/i>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-57256f5 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"57256f5\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4df8ea2\" data-id=\"4df8ea2\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-594dd08 elementor-widget elementor-widget-heading\" data-id=\"594dd08\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Baking the shaders\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-bf468b5 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"bf468b5\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e75ca40\" data-id=\"e75ca40\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3e50b8c elementor-widget elementor-widget-text-editor\" data-id=\"3e50b8c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tIf everything has been ported correctly, you are finally able to bake the shader files. There are two ways to achieve this:\n<ul>\n \t<li>Manually<\/li>\n \t<li>Let the build system handle the details<\/li>\n<\/ul>\nOf course, delegating the shader baking to your build system is recommended, but in the early Qt6 days things can still be a bit flaky. We explain both cases &#8211; manually baking the shaders into\u00a0<code>qsb<\/code>\u00a0files and using CMake as the build system\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2e5101e elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"2e5101e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b420114\" data-id=\"b420114\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ebd7e6a elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"ebd7e6a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<i aria-hidden=\"true\" class=\"hm hm-compass-math\"><\/i>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d8b3628 elementor-widget elementor-widget-heading\" data-id=\"d8b3628\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Manually<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7f35da2 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"7f35da2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-25146f0\" data-id=\"25146f0\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3c8d00c elementor-widget elementor-widget-text-editor\" data-id=\"3c8d00c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tUse the command line tool <code>qsb<\/code> as described below:\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2f706a6 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"2f706a6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7142b19\" data-id=\"7142b19\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d32d451 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"d32d451\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-bash'>qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o  wiggleblender.vert.qsb wiggleblender.vert\r\nqsb --glsl 100es,120,150 --hlsl 50 --msl 12    -o  wiggleblender.frag.qsb wiggleblender.frag <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fb1c90b elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"fb1c90b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5173b4f\" data-id=\"5173b4f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-01911f5 elementor-widget elementor-widget-text-editor\" data-id=\"01911f5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tThis creates the vertex and fragment shader qsb files suitable for rendering with OpenGL, Vulkan, DirectX and Metal backends. The\u00a0<code>-b<\/code>\u00a0parameter adds some magic so that the scenegraph renderer is able to properly batch the ShaderEffect. For more information on qsb and its parameters, please consult the\u00a0<a href=\"https:\/\/doc.qt.io\/qt-6\/qtshadertools-qsb.html\" rel=\"nofollow noopener\" target=\"_blank\">official documentation<\/a>.\n\nOptionally add the files to the Qt resource system:\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ee95d9e elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"ee95d9e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e4c6ceb\" data-id=\"e4c6ceb\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-95ac393 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"95ac393\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-qml'>&lt;RCC&gt;\r\n    &lt;qresource prefix=&quot;\/&quot;&gt;\r\n        &lt;file&gt;qml\/Shader\/qsb\/wiggleblender.vert.qsb&lt;\/file&gt;\r\n        &lt;file&gt;qml\/Shader\/qsb\/wiggleblender.frag.qsb&lt;\/file&gt;\r\n    &lt;\/qresource&gt;\r\n&lt;\/RCC&gt; <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-85feb7e elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"85feb7e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e7ec6fa\" data-id=\"e7ec6fa\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-520f9e6 elementor-widget elementor-widget-heading\" data-id=\"520f9e6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Using CMake<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fa50ec9 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"fa50ec9\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8d2a304\" data-id=\"8d2a304\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2cac22b elementor-widget elementor-widget-text-editor\" data-id=\"2cac22b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Add the following lines to CMakeLists.txt:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-95b8586 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"95b8586\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c2c36ef\" data-id=\"c2c36ef\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-01f0a6a elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"01f0a6a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-c'>qt6_add_shaders(${PROJECT_NAME} &quot;porting-example-shaders&quot;\r\n    BATCHABLE\r\n    PRECOMPILE\r\n    OPTIMIZED\r\n    PREFIX\r\n        &quot;\/shader&quot;\r\n    FILES\r\n        &quot;shader\/wiggleblender.vert&quot;\r\n        &quot;shader\/wiggleblender.frag&quot;\r\n) <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b6337ee elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"b6337ee\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-bcc3a21\" data-id=\"bcc3a21\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-cfa1b18 elementor-widget elementor-widget-text-editor\" data-id=\"cfa1b18\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Unfortunately, as of today\u00a0<a class=\"external-link\" href=\"https:\/\/bugreports.qt.io\/browse\/QTBUG-89590\" rel=\"nofollow noopener\" target=\"_blank\">there seems to be a bug<\/a> when the Makefile generator is used, meaning the qsb command line tool is not called. In the future qsb should just be an arbitrary build step like calling moc on header files, working silently in the background.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-714b920 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"714b920\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-033ee77\" data-id=\"033ee77\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5661e24 elementor-widget elementor-widget-heading\" data-id=\"5661e24\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Conclusion<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4c27c43 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no\" data-id=\"4c27c43\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7ff2c4c\" data-id=\"7ff2c4c\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7979c69 elementor-widget elementor-widget-text-editor\" data-id=\"7979c69\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Qt made the transition from Qt5 to Qt6 a breeze. What we have learned is, that if you port from Qt5 to Qt6 and have refined your QML code with a lot of shaders, you need to pay attention on this detail. While following our guide gives you the right tools at hand to master this challenge, feel free to drop a comment down below if any question arise while doing so.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>In this blog post, we give you a step-by-step guide on how to port shader code you might have in your Qt 5 application to Qt 6.<\/p>","protected":false},"author":16,"featured_media":4011,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1,2,8],"tags":[13,126,15,229],"class_list":["post-4449","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-allgemein","category-blog","category-qt","tag-hmi","tag-qml","tag-qt","tag-qt6"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/4449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/comments?post=4449"}],"version-history":[{"count":96,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/4449\/revisions"}],"predecessor-version":[{"id":7472,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/4449\/revisions\/7472"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/media\/4011"}],"wp:attachment":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/media?parent=4449"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/categories?post=4449"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/tags?post=4449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}