PPCreateTonemapLUT.bsl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "$ENGINE$\PPTonemapCommon.bslinc"
  2. #include "$ENGINE$\PPWhiteBalance.bslinc"
  3. technique PPCreateTonemapLUT
  4. {
  5. mixin PPTonemapCommon;
  6. mixin PPWhiteBalance;
  7. code
  8. {
  9. [internal]
  10. cbuffer Input
  11. {
  12. // [0]: x - shoulder strength, y - linear strength, z - linear angle, w - toe strength
  13. // [1]: x - toe numerator, y - toe denominator, z - linear white point, w - unused
  14. float4 gTonemapParams[2];
  15. float gGammaAdjustment;
  16. // 0 - sRGB, 1 - Rec.709, 2 - 2.2 gamma
  17. uint gGammaCorrectionType;
  18. float3 gSaturation;
  19. float3 gContrast;
  20. float3 gGain;
  21. float3 gOffset;
  22. };
  23. /**
  24. * Filmic curve used for tonemapping.
  25. *
  26. * @param linearColor Linear color.
  27. * @return Transformed color.
  28. */
  29. float3 FilmicCurve(float3 color)
  30. {
  31. // Formula from John Hable's Uncharted 2 presentation
  32. float3 a = color * (gTonemapParams[0].x * color + gTonemapParams[0].y * gTonemapParams[0].z);
  33. float b = gTonemapParams[0].w * gTonemapParams[1].x;
  34. float3 c = color * (gTonemapParams[0].x * color + gTonemapParams[0].y);
  35. float d = gTonemapParams[0].w * gTonemapParams[1].y;
  36. return (a + b)/(c + d) - gTonemapParams[1].x / gTonemapParams[1].y;
  37. }
  38. /**
  39. * Applies filmic curve tonemapping to the provided color.
  40. *
  41. * @param linearColor Linear color in ACEScg color space.
  42. * @return Tonemapped color in ACEScg color space.
  43. */
  44. float3 FilmicTonemapping(float3 color)
  45. {
  46. return FilmicCurve(color) / FilmicCurve(gTonemapParams[1].z);
  47. }
  48. /**
  49. * Applies color grading to the provided color.
  50. *
  51. * @param linearColor Linear color in ACEScg color space.
  52. * @return Graded color in ACEScg color space.
  53. */
  54. float3 ColorGrading(float3 color)
  55. {
  56. const float3 RGBToY = float3(0.2722287168f, 0.6740817658f, 0.0536895174f);
  57. float luminance = dot(color, RGBToY);
  58. color = max(0, lerp(luminance.xxx, color, gSaturation));
  59. color = pow(color * (1.0f / 0.18f), gContrast) * 0.18f;
  60. color = color * gGain + gOffset;
  61. return color;
  62. }
  63. RWTexture3D<unorm float4> gOutputTex;
  64. [numthreads(8, 8, 1)]
  65. void csmain(
  66. uint3 dispatchThreadId : SV_DispatchThreadID,
  67. uint threadIndex : SV_GroupIndex)
  68. {
  69. // Constants
  70. const float3x3 sRGBToACES2065Matrix = mul(XYZToACES2065Matrix, mul(D65ToD60Matrix, sRGBToXYZMatrix));
  71. const float3x3 sRGBToACEScgMatrix = mul(XYZToACEScgMatrix, mul(D65ToD60Matrix, sRGBToXYZMatrix));
  72. const float3x3 ACEScgTosRGBMatrix = mul(XYZTosRGBMatrix, mul(D60ToD65Matrix, ACEScgToXYZMatrix));
  73. float3 logColor = float3(dispatchThreadId.xyz / (float)(LUT_SIZE - 1));
  74. float3 linearColor = LogToLinearColor(logColor);
  75. linearColor = WhiteBalance(linearColor);
  76. linearColor = mul(sRGBToACEScgMatrix, linearColor);
  77. linearColor = ColorGrading(linearColor);
  78. // Note: Improve this so it's closer to the ACES curve?
  79. linearColor = FilmicTonemapping(linearColor);
  80. // TODO - Does the white point provided in filmic curve conflict with the white balancing?
  81. linearColor = mul(ACEScgTosRGBMatrix, linearColor);
  82. // Transform to gamma space
  83. float3 gammaColor = pow(linearColor, gGammaAdjustment); // User adjustment, usually 1.0f
  84. if(gGammaCorrectionType == 0)
  85. gammaColor = LinearToGammasRGB(gammaColor);
  86. else if(gGammaCorrectionType == 1)
  87. gammaColor = LinearToGammaRec709(gammaColor);
  88. else
  89. gammaColor = pow(gammaColor, 1.0f/2.2f);
  90. // TODO - Divide by 1.05f here and then re-apply it when decoding from the texture?
  91. gOutputTex[dispatchThreadId] = float4(gammaColor, 1.0f);
  92. }
  93. };
  94. };