#include "Common.hlsli"
#include "Shared.h"

struct VSOutput
{
  float4 position : SV_POSITION;
  float2 texCoord : TEXCOORD0;
};

Texture2D<float4>   hdrTexture : register(t0);
SamplerState        samp : register(s0);

static const float2 vertices[6] = {
    float2(-1.0, -1.0), float2(-1.0, 1.0), float2(1.0, 1.0), float2(-1.0, -1.0), float2(1.0, 1.0), float2(1.0, -1.0),
};

static const float2 texCoords[6] = {
    float2(0.0, 1.0), float2(0.0, 0.0), float2(1.0, 0.0), float2(0.0, 1.0), float2(1.0, 0.0), float2(1.0, 1.0),
};

VSOutput
VertexMain(uint id : SV_VertexID)
{
  VSOutput output;

  output.position = float4(vertices[id], 0.0f, 1.0f);
  output.texCoord = texCoords[id];

  return output;
}

// https://64.github.io/tonemapping/
float3 ACESToneMap(float3 v) {
  v *= 0.6f;
  float a = 2.51f;
  float b = 0.03f;
  float c = 2.43f;
  float d = 0.59f;
  float e = 0.14f;
  return saturate((v * (a * v + b)) / (v * (c * v + d) + e));
}

// luma weights for Rec.709
static const float3 Luma = float3(0.2126, 0.7152, 0.0722);
float3 ApplyColorCorrection(float3 c, float brightness, float contrast, float saturation) {
  c += brightness;
  c = (c - 0.5) * contrast + 0.5;

  float l = dot(c, Luma);
  c = lerp(float3(l, l, l), c, saturation);
  return c;
}

ConstantBuffer<PostParameters> params : register(b0, space0);

float4
PixelMain(VSOutput input)
    : SV_TARGET
{
  float4 linearPixel = hdrTexture.Sample(samp, input.texCoord);
  float3 color = linearPixel.rgb;

  color *= exp2(params.exposure);
  color = ACESToneMap(color);
  color = ApplyColorCorrection(color, params.brightness, params.constrast, params.saturation);

  // TODO: maybe do FXAA, dither, bloom?

  color = LinearToSRGB(color.rgb);
  color = saturate(color);
  return float4(color, linearPixel.a);
}