垂直褪色和水平颜色不同

问题描述 投票:0回答:2

我们如何创建具有不同颜色的线性渐变并使用

qml
javascript
从上到下淡化(垂直淡化)?

或者可以用

fragment
?有教程吗!!

换句话说,结合两个图像。

javascript qt qml fragment gradient
2个回答
1
投票

根据你的问题,我假设你想将两张图片合并在一起,并从一张图片到另一张图片进行某种淡入淡出?

我使用了 OpacityMaskLinearGradient,它们都是 Qt 5 Compatibility API 的一部分。根据您使用的 Qt 版本,您可以使用:

示例工作如下:

  1. 创建一个从黑色变为透明的
    LinearGradient
    ,用作遮罩。
  2. 加载两张图片(如果你不想看到原来的你应该用
    visible: false
    隐藏它们)。
  3. 在彼此之上创建两个
    OpacityMask
    实例,它们都应用了相同的蒙版(底部使用
    invert: true
    )和不同的源图像。

我还建议使用自定义 shaders 以实现该效果,因为它会更快并且不像绘制

OpacityMask
两次那样多余。


编辑: 我已经添加了提到的

ShaderEffect
和随附的片段着色器。结果与
OpacityMask
解决方案有点不同,但这也可能是由于该示例使用的 GLSL
mix()
函数。

我的示例使用的是 Qt 6.4.0,您可以从这里获得完整的源代码。

import QtQuick
import Qt5Compat.GraphicalEffects

Window {
    id: root
    width: 640
    height: 940
    visible: true
    title: qsTr("Hello World")

    readonly property int _width: 200
    readonly property int _height: 300

    LinearGradient {
        id: mask
        width: root._width
        height: root._height
        start: Qt.point(0, 0)
        end: Qt.point(0, root._height)
        visible: false
        gradient: Gradient {
            GradientStop { position: 0.0; color: "black" }
            GradientStop { position: 1.0; color: "transparent" }
        }
    }

    Grid {
        columns: 3
        spacing: 20

        Image {
            id: imgSourceTop
            source: "https://picsum.photos/id/54/%1/%2".arg(root._width).arg(root._height)
            smooth: true
        }

        Image {
            id: imgSourceBottom
            source: "https://picsum.photos/id/93/%1/%2".arg(root._width).arg(root._height)
            smooth: true
        }

        Item {
            width: root._width
            height: root._height

            OpacityMask {
                anchors.fill: parent
                source: imgSourceTop
                maskSource: mask
            }

            OpacityMask {
                anchors.fill: parent
                source: imgSourceBottom
                maskSource: mask
                invert: true
            }
        }

        LinearGradient {
            id: gradientSourceTop
            width: root._width
            height: root._height
            start: Qt.point(0, 0)
            end: Qt.point(root._width, 0)
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#1E9600" }
                GradientStop { position: 0.5; color: "#FFF200" }
                GradientStop { position: 1.0; color: "#FF0000" }
            }
        }

        LinearGradient {
            id: gradientSourceBottom
            width: root._width
            height: root._height
            start: Qt.point(0, 0)
            end: Qt.point(root._width, 0)
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#833ab4" }
                GradientStop { position: 0.5; color: "#fd1d1d" }
                GradientStop { position: 1.0; color: "#fcb045" }
            }
        }

        Item {
            width: root._width
            height: root._height

            OpacityMask {
                anchors.fill: parent
                source: gradientSourceTop
                maskSource: mask
            }

            OpacityMask {
                anchors.fill: parent
                source: gradientSourceBottom
                maskSource: mask
                invert: true
            }
        }

        Image {
            id: shaderSourceTop
            source: "https://picsum.photos/id/54/%1/%2".arg(root._width).arg(root._height)
            smooth: true
        }

        Image {
            id: shaderSourceBottom
            source: "https://picsum.photos/id/93/%1/%2".arg(root._width).arg(root._height)
            smooth: true
        }

        ShaderEffect {
            width: root._width
            height: root._height
            property variant sourceTop: shaderSourceTop
            property variant sourceBottom: shaderSourceBottom
            fragmentShader: "shaders/blend.frag.qsb"
        }
    }
}

#version 440

layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;

layout(binding = 1) uniform sampler2D sourceTop;
layout(binding = 2) uniform sampler2D sourceBottom;

layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};

void main()
{
    vec4 top = texture(sourceTop, qt_TexCoord0);
    vec4 bottom = texture(sourceBottom, qt_TexCoord0);
    fragColor = mix(top, bottom, qt_TexCoord0.y);
}

0
投票

我不确定这是你要问的,但是,我尝试使用 QML 重新创建你的图像。第二张图片我使用平铺的 SVG 图像作为基础,然后在顶部我使用 LinearGradient 但我设置了不透明度所以我可以看到部分基础:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
Page {
    id: page
    ColumnLayout {
        Frame {
            Layout.preferredWidth: 500
            Layout.preferredHeight: 300
            LinearGradient {
                anchors.fill: parent
                start: Qt.point(0, 0)
                end: Qt.point(width, 0)
                gradient: Gradient {
                    GradientStop { position: 0.0; color: "yellow" }
                    GradientStop { position: 1.0; color: "purple" }
                }
            }
        }
        Frame {
            Layout.preferredWidth: 300
            Layout.preferredHeight: 300
            padding: 0
            Image {
                anchors.fill: parent
                source: "squares.svg"
                fillMode: Image.Tile
            }
            LinearGradient {
                anchors.fill: parent
                start: Qt.point(0, height)
                end: Qt.point(0, 0)
                gradient: Gradient {
                    GradientStop { position: 0.0; color: "white" }
                    GradientStop { position: 1.0; color: "blue" }
                }
                opacity: 0.5
            }
        }
    }
}

// squares.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect x="0" y="0" width="16" height="16" fill="#ccc"/>
<rect x="16" y="0" width="16" height="16" fill="#eee"/>
<rect x="0" y="16" width="16" height="16" fill="#eee"/>
<rect x="16" y="16" width="16" height="16" fill="#ccc"/>
</svg>

您可以在线试用!

© www.soinside.com 2019 - 2024. All rights reserved.