ShaderUtility.hlsli 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // This code is licensed under the MIT License (MIT).
  4. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  5. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  6. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  7. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  8. //
  9. // Developed by Minigraph
  10. //
  11. // Author: James Stanard
  12. //
  13. #pragma warning( disable : 3571 )
  14. // This approximates sRGB sufficiently enough that for 8-bit encodings is indistinguishable
  15. // from the "slow" version. This can be a lot faster due to avoiding three pow() calls.
  16. float3 LinearToSRGB_Fast( float3 x )
  17. {
  18. return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(x - 0.00228) - 0.13448 * x + 0.005719;
  19. }
  20. float3 LinearToSRGB( float3 x )
  21. {
  22. return x < 0.0031308 ? 12.92 * x : 1.055 * pow(x, 1.0 / 2.4) - 0.055;
  23. }
  24. float3 SRGBToLinear( float3 x )
  25. {
  26. return x < 0.04045 ? x / 12.92 : pow( (x + 0.055) / 1.055, 2.4 );
  27. }
  28. float3 LinearToREC709( float3 x )
  29. {
  30. return x < 0.018 ? 4.5 * x : 1.099 * pow(x, 0.45) - 0.099;
  31. }
  32. float3 REC709ToLinear( float3 x )
  33. {
  34. return x < 0.081 ? x / 4.5 : pow((x + 0.099) / 1.099, 1.0 / 0.45);
  35. }
  36. // Same as Rec.709 transfer but more precise (intended for 12-bit rather than 10-bit)
  37. float3 LinearToREC2020(float3 x)
  38. {
  39. return x < 0.0181 ? 4.5 * x : 1.0993 * pow(x, 0.45) - 0.0993;
  40. }
  41. float3 REC2020ToLinear(float3 x)
  42. {
  43. return x < 0.08145 ? x / 4.5 : pow((x + 0.0993) / 1.0993, 1.0 / 0.45);
  44. }
  45. float3 LinearToREC2084( float3 L )
  46. {
  47. float m1 = 2610.0 / 4096.0 / 4;
  48. float m2 = 2523.0 / 4096.0 * 128;
  49. float c1 = 3424.0 / 4096.0;
  50. float c2 = 2413.0 / 4096.0 * 32;
  51. float c3 = 2392.0 / 4096.0 * 32;
  52. float3 Lp = pow(L, m1);
  53. return pow((c1 + c2 * Lp) / (1 + c3 * Lp), m2);
  54. }
  55. float3 REC2084ToLinear( float3 N )
  56. {
  57. float m1 = 2610.0 / 4096.0 / 4;
  58. float m2 = 2523.0 / 4096.0 * 128;
  59. float c1 = 3424.0 / 4096.0;
  60. float c2 = 2413.0 / 4096.0 * 32;
  61. float c3 = 2392.0 / 4096.0 * 32;
  62. float3 Np = pow(N, 1 / m2);
  63. return pow(max(Np - c1, 0) / (c2 - c3 * Np), 1 / m1);
  64. }
  65. // Encodes a smooth logarithmic gradient for even distribution of precision natural to vision
  66. float LinearToLogLuminance( float x, float gamma = 4.0 )
  67. {
  68. return log2(lerp(1, exp2(gamma), x)) / gamma;
  69. }
  70. // This assumes the default color gamut found in sRGB and REC709. The color primaries determine these
  71. // coefficients. Note that this operates on linear values, not gamma space.
  72. float RGBToLuminance( float3 x )
  73. {
  74. return dot( x, float3(0.212671, 0.715160, 0.072169) ); // Defined by sRGB gamut
  75. // return dot( x, float3(0.2989164, 0.5865990, 0.1144845) ); // NTSC - don't use this
  76. }
  77. // Assumes the "white point" is 1.0. Prescale your HDR values if otherwise. 'E' affects the rate
  78. // at which colors blow out to white.
  79. float3 ToneMap( float3 hdr, float E = 4.0 )
  80. {
  81. return (1 - exp2(-E * hdr)) / (1 - exp2(-E));
  82. }
  83. // This variant rescales only the luminance of the color to fit in the [0, 1] range while preserving hue.
  84. float3 ToneMap2( float3 hdr, float E = 4.0 )
  85. {
  86. float luma = RGBToLuminance(hdr);
  87. return hdr * (1 - exp2(-E * luma)) / (1 - exp2(-E)) / (luma + 0.0001);
  88. }
  89. float ToneMapLuma( float Luma, float E = 4.0 )
  90. {
  91. return (1 - exp2(-E * Luma)) / (1 - exp2(-E));
  92. }
  93. // This is the same as above, but converts the linear luminance value to a more subjective "perceived luminance",
  94. // which could be called the Log-Luminance.
  95. float RGBToLogLuminance( float3 x, float gamma = 4.0 )
  96. {
  97. return LinearToLogLuminance( RGBToLuminance(x), gamma );
  98. }
  99. float3 RGBFullToLimited( float3 x )
  100. {
  101. return saturate(x) * 219.0 / 255.0 + 16.0 / 255.0;
  102. }
  103. float3 RGBLimitedToFull( float3 x )
  104. {
  105. return saturate((x - 16.0 / 255.0) * 255.0 / 219.0);
  106. }
  107. #define COLOR_FORMAT_LINEAR 0
  108. #define COLOR_FORMAT_sRGB_FULL 1
  109. #define COLOR_FORMAT_sRGB_LIMITED 2
  110. #define COLOR_FORMAT_Rec709_FULL 3
  111. #define COLOR_FORMAT_Rec709_LIMITED 4
  112. #define COLOR_FORMAT_7e3_FLOAT_FULL 5
  113. #define COLOR_FORMAT_6e4_FLOAT_FULL 6
  114. #define COLOR_FORMAT_TV_DEFAULT COLOR_FORMAT_Rec709_LIMITED
  115. #define COLOR_FORMAT_PC_DEFAULT COLOR_FORMAT_sRGB_FULL
  116. #define HDR_COLOR_FORMAT COLOR_FORMAT_LINEAR
  117. #define LDR_COLOR_FORMAT COLOR_FORMAT_LINEAR
  118. #if _XBOX_ONE
  119. #define DISPLAY_PLANE_FORMAT COLOR_FORMAT_TV_DEFAULT
  120. #define OVERLAY_PLANE_FORMAT COLOR_FORMAT_sRGB_FULL
  121. #else
  122. #define DISPLAY_PLANE_FORMAT COLOR_FORMAT_PC_DEFAULT
  123. #endif
  124. float3 ApplyColorProfile( float3 x, int Format )
  125. {
  126. switch (Format)
  127. {
  128. default:
  129. case COLOR_FORMAT_LINEAR:
  130. return x;
  131. case COLOR_FORMAT_sRGB_FULL:
  132. return LinearToSRGB(x);
  133. case COLOR_FORMAT_sRGB_LIMITED:
  134. return RGBFullToLimited(LinearToSRGB(x));
  135. case COLOR_FORMAT_Rec709_FULL:
  136. return LinearToREC709(x);
  137. case COLOR_FORMAT_Rec709_LIMITED:
  138. return RGBFullToLimited(LinearToREC709(x));
  139. // Xbox formats: 10-bit floats with biased exponents; range: [0, 2)
  140. case COLOR_FORMAT_7e3_FLOAT_FULL:
  141. return x * 16.0;
  142. case COLOR_FORMAT_6e4_FLOAT_FULL:
  143. return x * 256.0;
  144. };
  145. }
  146. float3 LinearizeColor( float3 x, int Format )
  147. {
  148. switch (Format)
  149. {
  150. default:
  151. case COLOR_FORMAT_LINEAR:
  152. return x;
  153. case COLOR_FORMAT_sRGB_FULL:
  154. return SRGBToLinear(x);
  155. case COLOR_FORMAT_sRGB_LIMITED:
  156. return SRGBToLinear(RGBLimitedToFull(x));
  157. case COLOR_FORMAT_Rec709_FULL:
  158. return REC709ToLinear(x);
  159. case COLOR_FORMAT_Rec709_LIMITED:
  160. return REC709ToLinear(RGBLimitedToFull(x));
  161. // Xbox formats: 10-bit floats with biased exponents; range: [0, 2)
  162. case COLOR_FORMAT_7e3_FLOAT_FULL:
  163. return x / 16.0;
  164. case COLOR_FORMAT_6e4_FLOAT_FULL:
  165. return x / 256.0;
  166. };
  167. }
  168. float3 ConvertColor( float3 x, int FromFormat, int ToFormat )
  169. {
  170. if (FromFormat == ToFormat)
  171. return x;
  172. return ApplyColorProfile(LinearizeColor(x, FromFormat), ToFormat);
  173. }