#version 430

// layout (location=0) in vec3 vertexPosition;

out vec2 uv;
out float br;

out vec2 puv;

// out float foc;

out vec3 pw;
out vec3 pv;

//out float targetLayer;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionInvMatrix;
uniform float g_windowWidth;
uniform float g_windowHeight;

uniform float g_time;

uniform float size = 32.0;
uniform float rot;

vec2 rot2(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;
}

float zn = 0.0;
float zf = 1.0;


vec4 CalcEyeFromWindow(in vec3 windowSpace) {
    vec3 ndcPos;
    vec4 viewport = vec4(0.0, 0.0, g_windowWidth, g_windowHeight);
    ndcPos.xy = ((2.0 * windowSpace.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1;
    ndcPos.z = (2.0 * windowSpace.z - zn - zf) / (zf - zn);
    vec4 clipPos;
    clipPos.w = projectionMatrix[3][2]/(ndcPos.z-(projectionMatrix[2][2]/projectionMatrix[2][3]));
    clipPos.xyz = ndcPos * clipPos.w;
    return projectionInvMatrix * clipPos;
}

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

layout(binding=3, rgba32f) uniform image2D pardexAge;
// layout(binding=1, r32i) uniform iimage2D pardexTransmittance;


uniform float drawSize = 1.0;
uniform float simMode = 0.0;


ivec2 getTrip(int idt) {
    ivec2 triBufSize = imageSize(pardexPos)/2;
    ivec2 trip;
    trip.y = idt/triBufSize.x;
    trip.x = idt-trip.y*triBufSize.x;
   // trip.y = 0;
    return trip;
}

uniform float shadowZOfs = -150.0;
uniform float shadowZScale = -5.0;

uniform float baseDim = 16.0;


void main() {
  vec4 vp = vec4(0.0);

  float id = float(gl_VertexID);

  float id3 = fract(id/3.0)*3.0; // index of the vertex in a triangle 0,1,2
  float idv = floor((id/3.0-fract(id/3.0))+0.5); // triangle index 0,1,2,3,...
  float idv2 = fract(idv/2.0)*2.0; // every second triangle 0 and 1
  float idq = floor((id/6.0-fract(id/6.0))+0.5); // quad index 0,1,2,3,...

  if (idv2 < 0.5) {
      if (id3 < 0.50) {
          vp = vec4(0.0, 0.0, 0.0, 1.0);
      } else if (id3 < 1.5) {
          vp = vec4(1.0, 0.0, 0.0, 1.0);
      } else if (id3 < 2.5) {
          vp = vec4(0.0, 1.0, 0.0, 1.0);
      }
  } else {
      if (id3 < 0.50) {
          vp = vec4(1.0, 0.0, 0.0, 1.0);
      } else if (id3 < 1.5) {
          vp = vec4(1.0, 1.0, 0.0, 1.0);
      } else if (id3 < 2.5) {
          vp = vec4(0.0, 1.0, 0.0, 1.0);
      }
  }
  puv = vp.xy;

//  int qi = int(idq);
//  qi = imageLoad(pardexOfs, getTrip(qi)).x;
  int qi = int(idq);

 // float size = 1.0-smoothstep(0.0, 1.0, float(qi)*0.0015);
  float size = 0.0;

  vp.xy -= vec2(0.50);
  vp.xyz *= drawSize*(1.0+size*6.0);

  vec4 vpo = vp;

  vp.xzy = vp.xyz;

  vec4 pp = imageLoad(pardexPos, getTrip(qi));

  float ageLeft = imageLoad(pardexAge, getTrip(qi)).x;


  vp.xyz += pp.xyz;

 // uv = vec2(pp.xy)*0.01;
  float qit = -qi*1.0;
//  float ne = -200.0;
  uv = vec2((qit)*0.01, (qit)*0.02);


 // uv = vec2(vp.xz)*0.010;

//  foc = clamp(abs(pp.y)-30.0, 0.0, 100000.0);


  pw = pp.xyz;

  vp = viewMatrix*vec4(vp.xyz, 1.0);

  pv = vp.xyz;

  vp = projectionMatrix*vp;

//  vp = vp3d;

 // vp /= vp.w;

 // vp.x += idv*0.11;
 // vp.x += sin(idq*0.1);
 // vp.y += cos(idq*0.112);

 // uint counter = atomicCounterIncrement(ac);

 // br = float(counter)*0.0001;
 // br = 0.70-pp.z*0.1;
  br = 1.0-size;


  vp = viewMatrix*vec4(pp.xyz, 1.0);
  vec3 pvLev = vp.xyz;
  vp.xyz += vpo.xyz;
  vp = projectionMatrix*vp;

  int baseDimi = int(baseDim);

  int zLevel = int(shadowZOfs+pvLev.z*shadowZScale);
  zLevel = clamp(zLevel, 0, baseDimi*baseDimi-1);
  int zLevelY = zLevel/baseDimi;
  int zLevelX = zLevel-zLevelY*baseDimi;
  ivec2 zLevel2 = ivec2(zLevelX, zLevelY);

//  targetLayer = zLevel;
  //

  vp /= vp.w;

  vp.xy *= vec2(1.0/baseDim);
  vp.xy += vec2(-1.0+1.0/baseDim);
  vp.xy += 2.0*vec2(zLevel2)/baseDim;


  if (ageLeft <= 0.0 && simMode > 0.5) {
      vp.xyz *= 0.0;
  }

 // vp.xyz *= 0.0;


  gl_Position = vp;



  //vp /= vp.w;
//  vpoo = vec2(vp.xy);

}
