// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/ScriptingObject.h" #include "Engine/Graphics/Textures/GPUTexture.h" // GBuffer render targets formats #define GBUFFER0_FORMAT PixelFormat::R8G8B8A8_UNorm #define GBUFFER1_FORMAT PixelFormat::R10G10B10A2_UNorm #define GBUFFER2_FORMAT PixelFormat::R8G8B8A8_UNorm #define GBUFFER3_FORMAT PixelFormat::R8G8B8A8_UNorm /// /// The scene rendering buffers container. /// API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject { DECLARE_SCRIPTING_TYPE(RenderBuffers); /// /// The custom rendering state. /// class FLAXENGINE_API CustomBuffer : public Object { public: String Name; uint64 LastFrameUsed = 0; String ToString() const override; }; protected: int32 _width = 0; int32 _height = 0; float _aspectRatio = 0.0f; bool _useAlpha = false; Viewport _viewport; Array> _resources; public: union { struct { /// Gets the GBuffer texture 0. RGB: Color, A: AO API_FIELD(ReadOnly) GPUTexture* GBuffer0; /// Gets the GBuffer texture 1. RGB: Normal, A: ShadingModel API_FIELD(ReadOnly) GPUTexture* GBuffer1; /// Gets the GBuffer texture 2. R: Roughness, G: Metalness, B:Specular API_FIELD(ReadOnly) GPUTexture* GBuffer2; /// Gets the GBuffer texture 3. RGBA: Custom Data API_FIELD(ReadOnly) GPUTexture* GBuffer3; }; GPUTexture* GBuffer[4]; }; // Helper target for the eye adaptation float LastEyeAdaptationTime = 0.0f; GPUTexture* LuminanceMap = nullptr; uint64 LastFrameLuminanceMap = 0; // Helper target for volumetric fog rendering (used for the temporal filter and apply via fog shader) GPUTexture* VolumetricFogHistory = nullptr; GPUTexture* VolumetricFog = nullptr; GPUTexture* LocalShadowedLightScattering = nullptr; uint64 LastFrameVolumetricFog = 0; struct { float MaxDistance; } VolumetricFogData; // Helper buffer with half-resolution depth buffer shared by effects (eg. SSR, Motion Blur). Valid only during frame rendering and on request (see RequestHalfResDepth). // Should be released if not used for a few frames. GPUTexture* HalfResDepth = nullptr; uint64 LastFrameHalfResDepth = 0; // Helper target for the temporal SSR. // Should be released if not used for a few frames. GPUTexture* TemporalSSR = nullptr; uint64 LastFrameTemporalSSR = 0; // Helper target for the temporal AA. // Should be released if not used for a few frames. GPUTexture* TemporalAA = nullptr; uint64 LastFrameTemporalAA = 0; // Maps the custom buffer type into the object that holds the state. Array CustomBuffers; public: /// /// Finalizes an instance of the class. /// ~RenderBuffers(); public: /// /// Frees unused buffers to reduce memory usage for certain drawing effects that are state-dependant but unused for multiple frames. /// void ReleaseUnusedMemory(); /// /// Requests the half-resolution depth to be prepared for the current frame. /// /// The context. /// The half-res depth buffer. GPUTexture* RequestHalfResDepth(GPUContext* context); public: /// /// Gets the buffers width (in pixels). /// API_PROPERTY() FORCE_INLINE int32 GetWidth() const { return _width; } /// /// Gets the buffers height (in pixels). /// API_PROPERTY() FORCE_INLINE int32 GetHeight() const { return _height; } /// /// Gets the buffers width and height (in pixels). /// API_PROPERTY() FORCE_INLINE Float2 GetSize() const { return Float2((float)_width, (float)_height); } /// /// Gets the buffers aspect ratio. /// API_PROPERTY() FORCE_INLINE float GetAspectRatio() const { return _aspectRatio; } /// /// Gets the buffers rendering viewport. /// API_PROPERTY() FORCE_INLINE Viewport GetViewport() const { return _viewport; } /// /// Gets the output buffers format (R11G11B10 or R16G16B16A16 depending on UseAlpha property). /// API_PROPERTY() PixelFormat GetOutputFormat() const; /// /// True if support alpha output in the rendering buffers and pass-though alpha mask of the scene during rendering (at cost of reduced performance). /// API_PROPERTY() bool GetUseAlpha() const; /// /// True if support alpha output in the rendering buffers and pass-though alpha mask of the scene during rendering (at cost of reduced performance). /// API_PROPERTY() void SetUseAlpha(bool value); const CustomBuffer* FindCustomBuffer(const StringView& name) const; template const T* FindCustomBuffer(const StringView& name) const { return (const T*)FindCustomBuffer(name); } template T* GetCustomBuffer(const StringView& name) { if (LinkedCustomBuffers) return LinkedCustomBuffers->GetCustomBuffer(name); CustomBuffer* result = (CustomBuffer*)FindCustomBuffer(name); if (!result) { result = New(); result->Name = name; CustomBuffers.Add(result); } return (T*)result; } /// /// Gets the current GPU memory usage by all the buffers (in bytes). /// uint64 GetMemoryUsage() const; /// /// Gets the depth buffer render target allocated within this render buffers collection (read only). /// API_FIELD(ReadOnly) GPUTexture* DepthBuffer; /// /// Gets the motion vectors render target allocated within this render buffers collection (read only). /// /// /// Texture ca be null or not initialized if motion blur is disabled or not yet rendered. /// API_FIELD(ReadOnly) GPUTexture* MotionVectors; /// /// External Render Buffers used to redirect FindCustomBuffer/GetCustomBuffer calls. Can be linked to other rendering task (eg. main game viewport) to reuse graphics effect state from it (eg. use GI from main game view in in-game camera renderer). /// API_FIELD() RenderBuffers* LinkedCustomBuffers = nullptr; public: /// /// Allocates the buffers. /// /// The surface width (in pixels). /// The surface height (in pixels). /// True if cannot allocate buffers, otherwise false. API_FUNCTION() bool Init(int32 width, int32 height); /// /// Release the buffers data. /// API_FUNCTION() void Release(); };