正确的做法应该是上 noise 而不是叠加 sin 波,不过如果不想麻烦的话叠波还是一个不错的选择:整体效果如下,已经非常形似

shadertoy 游戏《来自星尘》摇杆复刻-LMLPHP

直接上链接: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);
}

整体没啥难度,就不上教学了吧,链接里左边效果右边就是代码了,可以自行参考

03-05 02:55