Overte C++ Documentation
LightClusters.h
1 //
2 // LightClusters.h
3 //
4 // Created by Sam Gateau on 9/7/2016.
5 // Copyright 2015 High Fidelity, Inc.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 //
10 
11 #ifndef hifi_render_utils_LightClusters_h
12 #define hifi_render_utils_LightClusters_h
13 
14 #include <ViewFrustum.h>
15 #include <gpu/Buffer.h>
16 #include <render/Engine.h>
17 #include "LightStage.h"
18 #include "DeferredFrameTransform.h"
19 #include "LightingModel.h"
20 #include "SurfaceGeometryPass.h"
21 
22 class FrustumGrid {
23 public:
24  float frustumNear { 0.1f };
25  float rangeNear { 0.1f };
26  float rangeFar { 200.0f };
27  float frustumFar { 10000.0f };
28 
29  glm::ivec3 dims { 1, 1, 1 };
30  float spare;
31 
32  glm::mat4 eyeToGridProj;
33  glm::mat4 worldToEyeMat;
34  glm::mat4 eyeToWorldMat;
35 
36  FrustumGrid() = default;
37  FrustumGrid(const FrustumGrid& source);
38 
39  void updateFrustum(const ViewFrustum& frustum) {
40  frustumNear = frustum.getNearClip();
41  frustumFar = frustum.getFarClip();
42 
43  eyeToGridProj = frustum.evalProjectionMatrixRange(rangeNear, rangeFar);
44 
45  Transform view;
46  frustum.evalViewTransform(view);
47  eyeToWorldMat = view.getMatrix();
48  worldToEyeMat = view.getInverseMatrix();
49  }
50 
51  // Copy paste of the slh functions
52  using vec3 = glm::vec3;
53  using ivec3 = glm::ivec3;
54  using mat4 = glm::mat4;
55 #define frustumGrid (*this)
56 #include "LightClusterGrid_shared.slh"
57 
58 
59  using Planes = std::vector < glm::vec4 >;
60  void generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& zPlanes);
61 };
62 
63 
64 
65 class LightClusters {
66 public:
67  using LightID = LightStage::Index;
68 
69  static const glm::uvec4 MAX_GRID_DIMENSIONS;
70 
71  LightClusters();
72 
73  void setDimensions(glm::uvec3 gridDims, uint32_t listBudget = MAX_GRID_DIMENSIONS.w);
74  void setRangeNearFar(float rangeNear, float rangeFar);
75 
76  uint32_t getNumClusters() const;
77 
78  void updateFrustum(const ViewFrustum& frustum);
79 
80  void updateLightStage(const LightStagePointer& lightStage);
81 
82  void updateLightFrame(const LightStage::FramePointer& lightFrame, bool points = true, bool spots = true);
83 
84  glm::ivec3 updateClusters();
85 
86 
87  ViewFrustum _frustum;
88 
89 
90  LightStagePointer _lightStage;
91 
92 
93 
94  gpu::StructBuffer<FrustumGrid> _frustumGridBuffer;
95 
96  FrustumGrid::Planes _gridPlanes[3];
97 
98  LightStage::LightIndices _visibleLightIndices;
99  gpu::BufferView _lightIndicesBuffer;
100 
101  const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
102  const LightID INVALID_LIGHT { LightStage::INVALID_INDEX };
103 
104  using LightIndex = uint16_t;
105 
106  std::vector<uint32_t> _clusterGrid;
107  std::vector<LightIndex> _clusterContent;
108  gpu::BufferView _clusterGridBuffer;
109  gpu::BufferView _clusterContentBuffer;
110  uint32_t _clusterContentBudget { 0 };
111 
112  bool _clusterResourcesInvalid { true };
113  void updateClusterResource();
114 };
115 
116 using LightClustersPointer = std::shared_ptr<LightClusters>;
117 
118 
119 
120 class LightClusteringPassConfig : public render::Job::Config {
121  Q_OBJECT
122  Q_PROPERTY(float rangeNear MEMBER rangeNear NOTIFY dirty)
123  Q_PROPERTY(float rangeFar MEMBER rangeFar NOTIFY dirty)
124 
125  Q_PROPERTY(int dimX MEMBER dimX NOTIFY dirty)
126  Q_PROPERTY(int dimY MEMBER dimY NOTIFY dirty)
127  Q_PROPERTY(int dimZ MEMBER dimZ NOTIFY dirty)
128 
129  Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty)
130 
131  Q_PROPERTY(int numClusteredLightReferences MEMBER numClusteredLightReferences NOTIFY dirty)
132  Q_PROPERTY(int numInputLights MEMBER numInputLights NOTIFY dirty)
133  Q_PROPERTY(int numClusteredLights MEMBER numClusteredLights NOTIFY dirty)
134 
135  Q_PROPERTY(int numSceneLights MEMBER numSceneLights NOTIFY dirty)
136  Q_PROPERTY(int numFreeSceneLights MEMBER numFreeSceneLights NOTIFY dirty)
137  Q_PROPERTY(int numAllocatedSceneLights MEMBER numAllocatedSceneLights NOTIFY dirty)
138 
139 public:
140  LightClusteringPassConfig() : render::Job::Config(true){}
141  float rangeNear{ 0.1f };
142  float rangeFar{ 200.0f };
143 
144  int dimX { 14 };
145  int dimY { 14 };
146  int dimZ { 14 };
147 
148 
149  bool freeze{ false };
150 
151  int numClusteredLightReferences { 0 };
152  int numInputLights { 0 };
153  int numClusteredLights { 0 };
154 
155  void setNumClusteredLightReferences(int numRefs) { numClusteredLightReferences = numRefs; }
156  void setNumInputLights(int numLights) { numInputLights = numLights; }
157  void setNumClusteredLights(int numLights) { numClusteredLights = numLights; }
158 
159  int numSceneLights { 0 };
160  int numFreeSceneLights { 0 };
161  int numAllocatedSceneLights { 0 };
162 signals:
163  void dirty();
164 
165 protected:
166 };
167 
168 class LightClusteringPass {
169 public:
170  using Input = render::VaryingSet4<DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer, LinearDepthFramebufferPointer>;
171  using Output = LightClustersPointer;
172  using Config = LightClusteringPassConfig;
173  using JobModel = render::Job::ModelIO<LightClusteringPass, Input, Output, Config>;
174 
175  LightClusteringPass();
176 
177  void configure(const Config& config);
178 
179  void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
180 
181 protected:
182  LightClustersPointer _lightClusters;
183  bool _freeze;
184 };
185 
186 
187 
188 
189 
190 
191 
192 class DebugLightClustersConfig : public render::Job::Config {
193  Q_OBJECT
194  Q_PROPERTY(bool doDrawGrid MEMBER doDrawGrid NOTIFY dirty)
195  Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty)
196  Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty)
197 public:
198  DebugLightClustersConfig() : render::Job::Config(false){}
199 
200 
201  bool doDrawGrid{ false };
202  bool doDrawClusterFromDepth { false };
203  bool doDrawContent { false };
204 
205 signals:
206  void dirty();
207 
208 protected:
209 };
210 
211 
212 #include "DeferredFramebuffer.h"
213 
214 class DebugLightClusters {
215 public:
216  using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, LightingModelPointer, LinearDepthFramebufferPointer, LightClustersPointer>;
217  using Config = DebugLightClustersConfig;
218  using JobModel = render::Job::ModelI<DebugLightClusters, Inputs, Config>;
219 
220  DebugLightClusters();
221 
222  void configure(const Config& config);
223 
224  void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
225 
226 protected:
227  gpu::BufferPointer _gridBuffer;
228  gpu::PipelinePointer _drawClusterGrid;
229  gpu::PipelinePointer _drawClusterFromDepth;
230  gpu::PipelinePointer _drawClusterContent;
231  const gpu::PipelinePointer getDrawClusterGridPipeline();
232  const gpu::PipelinePointer getDrawClusterFromDepthPipeline();
233  const gpu::PipelinePointer getDrawClusterContentPipeline();
234  bool doDrawGrid { false };
235  bool doDrawClusterFromDepth { false };
236  bool doDrawContent { false };
237 };
238 
239 #endif