Heart Slasher

https://www.shadertoy.com/view/l3G3R1

Shader code
shader_type canvas_item;

#define iTime TIME
#define iResolution 1.0/SCREEN_PIXEL_SIZE

uniform float ARROWS : hint_range(-1.0, 100.0, 1) = 5.0;
uniform float VANISH_TIME = 1.5;
uniform float animation_speed : hint_range(0.0, 10.0, 0.1) = 2.0;
uniform float shake_amplitude : hint_range(0.0, 5.0, 0.1) = 0.7;
uniform vec3 heart_color = vec3(1, 0, 0);
uniform vec3 halo_color = vec3(1.000, 0.922, 0.078);
uniform vec3 bg_color = vec3(0.5, 0.0, 0.0);
uniform bool remove_bg = false;

const float HPI = PI * 0.5;

float dot2(vec2 x) {
    return dot(x, x);
}

float hash11(float p) {
    p = fract(p * .1031);
    p *= p + 33.33;
    p *= p + p;
    return fract(p);
}

float noise(float p) {
	float fl = floor(p);
	float fc = fract(p);
	return mix(hash11(fl), hash11(fl + 1.0), fc);
}

float hash12(vec2 p) {
	vec3 p3 = fract(p.xyx * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

float noise2d(vec2 p) {
	vec2 ip = floor(p);
	vec2 u = fract(p);
	u = u * u * (3.0 - 2.0 * u);
	float res = mix(
		mix(hash12(ip), hash12(ip + vec2(1, 0)), u.x),
		mix(hash12(ip + vec2(0, 1)), hash12(ip + vec2(1)), u.x), u.y);
	return res * res;
}

float fbm(float p, int octaves) {
	float s = 0.0, m = 0.0, a = 1.0;
	for(int i = 0; i < octaves; i++) {
		s += a * noise(p);
		m += a;
		a *= 0.6;
		p *= 1.8;
	}
	return s / m;
}

float fbm2d(vec2 p, int octaves) {
	float s = 0.0, m = 0.0, a = 1.0;
	for(int i = 0; i < octaves; i++) {
		s += a * noise2d(p);
		m += a;
		a *= 0.6;
		p *= 1.8;
	}
	return s / m;
}


float heart(vec2 p) {
    p.y += 0.5;
    p.x = abs(p.x);
    if (p.y + p.x > 1.0)
        return sqrt(dot2(p - vec2(0.25,0.75))) - sqrt(2.0) / 4.0;
    return sqrt(min(dot2(p - vec2(0.00,1.00)),
                    dot2(p - 0.5 * max(p.x + p.y, 0.0)))) * sign(p.x-p.y);
}

float shake(float t) {
    t = clamp(t, 0.0, 1.0);
    return (fbm(pow(t, 0.3) * 8.0, 3) * (1.0 + cos(t * HPI)) - sin(t * HPI)) * (1.0 - t) * pow(t, 0.7);
}

float line(vec2 p, vec2 p1, vec2 p2) {
    vec2 center = (p1 + p2) * 0.5;
    float len = length(p2 - p1);
    vec2 dir = (p2 - p1) / len;
    vec2 rel_p = p - center;
    return dot(rel_p, vec2(dir.y, -dir.x));
}

float segment(vec2 p, vec2 p1, vec2 p2) {
    vec2 center = (p1 + p2) * 0.5;
    float len = length(p2 - p1);
    vec2 dir = (p2 - p1) / len;
    vec2 rel_p = p - center;
    float dist1 = abs(dot(rel_p, vec2(dir.y, -dir.x)));
    float dist2 = abs(dot(rel_p, dir)) - 0.5 * len;
    return max(dist1, dist2);
}

float arrow(vec2 uv) {
    const float outline = 0.01;
    const float line_width = 1.8;
    float height = 0.2 * max(0.5, sqrt(uv.x));
    const float head_size = 0.2;
    const float size = 0.02;
    uv.x -= line_width * 0.45 + head_size * 0.5;

    float a1 = line(uv, -head_size * vec2(1, -height), vec2(0));
    float a2 = line(uv, -head_size * vec2(1, -height), -vec2(3.0 * head_size / 4.0, 0));
    float a3 = line(uv, -head_size * vec2(1, height), vec2(0));
    float a4 = line(uv, -head_size * vec2(1, height), -vec2(3.0 * head_size / 4.0, 0));
    float head = max(max(-a1, a3), -max(-a2, a4));

    uv.y = abs(uv.y);
    vec2 n = vec2(0,(fbm(uv.x * 5.0 + iTime * 0.5, 3) * 2.0 - 1.0) * 0.03);
    float tail = segment(uv - n, vec2(-line_width*0.9, 0), vec2(-line_width - head_size * 0.9, head_size * 0.5));
    tail = min(tail, segment(uv - n, vec2(-line_width*0.85 - head_size , 0), vec2(-line_width - head_size * 1.4, head_size * 0.4)));
    tail = min(tail, segment(uv - n, vec2(-line_width*0.93 - head_size , 0), vec2(-line_width - head_size * 1.7, head_size * 0.3)));

    float stick = segment(uv, - vec2((head_size * 1.5 + line_width), 0), vec2(-0.2, 0));
    stick = min(stick, tail);

    return min(abs(head - size) - outline, mix(stick - outline * smoothstep(-1.9, -1.2, uv.x), max(outline, head - outline), step(head, size)));
}

float shoot_arrow(vec2 uv, float t, float id) {
    t = clamp(t - id, 0.0, 1.0);
    float f = length(fwidth(uv));
    vec2 auv = uv;
    float a = noise(-id * 5.0  - 0.05);
    auv = cos(a * TAU) * auv + sin(a * TAU) * vec2(-auv.y, auv.x);
    auv.x -= (smoothstep(0.0, 0.8, t * 2.0) - 1.0) * 7.0;
    return arrow(auv);
}

void fragment()
{
    float mr = min(iResolution.x, iResolution.y);
    vec2 uv = (FRAGCOORD.xy * 2.0 - iResolution.xy) / mr * 1.5;
	uv.y = -uv.y;
    float f = length(fwidth(uv));
    float t = mod(iTime * animation_speed, ARROWS + VANISH_TIME);
    float ft = floor(t);

    float a = noise(-ft * 5.0  - 0.05);
    vec2 dir = vec2(cos(-a * TAU), sin(-a * TAU));
    float ts = fract(min(t, ARROWS));
    float s = shake((ts * 2.0 - 0.65) * 2.5) * shake_amplitude;
    uv -= dir * s;


    float d = heart(uv);

    float m = smoothstep(0.0 + f, 0.0 - f, d);
    vec3 col = vec3(m) * heart_color;
    col += sqrt(max(0.0, -d * 4.0)) - m;
    col = abs(col);

    float arrw = shoot_arrow(uv, t, 0.0);
    for (float i = 1.0; i < ARROWS; ++i)
        arrw = min(arrw, shoot_arrow(uv, t, i));
    arrw += fbm2d(uv * 4.0, 4) * smoothstep(ARROWS, ARROWS + VANISH_TIME, t) * 0.5;
    col = mix(vec3(smoothstep(f, -f, arrw)), col, m);

    float flash = (1.0 - smoothstep(0.0, 1.0, ts)) * smoothstep(0.5, 0.9, ts * 2.0) * (1.0 + abs(s) * 6.0) * 0.7;
    float g = (1.0 - m) * exp(-sqrt(max(0.0, d)) * 3.0);
    col += g * sin(g * halo_color + bg_color);
    col.rb += (col.g + col.b) * vec2(1.0 / g, g + flash) - vec2(col.r, col.r);

    COLOR = vec4(col,1.0);
	if(remove_bg == true){
		COLOR.a = COLOR.r;
	}

}
This shader is a port from an existing Shadertoy project. Shadertoy shaders are by default protected under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) license unless anything else has been stated by the author. For more info, see our License terms.

More from RayL019

Kinetic Pupils

20151110_VHS

Circle Bokeh Blur

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments