#type vertex
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;
out vec2 PosXY;

void main() {
    TexCoords = aTexCoords;
    PosXY = vec2(aPos.x, aPos.y);
    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
}  

#type fragment
#version 330 core
layout (location = 0) out vec4 FragColor;

in vec2 TexCoords;
in vec2 PosXY;

uniform float t;

#define M_PI 3.141592654

float Function(float x) {
    x *= 20;
    float amplitude = 1;

    float wave = sin(amplitude*x)/(1.1*amplitude*x) + sin(amplitude*x)/7-0.2;
    float compensation =  (smoothstep(0,0.3,x*0.1+0.7) + smoothstep(0.3,0,x*0.1-0.7)) - 1;

    return wave * compensation;
}

float DistanceToLineSegment(vec2 p0, vec2 p1, vec2 p) {
    float distanceP0 = length(p0 - p);
    float distanceP1 = length(p1 - p);

    float l2 =pow(length(p0 - p1), 2.);
    float t = max(0., min(1., dot(p - p0, p1 - p0) / l2));
    vec2 projection = p0 + t * (p1 - p0); 
    float distanceToProjection = length(projection - p);
   
    return min(min(distanceP0, distanceP1), distanceToProjection);
}

float DistanceToFunction(vec2 p, float xDelta) {
float result = 100.;

for (float i = -3.; i < 3.; i += 1.) {
vec2 q = p;
q.x += xDelta * i;

vec2 p0 = vec2(q.x, Function(q.x));
vec2 p1 = vec2(q.x + xDelta, Function(q.x + xDelta));
result = min(result, DistanceToLineSegment(p0, p1, p));
}

return result;
}

void main() {
float persistence = 0.5;
vec4 bgColor = vec4(0,0.01,0,1);

FragColor = bgColor;

if ((PosXY.x > tan(t*M_PI)) && PosXY.x < tan(M_PI*t+persistence)) {
// Paint the formula because we are in the part of the screen that is being drawn
float width = 0.01;

float distanceToPlot = DistanceToFunction(PosXY, 0);
float intensity = smoothstep(0, 1, 1 - distanceToPlot/width);

vec3 col = vec3(intensity);

FragColor += vec4(col,1.0);
}
}