// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== // // Purpose: Takes a gamma linear value as input and returns the non-linear equivalent. // The linear value returned is normalized within 0 and 1. // Note: The gamma nonLinear->linear conversion is a special case of the nonLinear->linear // conversion, no matter what the allowed range is, NL[0.0, 1.0] always maps to the // L[0.0, 0.5] range. The rest of the range NL[1.0, max] maps to L[0.5, 1.0] // (this is as designed) // // Example: getGammaNonLinearFromLinear(x, 5) // case where x < 0.5 // x = 0.0 : -(2 * 0.0 - 1)^2 + 1 = 0.0 // x = 0.5 : -(2 * 0.5 - 1)^2 + 1 = 1.0 // case where x > 0.5 // x = 0.5 : (2 * 0.5 - 1)^2 * (5 - 1) + 1 = 1.0 // x = 1.0 : (2 * 1.0 - 1)^2 * (5 - 1) + 1 = 5.0 // global proc float getGammaNonLinearFromLinear(float $x, float $max) { if($x < 0.5) { float $y = pow(2 * $x - 1, 2) * -1 + 1; return $y; } else { float $y = pow(2 * $x - 1, 2) * ($max - 1) + 1; return $y; } } // // Purpose: Takes a gamma non-linear value as input and returns the linear equivalent. // The non-linear value returned is normalized within the min/max range specified. // Note: The gamma linear->nonLinear conversion is a special case of linear->nonLinear // conversion, no matter what the allowed range is, L[0.0, 0.5] always maps to the // NL[0.0, 1.0] range. The rest of the range L[0.5, 1.0] maps to NL[1.0, max] // (this is as designed) // // Example: getGammaLinearFromNonLinear(y, 5) // case where y < 1 // y = 0 : 1 - (sqrt(1 - 0) + 1) / 2 = 0.0 // y = 1 : 1 - (sqrt(1 - 1) + 1) / 2 = 0.5 // case where y > 1 // y = 1 : (sqrt((1 - 1)/(5 - 1)) + 1) / 2 = 0.5 // y = 5 : (sqrt((5 - 1)/(5 - 1)) + 1) / 2 = 1.0 // global proc float getGammaLinearFromNonLinear(float $y, float $max) { if($y < 1.0) { float $x = 1 - (sqrt(1 - $y) + 1) / 2; return $x; } else { float $x = (sqrt(($y - 1)/($max - 1)) + 1) / 2; return $x; } } // // Purpose: Takes a linear value as input and returns the non-linear equivalent. // The linear value returned is normalized within 0 and 1. // Note: This assumes that $min < 0 and $max > 0. // // Example: getNonLinearFromLinear(x, -2, 8) // totalRange = 10 // minRange = 0.2 // maxRange = 0.8 // // cases where x > minRange: // x' for x = 0.2 : (0.2 - 0.2)/0.8 = 0.0 // x' for x = 1.0 : (1.0 - 0.2)/0.8 = 1.0 // x' for x = 0.6 : (0.6 - 0.2)/0.8 = 0.5 // returned value : x'^2 * 8 // // cases where x < minRange: // x' for x = 0.2 : (0.2 - 0.2)/0.2 = 0.0 // x' for x = 0.0 : (0.2 - 0.0)/0.2 = 1.0 // x' for x = 0.1 : (0.2 - 0.1)/0.2 = 0.5 // returned value : x'^2 * -2 // global proc float getNonLinearFromLinear(float $x, float $min, float $max) { float $totalRange = $max - $min; float $minRange = abs($min) / $totalRange; float $maxRange = $max / $totalRange; if($x > $minRange) { // |minRange| maxRange | // 0--------|-----------------------1 // | x is somewhere here | float $xprime = ($x - $minRange) / $maxRange; float $y = pow($xprime, 2) * $max; return $y; } else { // |minRange| maxRange | // 0--------|-----------------------1 // | x here | float $xprime = ($minRange - $x) / $minRange; $y = pow($xprime, 2) * $min; return $y; } } // // Purpose: Takes a non-linear value as input and returns the linear equivalent. // The non-linear value returned is normalized within the min/max range specified // Note: This assumes that $min < 0 and $max > 0. // // Example: getLinearFromNonLinear(y, -2, 8) // totalRange = 10 // minRange = 0.2 // maxRange = 0.8 // // cases where y > 0: // x' for y = 0 : sqrt(0/8) = 0.0 // x' for y = 8 : sqrt(8/8) = 1.0 // x' for y = 4 : sqrt(4/8) = 0.707 // returned value : x' * 0.8 + 0.2 // // cases where y < 0: // x' for y = 0 : sqrt(0/2) = 0.0 // x' for y = 2 : sqrt(2/2) = 1.0 // x' for y = 1 : sqrt(1/2) = 0.707 // returned value : (1 - x') * 0.2 // global proc float getLinearFromNonLinear(float $y, float $min, float $max) { float $totalRange = $max - $min; float $minRange = abs($min) / $totalRange; float $maxRange = $max / $totalRange; if($y > 0.0) { // min --------0----------------------- max // | | y is somewhere here | float $xprime = sqrt($y / $max); float $x = ($xprime * $maxRange) + $minRange; return $x; } else { // min --------0----------------------- max // | y here | | float $xprime = sqrt($y / $min); float $x = (1 - $xprime) * $minRange; return $x; } }