Overte C++ Documentation
RenderShadowTask.h
1 //
2 // RenderShadowTask.h
3 // render-utils/src/
4 //
5 // Created by Zach Pomerantz on 1/7/2016.
6 // Copyright 2016 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_RenderShadowTask_h
13 #define hifi_RenderShadowTask_h
14 
15 #include <gpu/Framebuffer.h>
16 #include <gpu/Pipeline.h>
17 
18 #include <render/CullTask.h>
19 
20 #include "Shadows_shared.slh"
21 
22 #include "LightingModel.h"
23 #include "LightStage.h"
24 
25 class ViewFrustum;
26 
27 class RenderShadowMap {
28 public:
29  using Inputs = render::VaryingSet3<render::ShapeBounds, AABox, LightStage::ShadowFramePointer>;
30  using JobModel = render::Job::ModelI<RenderShadowMap, Inputs>;
31 
32  RenderShadowMap(render::ShapePlumberPointer shapePlumber, unsigned int cascadeIndex) : _shapePlumber{ shapePlumber }, _cascadeIndex{ cascadeIndex } {}
33  void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
34 
35 protected:
36  render::ShapePlumberPointer _shapePlumber;
37  unsigned int _cascadeIndex;
38 };
39 
40 //class RenderShadowTaskConfig : public render::Task::Config::Persistent {
41 class RenderShadowTaskConfig : public render::Task::Config {
42  Q_OBJECT
43 public:
44  // RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {}
45  RenderShadowTaskConfig() {}
46 
47 signals:
48  void dirty();
49 };
50 
51 class RenderShadowTask {
52 public:
53  // There is one AABox per shadow cascade
54  using CascadeBoxes = render::VaryingArray<AABox, SHADOW_CASCADE_MAX_COUNT>;
55  using Input = render::VaryingSet2<LightStage::FramePointer, LightingModelPointer>;
56  using Output = render::VaryingSet2<CascadeBoxes, LightStage::ShadowFramePointer>;
57  using Config = RenderShadowTaskConfig;
58  using JobModel = render::Task::ModelIO<RenderShadowTask, Input, Output, Config>;
59 
60  RenderShadowTask() {}
61  void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cameraCullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00);
62 
63  void configure(const Config& configuration);
64 
65  struct CullFunctor {
66  float _minSquareSize{ 0.0f };
67 
68  bool operator()(const RenderArgs* args, const AABox& bounds) const {
69  // Cull only objects that are too small relatively to shadow frustum
70  const auto boundsSquareRadius = glm::dot(bounds.getDimensions(), bounds.getDimensions());
71  return boundsSquareRadius > _minSquareSize;
72  }
73  };
74 
75  CullFunctor _cullFunctor;
76 };
77 
78 class RenderShadowSetupConfig : public render::Job::Config {
79  Q_OBJECT
80  Q_PROPERTY(float constantBias0 MEMBER constantBias0 NOTIFY dirty)
81  Q_PROPERTY(float constantBias1 MEMBER constantBias1 NOTIFY dirty)
82  Q_PROPERTY(float constantBias2 MEMBER constantBias2 NOTIFY dirty)
83  Q_PROPERTY(float constantBias3 MEMBER constantBias3 NOTIFY dirty)
84  Q_PROPERTY(float slopeBias0 MEMBER slopeBias0 NOTIFY dirty)
85  Q_PROPERTY(float slopeBias1 MEMBER slopeBias1 NOTIFY dirty)
86  Q_PROPERTY(float slopeBias2 MEMBER slopeBias2 NOTIFY dirty)
87  Q_PROPERTY(float slopeBias3 MEMBER slopeBias3 NOTIFY dirty)
88  Q_PROPERTY(float biasInput MEMBER biasInput NOTIFY dirty)
89  Q_PROPERTY(float maxDistance MEMBER maxDistance NOTIFY dirty)
90 
91 public:
92  // Set to > 0 to experiment with these values
93  float constantBias0 { 0.0f };
94  float constantBias1 { 0.0f };
95  float constantBias2 { 0.0f };
96  float constantBias3 { 0.0f };
97  float slopeBias0 { 0.0f };
98  float slopeBias1 { 0.0f };
99  float slopeBias2 { 0.0f };
100  float slopeBias3 { 0.0f };
101  float biasInput { 0.0f };
102  float maxDistance { 0.0f };
103 
104 signals:
105  void dirty();
106 };
107 
108 class RenderShadowSetup {
109 public:
110  using Input = RenderShadowTask::Input;
111  using Output = render::VaryingSet5<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer, LightStage::ShadowFramePointer, graphics::LightPointer>;
112  using Config = RenderShadowSetupConfig;
113  using JobModel = render::Job::ModelIO<RenderShadowSetup, Input, Output, Config>;
114 
115  RenderShadowSetup();
116  void configure(const Config& config);
117  void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
118 
119 private:
120  ViewFrustumPointer _cameraFrustum;
121  ViewFrustumPointer _coarseShadowFrustum;
122  struct {
123  float _constant;
124  float _slope;
125  } _bias[SHADOW_CASCADE_MAX_COUNT];
126 
127  LightStage::ShadowFrame::Object _globalShadowObject;
128  LightStage::ShadowFramePointer _shadowFrameCache;
129 
130  // Values from config
131  float constantBias0;
132  float constantBias1;
133  float constantBias2;
134  float constantBias3;
135  float slopeBias0;
136  float slopeBias1;
137  float slopeBias2;
138  float slopeBias3;
139  float biasInput;
140  float maxDistance;
141 
142  void setConstantBias(int cascadeIndex, float value);
143  void setSlopeBias(int cascadeIndex, float value);
144  void calculateBiases(float biasInput);
145 };
146 
147 class RenderShadowCascadeSetup {
148 public:
149  using Inputs = LightStage::ShadowFramePointer;
150  using Outputs = render::VaryingSet3<render::ItemFilter, ViewFrustumPointer, RenderShadowTask::CullFunctor>;
151  using JobModel = render::Job::ModelIO<RenderShadowCascadeSetup, Inputs, Outputs>;
152 
153  RenderShadowCascadeSetup(unsigned int cascadeIndex, render::ItemFilter filter) : _cascadeIndex(cascadeIndex), _filter(filter) {}
154 
155  void run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output);
156 
157 private:
158  unsigned int _cascadeIndex;
159  render::ItemFilter _filter;
160 };
161 
162 class RenderShadowCascadeTeardown {
163 public:
164  using Input = render::ItemFilter;
165  using JobModel = render::Job::ModelI<RenderShadowCascadeTeardown, Input>;
166  void run(const render::RenderContextPointer& renderContext, const Input& input);
167 };
168 
169 class RenderShadowTeardown {
170 public:
171  using Input = RenderShadowSetup::Output;
172  using JobModel = render::Job::ModelI<RenderShadowTeardown, Input>;
173  void run(const render::RenderContextPointer& renderContext, const Input& input);
174 };
175 
176 class CullShadowBounds {
177 public:
178  using Inputs = render::VaryingSet5<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer, graphics::LightPointer, RenderShadowTask::CullFunctor>;
179  using Outputs = render::VaryingSet2<render::ShapeBounds, AABox>;
180  using JobModel = render::Job::ModelIO<CullShadowBounds, Inputs, Outputs>;
181 
182  void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
183 };
184 
185 #endif // hifi_RenderShadowTask_h