您当前的位置: 首页 > 

龚建波

暂无认证

  • 2浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QML使用ShaderEffect绘制波纹

龚建波 发布时间:2021-06-07 00:33:17 ,浏览量:2

0.前言

对于 ShaderEffect 的介绍请看 Qt 文档:https://doc.qt.io/qt-5/qml-qtquick-shadereffect.html

之前用 QtGraphicalEffects 模块的镜像渐变做过波纹效果,但是那个 GradientStop 不能放到 Repeator 里,要根据参数动态设置波纹大小就需要 createComponent 之类的。最近用 ShaderEffect 又重新实现了下波纹效果。感觉最麻烦的就是抗锯齿,最终效果勉强,不过没 QtGraphicalEffects 做的好,有空研究下他怎么实现的。

下图左侧 Shader,右侧渐变:

1.实现思路

波纹就是通过设置每一段间隔范围的透明度来实现,在此基础上加一个偏移量加减透明度值,使之看起来在移动。

抗锯齿我使用的 smoothstep  函数,但是目前效果还不大理想,后面再研究下怎么优化。

2.实现代码

(这里使用的 QML 默认的 OpenGL ES2.0 的 glsl)

Shader(就几句代码,懒得写注释了):

import QtQuick 2.12

//使用shader制作波纹效果
ShaderEffect{
    id: control
    width: 150
    height: 150
    //动画移动偏移量
    property real offset: 0
    //波纹间隔
    property real spacing: 20

    NumberAnimation {
        target: control
        property: "offset"
        duration: 2000
        from: 0
        to: control.spacing
        loops: Animation.Infinite //-1
        running: true
    }

    vertexShader: "
uniform mat4 qt_Matrix;
attribute vec4 qt_Vertex;
attribute vec2 qt_MultiTexCoord0;
varying vec2 thePos;

void main() {
thePos =  vec2(qt_MultiTexCoord0.x*2.0-1.0,-qt_MultiTexCoord0.y*2.0+1.0);
gl_Position = qt_Matrix * qt_Vertex;
}
"

    fragmentShader: "
varying vec2 thePos;
uniform float qt_Opacity;
uniform float width;
uniform float offset;
uniform float spacing;
vec4 outColor;
float mod(float x,float y)
{
return x-y*floor(x/y);
}
void main()
{
outColor = vec4(1,0,0,0);
float aSmoothWidth=3.0/float(width);
// distance(pos)=[0,1],on center=0,on border=1
float dis=distance(thePos,vec2(0.0,0.0))*width;
float maxlen=float(int(width)/int(spacing*2.0))*spacing*2.0-spacing*2.0+offset*2.0;
if(dis0.99-aSmoothWidth)
outColor.a=smoothstep(0.99,0.98-aSmoothWidth,outColor.a);
// erasing
outColor.a=pow(outColor.a,2.0);
}
gl_FragColor = outColor * qt_Opacity;
gl_FragColor.rgb *= gl_FragColor.a;
}
"
}

渐变:

import QtQuick 2.12
import QtGraphicalEffects 1.0

//使用渐变制作波纹效果
RadialGradient{
    id: control
    implicitWidth: 150
    implicitHeight: 150
    property double wave_offset: 0.0
    property color wave_color: "red"
    property alias running: animation.running

    NumberAnimation{
        id: animation
        target: control
        property: "wave_offset"
        from: 0
        to: 0.1
        duration: 2000
        running: control.visible
        loops: Animation.Infinite //-1
    }

    //待改进,根据参数来设置波纹数量
    gradient: Gradient{
        //很遗憾,不能用Repeater,可以试下createComponent,然后属性用binding绑定offset
        GradientStop{ position: 0; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.001; color: control.wave_color }
        GradientStop{ position: control.wave_offset+0.01; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.05; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.1; color: control.wave_color }
        GradientStop{ position: control.wave_offset+0.11; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.15; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.2; color: control.wave_color }
        GradientStop{ position: control.wave_offset+0.21; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.25; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.3; color: control.wave_color }
        GradientStop{ position: control.wave_offset+0.31; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.35; color: "transparent" }
        GradientStop{ position: control.wave_offset+0.4; color: control.wave_color }
        GradientStop{ position: control.wave_offset+0.41; color: "transparent" }
    }
}

 

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.0706s