2016-05-30 19 views
2

Es maskiert das Quellelement mit einem anderen Element, so dass die Quelle nur dort sichtbar ist, wo die Maske undurchsichtig ist. Wie kann die Quelle nur dort sichtbar gemacht werden, wo die Maske transparent ist?Gegenüber für OpacityMask

Derzeit ist es mit einem Shader gemacht, aber ich möchte das ersetzen.

Die Maske kann nicht invertiert werden, da sie aus mehreren Bildern besteht: Die Summe der einzelnen invertierten Bilder ist nicht identisch mit der Umkehrung der Summe.

+0

Alle Komponenten in GraphicalEffects verwenden Shadern. Sicherlich gibt es keine Komponente, die es für Sie tun kann - Sie müssen eine selbst erstellen. Ich weiß nicht, was ist das Problem hier. Eine Idee, die mir in den Sinn kommt, ist das manuelle Invertieren der Maske in C++ und dann das Anwenden in QML, aber ist es besser als ein Shader? Das glaube ich nicht. Im besten Fall wäre der Unterschied gering. Was ist falsch an deinem Shader? –

+1

@FilipHazubski, zumindest ist es gut, eine Bestätigung zu bekommen, dass es keine Komponente dafür gibt. Während der Code-Überprüfung verursachte der Shader einen Vorschlag, weiter zu untersuchen (das ist falsch bei meinem Shader). – Velkan

Antwort

2

Es gibt keine Komponente von Qt, die tun kann, was Sie brauchen. OpacityMask ist am nächsten, was Sie brauchen. Sie können den Code here im offiziellen Repository oder auf Ihrem Computer in diesem Pfad anzeigen: Qt_folder/Qt_version/Qt_kit/qml/QtGraphicalEffects/OpacityMask.qml. Auf diese Weise können Sie einfach die Quelle aller QtGraphicalEffects-Komponenten durchsuchen.

Verwenden ShaderEffect ist eine gute Wahl für die Aufgabe.

Als GrecKo darauf hingewiesen, gibt es bereits eine invert Eigenschaft in OpacityMask Objekt. Es wird mit Qt 5.7 verfügbar sein, aber der Code ist bereits im obigen Link verfügbar. Sie können entweder auf das Update warten oder die Komponente herunterladen und in Ihrem Projekt verwenden.

+2

In dem verknüpften Code (die Qt 5.7-Version von "OpacityMask") gibt es eine "invert" -Eigenschaft. Sie könnten also einfach den Code kopieren oder darauf warten, dass Qt 5.7 freigegeben wird und setzen Sie "invert: true". – GrecKo

+1

@GrecKo Sehr guter Rat! Ich habe es meiner Antwort hinzugefügt (ich hoffe, es ist in Ordnung mit dir). –

+0

Wahrscheinlich ist es in Ordnung mit @GrecKo. Also werde ich akzeptieren. – Velkan

0

Wenn Sie QML Artikel verwenden (Rectangle) Sie folgenden Codes verwenden:

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; 
       } 
      " 
     } 
    } 
} 

Opacity Mask using QML Item (Rectangle)