//Shadows
// ---- Created with 3Dmigoto v1.2.56 on Wed May 24 00:15:47 2017

cbuffer _Globals : register(b0)
{
  float4 ShadowProperties : packoffset(c0);
  float4 LightProperties : packoffset(c1);
  float4 ShadowFarPlanes : packoffset(c2);
  float4 ShadowFrustumWidths : packoffset(c3);
  row_major float4x4 ProjectionMatrix[4] : packoffset(c4);
}

Texture2D<float4> LinearDepth : register(t0);
Texture2D<float4> Shadow : register(t1);


// 3Dmigoto declarations
#define cmp -
Texture1D<float4> IniParams : register(t120);
Texture2D<float4> StereoParams : register(t125);

#include <ShaderFixes/matrix.hlsl>

void main( 
  float4 v0 : SV_Position0,
  float3 v1 : TexCoord0,
  float3 v2 : TexCoord1,
  out float4 o0 : SV_Target0)
{
  const float4 icb[] = { { 1.000000, 0, 0, 0},
                              { 0, 1.000000, 0, 0},
                              { 0, 0, 1.000000, 0},
                              { 0, 0, 0, 1.000000},
                              { 0, 0, 0.500000, 0.500000},
                              { 0, 0.500000, 0.500000, 1.000000},
                              { 0.500000, 0, 1.000000, 0.500000},
                              { 0.500000, 0.500000, 1.000000, 1.000000},
                              { 1.000000, 0, 0, 0},
                              { 1.000000, 1.000000, 0, 0},
                              { 0, 1.000000, 0, 0},
                              { 0, 0, 1.000000, 0} };
  float4 r0,r1,r2,r3,r4,r5,r6;
  uint4 bitmask, uiDest;
  float4 fDest;

  r0.xy = (int2)v0.xy;
  r0.zw = float2(0,0);
  r1.x = LinearDepth.Load(r0.xyw).x;
  r1.xyz = r1.xxx * v1.xyz + v2.xyz;
  r2.x = ShadowProperties.x * ShadowProperties.y;
  r2.x = (int)r2.x;
  r3.xyzw = float4(2,2,2,2) / ShadowProperties.xyxy;
  r2.y = (int)r2.x + -1;
  r1.w = 1;
  r4.xyz = float3(1,1,1);
  r2.z = 0;
  
//CORRECT WORLD COORD
float4 s = StereoParams.Load(0);
float4 r20, r21;
r1.w = 1;
r21 = mul(global_ViewProjection, r1);  
r21.x -= s.x * (r21.w - s.y); 
r1 = mul(inverse(global_ViewProjection), r21);
  
  while (true) {
    r2.w = cmp((int)r2.z >= (int)r2.x);
    if (r2.w != 0) break;
    r2.w = (uint)r2.z << 2;
    r5.x = dot(ProjectionMatrix[r2.w/4]._m00_m01_m02_m03, r1.xyzw);
    r5.y = dot(ProjectionMatrix[r2.w/4]._m10_m11_m12_m13, r1.xyzw);
    r5.z = dot(ProjectionMatrix[r2.w/4]._m20_m21_m22_m23, r1.xyzw);
    r4.w = dot(ProjectionMatrix[r2.w/4]._m30_m31_m32_m33, r1.xyzw);
    r5.xyz = r5.xyz / r4.www;
    r6.xy = icb[r2.z+4].xy * r3.zw;
    r4.w = dot(ShadowFrustumWidths.xyzw, icb[r2.z+0].xyzw);
    r4.w = LightProperties.z * r4.w;
    r4.w = 0.5 * r4.w;
    r5.xy = -icb[r2.z+4].xy * r3.zw + r5.xy;
    r6.xy = icb[r2.z+4].zw * r3.zw + -r6.xy;
    r5.xy = saturate(r5.xy / r6.xy);
    r5.xy = r5.xy * float2(2,2) + float2(-1,-1);
    r5.xy = float2(1,1) + -abs(r5.xy);
    r5.xy = saturate(r5.xy / LightProperties.zz);
    r5.z = saturate(1 + -r5.z);
    r5.w = dot(ShadowFarPlanes.xyzw, icb[r2.z+0].xyzw);
    r5.z = r5.z * r5.w;
    r4.w = saturate(r5.z / r4.w);
    r5.x = r5.x * r5.y;
    r5.y = r5.x * r4.w;
    r5.z = cmp(0 < r5.y);
    if (r5.z != 0) {
      r4.xyz = icb[r2.z+8].xyz * r5.yyy;
      r5.z = cmp(r5.y < 1);
      r5.w = cmp((int)r2.z < (int)r2.y);
      r5.z = r5.w ? r5.z : 0;
      if (r5.z != 0) {
        r2.w = (int)r2.w + 4;
        r6.x = dot(ProjectionMatrix[r2.w/4]._m00_m01_m02_m03, r1.xyzw);
        r6.y = dot(ProjectionMatrix[r2.w/4]._m10_m11_m12_m13, r1.xyzw);
        r6.z = dot(ProjectionMatrix[r2.w/4]._m20_m21_m22_m23, r1.xyzw);
        r2.w = dot(ProjectionMatrix[r2.w/4]._m30_m31_m32_m33, r1.xyzw);
        r6.xyz = r6.xyz / r2.www;
        r2.w = (int)r2.z + 1;
        r5.zw = icb[r2.w+4].xy * r3.xy;
        r6.w = dot(ShadowFrustumWidths.xyzw, icb[r2.w+0].xyzw);
        r6.w = LightProperties.z * r6.w;
        r6.w = 0.5 * r6.w;
        r6.xy = -icb[r2.w+4].xy * r3.xy + r6.xy;
        r5.zw = icb[r2.w+4].zw * r3.zw + -r5.zw;
        r5.zw = saturate(r6.xy / r5.zw);
        r5.zw = r5.zw * float2(2,2) + float2(-1,-1);
        r5.zw = float2(1,1) + -abs(r5.zw);
        r5.zw = saturate(r5.zw / LightProperties.zz);
        r6.x = saturate(1 + -r6.z);
        r6.y = dot(ShadowFarPlanes.xyzw, icb[r2.w+0].xyzw);
        r6.x = r6.x * r6.y;
        r6.x = saturate(r6.x / r6.w);
        r5.z = r5.z * r5.w;
        r5.z = r5.z * r6.x;
        r5.z = cmp(0 < r5.z);
        if (r5.z != 0) {
          r5.z = -r5.x * r4.w + 1;
          r4.xyz = r5.zzz * icb[r2.w+8].xyz + r4.xyz;
        }
      } else {
        r2.w = -r5.x * r4.w + 1;
        r4.xyz = icb[r2.z+8].xyz * r5.yyy + r2.www;
      }
      break;
    }
    r2.z = (int)r2.z + 1;
    r4.xyz = float3(1,1,1);
  }
  r0.x = Shadow.Load(r0.xyz).x;
  r0.xyz = r4.xyz * r0.xxx;
  r0.xyz = float3(0.699999988,0.699999988,0.699999988) * r0.xyz;
  o0.xyz = r4.xyz * float3(0.300000012,0.300000012,0.300000012) + r0.xyz;
  o0.w = 1;
  return;
}