
cbuffer _Globals : register(b0)
{
  float2 g_invScreenSize : packoffset(c0);
  float4x4 g_invViewProjMatrix : packoffset(c1);
  float g_indirectCubeMapMipCount : packoffset(c5);
  float4 g_exposureMultipliers : packoffset(c6);
  float4x4 g_cubeMapLocalToBBox : packoffset(c7);
  float3 g_cubeMapExtents : packoffset(c11);
  float3 g_cubeMapFadeDistInverse : packoffset(c12);
  float g_cubeMapScale : packoffset(c12.w);
}
SamplerState g_indirectCubeMapSampler_s : register(s0);
TextureCube<float4> g_indirectCubeMap : register(t0);
Texture2D<float4> g_depthTexture : register(t1);
Texture2D<float4> g_gbufferTexture0 : register(t2);
Texture2D<float4> g_gbufferTexture1 : register(t3);
Texture2D<float4> g_gbufferTexture2 : register(t4);

Texture2D<float4> StereoParams : register(t125);

void main(
  float4 v0 : SV_Position0,
  float4 v1 : TEXCOORD0,
  float4 v2 : TEXCOORD1,
  float4 v3 : TEXCOORD2,
  out float4 o0 : SV_Target0)
{
  float4 r0,r1,r2,r3,r4;
  uint4 bitmask;

//Work out Inverse
//...Variables
float4 a1, a2, a3, a4;
float4 b1, b2, b3, b4;
float det;
//...Original Matrix
a1 = g_invViewProjMatrix._m00_m10_m20_m30;
a2 = g_invViewProjMatrix._m01_m11_m21_m31;
a3 = g_invViewProjMatrix._m02_m12_m22_m32;
a4 = g_invViewProjMatrix._m03_m13_m23_m33;
//...Determinant
det  = a1.x*(a2.y*(a3.z*a4.w - a3.w*a4.z) + a2.z*(a3.w*a4.y - a3.y*a4.w) + a2.w*(a3.y*a4.z - a3.z*a4.y));
det += a1.y*(a2.x*(a3.w*a4.z - a3.z*a4.w) + a2.z*(a3.x*a4.w - a3.w*a4.z) + a2.w*(a3.z*a4.x - a3.x*a4.z));
det += a1.z*(a2.x*(a3.y*a4.w - a3.w*a4.y) + a2.y*(a3.w*a4.x - a3.x*a4.w) + a2.w*(a3.x*a4.y - a3.y*a4.x));
det += a1.w*(a2.x*(a3.z*a4.y - a3.y*a4.z) + a2.y*(a3.x*a4.z - a3.z*a4.x) + a2.z*(a3.y*a4.x - a3.x*a4.y));
//...Inverse Matrix Elements
b1.x = a2.y*(a3.z*a4.w - a3.w*a4.z) + a2.z*(a3.w*a4.y - a3.y*a4.w) + a2.w*(a3.y*a4.z - a3.z*a4.y);
b1.y = a1.y*(a3.w*a4.z - a3.z*a4.w) + a1.z*(a3.y*a4.w - a3.w*a4.y) + a1.w*(a3.z*a4.y - a3.y*a4.z);
b1.z = a1.y*(a2.z*a4.w - a2.w*a4.z) + a1.z*(a2.w*a4.y - a2.y*a4.w) + a1.w*(a2.y*a4.z - a2.z*a4.y);
b1.w = a1.y*(a2.w*a3.z - a2.z*a3.w) + a1.z*(a2.y*a3.w - a2.w*a3.y) + a1.w*(a2.z*a3.y - a2.y*a3.z);
b2.x = a2.x*(a3.w*a4.z - a3.z*a4.w) + a2.z*(a3.x*a4.w - a3.w*a4.x) + a2.w*(a3.z*a4.x - a3.x*a4.z);
b2.y = a1.x*(a3.z*a4.w - a3.w*a4.z) + a1.z*(a3.w*a4.x - a3.x*a4.w) + a1.w*(a3.x*a4.z - a3.z*a4.x);
b2.z = a1.x*(a2.w*a4.z - a2.z*a4.w) + a1.z*(a2.x*a4.w - a2.w*a4.x) + a1.w*(a2.z*a4.x - a2.x*a4.z);
b2.w = a1.x*(a2.z*a3.w - a2.w*a3.z) + a1.z*(a2.w*a3.x - a2.x*a3.w) + a1.w*(a2.x*a3.z - a2.z*a3.x);
b3.x = a2.x*(a3.y*a4.w - a3.w*a4.y) + a2.y*(a3.w*a4.x - a3.x*a4.w) + a2.w*(a3.x*a4.y - a3.y*a4.x);
b3.y = a1.x*(a3.w*a4.y - a3.y*a4.w) + a1.y*(a3.x*a4.w - a3.w*a4.x) + a1.w*(a3.y*a4.x - a3.x*a4.y);
b3.z = a1.x*(a2.y*a4.w - a2.w*a4.y) + a1.y*(a2.w*a4.x - a2.x*a4.w) + a1.w*(a2.x*a4.y - a2.y*a4.x);
b3.w = a1.x*(a2.w*a3.y - a2.y*a3.w) + a1.y*(a2.x*a3.w - a2.w*a3.x) + a1.w*(a2.y*a3.x - a2.x*a3.y);
b4.x = a2.x*(a3.z*a4.y - a3.y*a4.z) + a2.y*(a3.x*a4.z - a3.z*a4.x) + a2.z*(a3.y*a4.x - a3.x*a4.y);
b4.y = a1.x*(a3.y*a4.z - a3.z*a4.y) + a1.y*(a3.z*a4.x - a3.x*a4.z) + a1.z*(a3.x*a4.y - a3.y*a4.x);
b4.z = a1.x*(a2.z*a4.y - a2.y*a4.z) + a1.y*(a2.x*a4.z - a2.z*a4.x) + a1.z*(a2.y*a4.x - a2.x*a4.y);
b4.w = a1.x*(a2.y*a3.z - a2.z*a3.y) + a1.y*(a2.z*a3.x - a2.x*a3.z) + a1.z*(a2.x*a3.y - a2.y*a3.x);
b1.xyzw /= det;
b2.xyzw /= det;
b3.xyzw /= det;
b4.xyzw /= det;
//End Inverse


  r0.xy = g_invScreenSize.xy * v0.xy;
  r1.xy = (int2)v0.xy;
  r1.zw = float2(0.000000e+000,0.000000e+000);
  r2.xyzw = g_gbufferTexture0.Load(r1.xyw).xyzw;
  r3.xyzw = g_gbufferTexture1.Load(r1.xyw).xyzw;
  r0.z = g_gbufferTexture2.Load(r1.xyw).w;
  r1.z = g_depthTexture.Load(r1.xyz).x;
  r2.xyz = r2.xyz * float3(2.000000e+000,2.000000e+000,2.000000e+000) + float3(-1.000000e+000,-1.000000e+000,-1.000000e+000);
  r0.w = dot(r2.xyz, r2.xyz);
  r0.w = rsqrt(r0.w);
  r2.xyz = r2.xyz * r0.www;
  r0.z = 2.550000000e+002 * r0.z;
  r0.z = round(r0.z);
  r0.z = (int)r0.z;
  r3.xyzw = r3.xyzw * r3.xyzw;
  r0.w = r0.z == 5;
  if (r0.w == 0) {
    r0.z = r0.z == 1;
    if (r0.z != 0) {
      r3.xyz = r3.www * r3.xyz;
    } else {
      r3.xyz = r3.www;
    }
  }
  r0.z = 0.000000000e+000 < r3.x;
  r0.z = r0.z ? r2.w : 0;
  r0.xy = r0.xy * float2(2.000000e+000,2.000000e+000) + float2(-1.000000e+000,-1.000000e+000);
  r1.xy = float2(1.000000e+000,-1.000000e+000) * r0.xy;
  r1.w = 1.000000000e+000;
  r4.x = dot(r1.xyzw, g_invViewProjMatrix._m00_m10_m20_m30);
  r4.y = dot(r1.xyzw, g_invViewProjMatrix._m01_m11_m21_m31);
  r4.z = dot(r1.xyzw, g_invViewProjMatrix._m02_m12_m22_m32);
  r0.x = dot(r1.xyzw, g_invViewProjMatrix._m03_m13_m23_m33);
  r0.x = 1.000000e+000 / r0.x;


float4 r28, r26, r27;
r26.xyz = r4.xyz * r0.xxx;
r26.w = 1.0;
r28.x = dot(r26.xyzw, b1.xyzw);
r28.y = dot(r26.xyzw, b2.xyzw);
r28.z = dot(r26.xyzw, b3.xyzw);
r28.w = dot(r26.xyzw, b4.xyzw);
float4 stereo = StereoParams.Load(0);
r28.x -= stereo.x * (r28.w - stereo.y); 
r26.x = dot(r28.xyzw, a1.xyzw);
r26.y = dot(r28.xyzw, a2.xyzw);
r26.z = dot(r28.xyzw, a3.xyzw);
r26.w = dot(r28.xyzw, a4.xyzw);
r4.xyz = r26.xyz / r0.xxx;

  r0.xyw = r4.xyz * r0.xxx;


  r1.xyz = g_cubeMapLocalToBBox._m01_m11_m21 * r0.yyy;
  r1.xyz = g_cubeMapLocalToBBox._m00_m10_m20 * r0.xxx + r1.xyz;
  r1.xyz = g_cubeMapLocalToBBox._m02_m12_m22 * r0.www + r1.xyz;
  r1.xyz = g_cubeMapLocalToBBox._m03_m13_m23 + r1.xyz;
  r4.xyz = -g_cubeMapExtents.xyz + abs(r1.xyz);
  r4.xyz = saturate(-r4.xyz * g_cubeMapFadeDistInverse.xyz + float3(1.000000e+000,1.000000e+000,1.000000e+000));
  r1.w = min(r4.y, r4.x);
  r1.w = min(r4.z, r1.w);
  r2.w = dot(r0.xyw, r0.xyw);
  r2.w = rsqrt(r2.w);
  r0.xyw = r2.www * r0.xyw;
  r2.w = dot(r0.xyw, r2.xyz);
  r2.w = r2.w + r2.w;
  r0.xyw = r2.xyz * -r2.www + r0.xyw;
  r2.xy = g_cubeMapExtents.xz + -r1.xz;
  r2.zw = -g_cubeMapExtents.xz + -r1.xz;
  r4.xy = float2(0.000000e+000,0.000000e+000) < r0.xw;
  r2.xy = r4.xy ? r2.xy : r2.zw;
  r2.xy = r2.xy / r0.xw;
  r2.x = min(r2.y, r2.x);
  r0.xyw = r0.xyw * r2.xxx + r1.xyz;
  r1.x = g_indirectCubeMapMipCount;
  r1.y = trunc(g_indirectCubeMapMipCount);
  r0.z = -r0.z * 1.500000000e+001 + r1.y;
  r0.z = 5.000000000e+000 + r0.z;
  r1.x = (int)r1.x + -1;
  r1.x = r1.x;
  r0.z = max(r0.z, 0.000000000e+000);
  r0.z = min(r1.x, r0.z);
  r0.xyz = g_indirectCubeMap.SampleLevel(g_indirectCubeMapSampler_s, r0.xyw, r0.z).xyz;
  r0.xyz = r0.xyz * r3.xyz;
  r0.xyz = r0.xyz * r1.www;
  o0.xyz = g_cubeMapScale * r0.xyz;
  o0.w = 0.000000000e+000;
  return;
}
