{
    "QEN": {
        "description": "This node matches to features and API of the Qt Quick MultiEffect element. This makes it easy to build customized MultiEffects.",
        "extraMargin": 80,
        "fragmentCode": [
            "@requires BlurHelper",
            "@main",
            "{",
            "    vec4 color = fragColor;",
            "    if (blurEnabled) {",
            "        // blur",
            "        vec4 blurredColor = texture(iSource, texCoord) * multiEffectBlurWeight1[0];",
            "        blurredColor += texture(iSourceBlur1, texCoord) * multiEffectBlurWeight1[1];",
            "#if (BLUR_HELPER_MAX_LEVEL > 2)",
            "        blurredColor += texture(iSourceBlur2, texCoord) * multiEffectBlurWeight1[2];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 8)",
            "        blurredColor += texture(iSourceBlur3, texCoord) * multiEffectBlurWeight1[3];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 16)",
            "        blurredColor += texture(iSourceBlur4, texCoord) * multiEffectBlurWeight2[0];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 32)",
            "        blurredColor += texture(iSourceBlur5, texCoord) * multiEffectBlurWeight2[1];",
            "#endif",
            "        color = blurredColor;",
            "    }",
            "    // contrast, brightness, saturation and colorization",
            "    color.rgb = (color.rgb - 0.5 * color.a) * (1.0 + contrast) + 0.5 * color.a;",
            "    color.rgb += brightness * color.a;",
            "    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));",
            "    float colorizationAlpha = colorization * colorizationColor.a;",
            "    color.rgb = mix(color.rgb, gray * colorizationColor.rgb, colorizationAlpha);",
            "    color.rgb = mix(vec3(gray), color.rgb, 1.0 + saturation);",
            "    if (shadowEnabled) {",
            "        // shadow",
            "        float shadow = texture(iSource, shadowTexCoord).a * shadowBlurWeight1[0];",
            "        shadow += texture(iSourceBlur1, shadowTexCoord).a * shadowBlurWeight1[1];",
            "#if (BLUR_HELPER_MAX_LEVEL > 2)",
            "        shadow += texture(iSourceBlur2, shadowTexCoord).a * shadowBlurWeight1[2];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 8)",
            "        shadow += texture(iSourceBlur3, shadowTexCoord).a * shadowBlurWeight1[3];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 16)",
            "        shadow += texture(iSourceBlur4, shadowTexCoord).a * shadowBlurWeight2[0];",
            "#endif",
            "#if (BLUR_HELPER_MAX_LEVEL > 32)",
            "        shadow += texture(iSourceBlur5, shadowTexCoord).a * shadowBlurWeight2[1];",
            "#endif",
            "        shadow *= (shadowColor.a * shadowOpacity);",
            "        float saa = (1.0 - color.a) * (1.0 - shadow);",
            "        color.rgb = mix(shadowColor.rgb * shadow, color.rgb, color.a + saa);",
            "        color.a = 1.0 - saa;",
            "    }",
            "    if (maskEnabled) {",
            "        // mask",
            "        vec4 maskTexture = texture(maskSource, texCoord);",
            "        float alphaMask = maskTexture.a;",
            "        const float mSLow = 1.0 + maskSpreadAtMin;",
            "        const float mSUp = 1.0 + maskSpreadAtMax;",
            "        float m1 = smoothstep(maskThresholdMin * mSLow - (mSLow - 0.999), maskThresholdMin * mSLow, alphaMask);",
            "        float m2 = smoothstep((1.0 - maskThresholdMax) * mSUp - (mSUp - 0.999), (1.0 - maskThresholdMax) * mSUp, (1.0 - alphaMask));",
            "        float mm = m1 * m2;",
            "        color *= (1.0 - float(maskInverted)) * mm + float(maskInverted) * (1.0 - mm);",
            "    }",
            "    fragColor = color;",
            "}"
        ],
        "name": "Multi Effect",
        "properties": [
            {
                "defaultValue": "0",
                "description": "Sets the contrast for the effect.",
                "maxValue": "1",
                "minValue": "-1",
                "name": "contrast",
                "displayName": "Contrast",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the brightness for the effect.",
                "maxValue": "1",
                "minValue": "-1",
                "name": "brightness",
                "displayName": "Brightness",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the saturation for the effect.",
                "maxValue": "1",
                "minValue": "-1",
                "name": "saturation",
                "displayName": "Saturation",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the colorization for the effect.",
                "maxValue": "1",
                "minValue": "0",
                "name": "colorization",
                "displayName": "Colorization",
                "type": "float"
            },
            {
                "defaultValue": "1, 0, 0, 1",
                "description": "Sets the color used for colorization.",
                "name": "colorizationColor",
                "displayName": "Colorization Color",
                "type": "color"
            },
            {
                "defaultValue": "true",
                "description": "Enables the blur effect.",
                "name": "blurEnabled",
                "displayName": "Blur Enabled",
                "type": "bool"
            },
            {
                "defaultValue": "32",
                "description": "Sets the maximum pixel radius that blur with value 1.0 will reach.",
                "maxValue": "64",
                "minValue": "0",
                "name": "blurMax",
                "displayName": "Blur Max",
                "type": "int"
            },
            {
                "defaultValue": "0",
                "description": "Sets the amount of blur.",
                "maxValue": "1",
                "minValue": "0",
                "name": "blur",
                "displayName": "Blur",
                "type": "float"
            },
            {
                "defaultValue": "false",
                "description": "Enables the shadow effect.",
                "name": "shadowEnabled",
                "displayName": "Shadow Enabled",
                "type": "bool"
            },
            {
                "defaultValue": "1",
                "description": "Sets the amount of blur applied to the shadow.\n\nThe amount of blur is also affected by the Blur Helper Multiplier property.",
                "maxValue": "1",
                "minValue": "0",
                "name": "shadowBlur",
                "displayName": "Shadow Blur",
                "type": "float"
            },
            {
                "defaultValue": "1",
                "description": "Sets the opacity of the shadow.",
                "maxValue": "1",
                "minValue": "0",
                "name": "shadowOpacity",
                "displayName": "Shadow Opacity",
                "type": "float"
            },
            {
                "defaultValue": "0, 0, 0, 1",
                "description": "Sets the color of the shadow.",
                "name": "shadowColor",
                "displayName": "Shadow Color",
                "type": "color"
            },
            {
                "defaultValue": "1",
                "description": "Sets the size of the shadow.\n\nScaling is applied from the center of the shadow.",
                "maxValue": "1.2",
                "minValue": "0.8",
                "name": "shadowScale",
                "displayName": "Shadow Scale",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the horizontal position of the shadow.",
                "maxValue": "30",
                "minValue": "-30",
                "name": "shadowHorizontalOffset",
                "displayName": "Shadow Horizontal Offset",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the vertical position of the shadow.",
                "maxValue": "30",
                "minValue": "-30",
                "name": "shadowVerticalOffset",
                "displayName": "Shadow Vertical Offset",
                "type": "float"
            },
            {
                "defaultValue": "false",
                "description": "Enables the mask effect.",
                "name": "maskEnabled",
                "displayName": "Mask Enabled",
                "type": "bool"
            },
            {
                "defaultValue": "",
                "description": "Sets the texture for the mask effect. The alpha channel of the texture is used for masking.",
                "name": "maskSource",
                "displayName": "Mask Source",
                "type": "image"
            },
            {
                "defaultValue": "0",
                "description": "Sets the lower threshold value for the mask pixels. The mask pixels that have an alpha value below this property are used to completely mask away the corresponding pixels from the texture. The mask pixels that have a higher alpha value are used to blend the texture to the display.\n\nThe value ranges from 0.0 (alpha value 0) to 1.0 (alpha value 255).",
                "maxValue": "1",
                "minValue": "0",
                "name": "maskThresholdMin",
                "displayName": "Mask Threshold Min",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the smoothness of the mask edges near the Mask Threshold Min. Higher spread values softens the transition from the transparent mask pixels towards opaque mask pixels by adding interpolated values between them.\n\nThe value ranges from 0.0 (sharp mask edge) to 1.0 (smooth mask edge).",
                "maxValue": "1",
                "minValue": "0",
                "name": "maskSpreadAtMin",
                "displayName": "Mask Spread At Min",
                "type": "float"
            },
            {
                "defaultValue": "1",
                "description": "Sets the upper threshold value for the mask pixels. The mask pixels that have an alpha value below this property are used to completely mask away the corresponding pixels from the texture. The mask pixels that have a higher alpha value are used to alphablend the texture to the display.\n\nThe value ranges from 0.0 (alpha value 0) to 1.0 (alpha value 255).",
                "maxValue": "1",
                "minValue": "0",
                "name": "maskThresholdMax",
                "displayName": "Mask Spread Max",
                "type": "float"
            },
            {
                "defaultValue": "0",
                "description": "Sets the smoothness of the mask edges near the Mask Threshold Max. Higher spread values softens the transition from the transparent mask pixels towards opaque mask pixels by adding interpolated values between them.\n\nThe value ranges from 0.0 (sharp mask edge) to 1.0 (smooth mask edge).",
                "maxValue": "1",
                "minValue": "0",
                "name": "maskSpreadAtMax",
                "displayName": "Mask Spread At Max",
                "type": "float"
            },
            {
                "defaultValue": "false",
                "description": "Inverts the mask; instead of masking away the content outside Mask Threshold Min and Mask Threshold Max, the content between them is masked away.",
                "name": "maskInverted",
                "displayName": "Mask Inverted",
                "type": "bool"
            }
        ],
        "version": 1,
        "vertexCode": [
            "out vec4 multiEffectBlurWeight1;",
            "out vec2 multiEffectBlurWeight2;",
            "out vec2 shadowTexCoord;",
            "out vec4 shadowBlurWeight1;",
            "out vec2 shadowBlurWeight2;",
            "",
            "float multiEffectBlurWeight(float v) {",
            "    return max(0.0, min(1.0, 1.0 - v * 2.0));",
            "}",
            "",
            "@main",
            "{",
            "    if (blurEnabled) {",
            "        float blurLod = sqrt(blur * (blurMax / 64.0)) * 1.2 - 0.2;",
            "        float bw1 = multiEffectBlurWeight(abs(blurLod - 0.1));",
            "        float bw2 = multiEffectBlurWeight(abs(blurLod - 0.3));",
            "        float bw3 = multiEffectBlurWeight(abs(blurLod - 0.5));",
            "        float bw4 = multiEffectBlurWeight(abs(blurLod - 0.7));",
            "        float bw5 = multiEffectBlurWeight(abs(blurLod - 0.9));",
            "        float bw6 = multiEffectBlurWeight(abs(blurLod - 1.1));",
            "",
            "        float bsum = bw1 + bw2 + bw3 + bw4 + bw5 + bw6;",
            "        multiEffectBlurWeight1 = vec4(bw1 / bsum, bw2 / bsum, bw3 / bsum, bw4 / bsum);",
            "        multiEffectBlurWeight2 = vec2(bw5 / bsum, bw6 / bsum);",
            "    }",
            "    if (shadowEnabled) {",
            "        float shadowBlurLod = sqrt(shadowBlur * (blurMax / 64.0)) * 1.2 - 0.2;",
            "        float sbw1 = multiEffectBlurWeight(abs(shadowBlurLod - 0.1));",
            "        float sbw2 = multiEffectBlurWeight(abs(shadowBlurLod - 0.3));",
            "        float sbw3 = multiEffectBlurWeight(abs(shadowBlurLod - 0.5));",
            "        float sbw4 = multiEffectBlurWeight(abs(shadowBlurLod - 0.7));",
            "        float sbw5 = multiEffectBlurWeight(abs(shadowBlurLod - 0.9));",
            "        float sbw6 = multiEffectBlurWeight(abs(shadowBlurLod - 1.1));",
            "",
            "        float sbsum = sbw1 + sbw2 + sbw3 + sbw4 + sbw5 + sbw6;",
            "        shadowBlurWeight1 = vec4(sbw1 / sbsum, sbw2 / sbsum, sbw3 / sbsum, sbw4 / sbsum);",
            "        shadowBlurWeight2 = vec2(sbw5 / sbsum, sbw6 / sbsum);",
            "",
            "        vec2 shadowOffset = vec2(shadowHorizontalOffset / iResolution.x, shadowVerticalOffset / iResolution.y);",
            "        float invertedScale = 1.0 / shadowScale;",
            "        float s = (1.0 - invertedScale) * 0.5;",
            "        vec2 shadowCenterOffset = vec2(s);",
            "        shadowTexCoord = qt_MultiTexCoord0 - shadowOffset;",
            "        shadowTexCoord = (shadowTexCoord * invertedScale) + shadowCenterOffset;",
            "    }",
            "}"
        ]
    }
}
