This is not 100% my shader, I found an example on the web and adapted it for March. It is quite optimized and can be further optimized. I did it rather quickly because I can't really afford to use up my time and resources without having a financial or health-related gain. You can turn it into wallpaper with the ShaderToy Android application.
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define _ParticlesAmount 10
uniform vec2 resolution;
uniform float time;
float rnd(float x)
{
return fract(sin(dot(vec2(x + 47.49,38.2467 / (x + 2.3)), vec2(12.9898, 78.233))) * (43758.5453));
}
float draw_leaf(vec2 uv, float scale, float d) {
float ret;
vec2 root = uv - vec2(1.0, scale);
float r = length(root) / scale;
float t = abs(atan(root.x, root.y) / 3.1415);
float edge = (3.0 * t - 8.0 * t*t*t*t + 6.0 * t*t*t*t*t) / (4.0 - 3.0 * t);
ret = smoothstep(edge - d, edge + d, r);
return ret;
}
mat2 rotate(float t) {
return mat2(cos(t), -sin(t), sin(t), cos(t));
}
float drawClover(vec2 uv, float scale, float d) {
float ret = draw_leaf(uv, scale, d);
uv = rotate(2.0) * uv;
ret *= draw_leaf(uv, scale, d);
return 1.0 - ret;
}
vec4 alphaBlend(vec4 base, vec4 blend)
{
return vec4(base.rgb * base.a * (1.0 - blend.a) + blend.rgb * blend.a, blend.a + base.a * (1.0 - blend.a));
}
// conversion from a web shadertoy
//void mainImage( out vec4 fragColor, in vec2 fragCoord )
void main() {
{
vec2 uv = (2.0 * gl_FragCoord.xy - resolution.xy) / min(resolution.x, resolution.y);
float t = smoothstep(1.5, 0.0, length(uv));
gl_FragColor = vec4(t * vec3(1, 0.8784, 0.9333) + (1.0 - t) * vec3(0.9568, 0.7451, 0.8118), 1.0);
float j;
float move_max = 1.0;
vec2 spawn_center = vec2(0.0, 0.0);
float spawn_length = 0.5;
float _ParticlesAmount_f = float(_ParticlesAmount);
for (int i = 1; i < _ParticlesAmount; i++)
{
j = float(i);
float rnd1 = rnd(cos(j));
float delayedTime = (0.2 + 0.2 * rnd1) * time;
float d = floor(delayedTime / move_max);
float rnd2 = rnd(j * d);
float rnd3 = rnd(j * j * d);
float r = delayedTime / move_max - d;
float x_wave = 0.15 * sin(delayedTime * 7.0 + 6.282 / j);
vec2 spawn = vec2(0.0, rnd3 * spawn_length);
float ease = pow(2.0, 5.0 * (r - 1.0));
float y_move = move_max * ease;
float opacity = 1.0 - ease - pow(2.0, -30.0 * r);
float scale = 1.0 - 0.65 * rnd1 + 0.15 * sin(1.8 * time * j / _ParticlesAmount_f + 6.282 / j);
float rot_wave = 2.0 * sin(delayedTime * 3.0 * j / _ParticlesAmount_f * 2.0 + 6.282 / j);
vec2 center = rotate(rot_wave) * (rotate(6.282 * rnd2) * (uv + spawn_center) + spawn + vec2(x_wave, y_move)) * scale;
vec3 cloverColor = vec3(0.3 + 0.3 * rnd2, 0.98, 0.3) * (1.0 - 0.3 * rnd3);
vec3 cloverCenterColor = cloverColor + (vec3(1.0) - cloverColor) * 0.5;
vec3 cloverBgColor = vec3(1.0, 0.98, 0.7);
gl_FragColor = alphaBlend(gl_FragColor, vec4(cloverBgColor, opacity * drawClover(center, 0.1, 0.3)));
gl_FragColor = alphaBlend(gl_FragColor, vec4(cloverColor, opacity * drawClover(center, 0.1, 0.01)));
gl_FragColor = alphaBlend(gl_FragColor, vec4(cloverCenterColor, opacity * drawClover(center, 0.05, 0.3)));
}
}
}