#version 430

layout(binding=0) uniform sampler2D tex;
//layout(binding=1) uniform sampler2D tex1;

layout(binding=0, r32ui) uniform uimage2D headPointers;
layout(binding=1, r32ui) uniform uimage2D nextPointers;
layout(binding=2, rgba16f) uniform image2D pixelListColors;
layout(binding=3, rgba32f) uniform image2D pixelListDepthNorm;


in vec2 uv;

layout(location = 0) out vec4 frag;
layout(location = 1) out vec4 frag2;

uniform float g_time;

uniform float g_windowWidth = 1280.0;
uniform float g_windowHeight = 720.0;

#define MAX_PIXELS 32

struct PixelInfo {
    //uint nextPointer;
    vec4 depthNorm;
    vec4 color;
};


void main() {

    vec2 uvS = uv;
    vec2 uvO = uv;
//    ivec4 screen = texture2D(tex0, uvS);
//    if (screen.r > 1) {
//        frag = vec4(1.0, 1.0, 1.0, 1.0);
//    } else {
//        frag = vec4(0.0, 0.0, 0.0, 1.0);
//    }

    uvS.y = -uvS.y;


    struct PixelInfo pixels[MAX_PIXELS];

    uvec4 kk = imageLoad(headPointers, ivec2(gl_FragCoord.xy));
    if (kk.r > 0) {
//        float k = float(kk.r)/256.0;
//        frag = vec4(k);
//        frag.a = 1.0;

        uint counter = kk.r;
        uint cy;
        uint cx;
        ivec2 listCoord;

        uint nc = kk.r;
        uint countPixels = 0;

        frag = vec4(0.0, 0.0, 0.0, 1.0);

        frag.rgb = texture2D(tex, uvS.xy).rgb;


        uint maxLoops = MAX_PIXELS;
        while (nc > 0 && maxLoops>0) {
            counter = nc;
            cy = counter/(1280*4);
            cx = counter-cy*1280*4;
            listCoord = ivec2(cx,cy);

            pixels[countPixels].color = imageLoad(pixelListColors, listCoord);
            pixels[countPixels].depthNorm = imageLoad(pixelListDepthNorm, listCoord);

            countPixels++;
            maxLoops--;
            nc = imageLoad(nextPointers, listCoord).r;
          //  frag += imageLoad(pixelListColors, listCoord);
        }


//        for (uint i=1; i<countPixels; i++) {
//            struct PixelInfo pixelToInsert = pixels[i];
//            uint j=i;
//            while (j>0 && pixelToInsert.depthNorm.x < pixels[j-1].depthNorm.x) {
//                struct PixelInfo sw = pixels[j];
//                pixels[j] = pixels[j-1];
//                j--;
//            }
//            pixels[j] = pixelToInsert;
//        }

        for (uint i=0; i<countPixels; i++) {
            struct PixelInfo pi = pixels[i];
            for (uint j=i; j<countPixels; j++) {
                struct PixelInfo pers = pixels[j];
                if (pers.depthNorm.x > pi.depthNorm.x) {
                    pixels[j] = pi;
                    pixels[i] = pers;
                    pi = pers;
                }
            }
        }


        float depthiPrev = 100.0;
        float alfPrev = 1.0;

        float levelPrev = 100.0;
        float level = 0.0;

        int cw = 0;
        for (uint ki=0; ki<countPixels; ki++) {
           // frag += 1.0/(1.0+4.0*pow(pixels[ki].depthNorm.x, 10.0));
           // frag += 1.0-pow(pixels[ki].depthNorm.x, 16.0);
           // float alffa = pixels[ki].color.a;
           // frag.rgb = frag.rgb*(1.0-alffa)+pixels[ki].color.rgb*alffa;
           // frag.rgb += pixels[ki].color.rgb;


            // frag.rgb = mix(frag.rgb, pixels[ki].color.rgb, pixels[ki].color.a);
           float depthi = pixels[ki].depthNorm.x;
           float alf = pixels[ki].color.a;
           level = pixels[ki].depthNorm.y;

           float diff = depthi-depthiPrev; // +alfPrev-alf-0.0;

           depthi -= level;

           if (pixels[ki].color.a > 0.01) {
           float am = 0.50;
           float kb = (1.0-am)+am*smoothstep(0.0, 1.0, -diff);
/*
           kb = clamp(kb, 0.0, 1.0);

           float alfs = kb;

//           alfs = pixels[ki].color.a;

           alfs = kb;

          // if (cw == 0) alfs = 1.0;

          // frag.rgb = mix(frag.rgb, vec3(1.0-pow(depthi*1.0, 4.0)), alfs);

           frag.rgb = (1.0-alfs)*frag.rgb+ vv*(alfs);
*/


           float b1 = 1.0-1.0*pow(-diff/(depthiPrev+0.0*levelPrev), 1.0);
           b1 = 0.0*pow(b1, 8.0)+0.0;
          // b1 *= pow((1.0-alf), 1.0); //*smoothstep(0.0, 4.0, -diff);
//           if (cw==0) b1 = 0;
           depthi += level;


         //  if (-diff/depthi< 0.5) {
//             depthi = (depthi+depthiPrev)/2.0*b1 + (depthi)*(1.0-b1);
             depthi = (depthiPrev+depthi)/2.0*b1 + (depthi)*(1.0-b1);
        //   }

           vec3 vv = vec3(1.0-depthi); //vec3(1.0-pow(depthi*1.0, 4.0))*2.0;
         //  vv = clamp(vec3(1.0)-pow(vv*0.20, vec3(0.50)), 0.0, 1.0);
           frag.rgb = vv+5.0;

            depthiPrev = depthi;
            levelPrev = level;




            alfPrev = alf;
            cw++;
           }

          // vec3 cp = vec3(gl_FragCoord.x/g_windowWidth-0.5, gl_FragCoord.y/g_windowHeight-0.5, frag.r);

         //  vec3 lp = vec3(0.5, 0.5, 1.0);



//           depthiPrev = depthi;

        }
        if (cw >= 0) {
      //    frag.rgb = clamp(pow(frag.rgb*0.2, vec3(1.0)), 0.0, 10000.0);
        }
        //frag /= float(countPixels);

         //frag = pixels[countPixels-1].color;
       // frag.rg = pixels[0].depthNorm.gb;
       // frag.b = 1.0;

       // frag = vec4(float(countPixels)/8.0, 0.0, 0.0, 1.0);
        // vec4 cc = imageLoad(pixelListColors, listCoord);
        // frag = cc;
//        if (cw > 0) {
                frag.a = 1.0;
//        } else {
            frag.a = 1.0;
 //       }
    } else {
        //frag = vec4(0.0, 0.0, 0.0, 0.0);
        frag.rgb = texture2D(tex, uvS.xy).rgb;

        frag.a = 0.0;
    }


    // frag = vec4(1.0, 0.0, 0.0, 1.0);

   // frag.rgb = pow(frag.rgb, vec3(0.5));

    // frag = screen;
    frag2 = vec4(0.0, 0.0, 0.0, 1.0);
}
