rafx-plugins 0.0.16

Rendering framework built on an extensible asset pipeline
Documentation
//=================================================================================================
//  The following code is licensed under the MIT license and has been ported from hlsl code
//  in Baking Lab by MJP and David Neubelt
//  http://mynameismjp.wordpress.com/
//=================================================================================================

// The two functions below were based on code and explanations provided by Padraic Hennessy (@PadraicHennessy).
// See this for more info: https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/


// Scale factor used for storing physical light units in fp16 floats (equal to 2^-10).
const float FP16Scale = 0.0009765625f;

const float APERTURE_F_NUMBER = 0.01;
const float ISO = 1.0;
const float SHUTTER_SPEED_VALUE = 1.0;
const float KEY_VALUE = 0.1150;
const float MANUAL_EXPOSURE = -16.0;
const float WHITE_POINT_HABLE = 6.0;
const float WHITE_POINT_HEJL = 1.0;
const int EXPOSURE_MODE_AUTO = 1;
const int EXPOSURE_MODE_MANUAL_SBS = 2;
const int EXPOSURE_MODE_MANUAL_SOS = 3;
const int EXPOSURE_MODE = EXPOSURE_MODE_MANUAL_SBS;

float saturation_based_exposure()
{
    float maxLuminance = (7800.0f / 65.0f) * (APERTURE_F_NUMBER * APERTURE_F_NUMBER) / (ISO * SHUTTER_SPEED_VALUE);
    return log2(1.0f / maxLuminance);
}

float standard_output_based_exposure(float middleGrey /* = 0.18f */)
{
    float lAvg = (1000.0f / 65.0f) * (APERTURE_F_NUMBER * APERTURE_F_NUMBER) / (ISO * SHUTTER_SPEED_VALUE);
    return log2(middleGrey / lAvg);
}
float default_standard_output_based_exposure()
{
    return standard_output_based_exposure(0.18);
}

float log2_exposure(float avgLuminance)
{
    float exposure = 0.0f;

    if(EXPOSURE_MODE == EXPOSURE_MODE_AUTO)
    {
        avgLuminance = max(avgLuminance, 0.00001f);
        float linearExposure = (KEY_VALUE / avgLuminance);
        exposure = log2(max(linearExposure, 0.00001f));
    }
    else if(EXPOSURE_MODE == EXPOSURE_MODE_MANUAL_SBS)
    {
        exposure = saturation_based_exposure();
        exposure -= log2(FP16Scale);
    }
    else if(EXPOSURE_MODE == EXPOSURE_MODE_MANUAL_SOS)
    {
        exposure = default_standard_output_based_exposure();
        exposure -= log2(FP16Scale);
    }
    else
    {
        exposure = MANUAL_EXPOSURE;
        exposure -= log2(FP16Scale);
    }

    return exposure;
}

float linear_exposure(float avgLuminance)
{
    return exp2(log2_exposure(avgLuminance));
}

// Determines the color based on exposure settings
vec3 calc_exposed_color(vec3 color, float avgLuminance, float offset, out float exposure)
{
    exposure = log2_exposure(avgLuminance);
    exposure += offset;
    return exp2(exposure) * color;
}