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 | |
11 | namespace 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 | |