正确的做法应该是上 noise 而不是叠加 sin 波,不过如果不想麻烦的话叠波还是一个不错的选择:整体效果如下,已经非常形似
直接上链接:Shader - Shadertoy BETA
float radiusScale = 0.9;
float variation(vec2 v1, vec2 v2, float strength, float speed)
{
float v = dot(normalize(v1), normalize(v2));
return sin(v * strength - iTime * speed) / 50.0
+ sin(v * strength * 3.0 - iTime * speed) / 450.0;
}
float paintCircle(vec2 uv, vec2 center, vec2 center2, float rad, float width, float strong, float speed)
{
width *= radiusScale;
rad *= radiusScale;
vec2 diff = center - uv;
float len = max(step(center2.y, uv.y) * length(center2 - uv) + step(uv.y, center.y) * length(center - uv),
abs(uv.x - center.x));
float normal = max(-normalize(diff).y, 0.0) * max(-normalize(diff).y, 0.0);
len += variation(diff, vec2(0.0, 1.0), strong, speed) * normal;
len -= variation(diff, vec2(1.0, 0.0), strong, speed) * normal;
rad -= 0.15 * max((uv.y - 0.55), 0.0);
return step(abs(len - rad), width);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv.y += 0.1;
uv.x *= 1.5;
uv.x -= 0.25;
float color;
float radius = 0.24 * radiusScale;
float think1 = radius / 13.0;
float think2 = think1 / 3.0;
vec2 center = vec2(0.5, 0.5);
color = max(color, paintCircle(uv, center, vec2(0.5, 0.7), radius, think1, 5.0, 7.2));
color += paintCircle(uv, center, vec2(0.5, 0.72), radius + think1 / 2.0, think2, 6.5, 7.8);
color = max(color, paintCircle(uv, center, vec2(0.5, 0.74), radius + think1 * 2.0, think2, 6.5, 8.4));
color = max(color, paintCircle(uv, center, vec2(0.5, 0.76), radius + think1 * 2.0 + think2 * 4.0, think2, 7.0, 9.0));
color = max(color, paintCircle(uv, center, vec2(0.5, 0.78), radius + think1 * 2.0 + think2 * 8.0, think2, 8.0, 10.2));
fragColor = vec4(color * vec3(1.5 - uv.y, 1.0, 1.0), 1.0);
}
整体没啥难度,就不上教学了吧,链接里左边效果右边就是代码了,可以自行参考