| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- //
- // Copyright (c) Microsoft. All rights reserved.
- // This code is licensed under the MIT License (MIT).
- // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
- // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
- // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
- //
- // Developed by Minigraph
- //
- // Author: James Stanard
- //
- #pragma warning( disable : 3571 )
- // This approximates sRGB sufficiently enough that for 8-bit encodings is indistinguishable
- // from the "slow" version. This can be a lot faster due to avoiding three pow() calls.
- float3 LinearToSRGB_Fast( float3 x )
- {
- return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(x - 0.00228) - 0.13448 * x + 0.005719;
- }
- float3 LinearToSRGB( float3 x )
- {
- return x < 0.0031308 ? 12.92 * x : 1.055 * pow(x, 1.0 / 2.4) - 0.055;
- }
- float3 SRGBToLinear( float3 x )
- {
- return x < 0.04045 ? x / 12.92 : pow( (x + 0.055) / 1.055, 2.4 );
- }
- float3 LinearToREC709( float3 x )
- {
- return x < 0.018 ? 4.5 * x : 1.099 * pow(x, 0.45) - 0.099;
- }
- float3 REC709ToLinear( float3 x )
- {
- return x < 0.081 ? x / 4.5 : pow((x + 0.099) / 1.099, 1.0 / 0.45);
- }
- // Same as Rec.709 transfer but more precise (intended for 12-bit rather than 10-bit)
- float3 LinearToREC2020(float3 x)
- {
- return x < 0.0181 ? 4.5 * x : 1.0993 * pow(x, 0.45) - 0.0993;
- }
- float3 REC2020ToLinear(float3 x)
- {
- return x < 0.08145 ? x / 4.5 : pow((x + 0.0993) / 1.0993, 1.0 / 0.45);
- }
- float3 LinearToREC2084( float3 L )
- {
- float m1 = 2610.0 / 4096.0 / 4;
- float m2 = 2523.0 / 4096.0 * 128;
- float c1 = 3424.0 / 4096.0;
- float c2 = 2413.0 / 4096.0 * 32;
- float c3 = 2392.0 / 4096.0 * 32;
- float3 Lp = pow(L, m1);
- return pow((c1 + c2 * Lp) / (1 + c3 * Lp), m2);
- }
- float3 REC2084ToLinear( float3 N )
- {
- float m1 = 2610.0 / 4096.0 / 4;
- float m2 = 2523.0 / 4096.0 * 128;
- float c1 = 3424.0 / 4096.0;
- float c2 = 2413.0 / 4096.0 * 32;
- float c3 = 2392.0 / 4096.0 * 32;
- float3 Np = pow(N, 1 / m2);
- return pow(max(Np - c1, 0) / (c2 - c3 * Np), 1 / m1);
- }
- // Encodes a smooth logarithmic gradient for even distribution of precision natural to vision
- float LinearToLogLuminance( float x, float gamma = 4.0 )
- {
- return log2(lerp(1, exp2(gamma), x)) / gamma;
- }
- // This assumes the default color gamut found in sRGB and REC709. The color primaries determine these
- // coefficients. Note that this operates on linear values, not gamma space.
- float RGBToLuminance( float3 x )
- {
- return dot( x, float3(0.212671, 0.715160, 0.072169) ); // Defined by sRGB gamut
- // return dot( x, float3(0.2989164, 0.5865990, 0.1144845) ); // NTSC - don't use this
- }
- // Assumes the "white point" is 1.0. Prescale your HDR values if otherwise. 'E' affects the rate
- // at which colors blow out to white.
- float3 ToneMap( float3 hdr, float E = 4.0 )
- {
- return (1 - exp2(-E * hdr)) / (1 - exp2(-E));
- }
- // This variant rescales only the luminance of the color to fit in the [0, 1] range while preserving hue.
- float3 ToneMap2( float3 hdr, float E = 4.0 )
- {
- float luma = RGBToLuminance(hdr);
- return hdr * (1 - exp2(-E * luma)) / (1 - exp2(-E)) / (luma + 0.0001);
- }
- float ToneMapLuma( float Luma, float E = 4.0 )
- {
- return (1 - exp2(-E * Luma)) / (1 - exp2(-E));
- }
- // This is the same as above, but converts the linear luminance value to a more subjective "perceived luminance",
- // which could be called the Log-Luminance.
- float RGBToLogLuminance( float3 x, float gamma = 4.0 )
- {
- return LinearToLogLuminance( RGBToLuminance(x), gamma );
- }
- float3 RGBFullToLimited( float3 x )
- {
- return saturate(x) * 219.0 / 255.0 + 16.0 / 255.0;
- }
- float3 RGBLimitedToFull( float3 x )
- {
- return saturate((x - 16.0 / 255.0) * 255.0 / 219.0);
- }
- #define COLOR_FORMAT_LINEAR 0
- #define COLOR_FORMAT_sRGB_FULL 1
- #define COLOR_FORMAT_sRGB_LIMITED 2
- #define COLOR_FORMAT_Rec709_FULL 3
- #define COLOR_FORMAT_Rec709_LIMITED 4
- #define COLOR_FORMAT_7e3_FLOAT_FULL 5
- #define COLOR_FORMAT_6e4_FLOAT_FULL 6
- #define COLOR_FORMAT_TV_DEFAULT COLOR_FORMAT_Rec709_LIMITED
- #define COLOR_FORMAT_PC_DEFAULT COLOR_FORMAT_sRGB_FULL
- #define HDR_COLOR_FORMAT COLOR_FORMAT_LINEAR
- #define LDR_COLOR_FORMAT COLOR_FORMAT_LINEAR
- #if _XBOX_ONE
- #define DISPLAY_PLANE_FORMAT COLOR_FORMAT_TV_DEFAULT
- #define OVERLAY_PLANE_FORMAT COLOR_FORMAT_sRGB_FULL
- #else
- #define DISPLAY_PLANE_FORMAT COLOR_FORMAT_PC_DEFAULT
- #endif
- float3 ApplyColorProfile( float3 x, int Format )
- {
- switch (Format)
- {
- default:
- case COLOR_FORMAT_LINEAR:
- return x;
- case COLOR_FORMAT_sRGB_FULL:
- return LinearToSRGB(x);
- case COLOR_FORMAT_sRGB_LIMITED:
- return RGBFullToLimited(LinearToSRGB(x));
- case COLOR_FORMAT_Rec709_FULL:
- return LinearToREC709(x);
- case COLOR_FORMAT_Rec709_LIMITED:
- return RGBFullToLimited(LinearToREC709(x));
- // Xbox formats: 10-bit floats with biased exponents; range: [0, 2)
- case COLOR_FORMAT_7e3_FLOAT_FULL:
- return x * 16.0;
- case COLOR_FORMAT_6e4_FLOAT_FULL:
- return x * 256.0;
- };
- }
- float3 LinearizeColor( float3 x, int Format )
- {
- switch (Format)
- {
- default:
- case COLOR_FORMAT_LINEAR:
- return x;
- case COLOR_FORMAT_sRGB_FULL:
- return SRGBToLinear(x);
- case COLOR_FORMAT_sRGB_LIMITED:
- return SRGBToLinear(RGBLimitedToFull(x));
- case COLOR_FORMAT_Rec709_FULL:
- return REC709ToLinear(x);
- case COLOR_FORMAT_Rec709_LIMITED:
- return REC709ToLinear(RGBLimitedToFull(x));
- // Xbox formats: 10-bit floats with biased exponents; range: [0, 2)
- case COLOR_FORMAT_7e3_FLOAT_FULL:
- return x / 16.0;
- case COLOR_FORMAT_6e4_FLOAT_FULL:
- return x / 256.0;
- };
- }
- float3 ConvertColor( float3 x, int FromFormat, int ToFormat )
- {
- if (FromFormat == ToFormat)
- return x;
- return ApplyColorProfile(LinearizeColor(x, FromFormat), ToFormat);
- }
|