// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Collections/Array.h" #include "Engine/Core/Math/Half.h" #include "Engine/Graphics/PostProcessSettings.h" #include "Engine/Graphics/DynamicBuffer.h" #include "Engine/Scripting/ScriptingObject.h" #include "DrawCall.h" enum class StaticFlags; class RenderBuffers; class LightWithShadow; class IPostFxSettingsProvider; class CubeTexture; class PostProcessBase; struct RenderContext; struct RendererDirectionalLightData { Vector3 Position; float MinRoughness; Vector3 Color; float ShadowsStrength; Vector3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; float ShadowsDistance; int32 CascadeCount; float ContactShadowsLength; ShadowsCastingMode ShadowsMode; void SetupLightData(LightData* data, const RenderView& view, bool useShadow) const; }; struct RendererSpotLightData { Vector3 Position; float MinRoughness; Vector3 Color; float ShadowsStrength; Vector3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; float ShadowsDistance; float Radius; float FallOffExponent; float SourceRadius; Vector3 UpVector; float OuterConeAngle; float CosOuterCone; float InvCosConeDifference; float ContactShadowsLength; ShadowsCastingMode ShadowsMode; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; int8 UseInverseSquaredFalloff : 1; GPUTexture* IESTexture; void SetupLightData(LightData* data, const RenderView& view, bool useShadow) const; }; struct RendererPointLightData { Vector3 Position; float MinRoughness; Vector3 Color; float ShadowsStrength; Vector3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; float ShadowsDistance; float Radius; float FallOffExponent; float SourceRadius; float SourceLength; float ContactShadowsLength; ShadowsCastingMode ShadowsMode; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; int8 UseInverseSquaredFalloff : 1; GPUTexture* IESTexture; void SetupLightData(LightData* data, const RenderView& view, bool useShadow) const; }; struct RendererSkyLightData { Vector3 Position; float VolumetricScatteringIntensity; Vector3 Color; float Radius; Vector3 AdditiveColor; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; CubeTexture* Image; void SetupLightData(LightData* data, const RenderView& view, bool useShadow) const; }; /// /// The draw calls list types. /// API_ENUM() enum class DrawCallsListType { /// /// Hardware depth rendering. /// Depth, /// /// GBuffer rendering. /// GBuffer, /// /// GBuffer rendering after decals. /// GBufferNoDecals, /// /// Transparency rendering. /// Forward, /// /// Distortion accumulation rendering. /// Distortion, /// /// Motion vectors rendering. /// MotionVectors, MAX, }; /// /// Represents a patch of draw calls that can be submitted to rendering. /// struct DrawBatch { /// /// Draw calls sorting key (shared by the all draw calls withing a patch). /// uint32 SortKey; /// /// The first draw call index. /// int32 StartIndex; /// /// A number of draw calls to be submitted at once. /// int32 BatchSize; /// /// The total amount of instances (sum from all draw calls in this batch). /// int32 InstanceCount; bool operator<(const DrawBatch& other) const { return SortKey < other.SortKey; } }; /// /// Represents a list of draw calls. /// struct DrawCallsList { /// /// The list of draw calls indices to render. /// Array Indices; /// /// The draw calls batches (for instancing). /// Array Batches; /// /// True if draw calls batches list can be rendered using hardware instancing, otherwise false. /// bool CanUseInstancing; void Clear() { Indices.Clear(); Batches.Clear(); CanUseInstancing = true; } bool IsEmpty() const { return Indices.IsEmpty(); } }; /// /// Rendering cache container object for the draw calls collecting, sorting and executing. /// API_CLASS(Sealed) class FLAXENGINE_API RenderList : public PersistentScriptingObject { DECLARE_SCRIPTING_TYPE(RenderList); public: /// /// Allocates the new renderer list object or reuses already allocated one. /// /// The cache object. API_FUNCTION() static RenderList* GetFromPool(); /// /// Frees the list back to the pool. /// /// The cache. API_FUNCTION() static void ReturnToPool(RenderList* cache); /// /// Cleanups the static data cache used to accelerate draw calls sorting. Use it to reduce memory pressure. /// static void CleanupCache(); public: /// /// Draw calls list (for all draw passes). /// Array DrawCalls; /// /// The draw calls lists. Each for the separate draw pass. /// DrawCallsList DrawCallsLists[(int32)DrawCallsListType::MAX]; /// /// Light pass members - directional lights /// Array DirectionalLights; /// /// Light pass members - point lights /// Array PointLights; /// /// Light pass members - spot lights /// Array SpotLights; /// /// Light pass members - sky lights /// Array SkyLights; /// /// Environment probes to use for rendering reflections /// Array EnvironmentProbes; /// /// Decals registered for the rendering. /// Array Decals; /// /// Sky/skybox renderer proxy to use (only one per frame) /// ISkyRenderer* Sky; /// /// Atmospheric fog renderer proxy to use (only one per frame) /// IAtmosphericFogRenderer* AtmosphericFog; /// /// Fog renderer proxy to use (only one per frame) /// IFogRenderer* Fog; /// /// Post effect to render (TEMPORARY! cleared after and before rendering). /// Array PostFx; /// /// The post process settings. /// PostProcessSettings Settings; struct FLAXENGINE_API BlendableSettings { IPostFxSettingsProvider* Provider; float Weight; int32 Priority; float VolumeSizeSqr; bool operator<(const BlendableSettings& other) const; }; /// /// The blendable postFx volumes collected during frame draw calls gather pass. /// Array Blendable; void AddSettingsBlend(IPostFxSettingsProvider* provider, float weight, int32 priority, float volumeSizeSqr); /// /// Camera frustum corners in World Space /// Vector3 FrustumCornersWs[8]; /// /// Camera frustum corners in View Space /// Vector3 FrustumCornersVs[8]; private: /// /// Represents data per instance element used for instanced rendering. /// struct InstanceData { Vector4 InstanceOrigin; // .w contains PerInstanceRandom Vector4 InstanceTransform1; // .w contains LODDitherFactor Vector3 InstanceTransform2; Vector3 InstanceTransform3; Half4 InstanceLightmapArea; }; DynamicVertexBuffer _instanceBuffer; public: /// /// Blends the postprocessing settings into the final options. /// void BlendSettings(); /// /// Runs the post fx materials pass. Uses input/output buffer to render all materials. Uses temporary render target as a ping pong buffer if required (the same format and description). /// /// The context. /// The rendering context. /// The material postFx location. /// The custom postFx location. /// The input and output texture. void RunPostFxPass(GPUContext* context, RenderContext& renderContext, MaterialPostFxLocation locationA, PostProcessEffectLocation locationB, GPUTexture*& inputOutput); /// /// Runs the material post fx pass. Uses input and output buffers as a ping pong to render all materials. /// /// The context. /// The rendering context. /// The material postFx location. /// The input texture. /// The output texture. void RunMaterialPostFxPass(GPUContext* context, RenderContext& renderContext, MaterialPostFxLocation location, GPUTexture*& input, GPUTexture*& output); /// /// Runs the custom post fx pass. Uses input and output buffers as a ping pong to render all effects. /// /// The context. /// The rendering context. /// The custom postFx location. /// The input texture. /// The output texture. void RunCustomPostFxPass(GPUContext* context, RenderContext& renderContext, PostProcessEffectLocation location, GPUTexture*& input, GPUTexture*& output); /// /// Determines whether any Custom PostFx or Material PostFx has to be rendered after AA pass. Used to pick a faster rendering path by the frame rendering module. /// /// The rendering context. /// True if render any postFx after AA, otherwise false. bool HasAnyPostAA(RenderContext& renderContext) const; public: /// /// Init cache for given task /// /// The rendering context. void Init(RenderContext& renderContext); /// /// Clear cached data /// void Clear(); public: /// /// Adds the draw call to the draw lists. /// /// The object draw modes. /// The object static flags. /// The draw call data. /// True if the rendered mesh can receive decals. void AddDrawCall(DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals); /// /// Sorts the collected draw calls list. /// /// The rendering context. /// If set to true reverse draw call distance to the view. Results in back to front sorting. /// The collected draw calls list type. API_FUNCTION() FORCE_INLINE void SortDrawCalls(API_PARAM(Ref) const RenderContext& renderContext, bool reverseDistance, DrawCallsListType listType) { SortDrawCalls(renderContext, reverseDistance, DrawCallsLists[(int32)listType]); } /// /// Sorts the collected draw calls list. /// /// The rendering context. /// If set to true reverse draw call distance to the view. Results in back to front sorting. /// The collected draw calls list. void SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list); /// /// Executes the collected draw calls. /// /// The rendering context. /// The collected draw calls list type. API_FUNCTION() FORCE_INLINE void ExecuteDrawCalls(API_PARAM(Ref) const RenderContext& renderContext, DrawCallsListType listType) { ExecuteDrawCalls(renderContext, DrawCallsLists[(int32)listType]); } /// /// Executes the collected draw calls. /// /// The rendering context. /// The collected draw calls list. void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list); };