BsRenderBeastIBLUtility.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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. Vector<ShaderVariation::Param>{
  102. ShaderVariation::Param("SH_ORDER", shOrder)
  103. });
  104. return variation;
  105. }
  106. public:
  107. IrradianceComputeSHMat();
  108. /**
  109. * Computes spherical harmonic coefficients from a radiance texture and outputs a buffer containing a list of
  110. * coefficient sets (one set of coefficients for each thread group). Coefficients must be reduced and normalized
  111. * by IrradianceReduceSHMat before use. Output buffer should be created by calling createOutputBuffer().
  112. */
  113. void execute(const SPtr<Texture>& source, UINT32 face, const SPtr<GpuBuffer>& output);
  114. /** Creates a buffer of adequate size to be used as output for this material. */
  115. SPtr<GpuBuffer> createOutputBuffer(const SPtr<Texture>& source, UINT32& numCoeffSets);
  116. /**
  117. * Returns the material variation matching the provided parameters.
  118. *
  119. * @param order SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are
  120. * supported.
  121. */
  122. static IrradianceComputeSHMat* getVariation(int order = 5);
  123. private:
  124. SPtr<GpuParamBlockBuffer> mParamBuffer;
  125. GpuParamTexture mInputTexture;
  126. GpuParamBuffer mOutputBuffer;
  127. };
  128. BS_PARAM_BLOCK_BEGIN(IrradianceReduceSHParamDef)
  129. BS_PARAM_BLOCK_ENTRY(Vector2I, gOutputIdx)
  130. BS_PARAM_BLOCK_ENTRY(int, gNumEntries)
  131. BS_PARAM_BLOCK_END
  132. extern IrradianceReduceSHParamDef gIrradianceReduceSHParamDef;
  133. /**
  134. * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a single
  135. * set of normalized coefficients.
  136. */
  137. class IrradianceReduceSHMat : public RendererMaterial<IrradianceReduceSHMat>
  138. {
  139. RMAT_DEF("IrradianceReduceSH.bsl")
  140. /** Helper method used for initializing variations of this material. */
  141. template<int shOrder>
  142. static const ShaderVariation& getVariation()
  143. {
  144. static ShaderVariation variation = ShaderVariation(
  145. Vector<ShaderVariation::Param>{
  146. ShaderVariation::Param("SH_ORDER", shOrder)
  147. });
  148. return variation;
  149. }
  150. public:
  151. IrradianceReduceSHMat();
  152. /**
  153. * Sums spherical harmonic coefficients calculated by each thread group of IrradianceComputeSHMat and outputs a
  154. * single set of normalized coefficients. Output texture should be created by calling createOutputTexture(). The
  155. * value will be recorded at the @p outputIdx position in the texture.
  156. */
  157. void execute(const SPtr<GpuBuffer>& source, UINT32 numCoeffSets, const SPtr<Texture>& output, UINT32 outputIdx);
  158. /** Creates a texture of adequate size to be used as output for this material. */
  159. SPtr<Texture> createOutputTexture(UINT32 numCoeffSets);
  160. /**
  161. * Returns the material variation matching the provided parameters.
  162. *
  163. * @param order SH order, which defines the number of coefficients and quality. Only values of 3 and 5 are
  164. * supported.
  165. */
  166. static IrradianceReduceSHMat* getVariation(int order = 5);
  167. private:
  168. SPtr<GpuParamBlockBuffer> mParamBuffer;
  169. GpuParamBuffer mInputBuffer;
  170. GpuParamLoadStoreTexture mOutputTexture;
  171. };
  172. BS_PARAM_BLOCK_BEGIN(IrradianceComputeSHFragParamDef)
  173. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  174. BS_PARAM_BLOCK_ENTRY(int, gFaceSize)
  175. BS_PARAM_BLOCK_ENTRY(int, gCoeffEntryIdx)
  176. BS_PARAM_BLOCK_ENTRY(int, gCoeffComponentIdx)
  177. BS_PARAM_BLOCK_END
  178. extern IrradianceComputeSHFragParamDef gIrradianceComputeSHFragParamDef;
  179. /**
  180. * Computes spherical harmonic coefficients from a radiance cubemap. This is an alternative to IrradianceComputeSHMat
  181. * that does not require compute shader support.
  182. */
  183. class IrradianceComputeSHFragMat : public RendererMaterial<IrradianceComputeSHFragMat>
  184. {
  185. RMAT_DEF("IrradianceComputeSHFrag.bsl")
  186. public:
  187. IrradianceComputeSHFragMat();
  188. /**
  189. * Computes spherical harmonic coefficients from a face of an input cube radiance texture and outputs them to the
  190. * specified face of the output cube texture. Only a single coefficient is output per execution. The output texture
  191. * will contain the coefficients for red, green and blue channels in the corresponding texture channels, and
  192. * per-texel weight in the alpha channel. Output coefficients must be summed up and normalized before use (using
  193. * IrradianceAccumulateCubeSH).
  194. */
  195. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 coefficientIdx, const SPtr<RenderTarget>& output);
  196. /**
  197. * Returns the texture descriptor that can be used for initializing the output render target. Note that the
  198. * output texture is a cubemap but the execute() method expects a render target that is a single face of a
  199. * cubemap.
  200. */
  201. static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& source);
  202. private:
  203. SPtr<GpuParamBlockBuffer> mParamBuffer;
  204. GpuParamTexture mInputTexture;
  205. };
  206. BS_PARAM_BLOCK_BEGIN(IrradianceAccumulateSHParamDef)
  207. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  208. BS_PARAM_BLOCK_ENTRY(int, gCubeMip)
  209. BS_PARAM_BLOCK_ENTRY(Vector2, gHalfPixel)
  210. BS_PARAM_BLOCK_END
  211. extern IrradianceAccumulateSHParamDef gIrradianceAccumulateSHParamDef;
  212. /**
  213. * Downsamples a cubemap face containing SH coefficient and weight values as output by IrradianceComputeSHFragMat. Each
  214. * downsample sums up 2x2 pixel area coefficients/weights from the previous mip level.
  215. */
  216. class IrradianceAccumulateSHMat : public RendererMaterial<IrradianceAccumulateSHMat>
  217. {
  218. RMAT_DEF("IrradianceAccumulateSH.bsl")
  219. public:
  220. IrradianceAccumulateSHMat();
  221. /**
  222. * Downsamples the provided face and mip level of the source texture and outputs the downsampled (i.e summed up)
  223. * values in the resulting output texture.
  224. */
  225. void execute(const SPtr<Texture>& source, UINT32 face, UINT32 sourceMip, const SPtr<RenderTarget>& output);
  226. /**
  227. * Returns the texture descriptor that can be used for initializing the output render target. Note the output
  228. * is a cubemap.
  229. */
  230. static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& source);
  231. private:
  232. SPtr<GpuParamBlockBuffer> mParamBuffer;
  233. GpuParamTexture mInputTexture;
  234. };
  235. /**
  236. * Accumulates SH coefficient values from all six faces of a cubemap and normalizes them. The cubemap is expected to be
  237. * 1x1 in size (previously downsampled by IrradianceAccumulateSHMat). After this shader is ran for all SH coefficients
  238. * the output texture will contain final valid set of SH coefficients.
  239. */
  240. class IrradianceAccumulateCubeSHMat : public RendererMaterial<IrradianceAccumulateCubeSHMat>
  241. {
  242. RMAT_DEF("IrradianceAccumulateCubeSH.bsl")
  243. public:
  244. IrradianceAccumulateCubeSHMat();
  245. /**
  246. * Sums up all faces of the input cube texture and writes the value to the corresponding index in the output
  247. * texture. The source mip should point to a mip level with size 1x1.
  248. */
  249. void execute(const SPtr<Texture>& source, UINT32 sourceMip, const Vector2I& outputOffset, UINT32 coefficientIdx,
  250. const SPtr<RenderTarget>& output);
  251. /**
  252. * Returns the texture descriptor that can be used for initializing the output render target. The render target
  253. * will be able to hold all required SH coefficients (even though execute() outputs just one coefficient at a time).
  254. */
  255. static POOLED_RENDER_TEXTURE_DESC getOutputDesc();
  256. private:
  257. SPtr<GpuParamBlockBuffer> mParamBuffer;
  258. GpuParamTexture mInputTexture;
  259. };
  260. BS_PARAM_BLOCK_BEGIN(IrradianceProjectSHParamDef)
  261. BS_PARAM_BLOCK_ENTRY(int, gCubeFace)
  262. BS_PARAM_BLOCK_END
  263. extern IrradianceProjectSHParamDef gIrradianceProjectSHParamDef;
  264. /**
  265. * Projects spherical harmonic coefficients calculated by IrradianceReduceSHMat and projects them onto faces of
  266. * a cubemap.
  267. */
  268. class IrradianceProjectSHMat : public RendererMaterial<IrradianceProjectSHMat>
  269. {
  270. RMAT_DEF("IrradianceProjectSH.bsl")
  271. public:
  272. IrradianceProjectSHMat();
  273. /**
  274. * Projects spherical harmonic coefficients calculated by IrradianceReduceSHMat and projects them onto faces of
  275. * a cubemap.
  276. */
  277. void execute(const SPtr<Texture>& shCoeffs, UINT32 face, const SPtr<RenderTarget>& target);
  278. private:
  279. SPtr<GpuParamBlockBuffer> mParamBuffer;
  280. GpuParamTexture mInputTexture;
  281. };
  282. /** Render beast implementation of IBLUtility. */
  283. class RenderBeastIBLUtility : public IBLUtility
  284. {
  285. public:
  286. /** @copydoc IBLUtility::filterCubemapForSpecular */
  287. void filterCubemapForSpecular(const SPtr<Texture>& cubemap, const SPtr<Texture>& scratch) const override;
  288. /** @copydoc IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>&, const SPtr<Texture>&) const */
  289. void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output) const override;
  290. /** @copydoc IBLUtility::filterCubemapForIrradiance(const SPtr<Texture>&, const SPtr<Texture>&, UINT32) const */
  291. void filterCubemapForIrradiance(const SPtr<Texture>& cubemap, const SPtr<Texture>& output,
  292. UINT32 outputIdx) const override;
  293. /** @copydoc IBLUtility::scaleCubemap */
  294. void scaleCubemap(const SPtr<Texture>& src, UINT32 srcMip, const SPtr<Texture>& dst, UINT32 dstMip) const override;
  295. private:
  296. /**
  297. * Downsamples a cubemap using hardware bilinear filtering.
  298. *
  299. * @param[in] src Cubemap to downsample.
  300. * @param[in] srcMip Determines which mip level of the source texture to downsample.
  301. * @param[in] dst Desination texture to output the scaled data to. Must be usable as a render target.
  302. * @param[in] dstMip Determines which mip level of the destination texture to scale.
  303. */
  304. static void downsampleCubemap(const SPtr<Texture>& src, UINT32 srcMip, const SPtr<Texture>& dst, UINT32 dstMip);
  305. /**
  306. * Generates irradiance SH coefficients from the input cubemap and writes them to a 1D texture. Does not make
  307. * use of the compute shader.
  308. */
  309. static void filterCubemapForIrradianceNonCompute(const SPtr<Texture>& cubemap, UINT32 outputIdx,
  310. const SPtr<RenderTexture>& output);
  311. };
  312. /** @} */
  313. }}