// Copyright (c) 2012-2023 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" #include "RenderListBuffer.h" #include "RendererAllocation.h" #include "RenderSetup.h" enum class StaticFlags; class RenderBuffers; class PostProcessEffect; class SceneRendering; class LightWithShadow; class IPostFxSettingsProvider; class CubeTexture; struct RenderContext; struct RenderContextBatch; struct RendererDirectionalLightData { Float3 Position; float MinRoughness; Float3 Color; float ShadowsStrength; Float3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; StaticFlags StaticFlags; float IndirectLightingIntensity; int16 ShadowDataIndex = -1; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; float ShadowsDistance; int32 CascadeCount; float ContactShadowsLength; ShadowsCastingMode ShadowsMode; Guid ID; void SetupLightData(LightData* data, bool useShadow) const; }; struct RendererSpotLightData { Float3 Position; float MinRoughness; Float3 Color; float ShadowsStrength; Float3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; float ShadowsDistance; float Radius; float FallOffExponent; float SourceRadius; Float3 UpVector; float OuterConeAngle; float CosOuterCone; float InvCosConeDifference; float ContactShadowsLength; float IndirectLightingIntensity; ShadowsCastingMode ShadowsMode; StaticFlags StaticFlags; int16 ShadowDataIndex = -1; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; int8 UseInverseSquaredFalloff : 1; GPUTexture* IESTexture; Guid ID; void SetupLightData(LightData* data, bool useShadow) const; }; struct RendererPointLightData { Float3 Position; float MinRoughness; Float3 Color; float ShadowsStrength; Float3 Direction; float ShadowsFadeDistance; float ShadowsNormalOffsetScale; float ShadowsDepthBias; float ShadowsSharpness; float VolumetricScatteringIntensity; float ShadowsDistance; float Radius; float FallOffExponent; float SourceRadius; float SourceLength; float ContactShadowsLength; float IndirectLightingIntensity; ShadowsCastingMode ShadowsMode; StaticFlags StaticFlags; int16 ShadowDataIndex = -1; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; int8 UseInverseSquaredFalloff : 1; GPUTexture* IESTexture; Guid ID; void SetupLightData(LightData* data, bool useShadow) const; }; struct RendererSkyLightData { Float3 Position; float VolumetricScatteringIntensity; Float3 Color; float Radius; Float3 AdditiveColor; float IndirectLightingIntensity; StaticFlags StaticFlags; int8 CastVolumetricShadow : 1; int8 RenderedVolumetricFog : 1; CubeTexture* Image; Guid ID; void SetupLightData(LightData* data, 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). /// uint64 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; } }; struct BatchedDrawCall { DrawCall DrawCall; Array Instances; }; /// /// Represents a list of draw calls. /// struct DrawCallsList { /// /// The list of draw calls indices to render. /// RenderListBuffer Indices; /// /// The list of external draw calls indices to render. /// RenderListBuffer PreBatchedDrawCalls; /// /// 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(); bool IsEmpty() const; }; /// /// Rendering cache container object for the draw calls collecting, sorting and executing. /// API_CLASS(Sealed) class FLAXENGINE_API RenderList : public ScriptingObject { DECLARE_SCRIPTING_TYPE(RenderList); /// /// 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: /// /// All scenes for rendering. /// Array Scenes; /// /// Draw calls list (for all draw passes). /// RenderListBuffer DrawCalls; /// /// Draw calls list with pre-batched instances (for all draw passes). /// RenderListBuffer BatchedDrawCalls; /// /// The draw calls lists. Each for the separate draw pass. /// DrawCallsList DrawCallsLists[(int32)DrawCallsListType::MAX]; /// /// The additional draw calls list for Depth drawing into Shadow Projections that use DrawCalls from main render context. This assumes that RenderContextBatch contains main context and shadow projections only. /// DrawCallsList ShadowDepthDrawCallsList; /// /// 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; /// /// Local volumetric fog particles registered for the rendering. /// Array VolumetricFogParticles; /// /// 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 effects to render. /// Array PostFx; /// /// The renderer setup for the frame drawing. /// RenderSetup Setup; /// /// 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 /// Float3 FrustumCornersWs[8]; /// /// Camera frustum corners in View Space /// Float3 FrustumCornersVs[8]; private: 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 specified by given type. Used to pick a faster rendering path by the frame rendering module. /// /// The rendering context. /// The PostFx location to check (for scripts). /// True if render any postFx of the given type, otherwise false. bool HasAnyPostFx(const RenderContext& renderContext, PostProcessEffectLocation postProcess) const; /// /// Determines whether any Material PostFx specified by given type. Used to pick a faster rendering path by the frame rendering module. /// /// The rendering context. /// The PostFx location to check (for materials). /// True if render any postFx of the given type, otherwise false. bool HasAnyPostFx(const RenderContext& renderContext, MaterialPostFxLocation materialPostFx) const; /// /// Determines whether any Custom PostFx or Material PostFx specified by given type. Used to pick a faster rendering path by the frame rendering module. /// /// The rendering context. /// The PostFx location to check (for scripts). /// The PostFx location to check (for materials). /// True if render any postFx of the given type, otherwise false. bool HasAnyPostFx(const RenderContext& renderContext, PostProcessEffectLocation postProcess, MaterialPostFxLocation materialPostFx) const { return HasAnyPostFx(renderContext, postProcess) || HasAnyPostFx(renderContext, materialPostFx); } 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 rendering context. /// The object draw modes. /// The object static flags. /// The draw call data. /// True if the rendered mesh can receive decals. /// Object sorting key. void AddDrawCall(const RenderContext& renderContext, DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals = true, int16 sortOrder = 0); /// /// Adds the draw call to the draw lists and references it in other render contexts. Performs additional per-context frustum culling. /// /// The rendering context batch. This assumes that RenderContextBatch contains main context and shadow projections only. /// The object draw modes. /// The object static flags. /// The object shadows casting mode. /// The object bounds. /// The draw call data. /// True if the rendered mesh can receive decals. /// Object sorting key. void AddDrawCall(const RenderContextBatch& renderContextBatch, DrawPass drawModes, StaticFlags staticFlags, ShadowsCastingMode shadowsMode, const BoundingSphere& bounds, DrawCall& drawCall, bool receivesDecals = true, int16 sortOrder = 0); /// /// 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], DrawCalls); } /// /// 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 indices list. /// The collected draw calls list. void SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list, const RenderListBuffer& drawCalls); /// /// Executes the collected draw calls. /// /// The rendering context. /// The collected draw calls list type. /// The input scene color. It's optional and used in forward/postFx rendering. API_FUNCTION() FORCE_INLINE void ExecuteDrawCalls(API_PARAM(Ref) const RenderContext& renderContext, DrawCallsListType listType, GPUTextureView* input = nullptr) { ExecuteDrawCalls(renderContext, DrawCallsLists[(int32)listType], DrawCalls, input); } /// /// Executes the collected draw calls. /// /// The rendering context. /// The collected draw calls indices list. /// The input scene color. It's optional and used in forward/postFx rendering. FORCE_INLINE void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, GPUTextureView* input = nullptr) { ExecuteDrawCalls(renderContext, list, DrawCalls, input); } /// /// Executes the collected draw calls. /// /// The rendering context. /// The collected draw calls indices list. /// The collected draw calls list. /// The input scene color. It's optional and used in forward/postFx rendering. void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, const RenderListBuffer& drawCalls, GPUTextureView* input); }; /// /// Represents data per instance element used for instanced rendering. /// PACK_STRUCT(struct FLAXENGINE_API InstanceData { Float3 InstanceOrigin; float PerInstanceRandom; Float3 InstanceTransform1; float LODDitherFactor; Float3 InstanceTransform2; Float3 InstanceTransform3; Half4 InstanceLightmapArea; }); struct SurfaceDrawCallHandler { static void GetHash(const DrawCall& drawCall, uint32& batchKey); static bool CanBatch(const DrawCall& a, const DrawCall& b); static void WriteDrawCall(InstanceData* instanceData, const DrawCall& drawCall); };