// 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();
};