rsh*_*sht 5 opengl qt qml qt5 qtquick2
我ShaderEffect在 QML 中使用一些项目的缩放视觉副本。这个副本应该是可移动的和动态的(live属性ShaderEffectSource设置为true)。
我的问题是我希望它在一个圆形内,Rectangle但它不会被它剪掉。ShaderEffect只是与它的父对象重叠并且是二次的。
我编写了一个快速 QML 示例来显示问题:
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
title: qsTr("Hello Shaders")
width: 640
height: 480
visible: true
color: "green"
Rectangle {
id: exampleRect
property bool redState: false
anchors.centerIn: parent
width: parent.width / 3
height: parent.height / 3
color: redState ? "red" : "cyan"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "white"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "green"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "yellow"
}
}
}
Timer {
interval: 2000
repeat: true
running: true
onTriggered: {
exampleRect.redState = !exampleRect.redState
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
shaderEffectContainer.x = mouse.x
shaderEffectContainer.y = mouse.y
}
}
Rectangle {
id: shaderEffectContainer
width: 100; height: width;
radius: width / 2;
border.width: 2
ShaderEffectSource {
id: source
sourceItem: exampleRect
visible: false
}
ShaderEffect {
anchors.fill: parent
property variant source: source
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 qt_TexCoord0;
void main() {
qt_TexCoord0 = qt_MultiTexCoord0 * 1.5 * vec2(0.5, 0.5);
gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
uniform lowp float qt_Opacity;
void main() {
gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
}"
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,exampleRect被声明为圆形,但它的孩子正在重叠它。
我已经尝试了所有可能的clip属性组合,并花了一整天的时间尝试使用片段/顶点着色器来做到这一点。正如您可能猜到的那样,没有运气。:)
我已经使用图层解决了这个问题,如本答案所示。
感谢@DenimPowell 的提示。
下面是一个带有循环的更新示例代码ShaderEffect。
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
title: qsTr("Hello Shaders")
width: 640
height: 480
visible: true
color: "green"
Rectangle {
id: exampleRect
property bool redState: false
anchors.centerIn: parent
width: parent.width / 3
height: parent.height / 3
color: redState ? "red" : "cyan"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "white"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "green"
Rectangle {
anchors.centerIn: parent
width: parent.width / 2; height: width;
color: "yellow"
}
}
}
Timer {
interval: 2000
repeat: true
running: true
onTriggered: {
exampleRect.redState = !exampleRect.redState
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
shaderEffectContainer.x = mouse.x
shaderEffectContainer.y = mouse.y
}
}
Rectangle {
id: shaderEffectContainer
width: 100; height: width;
color: "transparent"
Rectangle {
id: rectangleSource
anchors.fill: parent
ShaderEffectSource {
id: source
sourceItem: exampleRect
visible: false
}
ShaderEffect {
anchors.fill: parent
property variant source: source
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 qt_TexCoord0;
void main() {
qt_TexCoord0 = qt_MultiTexCoord0 * 1.5 * vec2(0.5, 0.5);
gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
uniform lowp float qt_Opacity;
void main() {
gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
}"
}
visible: false
layer.enabled: true
}
Rectangle {
id: maskLayer
anchors.fill: parent
radius: parent.width / 2
color: "red"
border.color: "black"
layer.enabled: true
layer.samplerName: "maskSource"
layer.effect: ShaderEffect {
property var colorSource: rectangleSource
fragmentShader: "
uniform lowp sampler2D colorSource;
uniform lowp sampler2D maskSource;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor =
texture2D(colorSource, qt_TexCoord0)
* texture2D(maskSource, qt_TexCoord0).a
* qt_Opacity;
}
"
}
}
// only draw border line
Rectangle {
anchors.fill: parent
radius: parent.width / 2
border.color: "black"
border.width: 1
color: "transparent"
}
}
}
Run Code Online (Sandbox Code Playgroud)