#version 300 es

// From rcupisz light shafts package, "Coords" shader.
// Is using vector equality, which was translating wrong to Metal
// at some point.

#define gl_FragColor _glesFragData[0]
#define gl_FragData _glesFragData
layout(location = 0) out mediump vec4 _glesFragData[4];
float xll_saturate_f( float x) {
  return clamp( x, 0.0, 1.0);
}
vec4 xll_matrixindex_mf4x4_i (mat4 m, int i) { vec4 v; v.x=m[0][i]; v.y=m[1][i]; v.z=m[2][i]; v.w=m[3][i]; return v; }
struct posuv {
    highp vec4 pos;
    highp vec2 uv;
};
uniform highp vec4 _ZBufferParams;
uniform highp vec4 _LightPos;
uniform highp float _InterpolationStep;
uniform highp mat4 _FrustumRays;
uniform highp vec4 _CameraPosLocal;
uniform highp float _FrustumApex;
uniform highp vec4 _CoordTexDim;
uniform highp vec4 _ScreenTexDim;
uniform sampler2D _CameraDepthTexture;

highp vec2 GetEpipolarLineEntryPoint( in highp vec2 exit ) {
    return _LightPos.xy;
}

bool Cube( in highp vec3 org, in highp vec3 dir, out highp float tnear, out highp float tfar ) {
    highp vec3 invR = (1.0 / dir);
    highp vec3 tbot = (invR * (-0.5 - org));
    highp vec3 ttop = (invR * (0.5 - org));
    highp vec3 tmin = min( ttop, tbot);
    highp vec3 tmax = max( ttop, tbot);
    highp vec2 t0 = max( tmin.xx, tmin.yz);
    tnear = max( t0.x, t0.y);
    t0 = min( tmax.xx, tmax.yz);
    tfar = min( t0.x, t0.y);
    return ((tnear < tfar) && (tfar > 0.0));
}
highp vec3 FrustumRay( in highp vec2 uv, out highp float rayLength ) {
    highp vec3 ray0 = mix( xll_matrixindex_mf4x4_i (_FrustumRays, 0).xyz, xll_matrixindex_mf4x4_i (_FrustumRays, 1).xyz, vec3( uv.x));
    highp vec3 ray1 = mix( xll_matrixindex_mf4x4_i (_FrustumRays, 3).xyz, xll_matrixindex_mf4x4_i (_FrustumRays, 2).xyz, vec3( uv.x));
    highp vec3 ray = mix( ray0, ray1, vec3( uv.y));
    rayLength = length(ray);
    return (ray / rayLength);
}
bool IntersectVolume( in highp vec2 uv, out highp float near, out highp float far, out highp vec3 rayN, out highp float rayLength ) {
    rayN = FrustumRay( uv, rayLength);
    return Cube( _CameraPosLocal.xyz, rayN, near, far);
}
highp float Linear01Depth( in highp float z ) {
    return (1.0 / ((_ZBufferParams.x * z) + _ZBufferParams.y));
}
void frag( in posuv i, out highp vec4 coord, out highp vec4 depth ) {
    highp vec2 uv = i.uv;
    highp float sampleOnEpipolarLine = (uv.x - (0.5 / _CoordTexDim.x));
    highp float epipolarLine = xll_saturate_f((uv.y - (0.5 / _CoordTexDim.y)));
    sampleOnEpipolarLine *= (_CoordTexDim.x / (_CoordTexDim.x - 1.0));
    sampleOnEpipolarLine = xll_saturate_f(sampleOnEpipolarLine);
    highp int edge = int(clamp( floor((epipolarLine * 4.0)), 0.0, 3.0));
    highp float posOnEdge = fract((epipolarLine * 4.0));
    highp float edgeCoord = (-1.0 + (2.0 * posOnEdge));
    highp vec4 edgeX = vec4( -1.0, edgeCoord, 1.0, (-edgeCoord));
    highp vec4 edgeY = vec4( (-edgeCoord), -1.0, edgeCoord, 1.0);
    bvec4 edgeFlags = equal( ivec4( edge), ivec4( 0, 1, 2, 3));
    highp vec2 exit = (-vec2( dot( edgeY, vec4(edgeFlags)), dot( edgeX, vec4(edgeFlags))));
    highp vec2 entry = GetEpipolarLineEntryPoint( exit);
    highp vec2 coordTemp = mix( entry, exit, vec2( sampleOnEpipolarLine));
    coordTemp = ((coordTemp * 0.5) + 0.5);
    coord = vec4( coordTemp.x, coordTemp.y, 0.0, 0.0);
    coordTemp = ((floor((coordTemp * _ScreenTexDim.xy)) + 0.5) * _ScreenTexDim.zw);
    depth = vec4( Linear01Depth( texture( _CameraDepthTexture, coordTemp).x));
    highp float near;
    highp float far;
    highp float rayLength;
    highp vec3 rayN;
    if (((!IntersectVolume( coord.xy, near, far, rayN, rayLength)) || (depth.x < (near / rayLength)))){
        depth *= -1.0;
    }
    else{
        depth = min( depth, vec4( (far / rayLength)));
    }
}
in highp vec2 xlv_TEXCOORD0;
void main() {
    posuv xlt_i;
    xlt_i.pos = vec4(0.0);
    xlt_i.uv = vec2(xlv_TEXCOORD0);
    highp vec4 xlt_coord;
    highp vec4 xlt_depth;
    frag( xlt_i, xlt_coord, xlt_depth);
    gl_FragData[0] = vec4(xlt_coord);
    gl_FragData[1] = vec4(xlt_depth);
}
