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 "BsCorePrerequisites.h"
6#include "String/BsStringID.h"
7#include "Renderer/BsRendererMeshData.h"
8#include "Material/BsShaderVariation.h"
9
10namespace bs
11{
12 class RendererExtension;
13 class LightProbeVolume;
14 struct RenderSettings;
15 struct EvaluatedAnimationData;
16 struct ParticlePerFrameData;
17
18 /** Contains various data evaluated by external systems on a per-frame basis that is to be used by the renderer. */
19 struct PerFrameData
20 {
21 const EvaluatedAnimationData* animation = nullptr;
22 const ParticlePerFrameData* particles = nullptr;
23 };
24
25 namespace ct
26 {
27 class RendererTask;
28 class LightProbeVolume;
29 class Decal;
30
31 /** @addtogroup Renderer-Internal
32 * @{
33 */
34
35 /** Common shader variations. */
36
37 /** Returns a specific vertex input shader variation. */
38 template<bool skinned, bool morph>
39 static const ShaderVariation& getVertexInputVariation()
40 {
41 static ShaderVariation variation = ShaderVariation(
42 {
43 ShaderVariation::Param("SKINNED", skinned),
44 ShaderVariation::Param("MORPH", morph),
45 });
46
47 return variation;
48 }
49
50 /** Returns a specific forward rendering shader variation. */
51 template<bool skinned, bool morph, bool clustered>
52 static const ShaderVariation& getForwardRenderingVariation()
53 {
54 static ShaderVariation variation = ShaderVariation(
55 {
56 ShaderVariation::Param("SKINNED", skinned),
57 ShaderVariation::Param("MORPH", morph),
58 ShaderVariation::Param("CLUSTERED", clustered),
59 });
60
61 return variation;
62 }
63
64 /** Technique tags. */
65 static StringID RTag_Skinned = "Skinned";
66 static StringID RTag_Morph = "Morph";
67 static StringID RTag_SkinnedMorph = "SkinnedMorph";
68
69 /** Set of options that can be used for controlling the renderer. */
70 struct BS_CORE_EXPORT RendererOptions
71 {
72 virtual ~RendererOptions() = default;
73 };
74
75 /** Settings that control renderer scene capture. */
76 struct CaptureSettings
77 {
78 /** If true scene will be captured in a format that supports high dynamic range. */
79 bool hdr = true;
80
81 /**
82 * When enabled the alpha channel of the final render target will be populated with an encoded depth value.
83 * Parameters @p depthEncodeNear and @p depthEncodeFar control which range of the depth buffer to encode.
84 */
85 bool encodeDepth = false;
86
87 /**
88 * Controls at which position to start encoding depth, in view space. Only relevant with @p encodeDepth is enabled.
89 * Depth will be linearly interpolated between this value and @p depthEncodeFar.
90 */
91 float depthEncodeNear = 0.0f;
92
93 /**
94 * Controls at which position to stop encoding depth, in view space. Only relevant with @p encodeDepth is enabled.
95 * Depth will be linearly interpolated between @p depthEncodeNear and this value.
96 */
97 float depthEncodeFar = 0.0f;
98 };
99
100 /**
101 * Information about a shader that is part of a renderer extension point. These shaders can be specialized by the
102 * outside world, by overriding parts of their functionality through mixins. Those specialized shaders are then,
103 * depending on the extension point, either attached to a normal Shader as subshaders, or sent back to the renderer
104 * in some other way.
105 */
106 struct ExtensionShaderInfo
107 {
108 String name; /**< Unique name of the sub-shader type that is recognized by the renderer. */
109 Path path; /**< Path to the original shader. */
110 ShaderDefines defines; /**< Additional defines to use when compiling the shader. */
111 };
112
113 /**
114 * Information about a shader extension point provided by the renderer. Extension points allow the outside world to
115 * generate a customized version of shaders used by the renderer, usually overriding some functionality with custom
116 * code. Extension point can contain one or multiple shaders whose functionality can be overriden.
117 */
118 struct ShaderExtensionPointInfo
119 {
120 Vector<ExtensionShaderInfo> shaders;
121 };
122
123 /**
124 * Primarily rendering class that allows you to specify how to render objects that exist in the scene graph. You need
125 * to provide your own implementation of your class.
126 *
127 * @note
128 * Normally you would iterate over all cameras, find visible objects for each camera and render those objects in some
129 * way.
130 */
131 class BS_CORE_EXPORT Renderer
132 {
133 public:
134 Renderer();
135 virtual ~Renderer() = default;
136
137 /** Initializes the renderer. Must be called before using the renderer. */
138 virtual void initialize() { }
139
140 /** Called every frame. Triggers render task callbacks. */
141 void update();
142
143 /** Cleans up the renderer. Must be called before the renderer is deleted. */
144 virtual void destroy() { }
145
146 /** Name of the renderer. Used by materials to find an appropriate technique for this renderer. */
147 virtual const StringID& getName() const = 0;
148
149 /** Called in order to render all currently active cameras. */
150 virtual void renderAll(PerFrameData perFrameData) = 0;
151
152 /**
153 * Called whenever a new camera is created.
154 *
155 * @note Core thread.
156 */
157 virtual void notifyCameraAdded(Camera* camera) { }
158
159 /**
160 * Called whenever a camera's position or rotation is updated.
161 *
162 * @param[in] camera Camera that was updated.
163 * @param[in] updateFlag Optional flag that allows the camera to signal to the renderer exactly what was updated.
164 *
165 * @note Core thread.
166 */
167 virtual void notifyCameraUpdated(Camera* camera, UINT32 updateFlag) { }
168
169 /**
170 * Called whenever a camera is destroyed.
171 *
172 * @note Core thread.
173 */
174 virtual void notifyCameraRemoved(Camera* camera) { }
175
176 /**
177 * Called whenever a new renderable is created.
178 *
179 * @note Core thread.
180 */
181 virtual void notifyRenderableAdded(Renderable* renderable) { }
182
183 /**
184 * Called whenever a renderable is updated.
185 *
186 * @note Core thread.
187 */
188 virtual void notifyRenderableUpdated(Renderable* renderable) { }
189
190 /**
191 * Called whenever a renderable is destroyed.
192 *
193 * @note Core thread.
194 */
195 virtual void notifyRenderableRemoved(Renderable* renderable) { }
196
197 /**
198 * Called whenever a new light is created.
199 *
200 * @note Core thread.
201 */
202 virtual void notifyLightAdded(Light* light) { }
203
204 /**
205 * Called whenever a light is updated.
206 *
207 * @note Core thread.
208 */
209 virtual void notifyLightUpdated(Light* light) { }
210
211 /**
212 * Called whenever a light is destroyed.
213 *
214 * @note Core thread.
215 */
216 virtual void notifyLightRemoved(Light* light) { }
217
218 /**
219 * Called whenever a new reflection probe is created.
220 *
221 * @note Core thread.
222 */
223 virtual void notifyReflectionProbeAdded(ReflectionProbe* probe) { }
224
225 /**
226 * Called whenever a reflection probe is updated.
227 *
228 * @note Core thread.
229 */
230 virtual void notifyReflectionProbeUpdated(ReflectionProbe* probe, bool texture) { }
231
232 /**
233 * Called whenever a reflection probe is destroyed.
234 *
235 * @note Core thread.
236 */
237 virtual void notifyReflectionProbeRemoved(ReflectionProbe* probe) { }
238
239 /**
240 * Called whenever a new light probe volume is created.
241 *
242 * @note Core thread.
243 */
244 virtual void notifyLightProbeVolumeAdded(LightProbeVolume* volume) { }
245
246 /**
247 * Called whenever a light probe volume is updated.
248 *
249 * @note Core thread.
250 */
251 virtual void notifyLightProbeVolumeUpdated(LightProbeVolume* volume) { }
252
253 /**
254 * Called whenever a light probe volume is destroyed.
255 *
256 * @note Core thread.
257 */
258 virtual void notifyLightProbeVolumeRemoved(LightProbeVolume* volume) { }
259
260 /**
261 * Called whenever a skybox is created.
262 *
263 * @note Core thread.
264 */
265 virtual void notifySkyboxAdded(Skybox* skybox) { }
266
267 /**
268 * Called whenever a skybox is destroyed.
269 *
270 * @note Core thread.
271 */
272 virtual void notifySkyboxRemoved(Skybox* skybox) { }
273
274 /**
275 * Called whenever a new particle system is created.
276 *
277 * @note Core thread.
278 */
279 virtual void notifyParticleSystemAdded(ParticleSystem* particleSystem) { }
280
281 /**
282 * Called whenever a particle system is updated.
283 *
284 * @note Core thread.
285 */
286 virtual void notifyParticleSystemUpdated(ParticleSystem* particleSystem, bool tfrmOnly) { }
287
288 /**
289 * Called whenever a particle system is destroyed.
290 *
291 * @note Core thread.
292 */
293 virtual void notifyParticleSystemRemoved(ParticleSystem* particleSystem) { }
294
295 /**
296 * Called whenever a new decal is created.
297 *
298 * @note Core thread.
299 */
300 virtual void notifyDecalAdded(Decal* decal) { }
301
302 /**
303 * Called whenever a decal is updated.
304 *
305 * @note Core thread.
306 */
307 virtual void notifyDecalUpdated(Decal* decal) { }
308
309 /**
310 * Called whenever a decal is destroyed.
311 *
312 * @note Core thread.
313 */
314 virtual void notifyDecalRemoved(Decal* decal) { }
315
316 /**
317 * Captures the scene at the specified location into a cubemap.
318 *
319 * @param[in] cubemap Cubemap to store the results in.
320 * @param[in] position Position to capture the scene at.
321 * @param[in] settings Settings that allow you to customize the capture.
322 *
323 * @note Core thread.
324 */
325 virtual void captureSceneCubeMap(const SPtr<Texture>& cubemap, const Vector3& position,
326 const CaptureSettings& settings) = 0;
327
328 /**
329 * Creates a new empty renderer mesh data.
330 *
331 * @note Sim thread.
332 *
333 * @see RendererMeshData
334 */
335 virtual SPtr<RendererMeshData> _createMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout,
336 IndexType indexType = IT_32BIT);
337
338 /**
339 * Creates a new renderer mesh data using an existing generic mesh data buffer.
340 *
341 * @note Sim thread.
342 *
343 * @see RendererMeshData
344 */
345 virtual SPtr<RendererMeshData> _createMeshData(const SPtr<MeshData>& meshData);
346
347 /**
348 * Registers an extension object that will be called every frame by the renderer. Allows external code to perform
349 * custom rendering interleaved with the renderer's output.
350 *
351 * @note Core thread.
352 */
353 void addPlugin(RendererExtension* plugin) { mCallbacks.insert(plugin); }
354
355 /**
356 * Unregisters an extension registered with addPlugin().
357 *
358 * @note Core thread.
359 */
360 void removePlugin(RendererExtension* plugin) { mCallbacks.erase(plugin); }
361
362 /**
363 * Registers a new task for execution on the core thread.
364 *
365 * @note Thread safe.
366 */
367 void addTask(const SPtr<RendererTask>& task);
368
369 /** Sets options used for controlling the rendering. */
370 virtual void setOptions(const SPtr<RendererOptions>& options) { }
371
372 /** Returns current set of options used for controlling the rendering. */
373 virtual SPtr<RendererOptions> getOptions() const { return SPtr<RendererOptions>(); }
374
375 /**
376 * Returns information about a set of shaders corresponding to a renderer extension point. These shaders are the
377 * built-in shaders used by the renderer for specific functionality (e.g. deferred rendering). These shaders can
378 * be customized (usually through BSL mixin overrides) to provide user specific functionality (e.g. a custom BRDF
379 * model), without having to modify the (usually complex) original shaders.
380 *
381 * These modified shaders can then be passed back to the renderer through some means. If it's an extension point
382 * that does some kind of per-object rendering (e.g. shadow projection, or lighting in a forward renderer), then
383 * the shader should be passed as a SubShader of the Shader used by the Renderable's Material. If it's some global
384 * shader (e.g. deferred rendering lighting) then call setGlobalShaderOverride(). In both cases, the name of the
385 * extension point shader should be provided, as returned by this method.
386 *
387 * A single extension point can provide multiple shaders (e.g. deferred rendering can be implemented as both
388 * standard and tiled deferred), in which case you'll likely want to override all the relevant shaders.
389 *
390 * @param[in] name Name of the sub-shader extension point, e.g. "DeferredDirectLighting",
391 * "ShadowProjection". These are renderer specific and you should look them up in
392 * renderer documentation.
393 * @returns A list of overridable shaders in the extension point.
394 */
395 virtual ShaderExtensionPointInfo getShaderExtensionPointInfo(const String& name) { return {}; }
396
397 /**
398 * Allows the caller to override some built-in renderer functionality with a custom shader. The exact set of
399 * overridable shaders can be retrieved through getShaderExtensionPointInfo().
400 */
401 virtual void setGlobalShaderOverride(const String& name, const SPtr<bs::Shader>& shader) { }
402
403 /**
404 * Provides the same functionality as setGlobalShaderOverride(const String&, const SPtr<bs::Shader>&), but it automatically
405 * evaluates all sub-shaders of the provided shader and registers them as overrides.
406 */
407 void setGlobalShaderOverride(const SPtr<bs::Shader>& shader);
408 protected:
409 friend class RendererTask;
410
411 /** Information about a renderer task queued to be executed. */
412 struct RendererTaskQueuedInfo
413 {
414 RendererTaskQueuedInfo(const SPtr<RendererTask>& task, UINT64 frameIdx)
415 :task(task), frameIdx(frameIdx)
416 { }
417
418 SPtr<RendererTask> task;
419 UINT64 frameIdx;
420 };
421
422 /**
423 * Executes all renderer tasks queued for this frame.
424 *
425 * @param[in] forceAll If true, multi-frame tasks will be forced to execute fully within this call.
426 * @param[in] upToFrame Only tasks that were queued before or during the frame with the provided index will
427 * be processed.
428 *
429 * @note Core thread.
430 */
431 void processTasks(bool forceAll, UINT64 upToFrame = std::numeric_limits<UINT64>::max());
432
433 /**
434 * Executes the provided renderer task.
435 *
436 * @param[in] task Task to execute.
437 * @param[in] forceAll If true, multi-frame tasks will be forced to execute fully within this call.
438 *
439 * @note Core thread.
440 */
441 void processTask(RendererTask& task, bool forceAll);
442
443 /** Callback to trigger when comparing the order in which renderer extensions are called. */
444 static bool compareCallback(const RendererExtension* a, const RendererExtension* b);
445
446 Set<RendererExtension*, std::function<bool(const RendererExtension*, const RendererExtension*)>> mCallbacks;
447
448 Vector<RendererTaskQueuedInfo> mQueuedTasks; // Sim & core thread
449 Vector<SPtr<RendererTask>> mUnresolvedTasks; // Sim thread
450 Vector<SPtr<RendererTask>> mRemainingUnresolvedTasks; // Sim thread
451 Vector<SPtr<RendererTask>> mRunningTasks; // Core thread
452 Vector<SPtr<RendererTask>> mRemainingTasks; // Core thread
453 Mutex mTaskMutex;
454 };
455
456 /** Provides easy access to Renderer. */
457 SPtr<Renderer> BS_CORE_EXPORT gRenderer();
458
459 /**
460 * Task that represents an asynchonous operation queued for execution on the core thread. All such tasks are executed
461 * before main rendering happens, every frame.
462 *
463 * @note Thread safe except where stated otherwise.
464 */
465 class BS_CORE_EXPORT RendererTask
466 {
467 struct PrivatelyConstruct {};
468
469 public:
470 RendererTask(const PrivatelyConstruct& dummy, String name, std::function<bool()> taskWorker);
471
472 /**
473 * Creates a new task. Task should be provided to Renderer in order for it to start.
474 *
475 * @param[in] name Name you can use to more easily identify the task.
476 * @param[in] taskWorker Worker method that does all of the work in the task. Tasks can run over the course of
477 * multiple frames, in which case this method should return false (if there's more
478 * work to be done), or true (if the task has completed).
479 */
480 static SPtr<RendererTask> create(String name, std::function<bool()> taskWorker);
481
482 /** Returns true if the task has completed. */
483 bool isComplete() const;
484
485 /** Returns true if the task has been canceled. */
486 bool isCanceled() const;
487
488 /** Blocks the current thread until the task has completed. */
489 void wait();
490
491 /** Cancels the task and removes it from the Renderer's queue. */
492 void cancel();
493
494 /**
495 * Callback triggered on the sim thread, when the task completes. Is not triggered if the task is cancelled.
496 *
497 * @note Sim thread only.
498 */
499 Event<void()> onComplete;
500
501 private:
502 friend class Renderer;
503
504 String mName;
505 std::function<bool()> mTaskWorker;
506 std::atomic<UINT32> mState{0}; /**< 0 - Inactive, 1 - In progress, 2 - Completed, 3 - Canceled */
507 };
508
509 /** @} */
510}}
511