Qt OpacityMask的反面

Qt OpacityMask的反面,qt,qml,qt5,opacitymask,Qt,Qml,Qt5,Opacitymask,它用另一项遮罩源项,因此仅当遮罩不透明时,源才可见。如何使源仅在遮罩透明的情况下可见 目前它是用一个着色器完成的,但我想替换它 无法反转遮罩,因为它由多个图像组成:单个反转图像的总和与总和的反转不同。Qt制作的任何组件都不能满足您的需要OpacityMask最接近您的需要。您可以通过以下路径在官方存储库或计算机上查看其代码:Qt_文件夹/Qt_版本/Qt_工具包/qml/QtGraphicalEffects/OpacityMask.qml。通过这种方式,您可以轻松浏览所有QtGraphicalE

它用另一项遮罩源项,因此仅当遮罩不透明时,源才可见。如何使源仅在遮罩透明的情况下可见

目前它是用一个着色器完成的,但我想替换它


无法反转遮罩,因为它由多个图像组成:单个反转图像的总和与总和的反转不同。

Qt制作的任何组件都不能满足您的需要
OpacityMask
最接近您的需要。您可以通过以下路径在官方存储库或计算机上查看其代码:Qt_文件夹/Qt_版本/Qt_工具包/qml/QtGraphicalEffects/OpacityMask.qml。通过这种方式,您可以轻松浏览所有QtGraphicalEffects组件的源代码

对于该任务,使用
ShaderEffect
是一个不错的选择


如前所述,
OpacityMask
对象中已经存在一个
invert
属性。Qt 5.7将提供该代码,但上面的链接中已经提供了该代码。您可以等待更新,也可以下载组件并在项目中使用。

如果要使用QML项(矩形),可以使用以下代码:

import QtQuick 2.6

Item {
    anchors.fill: parent
    Image {
        anchors.fill: parent
        source: "http://i.imgur.com/R3yMj0y.jpg"
        fillMode: Image.PreserveAspectCrop
        focus: true
        Keys.onRightPressed: _mask.maskX += 100
        Keys.onLeftPressed: _mask.maskX -= 100
        Keys.onUpPressed: _mask.maskY -= 100
        Keys.onDownPressed: _mask.maskY += 100
        MouseArea {
            anchors.fill: parent
            hoverEnabled: true
            onPositionChanged: {
                _mask.maskX = mouseX;
                _mask.maskY = mouseY;
            }
        }
    }

    Rectangle {
        id: _bk
        anchors.fill: parent
        color: "#33000000"
        visible: false
        layer.enabled: true
        layer.smooth: true
    }

    Rectangle {
        id: _mask
        anchors.fill: parent
        color: "transparent"
        visible: true
        property int maskX: 0
        property int maskY: 0
        Rectangle {
            id: circle
            width: 100; height: 100
            x: _mask.maskX-50; y: _mask.maskY-50
            radius: 50
            color: "#000"
            Behavior on x { NumberAnimation { duration: 400; easing.type: Easing.OutBack; easing.overshoot: 1.4 } }
            Behavior on y { NumberAnimation { duration: 400; easing.type: Easing.OutBack; easing.overshoot: 1.4 } }
        }
        layer.enabled: true
        layer.samplerName: "maskSource"
        layer.effect: ShaderEffect {
            property variant source: _bk
            fragmentShader: "
                varying highp vec2 qt_TexCoord0;
                uniform highp float qt_Opacity;
                uniform lowp sampler2D source;
                uniform lowp sampler2D maskSource;
                void main(void) {
                    gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0-texture2D(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
                }
            "
        }
    }
    Rectangle {
        id: _mask2
        anchors.fill: parent
        color: "transparent"
        visible: true
        Rectangle {
            id: circle2
            width: 150; height: 150
            x: _mask.maskX-75; y: _mask.maskY-75
            radius: 75
            color: "#000"
            Behavior on x { NumberAnimation { duration: 550; easing.type: Easing.OutBack; easing.overshoot: 2.4 } }
            Behavior on y { NumberAnimation { duration: 550; easing.type: Easing.OutBack; easing.overshoot: 2.4 } }
        }
        layer.enabled: true
        layer.samplerName: "maskSource"
        layer.effect: ShaderEffect {
            property variant source: _bk
            fragmentShader: "
                varying highp vec2 qt_TexCoord0;
                uniform highp float qt_Opacity;
                uniform lowp sampler2D source;
                uniform lowp sampler2D maskSource;
                void main(void) {
                    gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0-texture2D(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
                }
            "
        }
    }
    Rectangle {
        id: _mask3
        anchors.fill: parent
        color: "transparent"
        visible: true
        Rectangle {
            id: circle3
            width: 220; height: 220
            x: _mask.maskX-110; y: _mask.maskY-110
            radius: 110
            color: "#000"
            Behavior on x { NumberAnimation { duration: 650; easing.type: Easing.OutBack; easing.overshoot: 3.0 } }
            Behavior on y { NumberAnimation { duration: 650; easing.type: Easing.OutBack; easing.overshoot: 3.0 } }
        }
        layer.enabled: true
        layer.samplerName: "maskSource"
        layer.effect: ShaderEffect {
            property variant source: _bk
            fragmentShader: "
                varying highp vec2 qt_TexCoord0;
                uniform highp float qt_Opacity;
                uniform lowp sampler2D source;
                uniform lowp sampler2D maskSource;
                void main(void) {
                    gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0-texture2D(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
                }
            "
        }
    }
}

GraphicalEffects中的所有组件都使用着色器。当然,没有任何组件可以为您做到这一点-您需要自己制作一个。我不知道这里有什么问题。我脑海中的一个想法是用C++手动切换你的面具,然后在QML上应用它,但它比着色器更好吗?我不这么认为。在最好的情况下,差别是很小的。你的着色器出了什么问题?@FilipHazubski,至少可以确认没有用于该着色器的组件。在代码审查期间,着色器提出了进一步调查的建议(这就是我的着色器的问题所在)。在链接的代码(Qt 5.7版本的
OpacityMask
)中,有一个
invert
属性。因此,您可以复制代码或等待Qt5.7发布,然后设置
invert:true
@GrecKo非常好的建议!我已将其添加到我的答案中(我希望您对此没有意见)。