#[compute]
#version 450

float clamp01( float value )
{
  return clamp( value, 0.0, 1.0 );
}

float normalizeToRange( float value, float min, float max )
{
  return ( value - min ) / ( max - min );
}

float normalizeToRange01( float value, float min, float max )
{
  return clamp01( normalizeToRange( value, min, max ) ); 
}

float map( float value, float inMin, float inMax, float outMin, float outMax )
{
  return mix( outMin, outMax, normalizeToRange( value, inMin, inMax ) );
}

float mapClamped( float value, float inMin, float inMax, float outMin, float outMax )
{
  return mix( outMin, outMax, normalizeToRange01( value, inMin, inMax ) );
}

layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in;

layout( set = 0, binding = 0 ) 
uniform sampler2D inputImage;

layout( rgba16, set = 1, binding = 0 ) 
uniform restrict writeonly image2D outputImage;

layout( push_constant, std430 ) 
uniform Parameters 
{
  float lumaWeightR;
  float lumaWeightG;
  float lumaWeightB;
  float lumaPower;

  float inputRangeMin;
  float inputRangeMax;
  float normalizationPower;
  float outputRangeMin;

  float outputRangeMax;
  float desaturation;
  float tintR;
  float tintG;

  float tintB;
  float p0;
  float p1;
  float p2;

} parameters;

void main() 
{
  ivec2 size = imageSize( outputImage );
	ivec2 xy = ivec2( gl_GlobalInvocationID.xy );

  if ( any( greaterThanEqual( xy, size ) )  ) 
  {
    return;
  }

  vec2 uv = ( vec2( xy ) + vec2( 0.5 ) ) / vec2( size ); 

  
	vec4 color = textureLod( inputImage, uv, 0 );  

  vec3 lumaWeight = vec3( parameters.lumaWeightR, parameters.lumaWeightG, parameters.lumaWeightB );
  float luma = pow( dot( lumaWeight, color.rgb ), parameters.lumaPower );
  
  luma = normalizeToRange01( luma, parameters.inputRangeMin, parameters.inputRangeMax );
  luma = pow( luma, parameters.normalizationPower );
  luma = mix( parameters.outputRangeMin, parameters.outputRangeMax, luma );

  color.rgb = mix( color.rgb, vec3( dot( color.rgb, vec3( 1.0/3.0 ) ) ), parameters.desaturation );  
  
  color.rgb = normalize( color.rgb );
  color.rgb = color.rgb * luma * vec3( parameters.tintR, parameters.tintG, parameters.tintB );

	imageStore( outputImage, xy, color );
}
