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 | |
19 | namespace 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 | |