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