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 "Utility/BsTriangulation.h"
7#include "Math/BsMatrix4.h"
8#include "Math/BsMatrixNxM.h"
9#include "Renderer/BsRendererMaterial.h"
10#include "Renderer/BsGpuResourcePool.h"
11#include "Renderer/BsParamBlocks.h"
12#include "BsRendererLight.h"
13
14namespace bs { namespace ct
15{
16 struct LightProbesInfo;
17 struct GBufferTextures;
18 struct FrameInfo;
19 class LightProbeVolume;
20
21 /** @addtogroup RenderBeast
22 * @{
23 */
24
25 BS_PARAM_BLOCK_BEGIN(TetrahedraRenderParamDef)
26 BS_PARAM_BLOCK_ENTRY(Vector2I, gDepthTexSize)
27 BS_PARAM_BLOCK_END
28
29 extern TetrahedraRenderParamDef gTetrahedraRenderParamDef;
30
31 /**
32 * Shader that renders the tetrahedra used for light probe evaluation. Tetrahedra depth is compare with current scene
33 * depth, and for each scene pixel the matching tetrahedron index is written to the output target.
34 */
35 class TetrahedraRenderMat : public RendererMaterial<TetrahedraRenderMat>
36 {
37 RMAT_DEF("TetrahedraRender.bsl");
38
39 /** Helper method used for initializing variations of this material. */
40 template<bool msaa, bool singleSampleMSAA>
41 static const ShaderVariation& getVariation()
42 {
43 static ShaderVariation variation = ShaderVariation(
44 {
45 ShaderVariation::Param("MSAA", msaa),
46 ShaderVariation::Param("MSAA_RESOLVE_0TH", singleSampleMSAA)
47 });
48
49 return variation;
50 }
51 public:
52 TetrahedraRenderMat();
53
54 /**
55 * Executes the material using the provided parameters.
56 *
57 * @param[in] view View that is currently being rendered.
58 * @param[in] sceneDepth Depth of scene objects that should be lit.
59 * @param[in] mesh Mesh to render.
60 * @param[in] output Output texture created using the descriptor returned by getOutputDesc().
61 */
62 void execute(const RendererView& view, const SPtr<Texture>& sceneDepth, const SPtr<Mesh>& mesh,
63 const SPtr<RenderTexture>& output);
64
65 /**
66 * Returns the descriptors that can be used for creating the output render texture for this material. The render
67 * texture is expected to have a single color attachment, and a depth attachment.
68 */
69 static void getOutputDesc(const RendererView& view, POOLED_RENDER_TEXTURE_DESC& colorDesc,
70 POOLED_RENDER_TEXTURE_DESC& depthDesc);
71
72 /**
73 * Returns the material variation matching the provided parameters.
74 *
75 * @param[in] msaa True if the shader will operate on a multisampled surface.
76 * @param[in] singleSampleMSAA Only relevant of @p msaa is true. When enabled only the first sample will be
77 * evaluated. Otherwise all samples will be evaluated.
78 * @return Requested variation of the material.
79 */
80 static TetrahedraRenderMat* getVariation(bool msaa, bool singleSampleMSAA);
81 private:
82 SPtr<GpuParamBlockBuffer> mParamBuffer;
83 GpuParamTexture mDepthBufferTex;
84 };
85
86 BS_PARAM_BLOCK_BEGIN(IrradianceEvaluateParamDef)
87 BS_PARAM_BLOCK_ENTRY(float, gSkyBrightness)
88 BS_PARAM_BLOCK_ENTRY(INT32, gNumTetrahedra)
89 BS_PARAM_BLOCK_END
90
91 extern IrradianceEvaluateParamDef gIrradianceEvaluateParamDef;
92
93 /** Evaluates radiance from the light probe volume, or the sky if light probes are not available. */
94 class IrradianceEvaluateMat : public RendererMaterial<IrradianceEvaluateMat>
95 {
96 RMAT_DEF("IrradianceEvaluate.bsl");
97
98 /** Helper method used for initializing variations of this material. */
99 template<bool msaa, bool singleSampleMSAA, bool skyOnly>
100 static const ShaderVariation& getVariation()
101 {
102 static ShaderVariation variation = ShaderVariation(
103 {
104 ShaderVariation::Param("MSAA", msaa),
105 ShaderVariation::Param("MSAA_RESOLVE_0TH", singleSampleMSAA),
106 ShaderVariation::Param("SKY_ONLY", skyOnly)
107 });
108
109 return variation;
110 }
111 public:
112 IrradianceEvaluateMat();
113
114 /**
115 * Executes the material using the provided parameters.
116 *
117 * @param[in] view View that is currently being rendered.
118 * @param[in] gbuffer Previously rendered GBuffer textures.
119 * @param[in] lightProbeIndices Indices calculated by TetrahedraRenderMat.
120 * @param[in] lightProbesInfo Information about light probes.
121 * @param[in] skybox Skybox, if available. If sky is not available, but sky rendering is enabled,
122 * the system will instead use a default irradiance texture.
123 * @param[in] ambientOcclusion Texture containing per-pixel ambient occlusion.
124 * @param[in] output Output texture to write the radiance to. The evaluated value will be added to
125 * existing radiance in the texture, using blending.
126 */
127 void execute(const RendererView& view, const GBufferTextures& gbuffer, const SPtr<Texture>& lightProbeIndices,
128 const LightProbesInfo& lightProbesInfo, const Skybox* skybox, const SPtr<Texture>& ambientOcclusion,
129 const SPtr<RenderTexture>& output);
130
131 /**
132 * Returns the material variation matching the provided parameters.
133 *
134 * @param[in] msaa True if the shader will operate on a multisampled surface.
135 * @param[in] singleSampleMSAA Only relevant of @p msaa is true. When enabled only the first sample will be
136 * evaluated. Otherwise all samples will be evaluated.
137 * @param[in] skyOnly When true, only the sky irradiance will be evaluated. Otherwise light probe
138 * irradiance will be evaluated.
139 * @return Requested variation of the material.
140 */
141 static IrradianceEvaluateMat* getVariation(bool msaa, bool singleSampleMSAA, bool skyOnly);
142 private:
143 GBufferParams mGBufferParams;
144 SPtr<GpuParamBlockBuffer> mParamBuffer;
145 GpuParamTexture mParamInputTex;
146 GpuParamTexture mParamSkyIrradianceTex;
147 GpuParamTexture mParamAmbientOcclusionTex;
148 GpuParamTexture mParamSHCoeffsTexture;
149 GpuParamBuffer mParamTetrahedraBuffer;
150 GpuParamBuffer mParamTetFacesBuffer;
151 bool mSkyOnly;
152 };
153
154 /** Contains information required by light probe shaders. Output by LightProbes. */
155 struct LightProbesInfo
156 {
157 /** Contains a set of spherical harmonic coefficients for every light probe. */
158 SPtr<Texture> shCoefficients;
159
160 /**
161 * Contains information about tetrahedra formed by light probes. First half of the buffer is populated by actual
162 * tetrahedrons, while the second half is populated by information about outer faces (triangles). @p numTetrahedra
163 * marks the spot where split happens.
164 */
165 SPtr<GpuBuffer> tetrahedra;
166
167 /** Contains additional information about outer tetrahedron faces, required for extrapolating tetrahedron data. */
168 SPtr<GpuBuffer> faces;
169
170 /**
171 * Mesh representing the entire light probe volume. Each vertex has an associated tetrahedron (or face) index which
172 * can be used to map into the tetrahedra array to retrieve probe information.
173 */
174 SPtr<Mesh> tetrahedraVolume;
175
176 /** Total number of valid tetrahedra in the @p tetrahedra buffer. */
177 UINT32 numTetrahedra;
178 };
179
180 /** Handles any pre-processing for light (irradiance) probe lighting. */
181 class LightProbes
182 {
183 /** Internal information about a single light probe volume. */
184 struct VolumeInfo
185 {
186 /** Volume containing the information about the probes. */
187 LightProbeVolume* volume;
188 /** Remains true as long as there are dirty probes in the volume. */
189 bool isDirty;
190 };
191
192 /**
193 * Information about a single tetrahedron, including neighbor information. Neighbor 4th index will be set to -1
194 * if the tetrahedron represents an outer face (which is not actually a tetrahedron, but a triangle, but is stored
195 * in the same array for convenience).
196 */
197 struct TetrahedronData
198 {
199 Tetrahedron volume;
200 Matrix4 transform;
201 };
202
203 /**
204 * Information about a single tetrahedron face, with information about extrusion and how to project a point in
205 * the extrusion volume, on to the face.
206 */
207 struct TetrahedronFaceData
208 {
209 UINT32 innerVertices[3];
210 UINT32 outerVertices[3];
211 Vector3 normals[3];
212 Matrix4 transform;
213 UINT32 tetrahedron;
214 bool quadratic;
215 };
216 public:
217 LightProbes();
218
219 /** Notifies sthe manager that the provided light probe volume has been added. */
220 void notifyAdded(LightProbeVolume* volume);
221
222 /** Notifies the manager that the provided light probe volume has some dirty light probes. */
223 void notifyDirty(LightProbeVolume* volume);
224
225 /** Notifies the manager that all the probes in the provided volume have been removed. */
226 void notifyRemoved(LightProbeVolume* volume);
227
228 /** Updates light probe tetrahedron data after probes changed (added/removed/moved). */
229 void updateProbes();
230
231 /** Returns true if there are any registered light probes. */
232 bool hasAnyProbes() const;
233
234 /**
235 * Returns a set of buffers that can be used for rendering the light probes. updateProbes() must be called
236 * at least once before the buffer is populated. If the probes changed since the last call, call updateProbes()
237 * to refresh the buffer.
238 */
239 LightProbesInfo getInfo() const;
240
241 private:
242 /**
243 * Perform tetrahedrization of the provided point list, and outputs a list of tetrahedrons and outer faces of the
244 * volume. Each entry contains connections to nearby tetrahedrons/faces, as well as a matrix that can be used for
245 * calculating barycentric coordinates within the tetrahedron (or projected triangle barycentric coordinates for
246 * faces).
247 *
248 * @param[in,out] positions A set of positions to generate the tetrahedra from. If
249 * @p generateExtrapolationVolume is enabled then this array will be
250 * appended with new vertices forming that volume.
251 * @param[out] tetrahedra A list of generated tetrahedra and relevant data.
252 * @param[out] faces A list of faces representing the surface of the tetrahedra volume.
253 * @param[in] generateExtrapolationVolume If true, the tetrahedron volume will be surrounded with points
254 * at "infinity" (technically just far away).
255 */
256 void generateTetrahedronData(Vector<Vector3>& positions, Vector<TetrahedronData>& tetrahedra,
257 Vector<TetrahedronFaceData>& faces, bool generateExtrapolationVolume = false);
258
259 /** Resizes the GPU buffer used for holding tetrahedron data, to the specified size (in number of tetraheda). */
260 void resizeTetrahedronBuffer(UINT32 count);
261
262 /** Resizes the GPU buffer used for holding tetrahedron face data, to the specified size (in number of faces). */
263 void resizeTetrahedronFaceBuffer(UINT32 count);
264
265 /**
266 * Resized the GPU buffer that stores light probe SH coefficients, to the specified number of rows (each row
267 * holds 4096 coefficients, and each volume starts in its own row.).
268 */
269 void resizeCoefficientTexture(UINT32 numRows);
270
271 Vector<VolumeInfo> mVolumes;
272 bool mTetrahedronVolumeDirty;
273
274 UINT32 mMaxCoefficientRows;
275 UINT32 mMaxTetrahedra;
276 UINT32 mMaxFaces;
277
278 Vector<TetrahedronData> mTetrahedronInfos;
279
280 SPtr<Texture> mProbeCoefficientsGPU;
281 SPtr<GpuBuffer> mTetrahedronInfosGPU;
282 SPtr<GpuBuffer> mTetrahedronFaceInfosGPU;
283 SPtr<Mesh> mVolumeMesh;
284 UINT32 mNumValidTetrahedra;
285
286 // Temporary buffers
287 Vector<Vector3> mTempTetrahedronPositions;
288 Vector<UINT32> mTempTetrahedronBufferIndices;
289 Vector<Vector2I> mTempTetrahedronBufferOffsets;
290 };
291
292 /** @} */
293}}
294