// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Delegate.h" #include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Platform/CriticalSection.h" #include "Engine/Scripting/ScriptingObjectReference.h" #include "Engine/Scripting/ScriptingType.h" #include "PostProcessBase.h" #include "RenderView.h" class GPUDevice; class GPUContext; class GPUTexture; class GPUTextureView; class GPUSwapChain; class RenderBuffers; struct RenderContext; class Camera; class Actor; /// /// Allows to perform custom rendering using graphics pipeline. /// API_CLASS() class FLAXENGINE_API RenderTask : public PersistentScriptingObject { DECLARE_SCRIPTING_TYPE(RenderTask); /// /// List with all registered tasks /// static Array Tasks; /// /// Static locker for render tasks list /// static CriticalSection TasksLocker; /// /// Amount of tasks rendered during last frame /// static int32 TasksDoneLastFrame; /// /// Draws all tasks. Called only during rendering by the graphics device. /// static void DrawAll(); private: RenderTask* _prevTask = nullptr; public: /// /// Finalizes an instance of the class. /// virtual ~RenderTask(); public: /// /// Gets or sets a value indicating whether task is enabled. /// API_FIELD() bool Enabled = true; /// /// The order of the task. Used for tasks rendering order. Lower first, higher later. /// API_FIELD() int32 Order = 0; /// /// The amount of frames rendered by this task. It is auto incremented on task drawing. /// API_FIELD(ReadOnly) int32 FrameCount = 0; /// /// The output window swap chain. Optional, used only when rendering to native window backbuffer. /// GPUSwapChain* SwapChain = nullptr; /// /// The index of the frame when this task was last time rendered. /// uint64 LastUsedFrame = 0; /// /// Action fired on task rendering. /// API_EVENT() Delegate Render; /// /// Action fired on task rendering begin. /// API_EVENT() Delegate Begin; /// /// Action fired on task rendering end. /// API_EVENT() Delegate End; /// /// Action fired just after frame present. /// API_EVENT() Delegate Present; /// /// Determines whether this task can be rendered. /// /// true if this task can be rendered; otherwise, false. API_PROPERTY() virtual bool CanDraw() const; /// /// Called by graphics device to draw this task. Can be used to invoke task rendering nested inside another task - use on own risk! /// API_FUNCTION() virtual void OnDraw(); /// /// Called on task rendering begin. /// /// The GPU context. virtual void OnBegin(GPUContext* context); /// /// Called on task rendering. /// /// The GPU context. virtual void OnRender(GPUContext* context); /// /// Called on task rendering end. /// /// The GPU context. virtual void OnEnd(GPUContext* context); /// /// Presents frame to the output. /// /// True if use vertical synchronization to lock frame rate. virtual void OnPresent(bool vsync); /// /// Changes the buffers and output size. Does nothing if size won't change. Called by window or user to resize rendering buffers. /// /// The width. /// The height. /// True if cannot resize the buffers. API_FUNCTION() virtual bool Resize(int32 width, int32 height); public: bool operator<(const RenderTask& other) const { return Order < other.Order; } }; /// /// Defines actors to draw sources. /// API_ENUM(Attributes="Flags") enum class ActorsSources { /// /// The actors won't be rendered. /// None = 0, /// /// The actors from the loaded scenes. /// Scenes = 1, /// /// The actors from the custom collection. /// CustomActors = 2, /// /// The actors from the loaded scenes and custom collection. /// ScenesAndCustomActors = Scenes | CustomActors, }; DECLARE_ENUM_OPERATORS(ActorsSources); /// /// Wrapper for PostProcessBase that allows to render to customized managed postFx. /// TODO: add support for managed inheritance of custom native types with proper spawn handling (like for ManagedScript) /// /// class ManagedPostProcessEffect : public PostProcessBase { public: /// /// The script to use. Inherits from C# class 'PostProcessEffect'. /// Script* Target = nullptr; public: /// /// Fetches the information about the PostFx location from the managed object. /// void FetchInfo(); public: // [PostProcessBase] bool IsLoaded() const override; void Render(RenderContext& renderContext, GPUTexture* input, GPUTexture* output) override; }; /// /// Render task which draws scene actors into the output buffer. /// /// API_CLASS() class FLAXENGINE_API SceneRenderTask : public RenderTask { DECLARE_SCRIPTING_TYPE(SceneRenderTask); /// /// Finalizes an instance of the class. /// ~SceneRenderTask(); public: /// /// True if the current frame is after the camera cut. Used to clear the temporal effects history and prevent visual artifacts blended from the previous frames. /// bool IsCameraCut = true; /// /// Marks the next rendered frame as camera cut. Used to clear the temporal effects history and prevent visual artifacts blended from the previous frames. /// API_FUNCTION() void CameraCut() { IsCameraCut = true; } /// /// The output texture (can be null if using rendering to window swap chain). Can be sued to redirect the default scene rendering output to a texture. /// API_FIELD() GPUTexture* Output = nullptr; /// /// The scene rendering buffers. Created and managed by the task. /// API_FIELD(ReadOnly) RenderBuffers* Buffers = nullptr; /// /// The scene rendering camera. Can be used to override the rendering view properties based on the current camera setup. /// API_FIELD() Camera* Camera = nullptr; /// /// The render view description. /// API_FIELD() RenderView View; /// /// The actors source to use (configures what objects to render). /// API_FIELD() ActorsSources ActorsSource = ActorsSources::Scenes; /// /// The custom set of actors to render. /// Array CustomActors; /// /// Adds the custom actor to the rendering. /// /// The actor. API_FUNCTION() void AddCustomActor(Actor* actor) { CustomActors.Add(actor); } /// /// Removes the custom actor from the rendering. /// /// The actor. API_FUNCTION() void RemoveCustomActor(Actor* actor) { CustomActors.Remove(actor); } /// /// The custom post fx to render (managed). /// Array CustomPostFx; public: /// /// The action called on view rendering to collect draw calls. It allows to extend rendering pipeline and draw custom geometry non-existing in the scene or custom actors set. /// API_EVENT() Delegate CollectDrawCalls; /// /// Calls collecting postFx volumes for rendering. /// /// The rendering context. virtual void CollectPostFxVolumes(RenderContext& renderContext); /// /// Calls drawing scene objects. /// /// The rendering context. virtual void OnCollectDrawCalls(RenderContext& renderContext); /// /// The action called after scene rendering. Can be used to render additional visual elements to the output. /// API_EVENT() Delegate PostRender; /// /// Called after scene rendering. Can be used to render additional visual elements to the output. /// /// The GPU commands context. /// The rendering context. virtual void OnPostRender(GPUContext* context, RenderContext& renderContext); public: /// /// Gets the rendering render task viewport. /// API_PROPERTY() Viewport GetViewport() const; /// /// Gets the rendering output view. /// API_PROPERTY() GPUTextureView* GetOutputView() const; public: // [RenderTask] bool Resize(int32 width, int32 height) override; bool CanDraw() const override; void OnBegin(GPUContext* context) override; void OnRender(GPUContext* context) override; void OnEnd(GPUContext* context) override; }; /// /// The main game rendering task used by the engine. /// /// /// For Main Render Task its may be null because game can be rendered directly to the native window backbuffer. /// This allows to increase game rendering performance (reduced memory usage and data transfer). /// User should use post effects pipeline to modify the final frame. /// /// API_CLASS() class FLAXENGINE_API MainRenderTask : public SceneRenderTask { DECLARE_SCRIPTING_TYPE(MainRenderTask); /// /// Finalizes an instance of the class. /// ~MainRenderTask(); public: /// /// Gets the main game rendering task. Use it to plug custom rendering logic for your game. /// API_FIELD(ReadOnly) static MainRenderTask* Instance; public: // [SceneRenderTask] void OnBegin(GPUContext* context) override; }; /// /// The high-level renderer context. Used to collect the draw calls for the scene rendering. Can be used to perform a custom rendering. /// API_STRUCT() struct RenderContext { DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContext); /// /// The render buffers. /// API_FIELD() RenderBuffers* Buffers = nullptr; /// /// The render list. /// API_FIELD() RenderList* List = nullptr; /// /// The render view. /// API_FIELD() RenderView View; /// /// The proxy render view used to synchronize objects level of detail during rendering (eg. during shadow maps rendering passes). It's optional. /// API_FIELD() RenderView* LodProxyView = nullptr; /// /// The scene rendering task that is a source of renderable objects (optional). /// API_FIELD() SceneRenderTask* Task = nullptr; RenderContext() { } RenderContext(SceneRenderTask* task); };