#include "common.inc"

#define GBUFFER_BASIC_SINGLE  1
#define GBUFFER_DUAL          2
#define GBUFFER_SINGLE        3

#ifdef VS

  layout ( location = 0 ) in float4 aPosition;

  #if defined(USE_BINDING)
  layout( binding = VSCB0Index, std140 ) uniform VSCB0
  #else
  layout (std140) uniform VSCB0
  #endif
  {
    float4x4 g_matViewVS;
    float4x4 matInvViewVS;
    float4x4 g_matViewProjectionVS;
    float4x4 g_InvViewProjVS;
    float4   taragetSizeInvSizeVS;
    float4   cameraPositionVS;
    float    timeVS;
    float    timeDeltaVS;
    float2   clipPlanesVS;
    float4   depthEncodeConstsVS;

    float4   fogParametersVS;
    float4   fogParameters2VS;
    float4   distanceFogVS;
    float4   heightFogVS;
  
    float2   depthDecodingHelperVS; //.x = (farZ / (farZ - nearZ)); .y = (-farZ * nearZ) / (farZ - nearZ);
    float2   dummyGCVS;
  };
  
  #if defined(USE_BINDING)
  layout( binding = VSCB1Index, std140 ) uniform VSCB1
  #else
  layout (std140) uniform VSCB1
  #endif
  {
    float4x4 g_DecalMatrix;
  };

  out float4 vPosCS;
  out float4 vPosES;


  void main()
  {
    float4 positionWS = float4( aPosition.xyz, 1.f ) * g_DecalMatrix;
    float4 positionES = positionWS * g_matViewVS;
    float4 positionCS = positionWS * g_matViewProjectionVS;
    
    gl_Position = positionCS;
    vPosCS = positionCS;
    vPosES = positionES;
  }

#endif //VS

#ifdef PS
  layout ( location = 0 ) out float4 FragColor;

  in float4 vPosCS;
  in float4 vPosES;

  #if defined(USE_BINDING)
  layout( binding = 0 ) uniform sampler2D gbuffer0;
  layout( binding = 2 ) uniform sampler2D diffuseTexture;
  #else
  uniform sampler2D gbuffer0;
  uniform sampler2D diffuseTexture;
  #endif
  
  #if GBUFFERTYPE == GBUFFER_DUAL
    #if defined(USE_BINDING)
    layout( binding = 1 ) uniform sampler2D gbuffer1;
	#else
	uniform sampler2D gbuffer1;
	#endif
  #endif
  
  #if GBUFFERTYPE == GBUFFER_SINGLE
    #if defined(USE_BINDING)
    layout( binding = 3 ) uniform sampler2D sDepthBuffer;
	#else
	uniform sampler2D sDepthBuffer;
	#endif
  #endif

  #if defined(USE_BINDING)
  layout( binding = PSCB0Index, std140 ) uniform PSCB0
  #else
  layout (std140) uniform PSCB0
  #endif
  {
    float4x4 g_matView;
    float4x4 matInvView;
    float4x4 g_matViewProjection;
    float4x4 g_InvViewProj;
    float4   taragetSizeInvSize;
    float4   cameraPosition;
    float    time;
    float    timeDelta;
    float2   clipPlanes;
    float4   depthEncodeConsts;

    float4   fogParameters;
    float4   fogParameters2;
    float4   distanceFog;
    float4   heightFog;
  
    float2   depthDecodingHelper; //.x = (farZ / (farZ - nearZ)); .y = (-farZ * nearZ) / (farZ - nearZ);
    float2   dummyGC;
  };
  
  #if defined(USE_BINDING)
  layout( binding = PSCB1Index, std140 ) uniform PSCB1
  #else
  layout (std140) uniform PSCB1
  #endif
  {
    float4x4  g_invDecalMatrix;
    float4    g_DecalColor; 
    float3    g_DecalPos;
    float     g_Height;
  };


  void main()
  {
    float4 projCS = vPosCS / vPosCS.wwww;

    float2 screenCoords = projCS.xy * float2(0.5, 0.5) + float2(0.5, 0.5);

  #if GBUFFERTYPE == GBUFFER_SINGLE  

    float depth = texture( sDepthBuffer, screenCoords ).x * 2.0 - 1.0;
    float4 positionWS = float4( projCS.x, projCS.y, depth, 1.f ) * g_InvViewProj;
    positionWS /= positionWS.w;

  #else

    float depth = 1;
    
    #if GBUFFERTYPE == GBUFFER_BASIC_SINGLE  
        depth = dot(texture( gbuffer0, screenCoords ).zw, DepthDecodingConsts.xy);
    #elif GBUFFERTYPE == GBUFFER_DUAL  
        depth = dot(texture( gbuffer1, screenCoords ).xy, DepthDecodingConsts.xy);
    #endif
   
    // Get Position in View Space
    float   temp  = depth / vPosES.z;
    float3  positionES  = vPosES.xyz * temp;

  #endif

    // Multiply by View inverse followed by decal
    float4 positionDS = float4( positionWS.xyz, 1.0 ) * g_invDecalMatrix;

    float2 uv = (positionDS.xy);
    uv.y =1-uv.y;

    const float clipEpsilon = 0.00002;

    float testA = min( uv.x, uv.y );
    float testB = min( 1.0 - uv.x, 1.0 - uv.y );
    float test  = min( testA, testB );

    clip(test);
    
    float4 tex = texture( diffuseTexture, uv );

    float alpha = g_DecalColor.a;

    //calculate height alpha
    float3 pos = positionDS.xyz - g_DecalPos.xyz;

    alpha *= 1 - saturate(abs( positionDS.z * g_Height ) );
    
    float4 final = tex * g_DecalColor;
    final.a = tex.a * alpha;

  #if ALPHA_COLOUR_MOD
    //for additive or substractive blend modes
    final.xyz *= final.w;
  #endif

    clip( final.a - 0.01f );

    FragColor = final;
  }

#endif //PS
