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 | |
14 | namespace 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 = 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 | |