#version 430

in vec2 uv;

layout(location = 0) out vec4 frag;

uniform float g_time;


vec2 rotateXY2(vec2 p, float a) {
  vec2 r = p;
  r.x = cos(a)*p.x - sin(a)*p.y;
  r.y = sin(a)*p.x + cos(a)*p.y;
  return r;
}


// TODO #include "noise.h"


uniform float noiseOct = 4.0;
uniform float noiseOctMul = 3.0;
uniform float noiseOctAmp = 0.75;
uniform float noiseSplineEnabled = 1.0;

// from pouet raymarching thread by las of mercury
float perlin(vec3 p) {
    vec3 i = floor(p);
    vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
    vec3 f = cos((p-i)*3.14159265)*(-.5)+.5;
    a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
    a.xy = mix(a.xz, a.yw, f.y);
    return mix(a.x, a.y, f.z)-0.0;
}
float turb3(vec3 c) {
        float r=0.0;
        float s=0.5;
        for (int i=0;i<noiseOct;i++) {
                r+=s*(perlin(c));
                c*=noiseOctMul;
                s*=noiseOctAmp;
        }
        return r;
}

vec3 posd(float pw) {
    return vec3(sin(pw)*17.0, cos(pw*1.7)*13.0, sin(pw*0.78+cos(pw*0.4))*11.0)*32.0;
}

float getSplineValue(float t, float p0, float pt0, float p1, float pt1) {
    float t2 = t*t;
    float t3 = t*t*t;
    float p = (2.0*t3-3.0*t2+1.0)*p0+(t3-2.0*t2+t)*pt0+(-2.0*t3+3.0*t2)*p1+(t3-t2)*pt1;
    return p;
}

float perlin4(vec4 p) {
//    vec4 pf1 = floor(p);
//    vec4 pf2 = floor(p+vec4(1.0));

    float p1 = perlin(p.xyz+posd(floor(p.w)+1.0));
    float p2 = perlin(p.xyz+posd(floor(p.w)+2.0));

    if (noiseSplineEnabled > 0.5) {
        float p0 = perlin(p.xyz+posd(floor(p.w)));
        float p3 = perlin(p.xyz+posd(floor(p.w)+3.0));
        float ki = fract(p.w);
        return getSplineValue(ki, p1, p2-p0, p2, p3-p1);
    } else {
        float ki = smoothstep(0.0, 1.0, fract(p.w));
        return p1*(1.0-ki)+p2*(ki);
    }
}

float turb4(vec4 c) {
        float r=0.0;
        float s=0.5;
        for (int i=0;i<noiseOct;i++) {
                r+=s*(perlin4(c));
                c*=noiseOctMul;
                s*=noiseOctAmp;
        }
        return r;
}

// end of "noise.h"


uniform float noisePos = 0.0;
uniform float noiseOfsX = 0.0;
uniform float noiseOfsY = 0.0;
uniform float noiseFreq = 0.20;

uniform float dispAmp = 0.50;
uniform float dispSub = 0.0;
uniform float dispExp = 1.0;
uniform float dispMinLim = -1.0;
uniform float dispMaxLim = 999.0;
uniform float dispSmooth = 0.0;

layout(binding=0, rgba32f) uniform image2D pardexPos;


float deg2pi = 2.0*3.141592/360.0;

uniform float div = 1.0;

uniform float scaleX = 25.0;
uniform float scaleY = 25.0;
uniform float scaleZ = 25.0;

uniform float partNum = 0.0;

void main() {
    ivec2 uvs = ivec2(gl_FragCoord.xy);

    vec4 screen = vec4(0.0);

    ivec2 triBufSize = imageSize(pardexPos);

    int divi = int(div);
    int pid = uvs.x+uvs.y*triBufSize.x;

    if (pid >= partNum) { discard; return; }

    int vid = pid;
    vec3 tvp = vec3(0.0f);
    int vpr = (divi);
    int vr = vid/vpr;
    int vx = vid-vr*vpr;
    float vprf = float(divi-1);
    // tvp.xy = vec2(float(vx)*2.0/vprf-1.0, float(vr)*2.0/vprf-1.0);



    float tt = g_time*6.0*16.0;
    float pidf = float(pid)*0.50+tt;


    tvp.xyz = vec3(sin(pidf*0.01), cos(pidf*0.012), 1.0*sin(pidf*0.014+cos(pidf*0.0123)));


    float no = 0.0;
    float no2 = 0.0;

    vec3 tvpm = tvp;
    vec2 dotPos = vec2(floor(tvpm.x)+0.5, floor(tvpm.y)+0.5);

    // noise
   // no = turb4(vec4(tvp.xy*noiseFreq+vec2(noiseOfsX, noiseOfsY+g_time*0.0), 0.0, noisePos+g_time*0.01*0.0));
   // float no2 = turb4(vec4(tvp.xy*noiseFreq*1.32+vec2(noiseOfsX+0.76, noiseOfsY+1.23+g_time*0.0), 0.0, noisePos+g_time*0.01*0.0));

    //float pidi = (smoothstep(0.0, 1.0, float(pid)*0.001-g_time*0.0)-0.0)*g_time*32.0;

    float pidi = (smoothstep(0.0, 1.0, float(pid)*0.0005)-0.0)*(g_time*1.0+0.00+float(pid)*0.0)*16.0+g_time*300.0;
    no = turb4(vec4(pidi*vec2(0.012, 0.017)*noiseFreq+vec2(noiseOfsX, noiseOfsY+g_time*0.0), 0.0, noisePos+g_time*0.02));
    no2 = turb4(vec4(pidi*vec2(0.0072, 0.0037)*noiseFreq*1.32+vec2(noiseOfsX+0.76, noiseOfsY+1.23), 0.0, noisePos));

//    // spikes
////    float frk = noiseFreq;
////    tvpm.xy *= frk;
////    vec3 dd = (vec3(tvpm.xy, 0.0)-vec3(dotPos, 0.0))*2.0;
////    no = length(dd)*1.0;

//    // balles
////    float frk = noiseFreq;
////    tvpm.xy *= frk;
////    vec3 dd = (vec3(tvpm.xy, 0.0)-vec3(dotPos, 0.0))*2.0;
////    float def = dot(dd, dd);
////    if (def<1.0) {
////        no = sqrt(1.0-def);
////    } else {
////        no = 0.0;
////    }
////    no = 1.0-no;

//    // modulos
////    no = 1.0-no;
////    float notu = turb4(vec4((dotPos.xy+tvp.xy*0.5)*noiseFreq+vec2(noiseOfsX, noiseOfsY), 0.0, noisePos));
////    no *= notu;
////    no = 1.0-no;


//    no = (sign(no)*pow(abs(no), dispExp)-dispSub);

//    if (dispSmooth < 0.5) {
//        no = clamp(no, dispMinLim, dispMaxLim);
//    } else {
//        no = -smoothstep(dispMinLim, dispMaxLim, -no)*(dispMaxLim-dispMinLim)-dispMinLim;
//    }
    float pam = (1.0-smoothstep(0.0, 1.0, float(pid)*0.001))*12.0;

    tvp.x += no*dispAmp*pam;
    tvp.y += no2*dispAmp*pam;


    tvp.xyz *= vec3(scaleX, scaleY, scaleZ);


    imageStore(pardexPos, uvs, vec4(tvp, 0.0));

    discard;

    screen.a = 1.0;
    frag = screen;


}
