BsRenderBeastIBLUtility.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisites.h"
  5. #include "Renderer/BsIBLUtility.h"
  6. #include "Renderer/BsRendererMaterial.h"
  7. #include "Renderer/BsParamBlocks.h"
  8. #include "BsGpuResourcePool.h"
  9. namespace bs { namespace ct
  10. {
  11. /** @addtogroup RenderBeast
  12. * @{
  13. */
  14. BS_PARAM_BLOCK_BEGIN(ReflectionCubeDownsampleParamDef)
  15. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  16. BS_PARAM_BLOCK_ENTRY(int, gMipLevel)
  17. BS_PARAM_BLOCK_END
  18. extern ReflectionCubeDownsampleParamDef gReflectionCubeDownsampleParamDef;
  19. /** Performs filtering on cubemap faces in order to prepare them for importance sampling. */
  20. class ReflectionCubeDownsampleMat : public RendererMaterial<ReflectionCubeDownsampleMat>
  21. {
  22. RMAT_DEF("ReflectionCubeDownsample.bsl")
  23. public:
  24. ReflectionCubeDownsampleMat();
  25. /** Downsamples the provided texture face and outputs it to the provided target. */
  26. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 mip, const SPtr<RenderTarget>& target);
  27. private:
  28. SPtr<GpuParamBlockBuffer> mParamBuffer;
  29. GpuParamTexture mInputTexture;
  30. };
  31. BS_PARAM_BLOCK_BEGIN(ReflectionCubeImportanceSampleParamDef)
  32. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  33. BS_PARAM_BLOCK_ENTRY(int, gMipLevel)
  34. BS_PARAM_BLOCK_ENTRY(int, gNumMips)
  35. BS_PARAM_BLOCK_ENTRY(float, gPrecomputedMipFactor)
  36. BS_PARAM_BLOCK_END
  37. extern ReflectionCubeImportanceSampleParamDef gReflectionCubeImportanceSampleParamDef;
  38. /** Performs importance sampling on cubemap faces in order for make them suitable for specular evaluation. */
  39. class ReflectionCubeImportanceSampleMat : public RendererMaterial<ReflectionCubeImportanceSampleMat>
  40. {
  41. RMAT_DEF_CUSTOMIZED("ReflectionCubeImportanceSample.bsl")
  42. public:
  43. ReflectionCubeImportanceSampleMat();
  44. /** Importance samples the provided texture face and outputs it to the provided target. */
  45. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 mip, const SPtr<RenderTarget>& target);
  46. private:
  47. static const UINT32 NUM_SAMPLES;
  48. SPtr<GpuParamBlockBuffer> mParamBuffer;
  49. GpuParamTexture mInputTexture;
  50. };
  51. /** Vector representing spherical harmonic coefficients for 5 bands. */
  52. struct SHVector5
  53. {
  54. SHVector5()
  55. :coeffs()
  56. { }
  57. float coeffs[25];
  58. };
  59. /** Vector representing spherical coefficients for 5 bands, separate for red, green and blue components. */
  60. struct SHVector5RGB
  61. {
  62. SHVector5 R, G, B;
  63. };
  64. /** Vector representing spherical harmonic coefficients for 3 bands. */
  65. struct SHVector3
  66. {
  67. float coeffs[9];
  68. };
  69. /** Vector representing spherical coefficients for 3 bands, separate for red, green and blue components. */
  70. struct SHVector3RGB
  71. {
  72. SHVector3 R, G, B;
  73. };
  74. /** Intermediate structure used for spherical coefficient calculation. Contains RGB coefficients and weight. */
  75. struct SHCoeffsAndWeight5
  76. {
  77. SHVector5RGB coeffs;
  78. float weight;
  79. };
  80. /** Intermediate structure used for spherical coefficient calculation. Contains RGB coefficients and weight. */
  81. struct SHCoeffsAndWeight3
  82. {
  83. SHVector3RGB coeffs;
  84. float weight;
  85. };
  86. BS_PARAM_BLOCK_BEGIN(IrradianceComputeSHParamDef)
  87. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  88. BS_PARAM_BLOCK_ENTRY(int, gFaceSize)
  89. BS_PARAM_BLOCK_ENTRY(Vector2I, gDispatchSize)
  90. BS_PARAM_BLOCK_END
  91. extern IrradianceComputeSHParamDef gIrradianceComputeSHParamDef;
  92. /** Computes spherical harmonic coefficients from a radiance cubemap. */
  93. class IrradianceComputeSHMat : public RendererMaterial<IrradianceComputeSHMat>
  94. {
  95. RMAT_DEF_CUSTOMIZED("IrradianceComputeSH.bsl")
  96. /** Helper method used for initializing variations of this material. */
  97. template<int shOrder>
  98. static const ShaderVariation& getVariation()
  99. {
  100. static ShaderVariation variation = ShaderVariation({
  101. ShaderVariation::Param("SH_ORDER", shOrder)
  102. });
  103. return variation;
  104. }
  105. public:
  106. IrradianceComputeSHMat();
  107. /**
  108. * Computes spherical harmonic coefficients from a radiance texture and outputs a buffer containing a list of
  109. * coefficient sets (one set of coefficients for each thread group). Coefficients must be reduced and normalized
  110. * by IrradianceReduceSHMat before use. Output buffer should be created by calling createOutputBuffer().
  111. */
  112. void execute(const SPtr<Texture>& source, UINT32 face, const SPtr<GpuBuffer>& output);
  113. /** Creates a buffer of adequate size to be used as output for this material. */
  114. SPtr<GpuBuffer> createOutputBuffer(const SPtr<Texture>& source, UINT32& numCoeffSets);
  115. /**
  116. * Returns the material variation matching the provided parameters.
  117. *
  118. * @param order SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are
  119. * supported.
  120. */
  121. static IrradianceComputeSHMat* getVariation(int order = 5);
  122. private:
  123. SPtr<GpuParamBlockBuffer> mParamBuffer;
  124. GpuParamTexture mInputTexture;
  125. GpuParamBuffer mOutputBuffer;
  126. };
  127. BS_PARAM_BLOCK_BEGIN(IrradianceReduceSHParamDef)
  128. BS_PARAM_BLOCK_ENTRY(Vector2I, gOutputIdx)
  129. BS_PARAM_BLOCK_ENTRY(int, gNumEntries)
  130. BS_PARAM_BLOCK_END
  131. extern IrradianceReduceSHParamDef gIrradianceReduceSHParamDef;
  132. /**
  133. * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a single
  134. * set of normalized coefficients.
  135. */
  136. class IrradianceReduceSHMat : public RendererMaterial<IrradianceReduceSHMat>
  137. {
  138. RMAT_DEF("IrradianceReduceSH.bsl")
  139. /** Helper method used for initializing variations of this material. */
  140. template<int shOrder>
  141. static const ShaderVariation& getVariation()
  142. {
  143. static ShaderVariation variation = ShaderVariation({
  144. ShaderVariation::Param("SH_ORDER", shOrder)
  145. });
  146. return variation;
  147. }
  148. public:
  149. IrradianceReduceSHMat();
  150. /**
  151. * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a
  152. * single set of normalized coefficients. Output texture should be created by calling createOutputTexture(). The
  153. * value will be recorded at the @p outputIdx position in the texture.
  154. */
  155. void execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, const SPtr<Texture>& output, UINT32 outputIdx);
  156. /** Creates a texture of adequate size to be used as output for this material. */
  157. SPtr<Texture> createOutputTexture(UINT32 numCoeffSets);
  158. /**
  159. * Returns the material variation matching the provided parameters.
  160. *
  161. * @param order SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are
  162. * supported.
  163. */
  164. static IrradianceReduceSHMat* getVariation(int order = 5);
  165. private:
  166. SPtr<GpuParamBlockBuffer> mParamBuffer;
  167. GpuParamBuffer mInputBuffer;
  168. GpuParamLoadStoreTexture mOutputTexture;
  169. };
  170. BS_PARAM_BLOCK_BEGIN(IrradianceComputeSHFragParamDef)
  171. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  172. BS_PARAM_BLOCK_ENTRY(int, gFaceSize)
  173. BS_PARAM_BLOCK_ENTRY(int, gCoeffIdx)
  174. BS_PARAM_BLOCK_END
  175. extern IrradianceComputeSHFragParamDef gIrradianceComputeSHFragParamDef;
  176. /**
  177. * Computes spherical harmonic coefficients from a radiance cubemap. This is an alternative to IrradianceComputeSHMat
  178. * that does not require compute shader support.
  179. */
  180. class IrradianceComputeSHFragMat : public RendererMaterial<IrradianceComputeSHFragMat>
  181. {
  182. RMAT_DEF("IrradianceComputeSHFrag.bsl")
  183. public:
  184. IrradianceComputeSHFragMat();
  185. /**
  186. * Computes spherical harmonic coefficients from a face of an input cube radiance texture and outputs them to the
  187. * specified face of the output cube texture. Only a single coefficient is output per execution. The output texture
  188. * will contain the coefficients for red, green and blue channels in the corresponding texture channels, and
  189. * per-texel weight in the alpha channel. Output coefficients must be summed up and normalized before use (using
  190. * IrradianceAccumulateCubeSH).
  191. */
  192. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 coefficientIdx, const SPtr<RenderTarget>& output);
  193. /**
  194. * Returns the texture descriptor that can be used for initializing the output render target. Note that the
  195. * output texture is a cubemap but the execute() method expects a render target that is a single face of a
  196. * cubemap.
  197. */
  198. static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& source);
  199. private:
  200. SPtr<GpuParamBlockBuffer> mParamBuffer;
  201. GpuParamTexture mInputTexture;
  202. };
  203. BS_PARAM_BLOCK_BEGIN(IrradianceAccumulateSHParamDef)
  204. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  205. BS_PARAM_BLOCK_ENTRY(int, gCubeMip)
  206. BS_PARAM_BLOCK_ENTRY(Vector2, gHalfPixel)
  207. BS_PARAM_BLOCK_END
  208. extern IrradianceAccumulateSHParamDef gIrradianceAccumulateSHParamDef;
  209. /**
  210. * Downsamples a cubemap face containing SH coefficient and weight values as output by IrradianceComputeSHFragMat. Each
  211. * downsample sums up 2x2 pixel area coefficients/weights from the previous mip level.
  212. */
  213. class IrradianceAccumulateSHMat : public RendererMaterial<IrradianceAccumulateSHMat>
  214. {
  215. RMAT_DEF("IrradianceAccumulateSH.bsl")
  216. public:
  217. IrradianceAccumulateSHMat();
  218. /**
  219. * Downsamples the provided face and mip level of the source texture and outputs the downsampled (i.e summed up)
  220. * values in the resulting output texture.
  221. */
  222. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 sourceMip, const SPtr<RenderTarget>& output);
  223. /**
  224. * Returns the texture descriptor that can be used for initializing the output render target. Note the output
  225. * is a cubemap.
  226. */
  227. static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& source);
  228. private:
  229. SPtr<GpuParamBlockBuffer> mParamBuffer;
  230. GpuParamTexture mInputTexture;
  231. };
  232. /**
  233. * Accumulates SH coefficient values from all six faces of a cubemap and normalizes them. The cubemap is expected to be
  234. * 1x1 in size (previously downsampled by IrradianceAccumulateSHMat). After this shader is ran for all SH coefficients
  235. * the output texture will contain final valid set of SH coefficients.
  236. */
  237. class IrradianceAccumulateCubeSHMat : public RendererMaterial<IrradianceAccumulateCubeSHMat>
  238. {
  239. RMAT_DEF("IrradianceAccumulateCubeSH.bsl")
  240. public:
  241. IrradianceAccumulateCubeSHMat();
  242. /**
  243. * Sums up all faces of the input cube texture and writes the value to the corresponding index in the output
  244. * texture. The source mip should point to a mip level with size 1x1.
  245. */
  246. void execute(const SPtr<Texture>& source, UINT32 sourceMip, const Vector2I& outputOffset, UINT32 coefficientIdx,
  247. const SPtr<RenderTarget>& output);
  248. /**
  249. * Returns the texture descriptor that can be used for initializing the output render target. The render target
  250. * will be able to hold all required SH coefficients (even though execute() outputs just one coefficient at a time).
  251. */
  252. static POOLED_RENDER_TEXTURE_DESC getOutputDesc();
  253. private:
  254. SPtr<GpuParamBlockBuffer> mParamBuffer;
  255. GpuParamTexture mInputTexture;
  256. };
  257. BS_PARAM_BLOCK_BEGIN(IrradianceProjectSHParamDef)
  258. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  259. BS_PARAM_BLOCK_END
  260. extern IrradianceProjectSHParamDef gIrradianceProjectSHParamDef;
  261. /**
  262. * Projects spherical harmonic coefficients calculated by IrradianceReduceSHMat and projects them onto faces of
  263. * a cubemap.
  264. */
  265. class IrradianceProjectSHMat : public RendererMaterial<IrradianceProjectSHMat>
  266. {
  267. RMAT_DEF("IrradianceProjectSH.bsl")
  268. public:
  269. IrradianceProjectSHMat();
  270. /**
  271. * Projects spherical harmonic coefficients calculated by IrradianceReduceSHMat and projects them onto faces of
  272. * a cubemap.
  273. */
  274. void execute(const SPtr<Texture>& shCoeffs, UINT32 face, const SPtr<RenderTarget>& target);
  275. private:
  276. SPtr<GpuParamBlockBuffer> mParamBuffer;
  277. GpuParamTexture mInputTexture;
  278. };
  279. /** Render beast implementation of IBLUtility. */
  280. class RenderBeastIBLUtility : public IBLUtility
  281. {
  282. public:
  283. /** @copydoc IBLUtility::filterCubemapForSpecular */
  284. void filterCubemapForSpecular(const SPtr<Texture>& cubemap, const SPtr<Texture>& scratch) const override;
  285. /** @copydoc IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>&, const SPtr<Texture>&) */
  286. void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output) const override;
  287. /** @copydoc IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>&, const SPtr<GpuBuffer>&, UINT32) */
  288. void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output,
  289. UINT32 outputIdx) const override;
  290. /** @copydoc IBLUtility::scaleCubemap */
  291. void scaleCubemap(const SPtr<Texture>& src, UINT32 srcMip, const SPtr<Texture>& dst, UINT32 dstMip) const override;
  292. private:
  293. /**
  294. * Downsamples a cubemap using hardware bilinear filtering.
  295. *
  296. * @param[in] src Cubemap to downsample.
  297. * @param[in] srcMip Determines which mip level of the source texture to downsample.
  298. * @param[in] dst Desination texture to output the scaled data to. Must be usable as a render target.
  299. * @param[in] dstMip Determines which mip level of the destination texture to scale.
  300. */
  301. static void downsampleCubemap(const SPtr<Texture>& src, UINT32 srcMip, const SPtr<Texture>& dst, UINT32 dstMip);
  302. /**
  303. * Generates irradiance SH coefficients from the input cubemap and writes them to a 1D texture. Does not make
  304. * use of the compute shader.
  305. */
  306. static void filterCubemapForIrradianceNonCompute(const SPtr<Texture>& cubemap, UINT32 outputIdx,
  307. const SPtr<RenderTexture>& output);
  308. };
  309. /** @} */
  310. }}