/* Shader for gamma correction of RGB and Luminance textures.
 * Uses extended formula for gamma correction:
 * out = bias + gain * ( ( (in - Lmin) / (Lmax - Lmin) ) ^ Gamma ).
 * 'Gamma' is the factor to apply, ie. the inverse gamma 1/G,
 * if applying correction for a display with gamma G.
 * 'in' is the input value (e.g., luminance), Lmin and Lmax are the expected
 * minimum and maximum values for 'in', 'gain' is a gain to post-multiply,
 * 'bias' is an offset to add to the final result.
 *
 * This shader is used by PsychColorCorrection() in 'SimpleGammaXXX' mode,
 * as part of PTB's built-in stimulus gamma correction.
 *
 * (w)2008, 2009 by Mario Kleiner. Licensed under MIT license.
*/

/* (RedGamma, GreenGamma, BlueGamma) vector of encoding gammas: */
/* To be initialized by PsychColorCorrection() typically: */
uniform vec3    ICMEncodingGamma;
uniform vec3    ICMMinInLuminance;
uniform vec3    ICMMaxInLuminance;
uniform vec3    ICMReciprocalLuminanceRange;
uniform vec3    ICMOutputGain;
uniform vec3    ICMOutputBias;

/* Allowable range for output values: To be initialized by PsychColorCorrection() typically: */
uniform vec2    ICMClampToColorRange;

vec4 icmTransformColor(vec4 incolor)
{
    vec4 outcolor;

    /* Return alpha component unmodified: */
    outcolor.a = incolor.a;

    /* Clamp input to valid [ICMMinInLuminance ; ICMMaxInLuminance] range: */
    incolor.rgb = clamp(incolor.rgb, ICMMinInLuminance, ICMMaxInLuminance);

    /* Convert clamped input to normalized 0-1 interval: */
    incolor.rgb = (incolor.rgb - ICMMinInLuminance) * ICMReciprocalLuminanceRange;

    /* Map RGB components through power function with Gamma coeff.: */
    outcolor.rgb = (pow(incolor.rgb, ICMEncodingGamma) * ICMOutputGain) + ICMOutputBias;

    /* Clamp outcolor to range given by ICMClampToColorRange: */
    outcolor.rgb = clamp(outcolor.rgb, vec3(ICMClampToColorRange[0]), vec3(ICMClampToColorRange[1]));

    return(outcolor);
}


float icmTransformColor1(float incolor)
{
    float outcolor;

    /* Clamp input to valid [ICMMinInLuminance ; ICMMaxInLuminance] range: */
    incolor = clamp(incolor, ICMMinInLuminance.r, ICMMaxInLuminance.r);

    /* Convert clamped input to normalized 0-1 interval: */
    incolor = (incolor - ICMMinInLuminance.r) * ICMReciprocalLuminanceRange.r;

    /* Map luminance component through power function with Gamma coeff.: */
    outcolor = (pow(incolor, ICMEncodingGamma.r) * ICMOutputGain.r) + ICMOutputBias.r;

    /* Clamp outcolor to range given by ICMClampToColorRange: */
    outcolor = clamp(outcolor, ICMClampToColorRange[0], ICMClampToColorRange[1]);

    return(outcolor);
}
