// @name Plastic Sunrise: Portal Flight
// @group Flight Camera
// @param uOffsetX "Camera Pan X" 0.0 -1.5 1.5 0.01
// @param uOffsetY "Camera Pan Y" 0.0 -1.0 1.0 0.01
// @param uScale "Tunnel Scale" 1.0 0.35 2.0 0.01
// @param uSpeed "Flight Speed" 0.42 -2.0 2.0 0.01
// @param uFocalLength "Focal Length" 1.45 0.7 2.8 0.01
// @param uDepth "Tunnel Depth" 7.5 3.0 14.0 0.1
// @param uPortalCount "Portal Count" 10.0 4.0 16.0 1.0
// @group Solar Portals
// @param uCoreRadius "Portal Radius" 0.72 0.25 1.3 0.01
// @param uRayCount "Ray Count" 12.0 5.0 22.0 1.0
// @param uRayLength "Ray Length" 0.46 0.05 1.1 0.01
// @param uRaySharpness "Ray Sharpness" 3.8 0.8 9.0 0.1
// @param uRingWidth "Plastic Thickness" 0.055 0.012 0.18 0.002
// @param uInnerRing "Inner Ring" 0.72 0.3 0.94 0.01
// @param uPortalWarp "Portal Warp" 0.16 0.0 0.55 0.01
// @group Tunnel Motion
// @param uTwist "Depth Twist" 0.34 -1.5 1.5 0.01
// @param uSpin "Portal Spin" 0.12 -1.5 1.5 0.01
// @param uSway "Camera Sway" 0.1 0.0 0.45 0.01
// @param uSwaySpeed "Sway Speed" 0.38 0.0 2.0 0.01
// @group Translucent Plastic
// @param uHue "Plastic Hue" 0.015 0.0 1.0 0.005
// @param uSaturation "Saturation" 0.68 0.0 1.0 0.01
// @param uHueShift "Depth Hue Shift" 0.18 -0.5 0.5 0.01
// @param uGloss "Gloss" 0.9 0.0 1.0 0.01
// @param uIridescence "Iridescence" 0.48 0.0 2.0 0.01
// @param uTransmission "Transmission" 0.36 0.0 1.0 0.01
// @group Atmosphere
// @param uGlow "Portal Glow" 1.12 0.0 3.0 0.01
// @param uTrailGlow "Motion Trails" 0.36 0.0 2.0 0.01
// @param uStarDensity "Star Density" 0.28 0.0 1.0 0.01
// @param uStarSpeed "Star Speed" 0.72 0.0 3.0 0.01
// @param uExposure "Exposure" 1.08 0.2 3.0 0.01
// @param uVignette "Vignette" 0.48 0.0 1.0 0.01
// @group Audio
// @param uAudioReact "Audio Reactivity" 0.62 0.0 2.0 0.01
// @param uBassThrust "Bass Thrust" 0.38 0.0 1.5 0.01
// @param uMidTwist "Mid Twist" 0.28 0.0 1.5 0.01
// @param uTrebleStrobe "Treble Strobe" 0.46 0.0 2.0 0.01

#define PF_PI 3.14159265359
#define PF_TAU 6.28318530718
mat2 pfRot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);}
vec3 pfHsv(vec3 c){vec3 p=abs(fract(c.xxx+vec3(0.,.666667,.333333))*6.-3.);return c.z*mix(vec3(1.),clamp(p-1.,0.,1.),c.y);}
float pfHash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}
float pfOutline(vec2 p,float phase){
    float r=length(p),a=atan(p.y,p.x);
    float n=max(5.,floor(uRayCount+.5));
    float petal=pow(.5+.5*cos(a*n+phase),uRaySharpness);
    float warp=sin(a*3.-phase*.7)*uPortalWarp;
    float outer=uCoreRadius+uRayLength*petal*(.72+.28*cos(a*n*.5+phase))+warp*.08;
    float inner=uCoreRadius*uInnerRing+warp*.04;
    return max(r-outer,inner-r);
}
void mainImage(out vec4 fragColor,in vec2 fragCoord){
    vec2 uv=(fragCoord-.5*iResolution.xy)/iResolution.y;
    float time=iTime*uSpeed*(1.+iBass*uAudioReact*uBassThrust*.12);
    vec2 camera=vec2(sin(iTime*uSwaySpeed),cos(iTime*uSwaySpeed*.73))*uSway;
    vec2 ray=(uv-vec2(uOffsetX,uOffsetY)-camera)/max(uScale,.001);
    vec3 col=mix(vec3(.001,.004,.014),vec3(.008,.022,.052),clamp(uv.y+.55,0.,1.));
    float count=max(4.,floor(uPortalCount+.5));
    for(int i=0;i<16;i++){
        float fi=float(i);if(fi>=count)break;
        float travel=fract(fi/count+time*.09);
        float z=mix(uDepth,.58,travel);
        float fade=smoothstep(uDepth,uDepth*.64,z)*smoothstep(.52,.9,z);
        vec2 p=ray*z/uFocalLength;
        p+=vec2(sin(fi*2.17+time*.27),cos(fi*1.43-time*.22))*uPortalWarp*.12;
        float phase=iTime*uSpin+fi*uTwist+iMid*uAudioReact*uMidTwist;
        p=pfRot(phase)*p;
        float d=pfOutline(p,phase);
        float width=uRingWidth*(.72+.28*travel);
        float band=exp(-abs(d)/max(width,.002));
        float core=smoothstep(width,-width,d);
        float edge=pow(band,mix(1.2,3.8,uGloss));
        float angle=atan(p.y,p.x);
        float highlight=pow(max(0.,.5+.5*cos(angle+phase+1.2)),mix(3.,18.,uGloss));
        vec3 plastic=pfHsv(vec3(fract(uHue+fi/count*uHueShift+highlight*.04),uSaturation,.72+.28*highlight));
        vec3 glass=pfHsv(vec3(fract(uHue+.14+fi/count*uHueShift),uSaturation*.48,1.));
        plastic=mix(plastic,glass,uTransmission*(.25+.75*highlight));
        plastic+=pfHsv(vec3(fract(uHue+.24+angle/PF_TAU),.58,1.))*uIridescence*edge*.34;
        plastic+=vec3(1.,.88,.72)*highlight*uGloss;
        float strobe=1.+iTreble*uAudioReact*uTrebleStrobe;
        col+=plastic*(edge*.48+core*.055)*fade*strobe;
        col+=pfHsv(vec3(fract(uHue+.03),.74,1.))*band*uGlow*.045*fade;
        col+=plastic*edge*uTrailGlow*.018*(1.-travel);
    }
    vec2 starP=ray/max(abs(ray.x)+abs(ray.y)+.14,.12);
    vec2 cell=floor(starP*42.);
    float star=step(1.-uStarDensity*.018,pfHash(cell));
    float streak=pow(max(0.,1.-abs(fract(length(ray)*18.-iTime*uStarSpeed)-.5)*2.),10.);
    col+=vec3(.46,.9,1.)*star*streak*uStarDensity*.5;
    col*=uExposure*(1.-uVignette*smoothstep(.18,1.1,length(uv)));
    col=col/(1.+col*.58);
    fragColor=vec4(pow(max(col,0.),vec3(.82,.85,.9)),1.);
}
