#ifndef UNITY_PHYSICAL_CAMERA_INCLUDED #define UNITY_PHYSICAL_CAMERA_INCLUDED // Has to be kept in sync with ColorUtils.cs // References: // "Moving Frostbite to PBR" (Sébastien Lagarde & Charles de Rousiers) // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf // "Implementing a Physically Based Camera" (Padraic Hennessy) // https://placeholderart.wordpress.com/2014/11/16/implementing-a-physically-based-camera-understanding-exposure/ float ComputeEV100(float aperture, float shutterSpeed, float ISO) { // EV number is defined as: // 2^ EV_s = N^2 / t and EV_s = EV_100 + log2 (S /100) // This gives // EV_s = log2 (N^2 / t) // EV_100 + log2 (S /100) = log2 (N^2 / t) // EV_100 = log2 (N^2 / t) - log2 (S /100) // EV_100 = log2 (N^2 / t . 100 / S) return log2((aperture * aperture) / shutterSpeed * 100.0 / ISO); } float ComputeEV100FromAvgLuminance(float avgLuminance) { // We later use the middle gray at 12.7% in order to have // a middle gray at 18% with a sqrt(2) room for specular highlights // But here we deal with the spot meter measuring the middle gray // which is fixed at 12.5 for matching standard camera // constructor settings (i.e. calibration constant K = 12.5) // Reference: http://en.wikipedia.org/wiki/Film_speed const float K = 12.5; // Reflected-light meter calibration constant return log2(avgLuminance * 100.0 / K); } float ConvertEV100ToExposure(float EV100) { // Compute the maximum luminance possible with H_sbs sensitivity // maxLum = 78 / ( S * q ) * N^2 / t // = 78 / ( S * q ) * 2^ EV_100 // = 78 / (100 * 0.65) * 2^ EV_100 // = 1.2 * 2^ EV // Reference: http://en.wikipedia.org/wiki/Film_speed float maxLuminance = 1.2 * pow(2.0, EV100); return 1.0 / maxLuminance; } float ComputeISO(float aperture, float shutterSpeed, float targetEV100) { // Compute the required ISO to reach the target EV100 return ((aperture * aperture) * 100.0) / (shutterSpeed * pow(2.0, targetEV100)); } float ComputeLuminanceAdaptation(float previousLuminance, float currentLuminance, float speedDarkToLight, float speedLightToDark, float deltaTime) { float delta = currentLuminance - previousLuminance; float speed = delta > 0.0 ? speedDarkToLight : speedLightToDark; // Exponential decay return previousLuminance + delta * (1.0 - exp2(-deltaTime * speed)); } #endif // UNITY_PHYSICAL_CAMERA_INCLUDED