Just a little thing that I had to do myself because I couldn't find anything similar elsewhere, so maybe it can help someone.
I made a prototype game where a cannon levitates balls and has to throw them at targets and I wanted to find a cool effect, so I had the idea of some kind of warping ray that would simulate magnetism or I do not know what.
In short, here is a demo that I made apart for the image:
The shader (surely optimizable):
Code: Select all
uniform float thickness; // Thickness (amplitude) of the ray
uniform float time;
uniform vec2 p1; // First point of the seg
uniform vec2 p2; // Second point of the seg
float attenuation(float distance, float thickness) {
return 1.0 - distance / thickness;
}
vec4 effect(vec4 c, Image tex, vec2 tc, vec2 sc) {
/* Calculation of the distance of the line p1->p2 */
vec2 v = p2 - p1;
vec2 w = sc - p1;
float c1 = dot(w, v);
float c2 = dot(v, v);
float distanceToPoint;
if (c1 <= 0.0) {
distanceToPoint = distance(sc, p1);
} else if (c2 <= c1) {
distanceToPoint = distance(sc, p2);
} else {
vec2 pb = p1 + v * (c1 / c2);
distanceToPoint = distance(sc, pb);
}
/* Ripple of line p1->p2 */
if (distanceToPoint < thickness) {
vec2 dir = normalize(p2 - p1); // direction vector between p1 and p2
vec2 parallel = vec2(dir.y, -dir.x); // line parallel vector
vec2 offset = sc - p1; // offset vector with respect to p1
float distance = dot(offset, dir); // distance along the line between p1 and p2
float angle = distance * 0.1 + time; // angle as a function of time and distance (0.1 = ripple factor)
float amplitude = thickness * 0.001; // 0.001 = deformation factor
amplitude *= attenuation(distanceToPoint, thickness); // attenuation so that it stays in line with the edges of the ray
vec2 wave = vec2(
cos(angle) * amplitude * parallel.x,
sin(angle) * amplitude * parallel.y
);
return Texel(tex, tc + wave);
}
return Texel(tex, tc);
}
If you want to use it you are free, it's done for, totally free of rights
Background source: https://opengameart.org/content/background-2