#pragma language glsl3
#ifdef VERTEX
vec4 position(mat4 transform_projection, vec4 vertex_position) {return transform_projection * vertex_position; }
#endif
#ifdef PIXEL
#define BOUNCES 4
uniform sampler2D gbuffer_diffuse;
uniform sampler2D gbuffer_position;
uniform sampler2D gbuffer_normal;
uniform sampler2D triangles;
uniform int numTris;
// uniform vec3 skyColor;
uniform vec3 ambientColor;
uniform int size = 256;
uniform float time = 100;
vec3 intersectPlane(vec3 origin, vec3 direction, vec3 p0, vec3 p1, vec3 p2)
{
    vec3 D = direction;
    vec3 N = cross(p1-p0, p2-p0);
    vec3 X = origin + D * dot(p0 - origin, N) / dot(D, N);

    return X;
}
float pointInOrOn( vec3 P1, vec3 P2, vec3 A, vec3 B )
{
    vec3 CP1 = cross(B - A, P1 - A);
    vec3 CP2 = cross(B - A, P2 - A);
    return step(0.0, dot(CP1, CP2));
}

float pointInTriangle( vec3 px, vec3 p0, vec3 p1, vec3 p2 )
{
    return 
        pointInOrOn(px, p0, p1, p2) *
        pointInOrOn(px, p1, p2, p0) *
        pointInOrOn(px, p2, p0, p1);
}
vec4 noise(vec4 p4) {
  p4 = fract(p4 * vec4(443.897, 441.423, 437.195, 444.129));
  p4 += dot(p4, p4.wzxy + vec4(19.19));
  return fract((p4.xxyz + p4.yzzw) * p4.zywx);
}
ivec2 getPixel (int index)
{
  return ivec2(mod(index,size), floor(index/size)*9);
}

vec4 effect(vec4 col, sampler2D gbuffer_light, vec2 textureCoords, vec2 screen_coords) {
  vec2 coord = screen_coords / love_ScreenSize.xy;
  vec4 g_diffuse = Texel(gbuffer_diffuse, coord);
  vec4 g_position = Texel(gbuffer_position, coord);
  vec3 g_normal= Texel(gbuffer_normal,   coord).xyz*2-vec3(1);
  vec3 position[3],normal[3],color[3];
  if (g_position.a==0){
    // discard;
    // return vec4(pow(ambientColor,vec3(2.2)),1);
    return vec4(1);
  }

  vec3 direction = normalize(noise(g_position*sin(time)).xyz*2-1);
  vec3 origin = g_position.xyz+g_normal;
  direction = dot(direction,g_normal)>0 ? direction : -direction;


  vec3 result = g_diffuse.rgb;//vec3(1,1,1);
  for (int b = 0; b <= BOUNCES; b++){
    float t = 99999999;
    vec3 intP=vec3(0);
    int intT = -1;
    for (int i = 0; i < numTris; i++){
      ivec2 pixel = getPixel(i);
      vec4 v0 = texelFetch(triangles,ivec2(pixel.x,pixel.y+0),0);
      vec4 v1 = texelFetch(triangles,ivec2(pixel.x,pixel.y+1),0);
      vec4 v2 = texelFetch(triangles,ivec2(pixel.x,pixel.y+2),0);
      vec3 e0 = v1.xyz - v0.xyz;
      vec3 e1 = v2.xyz - v0.xyz;
      vec3 pv = cross(direction, e1);
      float det = dot(e0, pv);

      vec3 tv = origin - v0.xyz;
      vec3 qv = cross(tv, e0);

      vec4 uvt;
      uvt.x = dot(tv, pv);
      uvt.y = dot(direction, qv);
      uvt.z = dot(e1, qv);
      uvt.xyz = uvt.xyz / det;
      uvt.w = 1.0 - uvt.x - uvt.y;

      if (all(greaterThanEqual(uvt, vec4(0.0))) && uvt.z < t)
      {
        t = uvt.z;
        intP = origin + t*direction;
        intT = i;
      }
    }

    if (intT>-1) {
      if (b==BOUNCES){
        return vec4(0,0,0,1); 
      }
      ivec2 pixel = getPixel(intT);
      color    = vec3[3](
        texelFetch(triangles,ivec2(pixel.x,pixel.y+3),0).xyz,
        texelFetch(triangles,ivec2(pixel.x,pixel.y+4),0).xyz,
        texelFetch(triangles,ivec2(pixel.x,pixel.y+5),0).xyz
      );
      normal   = vec3[3](
        texelFetch(triangles,ivec2(pixel.x,pixel.y+6),0).xyz,
        texelFetch(triangles,ivec2(pixel.x,pixel.y+7),0).xyz,
        texelFetch(triangles,ivec2(pixel.x,pixel.y+8),0).xyz
      );

      if  (dot(normal[1],vec3(0,1,0))>0.9 ){
        return vec4((result * color[1]*20),1);
      }
      result *= color[1];

      origin = intP+normalize(normal[1]);
      direction = normalize(noise(vec4(origin+g_position.xyz,sin(t+time))).xyz*2-1);
      direction = dot(direction,normal[1])>0 ? direction : -direction;
      //normal[1];// temp //random_in_hemisphere(tempNormal);
    }else{
      result*=ambientColor;
      break;
    }
  }

  return vec4(result,1);
}

#endif
