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 "BsRenderBeastPrerequisites.h"
6#include "Renderer/BsRendererMaterial.h"
7#include "Renderer/BsParamBlocks.h"
8#include "Renderer/BsRenderSettings.h"
9#include "Renderer/BsGpuResourcePool.h"
10#include "BsRendererLight.h"
11
12namespace bs { namespace ct
13{
14 struct RendererViewTargetData;
15
16 /** @addtogroup RenderBeast
17 * @{
18 */
19
20 BS_PARAM_BLOCK_BEGIN(DownsampleParamDef)
21 BS_PARAM_BLOCK_ENTRY_ARRAY(Vector2, gOffsets, 4)
22 BS_PARAM_BLOCK_END
23
24 extern DownsampleParamDef gDownsampleParamDef;
25
26 /** Shader that downsamples a texture to half its size. */
27 class DownsampleMat : public RendererMaterial<DownsampleMat>
28 {
29 RMAT_DEF("PPDownsample.bsl");
30
31 /** Helper method used for initializing variations of this material. */
32 template<UINT32 quality, bool MSAA>
33 static const ShaderVariation& getVariation()
34 {
35 static ShaderVariation variation = ShaderVariation(
36 {
37 ShaderVariation::Param("QUALITY", quality),
38 ShaderVariation::Param("MSAA", MSAA)
39 });
40
41 return variation;
42 };
43
44 public:
45 DownsampleMat();
46
47 /** Renders the post-process effect with the provided parameters. */
48 void execute(const SPtr<Texture>& input, const SPtr<RenderTarget>& output);
49
50 /** Returns the texture descriptor that can be used for initializing the output render target. */
51 static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& target);
52
53 /** Returns the downsample material variation matching the provided parameters. */
54 static DownsampleMat* getVariation(UINT32 quality, bool msaa);
55
56 private:
57 SPtr<GpuParamBlockBuffer> mParamBuffer;
58 GpuParamTexture mInputTexture;
59 };
60
61 BS_PARAM_BLOCK_BEGIN(EyeAdaptHistogramParamDef)
62 BS_PARAM_BLOCK_ENTRY(Vector4I, gPixelOffsetAndSize)
63 BS_PARAM_BLOCK_ENTRY(Vector2, gHistogramParams)
64 BS_PARAM_BLOCK_ENTRY(Vector2I, gThreadGroupCount)
65 BS_PARAM_BLOCK_END
66
67 extern EyeAdaptHistogramParamDef gEyeAdaptHistogramParamDef;
68
69 /** Shader that creates a luminance histogram used for eye adaptation. */
70 class EyeAdaptHistogramMat : public RendererMaterial<EyeAdaptHistogramMat>
71 {
72 RMAT_DEF_CUSTOMIZED("PPEyeAdaptHistogram.bsl");
73
74 public:
75 EyeAdaptHistogramMat();
76
77 /** Executes the post-process effect with the provided parameters. */
78 void execute(const SPtr<Texture>& input, const SPtr<Texture>& output, const AutoExposureSettings& settings);
79
80 /** Returns the texture descriptor that can be used for initializing the output render target. */
81 static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& target);
82
83 /** Calculates the number of thread groups that need to execute to cover the provided texture. */
84 static Vector2I getThreadGroupCount(const SPtr<Texture>& target);
85
86 /**
87 * Returns a vector containing scale and offset (in that order) that will be applied to luminance values
88 * to determine their position in the histogram.
89 */
90 static Vector2 getHistogramScaleOffset(const AutoExposureSettings& settings);
91
92 static const UINT32 THREAD_GROUP_SIZE_X = 8;
93 static const UINT32 THREAD_GROUP_SIZE_Y = 8;
94
95 static const UINT32 HISTOGRAM_NUM_TEXELS = (THREAD_GROUP_SIZE_X * THREAD_GROUP_SIZE_Y) / 4;
96 private:
97 SPtr<GpuParamBlockBuffer> mParamBuffer;
98 GpuParamTexture mSceneColor;
99 GpuParamLoadStoreTexture mOutputTex;
100
101 static const UINT32 LOOP_COUNT_X = 8;
102 static const UINT32 LOOP_COUNT_Y = 8;
103 };
104
105 BS_PARAM_BLOCK_BEGIN(EyeAdaptHistogramReduceParamDef)
106 BS_PARAM_BLOCK_ENTRY(int, gThreadGroupCount)
107 BS_PARAM_BLOCK_END
108
109 extern EyeAdaptHistogramReduceParamDef gEyeAdaptHistogramReduceParamDef;
110
111 /** Shader that reduces the luminance histograms created by EyeAdaptHistogramMat into a single histogram. */
112 class EyeAdaptHistogramReduceMat : public RendererMaterial<EyeAdaptHistogramReduceMat>
113 {
114 RMAT_DEF("PPEyeAdaptHistogramReduce.bsl");
115
116 public:
117 EyeAdaptHistogramReduceMat();
118
119 /** Executes the post-process effect with the provided parameters. */
120 void execute(const SPtr<Texture>& sceneColor, const SPtr<Texture>& histogram, const SPtr<Texture>& prevFrame,
121 const SPtr<RenderTarget>& output);
122
123 /** Returns the texture descriptor that can be used for initializing the output render target. */
124 static POOLED_RENDER_TEXTURE_DESC getOutputDesc();
125 private:
126 SPtr<GpuParamBlockBuffer> mParamBuffer;
127
128 GpuParamTexture mHistogramTex;
129 GpuParamTexture mEyeAdaptationTex;
130 };
131
132 BS_PARAM_BLOCK_BEGIN(EyeAdaptationParamDef)
133 BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gEyeAdaptationParams, 3)
134 BS_PARAM_BLOCK_END
135
136 extern EyeAdaptationParamDef gEyeAdaptationParamDef;
137
138 /** Shader that computes the eye adaptation value based on scene luminance. */
139 class EyeAdaptationMat : public RendererMaterial<EyeAdaptationMat>
140 {
141 RMAT_DEF_CUSTOMIZED("PPEyeAdaptation.bsl");
142
143 public:
144 EyeAdaptationMat();
145
146 /** Executes the post-process effect with the provided parameters. */
147 void execute(const SPtr<Texture>& reducedHistogram, const SPtr<RenderTarget>& output, float frameDelta,
148 const AutoExposureSettings& settings, float exposureScale);
149
150 /** Returns the texture descriptor that can be used for initializing the output render target. */
151 static POOLED_RENDER_TEXTURE_DESC getOutputDesc();
152
153 /**
154 * Populates the provided paramater buffer with eye adaptation parameters. The parameter buffer is expected to be
155 * created with EyeAdaptationParamDef block definition.
156 */
157 static void populateParams(const SPtr<GpuParamBlockBuffer>& paramBuffer, float frameDelta,
158 const AutoExposureSettings& settings, float exposureScale);
159 private:
160 SPtr<GpuParamBlockBuffer> mParamBuffer;
161 GpuParamTexture mReducedHistogramTex;
162 };
163
164 /**
165 * Shader that computes luminance of all the pixels in the provided texture, and stores them in log2 format, scaled
166 * to [0, 1] range (according to eye adapatation parameters) and stores those values in the alpha channel of the
167 * output texture. Color channel is just a copy of the input texture. Resulting texture is intended to be provided
168 * to the downsampling shader in order to calculate the average luminance, used for non-histogram eye adaptation
169 * calculation (when compute shader is not available).
170 */
171 class EyeAdaptationBasicSetupMat : public RendererMaterial<EyeAdaptationBasicSetupMat>
172 {
173 RMAT_DEF("PPEyeAdaptationBasicSetup.bsl");
174
175 public:
176 EyeAdaptationBasicSetupMat();
177
178 /** Executes the post-process effect with the provided parameters. */
179 void execute(const SPtr<Texture>& input, const SPtr<RenderTarget>& output, float frameDelta,
180 const AutoExposureSettings& settings, float exposureScale);
181
182 /** Returns the texture descriptor that can be used for initializing the output render target. */
183 static POOLED_RENDER_TEXTURE_DESC getOutputDesc(const SPtr<Texture>& input);
184 private:
185 SPtr<GpuParamBlockBuffer> mParamBuffer;
186 GpuParamTexture mInputTex;
187 };
188
189 BS_PARAM_BLOCK_BEGIN(EyeAdaptationBasicParamsMatDef)
190 BS_PARAM_BLOCK_ENTRY(Vector2I, gInputTexSize)
191 BS_PARAM_BLOCK_END
192
193 extern EyeAdaptationBasicParamsMatDef gEyeAdaptationBasicParamsMatDef;
194
195 /**
196 * Shader that computes eye adapatation value from a texture that has luminance encoded in its alpha channel (as done
197 * by EyeAdaptationBasicSetupMat). The result is a 1x1 texture containing the eye adaptation value.
198 */
199 class EyeAdaptationBasicMat : public RendererMaterial<EyeAdaptationBasicMat>
200 {
201 RMAT_DEF("PPEyeAdaptationBasic.bsl");
202
203 public:
204 EyeAdaptationBasicMat();
205
206 /** Executes the post-process effect with the provided parameters. */
207 void execute(const SPtr<Texture>& curFrame, const SPtr<Texture>& prevFrame, const SPtr<RenderTarget>& output,
208 float frameDelta, const AutoExposureSettings& settings, float exposureScale);
209
210 /** Returns the texture descriptor that can be used for initializing the output render target. */
211 static POOLED_RENDER_TEXTURE_DESC getOutputDesc();
212 private:
213 SPtr<GpuParamBlockBuffer> mEyeAdaptationParamsBuffer;
214 SPtr<GpuParamBlockBuffer> mParamsBuffer;
215 GpuParamTexture mCurFrameTexParam;
216 GpuParamTexture mPrevFrameTexParam;
217 };
218
219 BS_PARAM_BLOCK_BEGIN(CreateTonemapLUTParamDef)
220 BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gTonemapParams, 2)
221 BS_PARAM_BLOCK_ENTRY(float, gGammaAdjustment)
222 BS_PARAM_BLOCK_ENTRY(int, gGammaCorrectionType)
223 BS_PARAM_BLOCK_ENTRY(Vector3, gSaturation)
224 BS_PARAM_BLOCK_ENTRY(Vector3, gContrast)
225 BS_PARAM_BLOCK_ENTRY(Vector3, gGain)
226 BS_PARAM_BLOCK_ENTRY(Vector3, gOffset)
227 BS_PARAM_BLOCK_END
228
229 extern CreateTonemapLUTParamDef gCreateTonemapLUTParamDef;
230
231 BS_PARAM_BLOCK_BEGIN(WhiteBalanceParamDef)
232 BS_PARAM_BLOCK_ENTRY(float, gWhiteTemp)
233 BS_PARAM_BLOCK_ENTRY(float, gWhiteOffset)
234 BS_PARAM_BLOCK_END
235
236 extern WhiteBalanceParamDef gWhiteBalanceParamDef;
237
238 /**
239 * Shader that creates a 3D lookup texture that is used to apply tonemapping, color grading, white balancing and gamma
240 * correction.
241 */
242 class CreateTonemapLUTMat : public RendererMaterial<CreateTonemapLUTMat>
243 {
244 RMAT_DEF_CUSTOMIZED("PPCreateTonemapLUT.bsl");
245
246 /** Helper method used for initializing variations of this material. */
247 template<bool is3D>
248 static const ShaderVariation& getVariation()
249 {
250 static ShaderVariation variation = ShaderVariation(
251 {
252 ShaderVariation::Param("VOLUME_LUT", is3D),
253 });
254
255 return variation;
256 };
257
258 public:
259 CreateTonemapLUTMat();
260
261 /**
262 * Executes the post-process effect with the provided parameters, generating a 3D LUT using a compute shader.
263 * Should only be called on the appropriate variation (3D one).
264 */
265 void execute3D(const SPtr<Texture>& output, const RenderSettings& settings);
266
267 /**
268 * Executes the post-process effect with the provided parameters, generating an unwrapped 2D LUT without the use
269 * of a compute shader. Should only be called on the appropriate variation (non-3D one).
270 */
271 void execute2D(const SPtr<RenderTexture>& output, const RenderSettings& settings);
272
273 /** Returns the texture descriptor that can be used for initializing the output render target. */
274 POOLED_RENDER_TEXTURE_DESC getOutputDesc() const;
275
276 /**
277 * Returns the material variation matching the provided parameters.
278 *
279 * @param[in] is3D If true the material will generate a 3D LUT using a compute shader. Otherwise it will
280 * generate an unwrapped 2D LUT withou the use of a compute shader. Depending on this parameter
281 * you should call either execute3D() or execute2D() methods to render the material.
282 */
283 static CreateTonemapLUTMat* getVariation(bool is3D);
284
285 /** Size of the 3D color lookup table. */
286 static const UINT32 LUT_SIZE = 32;
287 private:
288 /** Populates the parameter block buffers using the provided settings. */
289 void populateParamBuffers(const RenderSettings& settings);
290
291 SPtr<GpuParamBlockBuffer> mParamBuffer;
292 SPtr<GpuParamBlockBuffer> mWhiteBalanceParamBuffer;
293
294 GpuParamLoadStoreTexture mOutputTex;
295 bool mIs3D;
296 };
297
298 BS_PARAM_BLOCK_BEGIN(TonemappingParamDef)
299 BS_PARAM_BLOCK_ENTRY(float, gRawGamma)
300 BS_PARAM_BLOCK_ENTRY(float, gManualExposureScale)
301 BS_PARAM_BLOCK_ENTRY(Vector2, gTexSize)
302 BS_PARAM_BLOCK_ENTRY(Color, gBloomTint)
303 BS_PARAM_BLOCK_ENTRY(int, gNumSamples)
304 BS_PARAM_BLOCK_END
305
306 extern TonemappingParamDef gTonemappingParamDef;
307
308 /** Shader that applies tonemapping and converts a HDR image into a LDR image. */
309 class TonemappingMat : public RendererMaterial<TonemappingMat>
310 {
311 RMAT_DEF_CUSTOMIZED("PPTonemapping.bsl");
312
313 /** Helper method used for initializing variations of this material. */
314 template<bool volumeLUT, bool gammaOnly, bool autoExposure, bool MSAA>
315 static const ShaderVariation& getVariation()
316 {
317 static ShaderVariation variation = ShaderVariation(
318 {
319 ShaderVariation::Param("VOLUME_LUT", volumeLUT),
320 ShaderVariation::Param("GAMMA_ONLY", gammaOnly),
321 ShaderVariation::Param("AUTO_EXPOSURE", autoExposure),
322 ShaderVariation::Param("MSAA", MSAA),
323 });
324
325 return variation;
326 }
327 public:
328 TonemappingMat();
329
330 /** Executes the post-process effect with the provided parameters. */
331 void execute(const SPtr<Texture>& sceneColor, const SPtr<Texture>& eyeAdaptation, const SPtr<Texture>& bloom,
332 const SPtr<Texture>& colorLUT, const SPtr<RenderTarget>& output, const RenderSettings& settings);
333
334 /** Returns the material variation matching the provided parameters. */
335 static TonemappingMat* getVariation(bool volumeLUT, bool gammaOnly, bool autoExposure, bool MSAA);
336
337 private:
338 SPtr<GpuParamBlockBuffer> mParamBuffer;
339
340 GpuParamTexture mInputTex;
341 GpuParamTexture mBloomTex;
342 GpuParamTexture mColorLUT;
343 GpuParamTexture mEyeAdaptationTex;
344 };
345
346 BS_PARAM_BLOCK_BEGIN(BloomClipParamDef)
347 BS_PARAM_BLOCK_ENTRY(float, gThreshold)
348 BS_PARAM_BLOCK_ENTRY(float, gManualExposureScale)
349 BS_PARAM_BLOCK_END
350
351 extern BloomClipParamDef gBloomClipParamDef;
352
353 /** Shader that clips parts of the image that shouldn't be affected by bloom (parts that aren't bright enough). */
354 class BloomClipMat : public RendererMaterial<BloomClipMat>
355 {
356 RMAT_DEF("PPBloomClip.bsl");
357
358 /** Helper method used for initializing variations of this material. */
359 template<bool AUTO_EXPOSURE>
360 static const ShaderVariation& getVariation()
361 {
362 static ShaderVariation variation = ShaderVariation(
363 {
364 ShaderVariation::Param("AUTO_EXPOSURE", AUTO_EXPOSURE)
365 });
366
367 return variation;
368 }
369 public:
370 BloomClipMat();
371
372 /**
373 * Executes the post-process effect with the provided parameters and writes the results to the currently bound
374 * render target.
375 *
376 * @param[in] input Texture to process.
377 * @param[in] threshold Treshold below which values will be ignored for purposes of bloom.
378 * @param[in] eyeAdaptation Texture containing eye adaptation exposure value. Only needed if using the
379 * AUTO_EXPOSURE variation of this material.
380 * @param[in] settings Render settings for the current view.
381 * @param[in] output Render target to write the results to.
382 */
383 void execute(const SPtr<Texture>& input, float threshold, const SPtr<Texture>& eyeAdaptation,
384 const RenderSettings& settings, const SPtr<RenderTarget>& output);
385
386 /**
387 * Returns the material variation matching the provided parameters.
388 *
389 * @param[in] autoExposure If true the exposure value will need to be provided in a texture output from the
390 * eye adaptation material. Otherwise manual exposure scale from render settings will
391 * be used.
392 */
393 static BloomClipMat* getVariation(bool autoExposure);
394
395 private:
396 SPtr<GpuParamBlockBuffer> mParamBuffer;
397
398 GpuParamTexture mInputTex;
399 GpuParamTexture mEyeAdaptationTex;
400 };
401
402 const int MAX_BLUR_SAMPLES = 128;
403
404 BS_PARAM_BLOCK_BEGIN(GaussianBlurParamDef)
405 BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gSampleOffsets, (MAX_BLUR_SAMPLES + 1) / 2)
406 BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gSampleWeights, MAX_BLUR_SAMPLES)
407 BS_PARAM_BLOCK_ENTRY(int, gNumSamples)
408 BS_PARAM_BLOCK_END
409
410 extern GaussianBlurParamDef gGaussianBlurParamDef;
411
412 /** Shader that performs Gaussian blur filtering on the provided texture. */
413 class GaussianBlurMat : public RendererMaterial<GaussianBlurMat>
414 {
415 // Direction of the Gaussian filter pass
416 enum Direction
417 {
418 DirVertical,
419 DirHorizontal
420 };
421
422 RMAT_DEF_CUSTOMIZED("PPGaussianBlur.bsl");
423
424 /** Helper method used for initializing variations of this material. */
425 template<bool ADDITIVE>
426 static const ShaderVariation& getVariation()
427 {
428 static ShaderVariation variation = ShaderVariation(
429 {
430 ShaderVariation::Param("ADDITIVE", ADDITIVE),
431 });
432
433 return variation;
434 }
435 public:
436 GaussianBlurMat();
437
438 /**
439 * Renders the post-process effect with the provided parameters.
440 *
441 * @param[in] source Input texture to blur.
442 * @param[in] filterSize Size of the blurring filter, in percent of the source texture. In range [0, 1].
443 * @param[in] destination Output texture to which to write the blurred image to.
444 * @param[in] tint Optional tint to apply all filtered pixels.
445 * @param[in] additive Optional texture whose values to add to the destination texture (won't be included
446 * in filtering). Only used if using the variation of this shader that supports additive
447 * input.
448 */
449 void execute(const SPtr<Texture>& source, float filterSize, const SPtr<RenderTexture>& destination,
450 const Color& tint = Color::White, const SPtr<Texture>& additive = nullptr);
451
452 /**
453 * Returns the material variation matching the provided parameters.
454 *
455 * @param[in] additive If true the returned variation will support and additional input texture that will be
456 * added on top of the filtered output.
457 */
458 static GaussianBlurMat* getVariation(bool additive);
459
460 private:
461 /** Calculates weights and offsets for the standard distribution of the specified filter size. */
462 static UINT32 calcStdDistribution(float filterRadius, std::array<float, MAX_BLUR_SAMPLES>& weights,
463 std::array<float, MAX_BLUR_SAMPLES>& offsets);
464
465 /** Calculates the radius of the blur kernel depending on the source texture size and provided scale. */
466 static float calcKernelRadius(const SPtr<Texture>& source, float scale, Direction filterDir);
467
468 SPtr<GpuParamBlockBuffer> mParamBuffer;
469 GpuParamTexture mInputTexture;
470 GpuParamTexture mAdditiveTexture;
471 bool mIsAdditive = false;
472 };
473
474 BS_PARAM_BLOCK_BEGIN(GaussianDOFParamDef)
475 BS_PARAM_BLOCK_ENTRY(float, gNearBlurPlane)
476 BS_PARAM_BLOCK_ENTRY(float, gFarBlurPlane)
477 BS_PARAM_BLOCK_ENTRY(float, gInvNearBlurRange)
478 BS_PARAM_BLOCK_ENTRY(float, gInvFarBlurRange)
479 BS_PARAM_BLOCK_ENTRY(Vector2, gHalfPixelOffset)
480 BS_PARAM_BLOCK_END
481
482 extern GaussianDOFParamDef sGaussianDOFParamDef;
483
484 /**
485 * Shader that masks pixels from the input color texture into one or two output textures. The masking is done by
486 * determining if the pixel falls into near or far unfocused plane, as determined by depth-of-field parameters. User
487 * can pick whether to output pixels just on the near plane, just on the far plane, or both.
488 *
489 */
490 class GaussianDOFSeparateMat : public RendererMaterial<GaussianDOFSeparateMat>
491 {
492 RMAT_DEF("PPGaussianDOFSeparate.bsl");
493
494 /** Helper method used for initializing variations of this material. */
495 template<bool near, bool far>
496 static const ShaderVariation& getVariation()
497 {
498 static ShaderVariation variation = ShaderVariation(
499 {
500 ShaderVariation::Param("NEAR", near),
501 ShaderVariation::Param("FAR", far)
502 });
503
504 return variation;
505 }
506 public:
507 GaussianDOFSeparateMat();
508
509 /**
510 * Renders the post-process effect with the provided parameters.
511 *
512 * @param[in] color Input color texture to process.
513 * @param[in] depth Input depth buffer texture that will be used for determining pixel depth.
514 * @param[in] view View through which the depth of field effect is viewed.
515 * @param[in] settings Settings used to control depth of field rendering.
516 */
517 void execute(const SPtr<Texture>& color, const SPtr<Texture>& depth, const RendererView& view,
518 const DepthOfFieldSettings& settings);
519
520 /**
521 * Returns the texture generated after the shader was executed. Only valid to call this in-between calls to
522 * execute() & release(), with @p idx value 0 or 1.
523 */
524 SPtr<PooledRenderTexture> getOutput(UINT32 idx);
525
526 /**
527 * Releases the interally allocated output render textures. Must be called after each call to execute(), when the
528 * caller is done using the textures.
529 */
530 void release();
531
532 /**
533 * Returns the material variation matching the provided parameters.
534 *
535 * @param near If true, near plane pixels are output to the first render target.
536 * @param far If true, far plane pixels are output to the first render target. If @p near is also enabled, the
537 * pixels are output to the second render target instead.
538 */
539 static GaussianDOFSeparateMat* getVariation(bool near, bool far);
540
541 private:
542 SPtr<GpuParamBlockBuffer> mParamBuffer;
543 GpuParamTexture mColorTexture;
544 GpuParamTexture mDepthTexture;
545
546 SPtr<PooledRenderTexture> mOutput0;
547 SPtr<PooledRenderTexture> mOutput1;
548 };
549
550 /**
551 * Shader that combines pixels for near unfocused, focused and far unfocused planes, as calculated by
552 * GaussianDOFSeparateMat. Outputs final depth-of-field filtered image.
553 */
554 class GaussianDOFCombineMat : public RendererMaterial<GaussianDOFCombineMat>
555 {
556 RMAT_DEF("PPGaussianDOFCombine.bsl");
557
558 /** Helper method used for initializing variations of this material. */
559 template<bool near, bool far>
560 static const ShaderVariation& getVariation()
561 {
562 static ShaderVariation variation = ShaderVariation(
563 {
564 ShaderVariation::Param("NEAR", near),
565 ShaderVariation::Param("FAR", far),
566 });
567
568 return variation;
569 }
570 public:
571 GaussianDOFCombineMat();
572
573 /**
574 * Renders the post-process effect with the provided parameters.
575 *
576 * @param[in] focused Input texture containing focused (default) scene color.
577 * @param[in] near Input texture containing filtered (blurred) values for the unfocused foreground area.
578 * Can be null if no near plane needs to be blended.
579 * @param[in] far Input texture containing filtered (blurred) values for the unfocused background area.
580 * Can be null if no far plane needs to be blended.
581 * @param[in] depth Input depth buffer texture that will be used for determining pixel depth.
582 * @param[in] output Texture to output the results to.
583 * @param[in] view View through which the depth of field effect is viewed.
584 * @param[in] settings Settings used to control depth of field rendering.
585 */
586 void execute(const SPtr<Texture>& focused, const SPtr<Texture>& near, const SPtr<Texture>& far,
587 const SPtr<Texture>& depth, const SPtr<RenderTarget>& output, const RendererView& view,
588 const DepthOfFieldSettings& settings);
589
590 /**
591 * Returns the material variation matching the provided parameters.
592 *
593 * @param near If true, near plane pixels are read from the near plane texture, otherwise near plane is assumed
594 * not to exist.
595 * @param far If true, far plane pixels are read from the far plane texture, otherwise far plane is assumed not
596 * to exist.
597 */
598 static GaussianDOFCombineMat* getVariation(bool near, bool far);
599
600 private:
601 SPtr<GpuParamBlockBuffer> mParamBuffer;
602 GpuParamTexture mFocusedTexture;
603 GpuParamTexture mNearTexture;
604 GpuParamTexture mFarTexture;
605 GpuParamTexture mDepthTexture;
606 };
607
608 BS_PARAM_BLOCK_BEGIN(BuildHiZFParamDef)
609 BS_PARAM_BLOCK_ENTRY(Vector2, gHalfPixelOffset)
610 BS_PARAM_BLOCK_ENTRY(int, gMipLevel)
611 BS_PARAM_BLOCK_END
612
613 extern BuildHiZFParamDef sBuildHiZFParamDef;
614
615 /** Shader that calculates a single level of the hierarchical Z mipmap chain. */
616 class BuildHiZMat : public RendererMaterial<BuildHiZMat>
617 {
618 RMAT_DEF("PPBuildHiZ.bsl");
619
620 /** Helper method used for initializing variations of this material. */
621 template<bool noTextureViews>
622 static const ShaderVariation& getVariation()
623 {
624 static ShaderVariation variation = ShaderVariation(
625 {
626 ShaderVariation::Param("NO_TEXTURE_VIEWS", noTextureViews),
627 });
628
629 return variation;
630 }
631 public:
632 BuildHiZMat();
633
634 /**
635 * Renders the post-process effect with the provided parameters.
636 *
637 * @param[in] source Input depth texture to use as the source.
638 * @param[in] srcMip Mip level to read from the @p source texture.
639 * @param[in] srcRect Rectangle in normalized coordinates, describing from which portion of the source
640 * texture to read the input.
641 * @param[in] dstRect Destination rectangle to limit the writes to.
642 * @param[in] output Output target to which to write to results.
643 */
644 void execute(const SPtr<Texture>& source, UINT32 srcMip, const Rect2& srcRect, const Rect2& dstRect,
645 const SPtr<RenderTexture>& output);
646
647 /**
648 * Returns the material variation matching the provided parameters.
649 *
650 * @param noTextureViews Specify as true if the current render backend doesn't support texture views, in
651 * which case the implementation falls back on using a simpler version of the shader.
652 */
653 static BuildHiZMat* getVariation(bool noTextureViews);
654 private:
655 GpuParamTexture mInputTexture;
656 SPtr<GpuParamBlockBuffer> mParamBuffer;
657 bool mNoTextureViews = false;
658 };
659
660 BS_PARAM_BLOCK_BEGIN(FXAAParamDef)
661 BS_PARAM_BLOCK_ENTRY(Vector2, gInvTexSize)
662 BS_PARAM_BLOCK_END
663
664 extern FXAAParamDef gFXAAParamDef;
665
666 /** Shader that performs Fast Approximate anti-aliasing. */
667 class FXAAMat : public RendererMaterial<FXAAMat>
668 {
669 RMAT_DEF("PPFXAA.bsl");
670
671 public:
672 FXAAMat();
673
674 /**
675 * Renders the post-process effect with the provided parameters.
676 *
677 * @param[in] source Input texture to apply FXAA to.
678 * @param[in] destination Output target to which to write the antialiased image to.
679 */
680 void execute(const SPtr<Texture>& source, const SPtr<RenderTarget>& destination);
681
682 private:
683 SPtr<GpuParamBlockBuffer> mParamBuffer;
684 GpuParamTexture mInputTexture;
685 };
686
687 BS_PARAM_BLOCK_BEGIN(SSAOParamDef)
688 BS_PARAM_BLOCK_ENTRY(float, gSampleRadius)
689 BS_PARAM_BLOCK_ENTRY(float, gWorldSpaceRadiusMask)
690 BS_PARAM_BLOCK_ENTRY(Vector2, gTanHalfFOV)
691 BS_PARAM_BLOCK_ENTRY(Vector2, gRandomTileScale)
692 BS_PARAM_BLOCK_ENTRY(float, gCotHalfFOV)
693 BS_PARAM_BLOCK_ENTRY(float, gBias)
694 BS_PARAM_BLOCK_ENTRY(Vector2, gDownsampledPixelSize)
695 BS_PARAM_BLOCK_ENTRY(Vector2, gFadeMultiplyAdd)
696 BS_PARAM_BLOCK_ENTRY(float, gPower)
697 BS_PARAM_BLOCK_ENTRY(float, gIntensity)
698 BS_PARAM_BLOCK_END
699
700 extern SSAOParamDef gSSAOParamDef;
701
702 /** Textures used as input when calculating SSAO. */
703 struct SSAOTextureInputs
704 {
705 /** Full resolution scene depth. Only used by final SSAO pass. */
706 SPtr<Texture> sceneDepth;
707
708 /** Full resolution buffer containing scene normals. Only used by final SSAO pass. */
709 SPtr<Texture> sceneNormals;
710
711 /** Precalculated texture containing downsampled normals/depth, to be used for AO input. */
712 SPtr<Texture> aoSetup;
713
714 /** Texture containing AO from the previous pass. Only used if upsampling is enabled. */
715 SPtr<Texture> aoDownsampled;
716
717 /** Tileable texture containing random rotations that will be applied to AO samples. */
718 SPtr<Texture> randomRotations;
719 };
720
721 /** Shader that computes ambient occlusion using screen based methods. */
722 class SSAOMat : public RendererMaterial<SSAOMat>
723 {
724 RMAT_DEF("PPSSAO.bsl");
725
726 /** Helper method used for initializing variations of this material. */
727 template<bool upsample, bool finalPass, int quality>
728 static const ShaderVariation& getVariation()
729 {
730 static ShaderVariation variation = ShaderVariation(
731 {
732 ShaderVariation::Param("MIX_WITH_UPSAMPLED", upsample),
733 ShaderVariation::Param("FINAL_AO", finalPass),
734 ShaderVariation::Param("QUALITY", quality)
735 });
736
737 return variation;
738 }
739 public:
740 SSAOMat();
741
742 /**
743 * Renders the post-process effect with the provided parameters.
744 *
745 * @param[in] view Information about the view we're rendering from.
746 * @param[in] textures Set of textures to be used as input. Which textures are used depends on the
747 * template parameters of this class.
748 * @param[in] destination Output texture to which to write the ambient occlusion data to.
749 * @param[in] settings Settings used to control the ambient occlusion effect.
750 */
751 void execute(const RendererView& view, const SSAOTextureInputs& textures, const SPtr<RenderTexture>& destination,
752 const AmbientOcclusionSettings& settings);
753
754 /**
755 * Returns the material variation matching the provided parameters.
756 *
757 * @param upsample If true the shader will blend the calculated AO with AO data from the previous pass.
758 * @param finalPass If true the shader will use the full screen normal/depth information and perform
759 * intensity scaling, as well as distance fade. Otherwise the shader will use the
760 * downsampled AO setup information, with no scaling/fade.
761 * @param quality Integer in range [0, 4] that controls the quality of SSAO sampling. Higher numbers yield
762 * better quality at the cost of performance.
763 */
764 static SSAOMat* getVariation(bool upsample, bool finalPass, int quality);
765
766 private:
767 SPtr<GpuParamBlockBuffer> mParamBuffer;
768 GpuParamTexture mDepthTexture;
769 GpuParamTexture mNormalsTexture;
770 GpuParamTexture mDownsampledAOTexture;
771 GpuParamTexture mSetupAOTexture;
772 GpuParamTexture mRandomTexture;
773 };
774
775 BS_PARAM_BLOCK_BEGIN(SSAODownsampleParamDef)
776 BS_PARAM_BLOCK_ENTRY(Vector2, gPixelSize)
777 BS_PARAM_BLOCK_ENTRY(float, gInvDepthThreshold)
778 BS_PARAM_BLOCK_END
779
780 extern SSAODownsampleParamDef gSSAODownsampleParamDef;
781
782 /**
783 * Shader that downsamples the depth & normal buffer and stores their results in a common texture, to be consumed
784 * by SSAOMat.
785 */
786 class SSAODownsampleMat : public RendererMaterial<SSAODownsampleMat>
787 {
788 RMAT_DEF("PPSSAODownsample.bsl");
789
790 public:
791 SSAODownsampleMat();
792
793 /**
794 * Renders the post-process effect with the provided parameters.
795 *
796 * @param[in] view Information about the view we're rendering from.
797 * @param[in] sceneDepth Input texture containing scene depth.
798 * @param[in] sceneNormals Input texture containing scene world space normals.
799 * @param[in] destination Output texture to which to write the downsampled data to.
800 * @param[in] depthRange Valid depth range (in view space) within which nearby samples will be averaged.
801 */
802 void execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Texture>& sceneNormals,
803 const SPtr<RenderTexture>& destination, float depthRange);
804
805 private:
806 SPtr<GpuParamBlockBuffer> mParamBuffer;
807 GpuParamTexture mDepthTexture;
808 GpuParamTexture mNormalsTexture;
809 };
810
811 BS_PARAM_BLOCK_BEGIN(SSAOBlurParamDef)
812 BS_PARAM_BLOCK_ENTRY(Vector2, gPixelSize)
813 BS_PARAM_BLOCK_ENTRY(Vector2, gPixelOffset)
814 BS_PARAM_BLOCK_ENTRY(float, gInvDepthThreshold)
815 BS_PARAM_BLOCK_END
816
817 extern SSAOBlurParamDef gSSAOBlurParamDef;
818
819 /**
820 * Shaders that blurs the ambient occlusion output, in order to hide the noise caused by the randomization texture.
821 */
822 class SSAOBlurMat : public RendererMaterial<SSAOBlurMat>
823 {
824 RMAT_DEF("PPSSAOBlur.bsl");
825
826 /** Helper method used for initializing variations of this material. */
827 template<bool horizontal>
828 static const ShaderVariation& getVariation()
829 {
830 static ShaderVariation variation = ShaderVariation(
831 {
832 ShaderVariation::Param("DIR_HORZ", horizontal)
833 });
834
835 return variation;
836 }
837 public:
838 SSAOBlurMat();
839
840 /**
841 * Renders the post-process effect with the provided parameters.
842 *
843 * @param[in] view Information about the view we're rendering from.
844 * @param[in] ao Input texture containing ambient occlusion data to be blurred.
845 * @param[in] sceneDepth Input texture containing scene depth.
846 * @param[in] destination Output texture to which to write the blurred data to.
847 * @param[in] depthRange Valid depth range (in view space) within which nearby samples will be averaged.
848 */
849 void execute(const RendererView& view, const SPtr<Texture>& ao, const SPtr<Texture>& sceneDepth,
850 const SPtr<RenderTexture>& destination, float depthRange);
851
852 /** Returns the material variation matching the provided parameters. */
853 static SSAOBlurMat* getVariation(bool horizontal);
854
855 private:
856 SPtr<GpuParamBlockBuffer> mParamBuffer;
857 GpuParamTexture mAOTexture;
858 GpuParamTexture mDepthTexture;
859 };
860
861 BS_PARAM_BLOCK_BEGIN(SSRStencilParamDef)
862 BS_PARAM_BLOCK_ENTRY(Vector2, gRoughnessScaleBias)
863 BS_PARAM_BLOCK_END
864
865 extern SSRStencilParamDef gSSRStencilParamDef;
866
867 /** Shader used for marking which parts of the screen require screen space reflections. */
868 class SSRStencilMat : public RendererMaterial<SSRStencilMat>
869 {
870 RMAT_DEF("PPSSRStencil.bsl");
871
872 /** Helper method used for initializing variations of this material. */
873 template<bool msaa, bool singleSampleMSAA>
874 static const ShaderVariation& getVariation()
875 {
876 static ShaderVariation variation = ShaderVariation(
877 {
878 ShaderVariation::Param("MSAA_COUNT", msaa ? 2 : 1),
879 ShaderVariation::Param("MSAA_RESOLVE_0TH", singleSampleMSAA)
880 });
881
882 return variation;
883 }
884 public:
885 SSRStencilMat();
886
887 /**
888 * Renders the effect with the provided parameters, using the currently bound render target.
889 *
890 * @param[in] view Information about the view we're rendering from.
891 * @param[in] gbuffer GBuffer textures.
892 * @param[in] settings Parameters used for controling the SSR effect.
893 */
894 void execute(const RendererView& view, GBufferTextures gbuffer, const ScreenSpaceReflectionsSettings& settings);
895
896 /**
897 * Returns the material variation matching the provided parameters.
898 *
899 * @param[in] msaa True if the shader will operate on a multisampled surface.
900 * @param[in] singleSampleMSAA Only relevant of @p msaa is true. When enabled only the first sample will be
901 * evaluated. Otherwise all samples will be evaluated.
902 * @return Requested variation of the material.
903 */
904 static SSRStencilMat* getVariation(bool msaa, bool singleSampleMSAA);
905 private:
906 SPtr<GpuParamBlockBuffer> mParamBuffer;
907 GBufferParams mGBufferParams;
908 };
909
910 BS_PARAM_BLOCK_BEGIN(SSRTraceParamDef)
911 BS_PARAM_BLOCK_ENTRY(Vector4, gNDCToHiZUV)
912 BS_PARAM_BLOCK_ENTRY(Vector2, gHiZUVToScreenUV)
913 BS_PARAM_BLOCK_ENTRY(Vector2I, gHiZSize)
914 BS_PARAM_BLOCK_ENTRY(int, gHiZNumMips)
915 BS_PARAM_BLOCK_ENTRY(float, gIntensity)
916 BS_PARAM_BLOCK_ENTRY(Vector2, gRoughnessScaleBias)
917 BS_PARAM_BLOCK_ENTRY(int, gTemporalJitter)
918 BS_PARAM_BLOCK_END
919
920 extern SSRTraceParamDef gSSRTraceParamDef;
921
922 /** Shader used for tracing rays for screen space reflections. */
923 class SSRTraceMat : public RendererMaterial<SSRTraceMat>
924 {
925 RMAT_DEF("PPSSRTrace.bsl");
926
927 /** Helper method used for initializing variations of this material. */
928 template<UINT32 quality, bool msaa, bool singleSampleMSAA>
929 static const ShaderVariation& getVariation()
930 {
931 static ShaderVariation variation = ShaderVariation(
932 {
933 ShaderVariation::Param("MSAA_COUNT", msaa ? 2 : 1),
934 ShaderVariation::Param("QUALITY", quality),
935 ShaderVariation::Param("MSAA_RESOLVE_0TH", singleSampleMSAA)
936 });
937
938 return variation;
939 }
940 public:
941 SSRTraceMat();
942
943 /**
944 * Renders the effect with the provided parameters.
945 *
946 * @param[in] view Information about the view we're rendering from.
947 * @param[in] gbuffer GBuffer textures.
948 * @param[in] sceneColor Scene color texture.
949 * @param[in] hiZ Hierarchical Z buffer.
950 * @param[in] settings Parameters used for controling the SSR effect.
951 * @param[in] destination Render target to which to write the results to.
952 */
953 void execute(const RendererView& view, GBufferTextures gbuffer, const SPtr<Texture>& sceneColor,
954 const SPtr<Texture>& hiZ, const ScreenSpaceReflectionsSettings& settings,
955 const SPtr<RenderTarget>& destination);
956
957 /**
958 * Calculates a scale & bias that is used for transforming roughness into a fade out value. Anything that is below
959 * @p maxRoughness will have the fade value of 1. Values above @p maxRoughness is slowly fade out over a range that
960 * is 1/2 the length of @p maxRoughness.
961 */
962 static Vector2 calcRoughnessFadeScaleBias(float maxRoughness);
963
964 /**
965 * Returns the material variation matching the provided parameters.
966 *
967 * @param[in] quality Determines how many rays to trace. In range [0, 4].
968 * @param[in] msaa True if the shader will operate on a multisampled surface.
969 * @param[in] singleSampleMSAA Only relevant of @p msaa is true. When enabled only the first sample will be
970 * evaluated. Otherwise all samples will be evaluated.
971 * @return Requested variation of the material.
972 */
973 static SSRTraceMat* getVariation(UINT32 quality, bool msaa, bool singleSampleMSAA = false);
974 private:
975 SPtr<GpuParamBlockBuffer> mParamBuffer;
976 GBufferParams mGBufferParams;
977 GpuParamTexture mSceneColorTexture;
978 GpuParamTexture mHiZTexture;
979 };
980
981 BS_PARAM_BLOCK_BEGIN(TemporalResolveParamDef)
982 BS_PARAM_BLOCK_ENTRY_ARRAY(float, gSampleWeights, 9)
983 BS_PARAM_BLOCK_ENTRY_ARRAY(float, gSampleWeightsLowpass, 9)
984 BS_PARAM_BLOCK_END
985
986 extern TemporalResolveParamDef gTemporalResolveParamDef;
987
988 BS_PARAM_BLOCK_BEGIN(SSRResolveParamDef)
989 BS_PARAM_BLOCK_ENTRY(Vector2, gSceneDepthTexelSize)
990 BS_PARAM_BLOCK_ENTRY(Vector2, gSceneColorTexelSize)
991 BS_PARAM_BLOCK_ENTRY(float, gManualExposure)
992 BS_PARAM_BLOCK_END
993
994 extern SSRResolveParamDef gSSRResolveParamDef;
995
996 /** Shader used for combining SSR information from the previous frame, in order to yield better quality. */
997 class SSRResolveMat : public RendererMaterial<SSRResolveMat>
998 {
999 RMAT_DEF("PPSSRResolve.bsl");
1000
1001 /** Helper method used for initializing variations of this material. */
1002 template<bool msaa>
1003 static const ShaderVariation& getVariation()
1004 {
1005 static ShaderVariation variation = ShaderVariation(
1006 {
1007 ShaderVariation::Param("MSAA", msaa)
1008 });
1009
1010 return variation;
1011 }
1012 public:
1013 SSRResolveMat();
1014
1015 /**
1016 * Renders the effect with the provided parameters.
1017 *
1018 * @param[in] view Information about the view we're rendering from.
1019 * @param[in] prevFrame SSR data calculated previous frame.
1020 * @param[in] curFrame SSR data calculated this frame.
1021 * @param[in] sceneDepth Buffer containing scene depth.
1022 * @param[in] destination Render target to which to write the results to.
1023 */
1024 void execute(const RendererView& view, const SPtr<Texture>& prevFrame, const SPtr<Texture>& curFrame,
1025 const SPtr<Texture>& sceneDepth, const SPtr<RenderTarget>& destination);
1026
1027 /**
1028 * Returns the material variation matching the provided parameters.
1029 *
1030 * @param[in] msaa True if the shader will operate on a multisampled surface. Note that previous
1031 * and current frame color textures must be non-MSAA, regardless of this parameter.
1032 * @return Requested variation of the material.
1033 */
1034 static SSRResolveMat* getVariation(bool msaa);
1035
1036 private:
1037 SPtr<GpuParamBlockBuffer> mSSRParamBuffer;
1038 SPtr<GpuParamBlockBuffer> mTemporalParamBuffer;
1039
1040 GpuParamTexture mSceneColorTexture;
1041 GpuParamTexture mPrevColorTexture;
1042 GpuParamTexture mSceneDepthTexture;
1043 GpuParamTexture mEyeAdaptationTexture;
1044 };
1045
1046 BS_PARAM_BLOCK_BEGIN(EncodeDepthParamDef)
1047 BS_PARAM_BLOCK_ENTRY(float, gNear)
1048 BS_PARAM_BLOCK_ENTRY(float, gFar)
1049 BS_PARAM_BLOCK_END
1050
1051 extern EncodeDepthParamDef gEncodeDepthParamDef;
1052
1053 /**
1054 * Shader that encodes depth from a specified range into [0, 1] range, and writes the result in the alpha channel
1055 * of the output texture.
1056 */
1057 class EncodeDepthMat : public RendererMaterial<EncodeDepthMat>
1058 {
1059 RMAT_DEF("PPEncodeDepth.bsl");
1060
1061 public:
1062 EncodeDepthMat();
1063
1064 /**
1065 * Renders the post-process effect with the provided parameters.
1066 *
1067 * @param[in] depth Resolved (non-MSAA) depth texture to encode.
1068 * @param[in] near Near range (in view space) to start encoding the depth. Any depth lower than this will
1069 * be encoded to 1.
1070 * @param[in] far Far range (in view space) to end encoding the depth. Any depth higher than this will
1071 * be encoded to 0.
1072 * @param[in] output Output texture to write the results in. Results will be written in the alpha channel.
1073 */
1074 void execute(const SPtr<Texture>& depth, float near, float far, const SPtr<RenderTarget>& output);
1075
1076 private:
1077 SPtr<GpuParamBlockBuffer> mParamBuffer;
1078 GpuParamTexture mInputTexture;
1079 };
1080
1081 /**
1082 * Shader that outputs a texture that determines which pixels require per-sample evaluation. Only relevant when
1083 * rendering with MSAA enabled.
1084 */
1085 class MSAACoverageMat : public RendererMaterial<MSAACoverageMat>
1086 {
1087 RMAT_DEF("MSAACoverage.bsl");
1088
1089 /** Helper method used for initializing variations of this material. */
1090 template<UINT32 msaa>
1091 static const ShaderVariation& getVariation()
1092 {
1093 static ShaderVariation variation = ShaderVariation(
1094 {
1095 ShaderVariation::Param("MSAA_COUNT", msaa)
1096 });
1097
1098 return variation;
1099 }
1100 public:
1101 MSAACoverageMat();
1102
1103 /**
1104 * Renders the effect with the provided parameters, using the currently bound render target.
1105 *
1106 * @param[in] view Information about the view we're rendering from.
1107 * @param[in] gbuffer GBuffer textures.
1108 */
1109 void execute(const RendererView& view, GBufferTextures gbuffer);
1110
1111 /** Returns the material variation matching the provided parameters. */
1112 static MSAACoverageMat* getVariation(UINT32 msaaCount);
1113 private:
1114 GBufferParams mGBufferParams;
1115 };
1116
1117 /**
1118 * Converts the coverage texture output by MSAACoverageMat and writes its information in the highest bit of the
1119 * currently bound stencil buffer. This allows coverage information to be used by normal (non-compute) rendering
1120 * shaders.
1121 */
1122 class MSAACoverageStencilMat : public RendererMaterial<MSAACoverageStencilMat>
1123 {
1124 RMAT_DEF("MSAACoverageStencil.bsl");
1125
1126 public:
1127 MSAACoverageStencilMat();
1128
1129 /**
1130 * Renders the effect with the provided parameters, using the currently bound render target.
1131 *
1132 * @param[in] view Information about the view we're rendering from.
1133 * @param[in] coverage Coverage texture as output by MSAACoverageMat.
1134 */
1135 void execute(const RendererView& view, const SPtr<Texture>& coverage);
1136 private:
1137 GpuParamTexture mCoverageTexParam;
1138 };
1139
1140 /** @} */
1141}}
1142