You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.7 KiB

  1. #ifndef __TONEMAPPING__
  2. #define __TONEMAPPING__
  3. #include "ACES.cginc"
  4. // Set to 1 to use the full reference ACES tonemapper. This should only be used for research
  5. // purposes and it's quite heavy and generally overkill.
  6. #define TONEMAPPING_USE_FULL_ACES 0
  7. //
  8. // Neutral tonemapping (Hable/Hejl/Frostbite)
  9. // Input is linear RGB
  10. //
  11. half3 NeutralCurve(half3 x, half a, half b, half c, half d, half e, half f)
  12. {
  13. return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
  14. }
  15. half3 NeutralTonemap(half3 x, half4 params1, half4 params2)
  16. {
  17. // ACES supports negative color values and WILL output negative values when coming from ACES or ACEScg
  18. // Make sure negative channels are clamped to 0.0 as this neutral tonemapper can't deal with them properly
  19. x = max((0.0).xxx, x);
  20. // Tonemap
  21. half a = params1.x;
  22. half b = params1.y;
  23. half c = params1.z;
  24. half d = params1.w;
  25. half e = params2.x;
  26. half f = params2.y;
  27. half whiteLevel = params2.z;
  28. half whiteClip = params2.w;
  29. half3 whiteScale = (1.0).xxx / NeutralCurve(whiteLevel, a, b, c, d, e, f);
  30. x = NeutralCurve(x * whiteScale, a, b, c, d, e, f);
  31. x *= whiteScale;
  32. // Post-curve white point adjustment
  33. x /= whiteClip.xxx;
  34. return x;
  35. }
  36. //
  37. // Filmic tonemapping (ACES fitting, unless TONEMAPPING_USE_FULL_ACES is set to 1)
  38. // Input is ACES2065-1 (AP0 w/ linear encoding)
  39. //
  40. half3 FilmicTonemap(half3 aces)
  41. {
  42. #if TONEMAPPING_USE_FULL_ACES
  43. half3 oces = RRT(aces);
  44. half3 odt = ODT_RGBmonitor_100nits_dim(oces);
  45. return odt;
  46. #else
  47. // --- Glow module --- //
  48. half saturation = rgb_2_saturation(aces);
  49. half ycIn = rgb_2_yc(aces);
  50. half s = sigmoid_shaper((saturation - 0.4) / 0.2);
  51. half addedGlow = 1.0 + glow_fwd(ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID);
  52. aces *= addedGlow;
  53. // --- Red modifier --- //
  54. half hue = rgb_2_hue(aces);
  55. half centeredHue = center_hue(hue, RRT_RED_HUE);
  56. half hueWeight;
  57. {
  58. //hueWeight = cubic_basis_shaper(centeredHue, RRT_RED_WIDTH);
  59. hueWeight = Pow2(smoothstep(0.0, 1.0, 1.0 - abs(2.0 * centeredHue / RRT_RED_WIDTH)));
  60. }
  61. aces.r += hueWeight * saturation * (RRT_RED_PIVOT - aces.r) * (1.0 - RRT_RED_SCALE);
  62. // --- ACES to RGB rendering space --- //
  63. half3 acescg = max(0.0, ACES_to_ACEScg(aces));
  64. // --- Global desaturation --- //
  65. //acescg = mul(RRT_SAT_MAT, acescg);
  66. acescg = lerp(dot(acescg, AP1_RGB2Y).xxx, acescg, RRT_SAT_FACTOR.xxx);
  67. // Luminance fitting of *RRT.a1.0.3 + ODT.Academy.RGBmonitor_100nits_dim.a1.0.3*.
  68. // https://github.com/colour-science/colour-unity/blob/master/Assets/Colour/Notebooks/CIECAM02_Unity.ipynb
  69. // RMSE: 0.0012846272106
  70. const half a = 278.5085;
  71. const half b = 10.7772;
  72. const half c = 293.6045;
  73. const half d = 88.7122;
  74. const half e = 80.6889;
  75. half3 x = acescg;
  76. half3 rgbPost = (x * (a * x + b)) / (x * (c * x + d) + e);
  77. // Scale luminance to linear code value
  78. // half3 linearCV = Y_2_linCV(rgbPost, CINEMA_WHITE, CINEMA_BLACK);
  79. // Apply gamma adjustment to compensate for dim surround
  80. half3 linearCV = darkSurround_to_dimSurround(rgbPost);
  81. // Apply desaturation to compensate for luminance difference
  82. //linearCV = mul(ODT_SAT_MAT, color);
  83. linearCV = lerp(dot(linearCV, AP1_RGB2Y).xxx, linearCV, ODT_SAT_FACTOR.xxx);
  84. // Convert to display primary encoding
  85. // Rendering space RGB to XYZ
  86. half3 XYZ = mul(AP1_2_XYZ_MAT, linearCV);
  87. // Apply CAT from ACES white point to assumed observer adapted white point
  88. XYZ = mul(D60_2_D65_CAT, XYZ);
  89. // CIE XYZ to display primaries
  90. linearCV = mul(XYZ_2_REC709_MAT, XYZ);
  91. return linearCV;
  92. #endif
  93. }
  94. #endif // __TONEMAPPING__