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 "Renderer/BsRenderQueue.h"
7#include "Renderer/BsLight.h"
8#include "Renderer/BsRenderSettings.h"
9#include "Math/BsBounds.h"
10#include "Math/BsConvexVolume.h"
11#include "Shading/BsLightGrid.h"
12#include "Shading/BsShadowRendering.h"
13#include "BsRendererView.h"
14#include "BsRendererRenderable.h"
15#include "BsRenderCompositor.h"
16#include "BsRendererParticles.h"
17#include "BsRendererDecal.h"
18
19namespace bs { namespace ct
20{
21 struct SceneInfo;
22 class RendererLight;
23
24 /** @addtogroup RenderBeast
25 * @{
26 */
27
28 BS_PARAM_BLOCK_BEGIN(PerCameraParamDef)
29 BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
30 BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
31 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
32 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
33 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
34 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
35 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
36 BS_PARAM_BLOCK_ENTRY(Matrix4, gMatScreenToWorld)
37 BS_PARAM_BLOCK_ENTRY(Matrix4, gNDCToPrevNDC)
38 BS_PARAM_BLOCK_ENTRY(Vector2, gDeviceZToWorldZ)
39 BS_PARAM_BLOCK_ENTRY(Vector2, gNDCZToWorldZ)
40 BS_PARAM_BLOCK_ENTRY(Vector2, gNDCZToDeviceZ)
41 BS_PARAM_BLOCK_ENTRY(Vector2, gNearFar)
42 BS_PARAM_BLOCK_ENTRY(Vector4I, gViewportRectangle)
43 BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
44 BS_PARAM_BLOCK_ENTRY(Vector4, gUVToClipScaleOffset)
45 BS_PARAM_BLOCK_ENTRY(float, gAmbientFactor)
46 BS_PARAM_BLOCK_END
47
48 extern PerCameraParamDef gPerCameraParamDef;
49
50 BS_PARAM_BLOCK_BEGIN(SkyboxParamDef)
51 BS_PARAM_BLOCK_ENTRY(Color, gClearColor)
52 BS_PARAM_BLOCK_END
53
54 extern SkyboxParamDef gSkyboxParamDef;
55
56 /** Shader that renders a skybox using a cubemap or a solid color. */
57 class SkyboxMat : public RendererMaterial<SkyboxMat>
58 {
59 RMAT_DEF("Skybox.bsl");
60
61 /** Helper method used for initializing variations of this material. */
62 template<bool color>
63 static const ShaderVariation& getVariation()
64 {
65 static ShaderVariation variation = ShaderVariation(
66 {
67 ShaderVariation::Param("SOLID_COLOR", color)
68 });
69
70 return variation;
71 }
72 public:
73 SkyboxMat();
74
75 /** Binds the material for rendering and sets up any parameters. */
76 void bind(const SPtr<GpuParamBlockBuffer>& perCamera, const SPtr<Texture>& texture, const Color& solidColor);
77
78 /**
79 * Returns the material variation matching the provided parameters.
80 *
81 * @param[in] color When true the material will use a solid color to render a skybox. When false a user
82 * provided texture will be used instead.
83 */
84 static SkyboxMat* getVariation(bool color);
85 private:
86 GpuParamTexture mSkyTextureParam;
87 SPtr<GpuParamBlockBuffer> mParamBuffer;
88 };
89
90 /** Data shared between RENDERER_VIEW_DESC and RendererViewProperties */
91 struct RendererViewData
92 {
93 RendererViewData();
94
95 Matrix4 viewTransform;
96 Matrix4 projTransform;
97 Vector3 viewDirection;
98 Vector3 viewOrigin;
99 bool flipView;
100 float nearPlane;
101 float farPlane;
102 ProjectionType projType;
103
104 /**
105 * Determines does this view output to the final render target. If false the view is usually used for some
106 * sort of helper rendering.
107 */
108 bool mainView;
109
110 /**
111 * When enabled, renderer extension callbacks will be triggered, allowing other systems to inject their own
112 * render operations into the view.
113 */
114 bool triggerCallbacks : 1;
115
116 /** When enabled, post-processing effects (like tonemapping) will be executed. */
117 bool runPostProcessing : 1;
118
119 /**
120 * Determines if the view is currently rendering reflection probes. This ensures the systems can disable refl.
121 * probe reads in order to prevent incorrect rendering (since probes won't yet have any data).
122 */
123 bool capturingReflections : 1;
124
125 /**
126 * When enabled the alpha channel of the final render target will be populated with an encoded depth value.
127 * Parameters @p depthEncodeNear and @p depthEncodeFar control which range of the depth buffer to encode.
128 */
129 bool encodeDepth : 1;
130
131 /**
132 * Controls at which position to start encoding depth, in view space. Only relevant with @p encodeDepth is enabled.
133 * Depth will be linearly interpolated between this value and @p depthEncodeFar.
134 */
135 float depthEncodeNear;
136
137 /**
138 * Controls at which position to stop encoding depth, in view space. Only relevant with @p encodeDepth is enabled.
139 * Depth will be linearly interpolated between @p depthEncodeNear and this value.
140 */
141 float depthEncodeFar;
142
143 UINT64 visibleLayers;
144 ConvexVolume cullFrustum;
145 };
146
147 /** Data shared between RENDERER_VIEW_TARGET_DESC and RendererViewTargetProperties */
148 struct RendererViewTargetData
149 {
150 SPtr<RenderTarget> target;
151
152 Rect2I viewRect;
153 Rect2 nrmViewRect;
154 UINT32 targetWidth;
155 UINT32 targetHeight;
156 UINT32 numSamples;
157
158 UINT32 clearFlags;
159 Color clearColor;
160 float clearDepthValue;
161 UINT16 clearStencilValue;
162 };
163
164 /** Set of properties describing the output render target used by a renderer view. */
165 struct RENDERER_VIEW_TARGET_DESC : RendererViewTargetData
166 { };
167
168 /** Set of properties used describing a specific view that the renderer can render. */
169 struct RENDERER_VIEW_DESC : RendererViewData
170 {
171 RENDERER_VIEW_TARGET_DESC target;
172
173 StateReduction stateReduction;
174 Camera* sceneCamera;
175 };
176
177 /** Set of properties used describing a specific view that the renderer can render. */
178 struct RendererViewProperties : RendererViewData
179 {
180 RendererViewProperties() {}
181 RendererViewProperties(const RENDERER_VIEW_DESC& src);
182
183 Matrix4 viewProjTransform;
184 Matrix4 prevViewProjTransform;
185 UINT32 frameIdx;
186
187 RendererViewTargetData target;
188 };
189
190 /** Information whether certain scene objects are visible in a view, per object type. */
191 struct VisibilityInfo
192 {
193 Vector<bool> renderables;
194 Vector<bool> radialLights;
195 Vector<bool> spotLights;
196 Vector<bool> reflProbes;
197 Vector<bool> particleSystems;
198 Vector<bool> decals;
199 };
200
201 /** Information used for culling an object against a view. */
202 struct CullInfo
203 {
204 CullInfo(const Bounds& bounds, UINT64 layer = -1, float cullDistanceFactor = 1.0f)
205 :layer(layer), bounds(bounds), cullDistanceFactor(cullDistanceFactor)
206 { }
207
208 UINT64 layer;
209 Bounds bounds;
210 float cullDistanceFactor;
211 };
212
213 /** Renderer information specific to a single render target. */
214 struct RendererRenderTarget
215 {
216 SPtr<RenderTarget> target;
217 Vector<Camera*> cameras;
218 };
219
220 /** Contains information about a single view into the scene, used by the renderer. */
221 class RendererView
222 {
223 public:
224 RendererView();
225 RendererView(const RENDERER_VIEW_DESC& desc);
226
227 /** Sets state reduction mode that determines how do render queues group & sort renderables. */
228 void setStateReductionMode(StateReduction reductionMode);
229
230 /** Updates the internal camera render settings. */
231 void setRenderSettings(const SPtr<RenderSettings>& settings);
232
233 /** Updates the internal information with a new view transform. */
234 void setTransform(const Vector3& origin, const Vector3& direction, const Matrix4& view,
235 const Matrix4& proj, const ConvexVolume& worldFrustum);
236
237 /** Updates all internal information with new view information. */
238 void setView(const RENDERER_VIEW_DESC& desc);
239
240 /** Returns a structure describing the view. */
241 const RendererViewProperties& getProperties() const { return mProperties; }
242
243 /** Returns the scene camera this object is based of. This can be null for manually constructed renderer cameras. */
244 Camera* getSceneCamera() const { return mCamera; }
245
246 /** Prepares render targets for rendering. When done call endFrame(). */
247 void beginFrame();
248
249 /** Ends rendering and frees any acquired resources. */
250 void endFrame();
251
252 /**
253 * Returns a render queue containing all opaque objects for the specified pipeline. Make sure to call
254 * determineVisible() beforehand if view or object transforms changed since the last time it was called. If @p
255 * forward is true then opaque objects using the forward pipeline are returned, otherwise deferred pipeline objects
256 * are returned.
257 */
258 const SPtr<RenderQueue>& getOpaqueQueue(bool forward) const { return forward ? mForwardOpaqueQueue : mDeferredOpaqueQueue; }
259
260 /**
261 * Returns a render queue containing all transparent objects. Make sure to call determineVisible() beforehand if
262 * view or object transforms changed since the last time it was called.
263 */
264 const SPtr<RenderQueue>& getTransparentQueue() const { return mTransparentQueue; }
265
266 /**
267 * Returns a render queue containing all decal renderable objects. Make sure to call determineVisible() beforehand
268 * if view or object transforms changed since the last time it was called.
269 */
270 const SPtr<RenderQueue>& getDecalQueue() const { return mDecalQueue; }
271
272 /** Returns the compositor in charge of rendering for this view. */
273 const RenderCompositor& getCompositor() const { return mCompositor; }
274
275 /**
276 * Populates view render queues by determining visible renderable objects.
277 *
278 * @param[in] renderables A set of renderable objects to iterate over and determine visibility for.
279 * @param[in] cullInfos A set of world bounds & other information relevant for culling the provided
280 * renderable objects. Must be the same size as the @p renderables array.
281 * @param[out] visibility Output parameter that will have the true bit set for any visible renderable
282 * object. If the bit for an object is already set to true, the method will never
283 * change it to false which allows the same bitfield to be provided to multiple
284 * renderer views. Must be the same size as the @p renderables array.
285 *
286 * As a side-effect, per-view visibility data is also calculated and can be
287 * retrieved by calling getVisibilityMask().
288 */
289 void determineVisible(const Vector<RendererRenderable*>& renderables, const Vector<CullInfo>& cullInfos,
290 Vector<bool>* visibility = nullptr);
291
292 /**
293 * Populates view render queues by determining visible particle systems.
294 *
295 * @param[in] particleSystems A set of particle systems to iterate over and determine visibility for.
296 * @param[in] cullInfos A set of world bounds & other information relevant for culling the provided
297 * renderable objects. Must be the same size as the @p particleSystems array.
298 * @param[out] visibility Output parameter that will have the true bit set for any visible particle system
299 * object. If the bit for an object is already set to true, the method will never
300 * change it to false which allows the same bitfield to be provided to multiple
301 * renderer views. Must be the same size as the @p particleSystems array.
302 *
303 * As a side-effect, per-view visibility data is also calculated and can be
304 * retrieved by calling getVisibilityMask().
305 */
306 void determineVisible(const Vector<RendererParticles>& particleSystems, const Vector<CullInfo>& cullInfos,
307 Vector<bool>* visibility = nullptr);
308
309 /**
310 * Populates view render queues by determining visible decals.
311 *
312 * @param[in] decals A set of decals to iterate over and determine visibility for.
313 * @param[in] cullInfos A set of world bounds & other information relevant for culling the provided
314 * renderable objects. Must be the same size as the @p decals array.
315 * @param[out] visibility Output parameter that will have the true bit set for any visible decal
316 * object. If the bit for an object is already set to true, the method will never
317 * change it to false which allows the same bitfield to be provided to multiple
318 * renderer views. Must be the same size as the @p decals array.
319 *
320 * As a side-effect, per-view visibility data is also calculated and can be
321 * retrieved by calling getVisibilityMask().
322 */
323 void determineVisible(const Vector<RendererDecal>& decals, const Vector<CullInfo>& cullInfos,
324 Vector<bool>* visibility = nullptr);
325
326 /**
327 * Calculates the visibility masks for all the lights of the provided type.
328 *
329 * @param[in] lights A set of lights to determine visibility for.
330 * @param[in] bounds Bounding sphere for each provided light. Must be the same size as the @p lights
331 * array.
332 * @param[in] type Type of all the lights in the @p lights array.
333 * @param[out] visibility Output parameter that will have the true bit set for any visible light. If the
334 * bit for a light is already set to true, the method will never change it to false
335 * which allows the same bitfield to be provided to multiple renderer views. Must
336 * be the same size as the @p lights array.
337 *
338 * As a side-effect, per-view visibility data is also calculated and can be
339 * retrieved by calling getVisibilityMask().
340 */
341 void determineVisible(const Vector<RendererLight>& lights, const Vector<Sphere>& bounds, LightType type,
342 Vector<bool>* visibility = nullptr);
343
344 /**
345 * Culls the provided set of bounds against the current frustum and outputs a set of visibility flags determining
346 * which entry is or isn't visible by this view. Both inputs must be arrays of the same size.
347 */
348 void calculateVisibility(const Vector<CullInfo>& cullInfos, Vector<bool>& visibility) const;
349
350 /**
351 * Culls the provided set of bounds against the current frustum and outputs a set of visibility flags determining
352 * which entry is or isn't visible by this view. Both inputs must be arrays of the same size.
353 */
354 void calculateVisibility(const Vector<Sphere>& bounds, Vector<bool>& visibility) const;
355
356 /**
357 * Culls the provided set of bounds against the current frustum and outputs a set of visibility flags determining
358 * which entry is or isn't visible by this view. Both inputs must be arrays of the same size.
359 */
360 void calculateVisibility(const Vector<AABox>& bounds, Vector<bool>& visibility) const;
361
362 /**
363 * Inserts all visible renderable elements into render queues. Assumes visibility has been calculated beforehand
364 * by calling determineVisible(). After the call render elements can be retrieved from the queues using
365 * getOpqueQueue or getTransparentQueue() calls.
366 */
367 void queueRenderElements(const SceneInfo& sceneInfo);
368
369 /** Returns the visibility mask calculated with the last call to determineVisible(). */
370 const VisibilityInfo& getVisibilityMasks() const { return mVisibility; }
371
372 /** Returns per-view settings that control rendering. */
373 const RenderSettings& getRenderSettings() const { return *mRenderSettings; }
374
375 /**
376 * Retrieves a hash value that is updated whenever render settings change. This can be used by external systems
377 * to detect when they need to update.
378 */
379 UINT64 getRenderSettingsHash() const { return mRenderSettingsHash; }
380
381 /** Updates the GPU buffer containing per-view information, with the latest internal data. */
382 void updatePerViewBuffer();
383
384 /** Returns a buffer that stores per-view parameters. */
385 SPtr<GpuParamBlockBuffer> getPerViewBuffer() const { return mParamBuffer; }
386
387 /**
388 * Returns information about visible lights, in the form of a light grid, used for forward rendering. Only valid
389 * after a call to updateLightGrid().
390 */
391 const LightGrid& getLightGrid() const { return mLightGrid; }
392
393 /** Updates the light grid used for forward rendering. */
394 void updateLightGrid(const VisibleLightData& visibleLightData, const VisibleReflProbeData& visibleReflProbeData);
395
396 /**
397 * Returns a value that can be used for transforming x, y coordinates from NDC into UV coordinates that can be used
398 * for sampling a texture projected on the view.
399 *
400 * @return Returns two 2D values that can be used to transform the coordinate as such: UV = NDC * xy + zw.
401 */
402 Vector4 getNDCToUV() const;
403
404 /** Returns an index of this view within the parent view group. */
405 UINT32 getViewIdx() const { return mViewIdx; }
406
407 /** Assigns a view index to the view. To be called by the parent view group when the view is added to it. */
408 void _setViewIdx(UINT32 viewIdx) { mViewIdx = viewIdx; }
409
410 /**
411 * Extracts the necessary values from the projection matrix that allow you to transform device Z value (range [0, 1]
412 * into view Z value.
413 *
414 * @param[in] projMatrix Projection matrix that was used to create the device Z value to transform.
415 * @return Returns two values that can be used to transform device z to view z using this formula:
416 * z = (deviceZ + y) * x.
417 */
418 static Vector2 getDeviceZToViewZ(const Matrix4& projMatrix);
419
420 /**
421 * Extracts the necessary values from the projection matrix that allow you to transform NDC Z value (range depending
422 * on render API) into view Z value.
423 *
424 * @param[in] projMatrix Projection matrix that was used to create the NDC Z value to transform.
425 * @return Returns two values that can be used to transform NDC z to view z using this formula:
426 * z = (NDCZ + y) * x.
427 */
428 static Vector2 getNDCZToViewZ(const Matrix4& projMatrix);
429
430 /**
431 * Returns a value that can be used for tranforming a depth value in NDC, to a depth value in device Z ([0, 1]
432 * range using this formula: (NDCZ + y) * x.
433 */
434 static Vector2 getNDCZToDeviceZ();
435 private:
436 RendererViewProperties mProperties;
437 Camera* mCamera;
438
439 SPtr<RenderQueue> mDeferredOpaqueQueue;
440 SPtr<RenderQueue> mForwardOpaqueQueue;
441 SPtr<RenderQueue> mTransparentQueue;
442 SPtr<RenderQueue> mDecalQueue;
443
444 RenderCompositor mCompositor;
445 SPtr<RenderSettings> mRenderSettings;
446 UINT32 mRenderSettingsHash;
447
448 SPtr<GpuParamBlockBuffer> mParamBuffer;
449 VisibilityInfo mVisibility;
450 LightGrid mLightGrid;
451 UINT32 mViewIdx;
452 };
453
454 /** Contains one or multiple RendererView%s that are in some way related. */
455 class RendererViewGroup
456 {
457 public:
458 RendererViewGroup(RendererView** views, UINT32 numViews, bool mainPass, UINT32 shadowMapSize = 2048);
459
460 /**
461 * Updates the internal list of views. This is more efficient than always constructing a new instance of this class
462 * when views change, as internal buffers don't need to be re-allocated.
463 */
464 void setViews(RendererView** views, UINT32 numViews);
465
466 /** Returns a view at the specified index. Index must be less than the value returned by getNumViews(). */
467 RendererView* getView(UINT32 idx) const { return mViews[idx]; }
468
469 /** Returns the total number of views in the group. */
470 UINT32 getNumViews() const { return (UINT32)mViews.size(); }
471
472 /** Determines is this the primary rendering pass for this frame. There can only be one primary pass per frame. */
473 bool isMainPass() const { return mIsMainPass; }
474
475 /**
476 * Returns information about visibility of various scene objects, from the perspective of all the views in the
477 * group (visibility will be true if the object is visible from any of the views. determineVisibility() must be
478 * called whenever the scene or view information changes (usually every frame).
479 */
480 const VisibilityInfo& getVisibilityInfo() const { return mVisibility; }
481
482 /**
483 * Returns information about lights visible from this group of views. Only valid after a call to
484 * determineVisibility().
485 */
486 const VisibleLightData& getVisibleLightData() const { return mVisibleLightData; }
487
488 /**
489 * Returns information about refl. probes visible from this group of views. Only valid after a call to
490 * determineVisibility().
491 */
492 const VisibleReflProbeData& getVisibleReflProbeData() const { return mVisibleReflProbeData; }
493
494 /** Returns the object responsible for rendering shadows for this view group. */
495 ShadowRendering& getShadowRenderer() { return mShadowRenderer; }
496
497 /** Returns the object responsible for rendering shadows for this view group. */
498 const ShadowRendering& getShadowRenderer() const { return mShadowRenderer; }
499
500 /**
501 * Updates visibility information for the provided scene objects, from the perspective of all views in this group,
502 * and updates the render queues of each individual view. Use getVisibilityInfo() to retrieve the calculated
503 * visibility information.
504 */
505 void determineVisibility(const SceneInfo& sceneInfo);
506
507 private:
508 Vector<RendererView*> mViews;
509 VisibilityInfo mVisibility;
510 bool mIsMainPass = false;
511
512 VisibleLightData mVisibleLightData;
513 VisibleReflProbeData mVisibleReflProbeData;
514
515 // Note: Ideally we would want to keep this global, so all views share it. This way each view group renders its
516 // own set of shadows, but there might be shadows that are shared, and therefore we could avoid rendering them
517 // multiple times. Since non-primary view groups are used for pre-processing tasks exclusively (at the moment)
518 // this isn't an issue right now.
519 ShadowRendering mShadowRenderer;
520 };
521
522 /** @} */
523}}
524