Overte C++ Documentation
AmbientOcclusionEffect.h
1 //
2 // AmbientOcclusionEffect.h
3 // libraries/render-utils/src/
4 //
5 // Created by Niraj Venkat on 7/15/15.
6 // Copyright 2015 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_AmbientOcclusionEffect_h
13 #define hifi_AmbientOcclusionEffect_h
14 
15 #include <string>
16 #include <DependencyManager.h>
17 
18 #include "render/DrawTask.h"
19 
20 #include "LightingModel.h"
21 #include "DeferredFrameTransform.h"
22 #include "DeferredFramebuffer.h"
23 #include "SurfaceGeometryPass.h"
24 #include "AmbientOcclusionStage.h"
25 
26 #include "ssao_shared.h"
27 
28 class AmbientOcclusionFramebuffer {
29 public:
30  AmbientOcclusionFramebuffer();
31 
32  gpu::FramebufferPointer getOcclusionFramebuffer();
33  gpu::TexturePointer getOcclusionTexture();
34 
35  gpu::FramebufferPointer getOcclusionBlurredFramebuffer();
36  gpu::TexturePointer getOcclusionBlurredTexture();
37 
38  gpu::FramebufferPointer getNormalFramebuffer();
39  gpu::TexturePointer getNormalTexture();
40 
41 #if SSAO_USE_QUAD_SPLIT
42  gpu::FramebufferPointer getOcclusionSplitFramebuffer(int index);
43  gpu::TexturePointer getOcclusionSplitTexture();
44 #endif
45 
46  // Update the source framebuffer size which will drive the allocation of all the other resources.
47  bool update(const gpu::TexturePointer& linearDepthBuffer, int resolutionLevel, int depthResolutionLevel, bool isStereo);
48  gpu::TexturePointer getLinearDepthTexture();
49  const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
50  bool isStereo() const { return _isStereo; }
51 
52 protected:
53 
54  void clear();
55  void allocate();
56 
57  gpu::TexturePointer _linearDepthTexture;
58 
59  gpu::FramebufferPointer _occlusionFramebuffer;
60  gpu::TexturePointer _occlusionTexture;
61 
62  gpu::FramebufferPointer _occlusionBlurredFramebuffer;
63  gpu::TexturePointer _occlusionBlurredTexture;
64 
65  gpu::FramebufferPointer _normalFramebuffer;
66  gpu::TexturePointer _normalTexture;
67 
68 #if SSAO_USE_QUAD_SPLIT
69  gpu::FramebufferPointer _occlusionSplitFramebuffers[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
70  gpu::TexturePointer _occlusionSplitTexture;
71 #endif
72 
73  glm::ivec2 _frameSize;
74  int _resolutionLevel { 0 };
75  int _depthResolutionLevel { 0 };
76  bool _isStereo { false };
77 };
78 
79 using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFramebuffer>;
80 
81 class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
82  Q_OBJECT
83  Q_PROPERTY(bool debug MEMBER debug NOTIFY dirty)
84  Q_PROPERTY(bool horizonBased MEMBER horizonBased NOTIFY dirty)
85  Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
86  Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
87  Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty)
88  Q_PROPERTY(bool jitterEnabled MEMBER jitterEnabled NOTIFY dirty)
89 
90  Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel)
91  Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness)
92  Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius)
93 
94  // SSAO
95  Q_PROPERTY(float ssaoRadius MEMBER ssaoRadius WRITE setSSAORadius)
96  Q_PROPERTY(float ssaoObscuranceLevel MEMBER ssaoObscuranceLevel WRITE setSSAOObscuranceLevel)
97  Q_PROPERTY(float ssaoFalloffAngle MEMBER ssaoFalloffAngle WRITE setSSAOFalloffAngle)
98  Q_PROPERTY(float ssaoNumSpiralTurns MEMBER ssaoNumSpiralTurns WRITE setSSAONumSpiralTurns)
99  Q_PROPERTY(int ssaoNumSamples MEMBER ssaoNumSamples WRITE setSSAONumSamples)
100 
101  // HBAO
102  Q_PROPERTY(float hbaoRadius MEMBER hbaoRadius WRITE setHBAORadius)
103  Q_PROPERTY(float hbaoObscuranceLevel MEMBER hbaoObscuranceLevel WRITE setHBAOObscuranceLevel)
104  Q_PROPERTY(float hbaoFalloffAngle MEMBER hbaoFalloffAngle WRITE setHBAOFalloffAngle)
105  Q_PROPERTY(int hbaoNumSamples MEMBER hbaoNumSamples WRITE setHBAONumSamples)
106 
107 public:
108  AmbientOcclusionEffectConfig();
109 
110  const int MAX_RESOLUTION_LEVEL = 4;
111  const int MAX_BLUR_RADIUS = 15;
112 
113  void setResolutionLevel(int level);
114  void setEdgeSharpness(float sharpness);
115  void setBlurRadius(int radius);
116 
117  void setSSAORadius(float newRadius);
118  void setSSAOObscuranceLevel(float level);
119  void setSSAOFalloffAngle(float bias);
120  void setSSAONumSamples(int samples);
121  void setSSAONumSpiralTurns(float turns);
122 
123  void setHBAORadius(float newRadius);
124  void setHBAOObscuranceLevel(float level);
125  void setHBAOFalloffAngle(float bias);
126  void setHBAONumSamples(int samples);
127 
128  bool debug { false };
129 
130  bool jitterEnabled { false }; // Add small jittering to AO samples at each frame
131  bool horizonBased { false }; // Use horizon based AO
132  int resolutionLevel { 2 };
133  float edgeSharpness { 1.0f };
134  int blurRadius { 4 }; // 0 means no blurring
135 
136  float ssaoRadius { 1.0f };
137  float ssaoObscuranceLevel { 0.4f }; // intensify or dim down the obscurance effect
138  float ssaoFalloffAngle { 0.15f };
139  int ssaoNumSamples { 32 };
140  float ssaoNumSpiralTurns { 7.0f }; // defining an angle span to distribute the samples ray directions
141 
142  float hbaoRadius { 0.7f };
143  float hbaoObscuranceLevel { 0.75f }; // intensify or dim down the obscurance effect
144  float hbaoFalloffAngle { 0.3f };
145  int hbaoNumSamples { 1 };
146 
147  float perspectiveScale { 1.0f };
148  bool ditheringEnabled { true }; // randomize the distribution of taps per pixel, should always be true
149  bool borderingEnabled { true }; // avoid evaluating information from non existing pixels out of the frame, should always be true
150  bool fetchMipsEnabled { true }; // fetch taps in sub mips to otpimize cache, should always be true
151 
152 signals:
153  void dirty();
154 };
155 
156 #define SSAO_RANDOM_SAMPLE_COUNT 16
157 
158 class AmbientOcclusionEffect {
159 public:
160  using Input = render::VaryingSet5<LightingModelPointer, DeferredFrameTransformPointer, DeferredFramebufferPointer,
161  LinearDepthFramebufferPointer, AmbientOcclusionStage::FramePointer>;
162  using Output = render::VaryingSet2<AmbientOcclusionFramebufferPointer, gpu::BufferView>;
163  using Config = AmbientOcclusionEffectConfig;
164  using JobModel = render::Job::ModelIO<AmbientOcclusionEffect, Input, Output, Config>;
165 
166  AmbientOcclusionEffect() {}
167 
168  void configure(const Config& config);
169  void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
170 
171  // Class describing the uniform buffer with all the parameters common to the AO shaders
172  class AOParameters : public AmbientOcclusionParams {
173  public:
174  AOParameters();
175 
176  int getResolutionLevel() const { return _resolutionInfo.x; }
177  float getRadius() const { return _radiusInfo.x; }
178  float getPerspectiveScale() const { return _resolutionInfo.z; }
179  float getObscuranceLevel() const { return _radiusInfo.w; }
180  float getFalloffAngle() const { return (float)_falloffInfo.x; }
181 
182  float getNumSpiralTurns() const { return _sampleInfo.z; }
183  int getNumSamples() const { return (int)_sampleInfo.x; }
184  bool isFetchMipsEnabled() const { return _sampleInfo.w; }
185 
186  bool isDitheringEnabled() const { return _ditheringInfo.x != 0.0f; }
187  bool isBorderingEnabled() const { return _ditheringInfo.w != 0.0f; }
188  bool isHorizonBased() const { return _resolutionInfo.y != 0.0f; }
189  };
190  using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
191 
192 private:
193 
194  // Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
195  class BlurParameters : public AmbientOcclusionBlurParams {
196  public:
197  BlurParameters();
198 
199  float getEdgeSharpness() const { return (float)_blurInfo.x; }
200  int getBlurRadius() const { return (int)_blurInfo.w; }
201  };
202  using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
203  using FrameParametersBuffer = gpu::StructBuffer< AmbientOcclusionFrameParams>;
204 
205  void updateParameters(const graphics::AmbientOcclusionPointer ambientOcclusion);
206  void updateBlurParameters();
207  void updateFramebufferSizes();
208  void updateRandomSamples();
209  void updateJitterSamples();
210 
211  int getDepthResolutionLevel() const;
212 
213  AOParametersBuffer _aoParametersBuffer;
214  FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
215  BlurParametersBuffer _vblurParametersBuffer;
216  BlurParametersBuffer _hblurParametersBuffer;
217  float _blurEdgeSharpness { 0.0f };
218 
219  static const gpu::PipelinePointer& getOcclusionPipeline();
220  static const gpu::PipelinePointer& getBilateralBlurPipeline();
221  static const gpu::PipelinePointer& getMipCreationPipeline();
222  static const gpu::PipelinePointer& getGatherPipeline();
223  static const gpu::PipelinePointer& getBuildNormalsPipeline();
224 
225  static gpu::PipelinePointer _occlusionPipeline;
226  static gpu::PipelinePointer _bilateralBlurPipeline;
227  static gpu::PipelinePointer _mipCreationPipeline;
228  static gpu::PipelinePointer _gatherPipeline;
229  static gpu::PipelinePointer _buildNormalsPipeline;
230 
231  AmbientOcclusionFramebufferPointer _framebuffer;
232  std::array<float, SSAO_RANDOM_SAMPLE_COUNT * SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT> _randomSamples;
233  int _frameId { 0 };
234  bool _debug { false };
235  float _perspectiveScale { 1.0f };
236  bool _ditheringEnabled { true };
237  bool _borderingEnabled { true };
238  bool _fetchMipsEnabled { true };
239  graphics::AmbientOcclusionPointer _debugAmbientOcclusion { std::make_shared<graphics::AmbientOcclusion>() };
240 
241  gpu::RangeTimerPointer _gpuTimer;
242 
243  friend class DebugAmbientOcclusion;
244 };
245 
246 
247 class DebugAmbientOcclusionConfig : public render::Job::Config {
248  Q_OBJECT
249 
250  Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty)
251  Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty)
252 public:
253  DebugAmbientOcclusionConfig() : render::Job::Config(false) {}
254 
255  bool showCursorPixel { false };
256  glm::vec2 debugCursorTexcoord { 0.5f, 0.5f };
257 
258 signals:
259  void dirty();
260 };
261 
262 
263 class DebugAmbientOcclusion {
264 public:
265  using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::AOParametersBuffer>;
266  using Config = DebugAmbientOcclusionConfig;
267  using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;
268 
269  DebugAmbientOcclusion() {}
270 
271  void configure(const Config& config);
272  void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
273 
274 private:
275 
276  // Class describing the uniform buffer with all the parameters common to the debug AO shaders
277  class Parameters {
278  public:
279  // Pixel info
280  glm::vec4 pixelInfo { 0.0f, 0.0f, 0.0f, 0.0f };
281 
282  Parameters() {}
283  };
284  gpu::StructBuffer<Parameters> _parametersBuffer;
285 
286  static gpu::PipelinePointer& getDebugPipeline();
287 
288  static gpu::PipelinePointer _debugPipeline;
289 
290  bool _showCursorPixel { false };
291 };
292 
293 #endif // hifi_AmbientOcclusionEffect_h