BsPostProcessing.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsRenderBeastPrerequisites.h"
  5. #include "BsRendererMaterial.h"
  6. #include "BsParamBlocks.h"
  7. #include "BsRenderTexturePool.h"
  8. namespace BansheeEngine
  9. {
  10. /** @addtogroup RenderBeast
  11. * @{
  12. */
  13. /** Settings that control automatic exposure (eye adaptation) post-process. */
  14. struct AutoExposureSettings
  15. {
  16. AutoExposureSettings();
  17. /**
  18. * Determines minimum luminance value in the eye adaptation histogram. The histogram is used for calculating the
  19. * average brightness of the scene. Any luminance value below this value will not be included in the histogram and
  20. * ignored in scene brightness calculations. In log2 units (-8 = 1/256). In the range [-16, 0].
  21. */
  22. float histogramLog2Min;
  23. /**
  24. * Determines maximum luminance value in the eye adaptation histogram. The histogram is used for calculating the
  25. * average brightness of the scene. Any luminance value above this value will not be included in the histogram and
  26. * ignored in scene brightness calculations. In log2 units (4 = 16). In the range [0, 16].
  27. */
  28. float histogramLog2Max;
  29. /**
  30. * Percentage below which to ignore values in the eye adaptation histogram. The histogram is used for calculating
  31. * the average brightness of the scene. Total luminance in the histogram will be summed up and multiplied by this
  32. * value to calculate minimal luminance. Luminance values below the minimal luminance will be ignored and not used
  33. * in scene brightness calculations. This allows you to remove outliers on the lower end of the histogram (e.g. a
  34. * few very dark pixels in an otherwise bright image). In range [0.0f, 1.0f].
  35. */
  36. float histogramPctLow;
  37. /**
  38. * Percentage above which to ignore values in the eye adaptation histogram. The histogram is used for calculating
  39. * the average brightness of the scene. Total luminance in the histogram will be summed up and multiplied by this
  40. * value to calculate maximum luminance. Luminance values above the maximum luminance will be ignored and not used
  41. * in scene brightness calculations. This allows you to remove outliers on the high end of the histogram (e.g. a few
  42. * very bright pixels). In range [0.0f, 1.0f].
  43. */
  44. float histogramPctHigh;
  45. /**
  46. * Clamps the minimum eye adaptation scale to this value. This allows you to limit eye adaptation so that exposure
  47. * is never too high (e.g. when in a very dark room you probably do not want the exposure to be so high that
  48. * everything is still visible). In range [0.0f, 10.0f].
  49. */
  50. float minEyeAdaptation;
  51. /**
  52. * Clamps the maximum eye adaptation scale to this value. This allows you to limit eye adaptation so that exposure
  53. * is never too low (e.g. when looking at a very bright light source you probably don't want the exposure to be so
  54. * low that the rest of the scene is all white (overexposed). In range [0.0f, 10.0f].
  55. */
  56. float maxEyeAdaptation;
  57. /**
  58. * Determines how quickly does the eye adaptation adjust to larger values. This affects how quickly does the
  59. * automatic exposure changes when the scene brightness increases. In range [0.01f, 20.0f]. */
  60. float eyeAdaptationSpeedUp;
  61. /**
  62. * Determines how quickly does the eye adaptation adjust to smaller values. This affects how quickly does the
  63. * automatic exposure changes when the scene brightness decreases. In range [0.01f, 20.0f].
  64. */
  65. float eyeAdaptationSpeedDown;
  66. };
  67. /** Settings that control tonemap post-process. */
  68. struct TonemappingSettings
  69. {
  70. TonemappingSettings();
  71. /**
  72. * Controls the shoulder (upper non-linear) section of the filmic curve used for tonemapping. Mostly affects bright
  73. * areas of the image and allows you to reduce over-exposure.
  74. */
  75. float filmicCurveShoulderStrength;
  76. /**
  77. * Controls the linear (middle) section of the filmic curve used for tonemapping. Mostly affects mid-range areas of
  78. * the image.
  79. */
  80. float filmicCurveLinearStrength;
  81. /**
  82. * Controls the linear (middle) section of the filmic curve used for tonemapping. Mostly affects mid-range areas of
  83. * the image and allows you to control how quickly does the curve climb.
  84. */
  85. float filmicCurveLinearAngle;
  86. /**
  87. * Controls the toe (lower non-linear) section of the filmic curve used for tonemapping. Mostly affects dark areas
  88. * of the image and allows you to reduce under-exposure.
  89. */
  90. float filmicCurveToeStrength;
  91. /** Controls the toe (lower non-linear) section of the filmic curve. used for tonemapping. Affects low-range. */
  92. float filmicCurveToeNumerator;
  93. /** Controls the toe (lower non-linear) section of the filmic curve used for tonemapping. Affects low-range. */
  94. float filmicCurveToeDenominator;
  95. /** Controls the white point of the filmic curve used for tonemapping. Affects the entire curve. */
  96. float filmicCurveLinearWhitePoint;
  97. };
  98. /** Settings that control white balance post-process. */
  99. struct WhiteBalanceSettings
  100. {
  101. WhiteBalanceSettings();
  102. /**
  103. * Temperature used for white balancing, in Kelvins.
  104. *
  105. * Moves along the Planckian locus. In range [1500.0f, 15000.0f].
  106. */
  107. float temperature;
  108. /**
  109. * Additional tint to be applied during white balancing. Can be used to further tweak the white balancing effect by
  110. * modifying the tint of the light. The tint is chosen on the Planckian locus isothermal, depending on the light
  111. * temperature specified by ::whiteTemperature.
  112. *
  113. * In range [-1.0f, 1.0f].
  114. */
  115. float tint;
  116. };
  117. /** Settings that control color grading post-process. */
  118. struct ColorGradingSettings
  119. {
  120. ColorGradingSettings();
  121. /**
  122. * Saturation to be applied during color grading. Larger values increase vibrancy of the image.
  123. * In range [0.0f, 2.0f].
  124. */
  125. Vector3 saturation;
  126. /**
  127. * Contrast to be applied during color grading. Larger values increase difference between light and dark areas of
  128. * the image. In range [0.0f, 2.0f]. */
  129. Vector3 contrast;
  130. /**
  131. * Gain to be applied during color grading. Simply increases all color values by an equal scale.
  132. * In range [0.0f, 2.0f].
  133. */
  134. Vector3 gain;
  135. /**
  136. * Gain to be applied during color grading. Simply offsets all color values by an equal amount.
  137. * In range [-1.0f, 1.0f].
  138. */
  139. Vector3 offset;
  140. };
  141. /** Settings that control the post-process operations. */
  142. struct PostProcessSettings
  143. {
  144. PostProcessSettings();
  145. /**
  146. * Determines should automatic exposure be applied to the HDR image. When turned on the average scene brightness
  147. * will be calculated and used to automatically expose the image to the optimal range. Use the parameters provided
  148. * by ::autoExposure to customize the automatic exposure effect. You may also use ::exposureScale to
  149. * manually adjust the automatic exposure. When automatic exposure is turned off you can use ::exposureScale to
  150. * manually set the exposure.
  151. */
  152. bool enableAutoExposure;
  153. /**
  154. * Parameters used for customizing automatic scene exposure.
  155. *
  156. * @see enableAutoExposure
  157. */
  158. AutoExposureSettings autoExposure;
  159. /**
  160. * Determines should the image be tonemapped. Tonemapping converts an HDR image into LDR image by applying
  161. * a filmic curve to the image, simulating the effect of film cameras. Filmic curve improves image quality by
  162. * tapering off lows and highs, preventing under- and over-exposure. This is useful if an image contains both
  163. * very dark and very bright areas, in which case the global exposure parameter would leave some areas either over-
  164. * or under-exposed. Use ::tonemapping to customize how tonemapping performed.
  165. *
  166. * If this is disabled, then color grading and white balancing will not be enabled either. Only relevant for HDR
  167. * images.
  168. */
  169. bool enableTonemapping;
  170. /**
  171. * Parameters used for customizing tonemapping.
  172. *
  173. * @see enableTonemapping
  174. */
  175. TonemappingSettings tonemapping;
  176. /**
  177. * Parameters used for customizing white balancing. White balancing converts a scene illuminated by a light of the
  178. * specified temperature into a scene illuminated by a standard D65 illuminant (average midday light) in order to
  179. * simulate the effects of chromatic adaptation of the human visual system.
  180. */
  181. WhiteBalanceSettings whiteBalance;
  182. /** Parameters used for customizing color grading. */
  183. ColorGradingSettings colorGrading;
  184. /**
  185. * Log2 value to scale the eye adaptation by (e.g. 2^0 = 1). Smaller values yield darker image, while larger yield
  186. * brighter image. Allows you to customize exposure manually, applied on top of eye adaptation exposure (if
  187. * enabled). In range [-8, 8].
  188. */
  189. float exposureScale;
  190. /**
  191. * Gamma value to adjust the image for. Larger values result in a brighter image. When tonemapping is turned
  192. * on the best gamma curve for the output device is chosen automatically and this value can by used to merely tweak
  193. * that curve. If tonemapping is turned off this is the exact value of the gamma curve that will be applied.
  194. */
  195. float gamma;
  196. };
  197. /** Contains per-camera data used by post process effects. */
  198. struct PostProcessInfo
  199. {
  200. PostProcessSettings settings;
  201. SPtr<PooledRenderTexture> downsampledSceneTex;
  202. SPtr<PooledRenderTexture> histogramTex;
  203. SPtr<PooledRenderTexture> histogramReduceTex;
  204. SPtr<PooledRenderTexture> eyeAdaptationTex[2];
  205. SPtr<PooledRenderTexture> colorLUT;
  206. INT32 lastEyeAdaptationTex = 0;
  207. };
  208. BS_PARAM_BLOCK_BEGIN(DownsampleParams)
  209. BS_PARAM_BLOCK_ENTRY(Vector2, gInvTexSize)
  210. BS_PARAM_BLOCK_END
  211. /** Shader that downsamples a texture to half its size. */
  212. class DownsampleMat : public RendererMaterial<DownsampleMat>
  213. {
  214. RMAT_DEF("PPDownsample.bsl");
  215. public:
  216. DownsampleMat();
  217. /** Renders the post-process effect with the provided parameters. */
  218. void execute(const SPtr<RenderTextureCore>& target, PostProcessInfo& ppInfo);
  219. /** Releases the output render target. */
  220. void release(PostProcessInfo& ppInfo);
  221. /** Returns the render texture where the output will be written. */
  222. SPtr<RenderTextureCore> getOutput() const { return mOutput; }
  223. private:
  224. DownsampleParams mParams;
  225. MaterialParamVec2Core mInvTexSize;
  226. MaterialParamTextureCore mInputTexture;
  227. POOLED_RENDER_TEXTURE_DESC mOutputDesc;
  228. SPtr<RenderTextureCore> mOutput;
  229. };
  230. BS_PARAM_BLOCK_BEGIN(EyeAdaptHistogramParams)
  231. BS_PARAM_BLOCK_ENTRY(Vector4I, gPixelOffsetAndSize)
  232. BS_PARAM_BLOCK_ENTRY(Vector2, gHistogramParams)
  233. BS_PARAM_BLOCK_ENTRY(Vector2I, gThreadGroupCount)
  234. BS_PARAM_BLOCK_END
  235. /** Shader that creates a luminance histogram used for eye adaptation. */
  236. class EyeAdaptHistogramMat : public RendererMaterial<EyeAdaptHistogramMat>
  237. {
  238. RMAT_DEF("PPEyeAdaptHistogram.bsl");
  239. public:
  240. EyeAdaptHistogramMat();
  241. /** Executes the post-process effect with the provided parameters. */
  242. void execute(PostProcessInfo& ppInfo);
  243. /** Releases the output render target. */
  244. void release(PostProcessInfo& ppInfo);
  245. /** Returns the render texture where the output was written. */
  246. SPtr<RenderTextureCore> getOutput() const { return mOutput; }
  247. /** Calculates the number of thread groups that need to execute to cover the provided render target. */
  248. static Vector2I getThreadGroupCount(const SPtr<RenderTextureCore>& target);
  249. /**
  250. * Returns a vector containing scale and offset (in that order) that will be applied to luminance values
  251. * to determine their position in the histogram.
  252. */
  253. static Vector2 getHistogramScaleOffset(const PostProcessInfo& ppInfo);
  254. static const UINT32 THREAD_GROUP_SIZE_X = 8;
  255. static const UINT32 THREAD_GROUP_SIZE_Y = 8;
  256. static const UINT32 HISTOGRAM_NUM_TEXELS = (THREAD_GROUP_SIZE_X * THREAD_GROUP_SIZE_Y) / 4;
  257. private:
  258. EyeAdaptHistogramParams mParams;
  259. MaterialParamTextureCore mSceneColor;
  260. MaterialParamLoadStoreTextureCore mOutputTex;
  261. POOLED_RENDER_TEXTURE_DESC mOutputDesc;
  262. SPtr<RenderTextureCore> mOutput;
  263. static const UINT32 LOOP_COUNT_X = 8;
  264. static const UINT32 LOOP_COUNT_Y = 8;
  265. };
  266. BS_PARAM_BLOCK_BEGIN(EyeAdaptHistogramReduceParams)
  267. BS_PARAM_BLOCK_ENTRY(int, gThreadGroupCount)
  268. BS_PARAM_BLOCK_END
  269. /** Shader that reduces the luminance histograms created by EyeAdaptHistogramMat into a single histogram. */
  270. class EyeAdaptHistogramReduceMat : public RendererMaterial<EyeAdaptHistogramReduceMat>
  271. {
  272. RMAT_DEF("PPEyeAdaptHistogramReduce.bsl");
  273. public:
  274. EyeAdaptHistogramReduceMat();
  275. /** Executes the post-process effect with the provided parameters. */
  276. void execute(PostProcessInfo& ppInfo);
  277. /** Releases the output render target. */
  278. void release(PostProcessInfo& ppInfo);
  279. /** Returns the render texture where the output was written. */
  280. SPtr<RenderTextureCore> getOutput() const { return mOutput; }
  281. private:
  282. EyeAdaptHistogramReduceParams mParams;
  283. MaterialParamTextureCore mHistogramTex;
  284. MaterialParamTextureCore mEyeAdaptationTex;
  285. POOLED_RENDER_TEXTURE_DESC mOutputDesc;
  286. SPtr<RenderTextureCore> mOutput;
  287. };
  288. BS_PARAM_BLOCK_BEGIN(EyeAdaptationParams)
  289. BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gEyeAdaptationParams, 3)
  290. BS_PARAM_BLOCK_END
  291. /** Shader that computes the eye adaptation value based on scene luminance. */
  292. class EyeAdaptationMat : public RendererMaterial<EyeAdaptationMat>
  293. {
  294. RMAT_DEF("PPEyeAdaptation.bsl");
  295. public:
  296. EyeAdaptationMat();
  297. /** Executes the post-process effect with the provided parameters. */
  298. void execute(PostProcessInfo& ppInfo, float frameDelta);
  299. private:
  300. EyeAdaptationParams mParams;
  301. MaterialParamTextureCore mReducedHistogramTex;
  302. };
  303. BS_PARAM_BLOCK_BEGIN(CreateTonemapLUTParams)
  304. BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gTonemapParams, 2)
  305. BS_PARAM_BLOCK_ENTRY(float, gGammaAdjustment)
  306. BS_PARAM_BLOCK_ENTRY(int, gGammaCorrectionType)
  307. BS_PARAM_BLOCK_ENTRY(Vector3, gSaturation)
  308. BS_PARAM_BLOCK_ENTRY(Vector3, gContrast)
  309. BS_PARAM_BLOCK_ENTRY(Vector3, gGain)
  310. BS_PARAM_BLOCK_ENTRY(Vector3, gOffset)
  311. BS_PARAM_BLOCK_END
  312. BS_PARAM_BLOCK_BEGIN(WhiteBalanceParams)
  313. BS_PARAM_BLOCK_ENTRY(float, gWhiteTemp)
  314. BS_PARAM_BLOCK_ENTRY(float, gWhiteOffset)
  315. BS_PARAM_BLOCK_END
  316. /**
  317. * Shader that creates a 3D lookup texture that is used to apply tonemapping, color grading, white balancing and gamma
  318. * correction.
  319. */
  320. class CreateTonemapLUTMat : public RendererMaterial<CreateTonemapLUTMat>
  321. {
  322. RMAT_DEF("PPCreateTonemapLUT.bsl");
  323. public:
  324. CreateTonemapLUTMat();
  325. /** Executes the post-process effect with the provided parameters. */
  326. void execute(PostProcessInfo& ppInfo);
  327. /** Releases the output render target. */
  328. void release(PostProcessInfo& ppInfo);
  329. /** Size of the 3D color lookup table. */
  330. static const UINT32 LUT_SIZE = 32;
  331. private:
  332. CreateTonemapLUTParams mParams;
  333. WhiteBalanceParams mWhiteBalanceParams;
  334. };
  335. BS_PARAM_BLOCK_BEGIN(TonemappingParams)
  336. BS_PARAM_BLOCK_ENTRY(float, gRawGamma)
  337. BS_PARAM_BLOCK_ENTRY(float, gManualExposureScale)
  338. BS_PARAM_BLOCK_END
  339. /** Shader that applies tonemapping and converts a HDR image into a LDR image. */
  340. template<bool GammaOnly, bool AutoExposure>
  341. class TonemappingMat : public RendererMaterial<TonemappingMat<GammaOnly, AutoExposure>>
  342. {
  343. RMAT_DEF("PPTonemapping.bsl");
  344. public:
  345. TonemappingMat();
  346. /** Executes the post-process effect with the provided parameters. */
  347. void execute(const SPtr<RenderTextureCore>& sceneColor, const SPtr<ViewportCore>& outputViewport,
  348. PostProcessInfo& ppInfo);
  349. private:
  350. TonemappingParams mParams;
  351. MaterialParamTextureCore mInputTex;
  352. MaterialParamTextureCore mColorLUT;
  353. MaterialParamTextureCore mEyeAdaptationTex;
  354. };
  355. /**
  356. * Renders post-processing effects for the provided render target.
  357. *
  358. * @note Core thread only.
  359. */
  360. class BS_BSRND_EXPORT PostProcessing : public Module<PostProcessing>
  361. {
  362. public:
  363. /** Renders post-processing effects for the provided render target. */
  364. void postProcess(const SPtr<RenderTextureCore>& sceneColor, const SPtr<ViewportCore>& outputViewport,
  365. PostProcessInfo& ppInfo, float frameDelta);
  366. private:
  367. DownsampleMat mDownsample;
  368. EyeAdaptHistogramMat mEyeAdaptHistogram;
  369. EyeAdaptHistogramReduceMat mEyeAdaptHistogramReduce;
  370. EyeAdaptationMat mEyeAdaptation;
  371. CreateTonemapLUTMat mCreateLUT;
  372. TonemappingMat<false, true> mTonemapping_AE;
  373. TonemappingMat<true, true> mTonemapping_AE_GO;
  374. TonemappingMat<false, false> mTonemapping;
  375. TonemappingMat<true, false> mTonemapping_GO;
  376. };
  377. /** @} */
  378. }