PPCreateTonemapLUT.bsl 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include "$ENGINE$\VolumeRenderBase.bslinc"
  2. #include "$ENGINE$\PPTonemapCommon.bslinc"
  3. #include "$ENGINE$\PPWhiteBalance.bslinc"
  4. Parameters =
  5. {
  6. };
  7. Technique
  8. : inherits("VolumeRenderBase")
  9. : inherits("PPTonemapCommon")
  10. : inherits("PPWhiteBalance") =
  11. {
  12. Language = "HLSL11";
  13. Pass =
  14. {
  15. DepthWrite = false;
  16. DepthRead = false;
  17. Fragment =
  18. {
  19. cbuffer Input
  20. {
  21. // [0]: x - shoulder strength, y - linear strength, z - linear angle, w - toe strength
  22. // [1]: x - toe numerator, y - toe denominator, z - linear white point, w - unused
  23. float4 gTonemapParams[2];
  24. float gGammaAdjustment;
  25. // 0 - sRGB, 1 - Rec.709, 2 - 2.2 gamma
  26. uint gGammaCorrectionType;
  27. float3 gSaturation;
  28. float3 gContrast;
  29. float3 gGain;
  30. float3 gOffset;
  31. };
  32. /**
  33. * Filmic curve used for tonemapping.
  34. *
  35. * @param linearColor Linear color.
  36. * @return Transformed color.
  37. */
  38. float3 FilmicCurve(float3 color)
  39. {
  40. // Formula from John Hable's Uncharted 2 presentation
  41. float3 a = color * (gTonemapParams[0].x * color + gTonemapParams[0].y * gTonemapParams[0].z);
  42. float b = gTonemapParams[0].w * gTonemapParams[1].x;
  43. float3 c = color * (gTonemapParams[0].x * color + gTonemapParams[0].y);
  44. float d = gTonemapParams[0].w * gTonemapParams[1].y;
  45. return (a + b)/(c + d) - gTonemapParams[1].x / gTonemapParams[1].y;
  46. }
  47. /**
  48. * Applies filmic curve tonemapping to the provided color.
  49. *
  50. * @param linearColor Linear color in ACEScg color space.
  51. * @return Tonemapped color in ACEScg color space.
  52. */
  53. float3 FilmicTonemapping(float3 color)
  54. {
  55. return FilmicCurve(color) / FilmicCurve(gTonemapParams[1].z);
  56. }
  57. /**
  58. * Applies color grading to the provided color.
  59. *
  60. * @param linearColor Linear color in ACEScg color space.
  61. * @return Graded color in ACEScg color space.
  62. */
  63. float3 ColorGrading(float3 color)
  64. {
  65. const float3 RGBToY = float3(0.2722287168f, 0.6740817658f, 0.0536895174f);
  66. float luminance = dot(color, RGBToY);
  67. color = max(0, lerp(luminance.xxx, color, gSaturation));
  68. color = pow(color * (1.0f / 0.18f), gContrast) * 0.18f;
  69. color = color * gGain + gOffset;
  70. return color;
  71. }
  72. float4 main(GStoFS input) : SV_Target0
  73. {
  74. // Constants
  75. const float3x3 sRGBToACES2065Matrix = mul(XYZToACES2065Matrix, mul(D65ToD60Matrix, sRGBToXYZMatrix));
  76. const float3x3 sRGBToACEScgMatrix = mul(XYZToACEScgMatrix, mul(D65ToD60Matrix, sRGBToXYZMatrix));
  77. const float3x3 ACEScgTosRGBMatrix = mul(XYZTosRGBMatrix, mul(D60ToD65Matrix, ACEScgToXYZMatrix));
  78. // By default pixel centers will be sampled, but we want to encode the entire range, so
  79. // offset the sampling by half a pixel, and extend the entire range by one pixel.
  80. float2 uv = input.uv0 - (0.5f / LUT_SIZE);
  81. float3 logColor = float3(uv * LUT_SIZE / (float)(LUT_SIZE - 1), input.layerIdx / (float)(LUT_SIZE - 1));
  82. float3 linearColor = LogToLinearColor(logColor);
  83. linearColor = WhiteBalance(linearColor);
  84. linearColor = mul(sRGBToACEScgMatrix, linearColor);
  85. linearColor = ColorGrading(linearColor);
  86. // Note: Improve this so it's closer to the ACES curve?
  87. linearColor = FilmicTonemapping(linearColor);
  88. // TODO - Does the white point provided in filmic curve conflict with the white balancing?
  89. linearColor = mul(ACEScgTosRGBMatrix, linearColor);
  90. // Transform to gamma space
  91. float3 gammaColor = pow(linearColor, gGammaAdjustment); // User adjustment, usually 1.0f
  92. if(gGammaCorrectionType == 0)
  93. gammaColor = LinearToGammasRGB(gammaColor);
  94. else if(gGammaCorrectionType == 1)
  95. gammaColor = LinearToGammaRec709(gammaColor);
  96. else
  97. gammaColor = pow(gammaColor, 1.0f/2.2f);
  98. // TODO - Divide by 1.05f here and then re-apply it when decoding from the texture?
  99. return float4(gammaColor, 0.0f);
  100. }
  101. };
  102. };
  103. };
  104. Technique
  105. : inherits("VolumeRenderBase")
  106. : inherits("PPTonemapCommon")
  107. : inherits("PPWhiteBalance") =
  108. {
  109. Language = "GLSL";
  110. Pass =
  111. {
  112. DepthWrite = false;
  113. DepthRead = false;
  114. Fragment =
  115. {
  116. uniform Input
  117. {
  118. // [0]: x - shoulder strength, y - linear strength, z - linear angle, w - toe strength
  119. // [1]: x - toe numerator, y - toe denominator, z - linear white point, w - unused
  120. vec4 gTonemapParams[2];
  121. float gGammaAdjustment;
  122. // 0 - sRGB, 1 - Rec.709, 2 - 2.2 gamma
  123. uint gGammaCorrectionType;
  124. vec3 gSaturation;
  125. vec3 gContrast;
  126. vec3 gGain;
  127. vec3 gOffset;
  128. };
  129. /**
  130. * Filmic curve used for tonemapping.
  131. *
  132. * @param linearColor Linear color.
  133. * @return Transformed color.
  134. */
  135. void FilmicCurve(vec3 color, out vec3 result)
  136. {
  137. // Formula from John Hable's Uncharted 2 presentation
  138. vec3 a = color * (gTonemapParams[0].x * color + vec3(gTonemapParams[0].y * gTonemapParams[0].z));
  139. vec3 b = vec3(gTonemapParams[0].w * gTonemapParams[1].x);
  140. vec3 c = color * (gTonemapParams[0].x * color + vec3(gTonemapParams[0].y));
  141. vec3 d = vec3(gTonemapParams[0].w * gTonemapParams[1].y);
  142. result = (a + b)/(c + d) - vec3(gTonemapParams[1].x / gTonemapParams[1].y);
  143. }
  144. /**
  145. * Applies filmic curve tonemapping to the provided color.
  146. *
  147. * @param linearColor Linear color in ACEScg color space.
  148. * @return Tonemapped color in ACEScg color space.
  149. */
  150. void FilmicTonemapping(vec3 color, out vec3 result)
  151. {
  152. vec3 filmicColor;
  153. FilmicCurve(color, filmicColor);
  154. vec3 filmicWhitePoint;
  155. FilmicCurve(vec3(gTonemapParams[1].z), filmicWhitePoint);
  156. result = filmicColor / filmicWhitePoint;
  157. }
  158. /**
  159. * Applies color grading to the provided color.
  160. *
  161. * @param linearColor Linear color in ACEScg color space.
  162. * @return Graded color in ACEScg color space.
  163. */
  164. void ColorGrading(vec3 color, out vec3 result)
  165. {
  166. const vec3 RGBToY = vec3(0.2722287168f, 0.6740817658f, 0.0536895174f);
  167. float luminance = dot(color, RGBToY);
  168. color = max(vec3(0.0f), mix(luminance.xxx, color, gSaturation));
  169. color = pow(color * (1.0f / 0.18f), gContrast) * 0.18f;
  170. color = color * gGain + gOffset;
  171. result = color;
  172. }
  173. in GStoFS
  174. {
  175. vec2 uv0;
  176. } input;
  177. out vec4 fragColor;
  178. in int gl_Layer;
  179. void main()
  180. {
  181. // Constants
  182. const mat3x3 sRGBToACES2065Matrix = XYZToACES2065Matrix * (D65ToD60Matrix * sRGBToXYZMatrix);
  183. const mat3x3 sRGBToACEScgMatrix = XYZToACEScgMatrix * (D65ToD60Matrix * sRGBToXYZMatrix);
  184. const mat3x3 ACEScgTosRGBMatrix = XYZTosRGBMatrix * (D60ToD65Matrix * ACEScgToXYZMatrix);
  185. // By default pixel centers will be sampled, but we want to encode the entire range, so
  186. // offset the sampling by half a pixel, and extend the entire range by one pixel.
  187. vec2 uv = input.uv0 - (0.5f / LUT_SIZE);
  188. vec3 logColor = vec3(uv * LUT_SIZE / float(LUT_SIZE - 1), gl_Layer / float(LUT_SIZE - 1));
  189. vec3 linearColor;
  190. LogToLinearColor(logColor, linearColor);
  191. WhiteBalance(linearColor, linearColor);
  192. linearColor = sRGBToACEScgMatrix * linearColor;
  193. ColorGrading(linearColor, linearColor);
  194. // Note: Improve this so it's closer to the ACES curve?
  195. FilmicTonemapping(linearColor, linearColor);
  196. // TODO - Does the white point provided in filmic curve conflict with the white balancing?
  197. linearColor = ACEScgTosRGBMatrix * linearColor;
  198. // Transform to gamma space
  199. vec3 gammaColor = pow(linearColor, vec3(gGammaAdjustment)); // User adjustment, usually 1.0f
  200. if(gGammaCorrectionType == 0)
  201. LinearToGammasRGB(gammaColor, gammaColor);
  202. else if(gGammaCorrectionType == 1)
  203. LinearToGammaRec709(gammaColor, gammaColor);
  204. else
  205. gammaColor = pow(gammaColor, vec3(1.0f/2.2f));
  206. // TODO - Divide by 1.05f here and then re-apply it when decoding from the texture?
  207. fragColor = vec4(gammaColor, 0.0f);
  208. }
  209. };
  210. };
  211. };