QML粒子系统-CustomParticle

834 阅读3分钟

本文已参加【新人创作礼】活动,一起开启掘金创作之路。


📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!


CustomParticle

前言

CustomParticle自定义渲染器是ParticlePainter粒子渲染器中的一员,之前已经介绍过它的兄弟ImageParticle图片渲染器了,本节来介绍一下CustomParticle自定义渲染器。

简介

CustomParticle自定义渲染器用于指定着色器来绘制粒子。这里的指定着色器指的是OpenGL里的着色器,意味着可以直接使用OpenGL着色器的一些特性。下面是CustomParticle自定义渲染器的属性列表:

属性类型描述
fragmentShaderstring这个属性保存片段着色器的GLSL源代码。默认的着色器期望从顶点着色器传递纹理坐标为“可变highp vec2 qt_TexCoord0”,它从名为“source”的sampler2D采样。
vertexShaderstring这个属性保存顶点着色器的GLSL源代码。默认的着色器将纹理坐标传递给片段着色器“highp vec2 qt_TexCoord0”。

着色器是使用一种叫GLSL的类C语言写成的。GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性。

着色器的开头总是要声明版本,接着是输入和输出变量、uniform和main函数。每个着色器的入口点都是main函数,在这个函数中我们处理所有的输入变量,并将结果输出到输出变量中。

这两个属性都可以将GLSL的代码进行使用,不同之处在于片段着色器和顶点着色器的使用。

使用

本节将创建一个自定义粒子渲染器,其作用是将输入的图片原子化分解,分解出的原子是以另一张图片做为原子的形式。本节中将要分解的图片设置为一个心型🧡,原子化的图片使用小颗粒的图片。以下代码是CustomParticle自定义渲染器部分的代码。其中GLSL的代码不做介绍了。

    CustomParticle {
        system: sys
        anchors.fill: parent
        property real maxWidth: root.width
        property real maxHeight: root.height
        ShaderEffectSource {
            id: pictureSource
            sourceItem: picture
            hideSource: false
        }
        Image {
            id: picture
            anchors.fill: parent
            source: "qrc:/heart.png"
            fillMode: Image.PreserveAspectFit
        }
        ShaderEffectSource {
            id: particleSource
            sourceItem: particle
            hideSource: true
        }
        Image {
            id: particle
            source: "qrc:///particleresources/fuzzydot.png"
        }
        //! [vertex]
        vertexShader:"
            uniform highp float maxWidth;
            uniform highp float maxHeight;
            varying highp vec2 fTex2;
            varying lowp float fFade;
            uniform lowp float qt_Opacity;

            void main() {

                fTex2 = vec2(qt_ParticlePos.x, qt_ParticlePos.y);
                //Uncomment this next line for each particle to use full texture, instead of the solid color at the center of the particle.
                //fTex2 = fTex2 + ((- qt_ParticleData.z / 2. + qt_ParticleData.z) * qt_ParticleTex); //Adjusts size so it's like a chunk of image.
                fTex2 = fTex2 / vec2(maxWidth, maxHeight);
                highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
                fFade = min(t*4., (1.-t*t)*.75) * qt_Opacity;
                defaultMain();
            }
        "
        //! [vertex]
        property variant particleTexture: particleSource
        property variant pictureTexture: pictureSource
        //! [fragment]
        fragmentShader: "
            uniform sampler2D particleTexture;
            uniform sampler2D pictureTexture;
            varying highp vec2 qt_TexCoord0;
            varying highp vec2 fTex2;
            varying lowp float fFade;
            void main() {
                gl_FragColor = texture2D(pictureTexture, fTex2) * texture2D(particleTexture, qt_TexCoord0).w * fFade;
        }"
        //! [fragment]
    }

效果展示

这里我将粒子效果做成了鼠标点击才会运行的状态,开始界面展示要分解的图形,每次点击鼠标就发将图片分解成粒子发射出去。

custom.gif