Lut3DBaker.compute 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "../StdLib.hlsl"
  2. #include "../Colors.hlsl"
  3. #include "../ACES.hlsl"
  4. #pragma kernel KGenLut3D_NoTonemap TONEMAPPING_NONE
  5. #pragma kernel KGenLut3D_AcesTonemap TONEMAPPING_ACES
  6. #pragma kernel KGenLut3D_NeutralTonemap TONEMAPPING_NEUTRAL
  7. #pragma kernel KGenLut3D_CustomTonemap TONEMAPPING_CUSTOM
  8. RWTexture3D<float4> _Output;
  9. CBUFFER_START(Params)
  10. float4 _Size; // x: lut_size, y: 1 / (lut_size - 1), zw: unused
  11. float4 _ColorBalance;
  12. float4 _ColorFilter;
  13. float4 _HueSatCon;
  14. float4 _ChannelMixerRed;
  15. float4 _ChannelMixerGreen;
  16. float4 _ChannelMixerBlue;
  17. float4 _Lift;
  18. float4 _InvGamma;
  19. float4 _Gain;
  20. float4 _CustomToneCurve;
  21. // Packing is currently borked, can't pass float arrays without it creating one vector4 per
  22. // float so we'll pack manually...
  23. float4 _ToeSegmentA;
  24. float4 _ToeSegmentB;
  25. float4 _MidSegmentA;
  26. float4 _MidSegmentB;
  27. float4 _ShoSegmentA;
  28. float4 _ShoSegmentB;
  29. CBUFFER_END
  30. Texture2D _Curves;
  31. SamplerState sampler_Curves;
  32. float3 LogGrade(float3 colorLog)
  33. {
  34. // Contrast feels a lot more natural when done in log rather than doing it in linear
  35. colorLog = Contrast(colorLog, ACEScc_MIDGRAY, _HueSatCon.z);
  36. return colorLog;
  37. }
  38. float3 LinearGrade(float3 colorLinear)
  39. {
  40. colorLinear = WhiteBalance(colorLinear, _ColorBalance.rgb);
  41. colorLinear *= _ColorFilter.rgb;
  42. colorLinear = ChannelMixer(colorLinear, _ChannelMixerRed.rgb, _ChannelMixerGreen.rgb, _ChannelMixerBlue.rgb);
  43. colorLinear = LiftGammaGainHDR(colorLinear, _Lift.rgb, _InvGamma.rgb, _Gain.rgb);
  44. // Do NOT feed negative values to RgbToHsv or they'll wrap around
  45. colorLinear = max(0.0, colorLinear);
  46. float3 hsv = RgbToHsv(colorLinear);
  47. // Hue Vs Sat
  48. float satMult;
  49. satMult = saturate(_Curves.SampleLevel(sampler_Curves, float2(hsv.x, 0.25), 0).y) * 2.0;
  50. // Sat Vs Sat
  51. satMult *= saturate(_Curves.SampleLevel(sampler_Curves, float2(hsv.y, 0.25), 0).z) * 2.0;
  52. // Lum Vs Sat
  53. satMult *= saturate(_Curves.SampleLevel(sampler_Curves, float2(Luminance(colorLinear), 0.25), 0).w) * 2.0;
  54. // Hue Vs Hue
  55. float hue = hsv.x + _HueSatCon.x;
  56. float offset = saturate(_Curves.SampleLevel(sampler_Curves, float2(hue, 0.25), 0).x) - 0.5;
  57. hue += offset;
  58. hsv.x = RotateHue(hue, 0.0, 1.0);
  59. colorLinear = HsvToRgb(hsv);
  60. colorLinear = Saturation(colorLinear, _HueSatCon.y * satMult);
  61. return colorLinear;
  62. }
  63. #if TONEMAPPING_ACES
  64. float3 ColorGrade(float3 colorLutSpace)
  65. {
  66. float3 colorLinear = LUT_SPACE_DECODE(colorLutSpace);
  67. float3 aces = unity_to_ACES(colorLinear);
  68. // ACEScc (log) space
  69. float3 acescc = ACES_to_ACEScc(aces);
  70. acescc = LogGrade(acescc);
  71. aces = ACEScc_to_ACES(acescc);
  72. // ACEScg (linear) space
  73. float3 acescg = ACES_to_ACEScg(aces);
  74. acescg = LinearGrade(acescg);
  75. // Tonemap ODT(RRT(aces))
  76. aces = ACEScg_to_ACES(acescg);
  77. colorLinear = AcesTonemap(aces);
  78. return colorLinear;
  79. }
  80. #else
  81. float3 ColorGrade(float3 colorLutSpace)
  82. {
  83. // colorLutSpace is already in log space
  84. colorLutSpace = LogGrade(colorLutSpace);
  85. // Switch back to linear
  86. float3 colorLinear = LUT_SPACE_DECODE(colorLutSpace);
  87. colorLinear = LinearGrade(colorLinear);
  88. colorLinear = max(0.0, colorLinear);
  89. // Tonemap
  90. #if TONEMAPPING_NEUTRAL
  91. {
  92. colorLinear = NeutralTonemap(colorLinear);
  93. }
  94. #elif TONEMAPPING_CUSTOM
  95. {
  96. colorLinear = CustomTonemap(
  97. colorLinear, _CustomToneCurve.xyz,
  98. _ToeSegmentA, _ToeSegmentB.xy,
  99. _MidSegmentA, _MidSegmentB.xy,
  100. _ShoSegmentA, _ShoSegmentB.xy
  101. );
  102. }
  103. #endif
  104. return colorLinear;
  105. }
  106. #endif
  107. void Eval(uint3 id)
  108. {
  109. if (float(id.x) < _Size.x && float(id.y) < _Size.x && float(id.z) < _Size.x)
  110. {
  111. // Lut space (log space)
  112. float3 colorLutSpace = float3(id) * _Size.y;
  113. // Color grade & tonemap
  114. float3 graded = ColorGrade(colorLutSpace);
  115. _Output[id] = float4(max(graded, 0.0), 1.0);
  116. }
  117. }
  118. #define GROUP_SIZE 4
  119. #ifdef DISABLE_COMPUTE_SHADERS
  120. TRIVIAL_COMPUTE_KERNEL(KGenLut3D_NoTonemap)
  121. TRIVIAL_COMPUTE_KERNEL(KGenLut3D_AcesTonemap)
  122. TRIVIAL_COMPUTE_KERNEL(KGenLut3D_NeutralTonemap)
  123. TRIVIAL_COMPUTE_KERNEL(KGenLut3D_CustomTonemap)
  124. #else
  125. [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
  126. void KGenLut3D_NoTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
  127. [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
  128. void KGenLut3D_AcesTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
  129. [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
  130. void KGenLut3D_NeutralTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
  131. [numthreads(GROUP_SIZE, GROUP_SIZE, GROUP_SIZE)]
  132. void KGenLut3D_CustomTonemap(uint3 id : SV_DispatchThreadID) { Eval(id); }
  133. #endif // DISABLE_COMPUTE_SHADERS