Add HDR env probes support
This commit is contained in:
@@ -69,6 +69,12 @@ public:
|
|||||||
API_FIELD(Attributes = "EditorOrder(1500), EditorDisplay(\"Quality\")")
|
API_FIELD(Attributes = "EditorOrder(1500), EditorDisplay(\"Quality\")")
|
||||||
ProbeCubemapResolution DefaultProbeResolution = ProbeCubemapResolution::_128;
|
ProbeCubemapResolution DefaultProbeResolution = ProbeCubemapResolution::_128;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If checked, Environment Probes will use HDR texture format. Improves quality in very bright scenes at cost of higher memory usage.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "EditorOrder(1502), EditorDisplay(\"Quality\")")
|
||||||
|
bool UeeHDRProbes = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If checked, enables Global SDF rendering. This can be used in materials, shaders, and particles.
|
/// If checked, enables Global SDF rendering. This can be used in materials, shaders, and particles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ GPUTexture* GPUTexture::ToStagingUpload() const
|
|||||||
return staging;
|
return staging;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPUTexture::Resize(int32 width, int32 height, int32 depth)
|
bool GPUTexture::Resize(int32 width, int32 height, int32 depth, PixelFormat format)
|
||||||
{
|
{
|
||||||
// Validate texture is created
|
// Validate texture is created
|
||||||
if (!IsAllocated())
|
if (!IsAllocated())
|
||||||
@@ -543,11 +543,14 @@ bool GPUTexture::Resize(int32 width, int32 height, int32 depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto desc = GetDescription();
|
auto desc = GetDescription();
|
||||||
|
if (format == PixelFormat::Unknown)
|
||||||
|
format = desc.Format;
|
||||||
|
|
||||||
// Skip if size won't change
|
// Skip if size won't change
|
||||||
if (desc.Width == width && desc.Height == height && desc.Depth == depth)
|
if (desc.Width == width && desc.Height == height && desc.Depth == depth && desc.Format == format)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
desc.Format = format;
|
||||||
desc.Width = width;
|
desc.Width = width;
|
||||||
desc.Height = height;
|
desc.Height = height;
|
||||||
desc.Depth = depth;
|
desc.Depth = depth;
|
||||||
|
|||||||
@@ -486,11 +486,12 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="width">The width.</param>
|
/// <param name="width">The width.</param>
|
||||||
/// <param name="height">The height.</param>
|
/// <param name="height">The height.</param>
|
||||||
|
/// <param name="format">The new texture format. Use Unknown to remain texture format unchanged.</param>
|
||||||
/// <returns>True if fails, otherwise false.</returns>
|
/// <returns>True if fails, otherwise false.</returns>
|
||||||
API_FUNCTION() bool Resize(int32 width, int32 height)
|
API_FUNCTION() bool Resize(int32 width, int32 height, PixelFormat format = PixelFormat::Unknown)
|
||||||
{
|
{
|
||||||
const auto depth = IsAllocated() ? Depth() : 1;
|
const auto depth = IsAllocated() ? Depth() : 1;
|
||||||
return Resize(width, height, depth);
|
return Resize(width, height, depth, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -499,8 +500,9 @@ public:
|
|||||||
/// <param name="width">The width.</param>
|
/// <param name="width">The width.</param>
|
||||||
/// <param name="height">The height.</param>
|
/// <param name="height">The height.</param>
|
||||||
/// <param name="depth">The depth.</param>
|
/// <param name="depth">The depth.</param>
|
||||||
|
/// <param name="format">The new texture format. Use Unknown to remain texture format unchanged.</param>
|
||||||
/// <returns>True if fails, otherwise false.</returns>
|
/// <returns>True if fails, otherwise false.</returns>
|
||||||
API_FUNCTION() bool Resize(int32 width, int32 height, int32 depth);
|
API_FUNCTION() bool Resize(int32 width, int32 height, int32 depth, PixelFormat format = PixelFormat::Unknown);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
#include "Engine/Engine/Time.h"
|
#include "Engine/Engine/Time.h"
|
||||||
#include "Engine/Content/Assets/Shader.h"
|
#include "Engine/Content/Assets/Shader.h"
|
||||||
#include "Engine/Content/AssetReference.h"
|
#include "Engine/Content/AssetReference.h"
|
||||||
|
#include "Engine/Graphics/Graphics.h"
|
||||||
#include "Engine/Graphics/GPUContext.h"
|
#include "Engine/Graphics/GPUContext.h"
|
||||||
#include "Engine/Graphics/Textures/GPUTexture.h"
|
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||||
#include "Engine/Graphics/Textures/TextureData.h"
|
#include "Engine/Graphics/Textures/TextureData.h"
|
||||||
#include "Engine/Graphics/RenderTask.h"
|
#include "Engine/Graphics/RenderTask.h"
|
||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
#include "Engine/Graphics/Graphics.h"
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom task called after downloading probe texture data to save it.
|
/// Custom task called after downloading probe texture data to save it.
|
||||||
@@ -202,6 +202,11 @@ int32 ProbesRenderer::Entry::GetResolution() const
|
|||||||
return (int32)resolution;
|
return (int32)resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixelFormat ProbesRenderer::Entry::GetFormat() const
|
||||||
|
{
|
||||||
|
return GraphicsSettings::Get()->UeeHDRProbes ? PixelFormat::R11G11B10_Float : PixelFormat::R8G8B8A8_UNorm;
|
||||||
|
}
|
||||||
|
|
||||||
int32 ProbesRenderer::GetBakeQueueSize()
|
int32 ProbesRenderer::GetBakeQueueSize()
|
||||||
{
|
{
|
||||||
return _probesToBake.Count();
|
return _probesToBake.Count();
|
||||||
@@ -245,7 +250,8 @@ bool ProbesRenderer::Init()
|
|||||||
// Init rendering pipeline
|
// Init rendering pipeline
|
||||||
_output = GPUDevice::Instance->CreateTexture(TEXT("Output"));
|
_output = GPUDevice::Instance->CreateTexture(TEXT("Output"));
|
||||||
const int32 probeResolution = _current.GetResolution();
|
const int32 probeResolution = _current.GetResolution();
|
||||||
if (_output->Init(GPUTextureDescription::New2D(probeResolution, probeResolution, PixelFormat::R8G8B8A8_UNorm)))
|
const PixelFormat probeFormat = _current.GetFormat();
|
||||||
|
if (_output->Init(GPUTextureDescription::New2D(probeResolution, probeResolution, probeFormat)))
|
||||||
return true;
|
return true;
|
||||||
_task = New<SceneRenderTask>();
|
_task = New<SceneRenderTask>();
|
||||||
auto task = _task;
|
auto task = _task;
|
||||||
@@ -270,14 +276,14 @@ bool ProbesRenderer::Init()
|
|||||||
view.MaxShadowsQuality = Quality::Low;
|
view.MaxShadowsQuality = Quality::Low;
|
||||||
task->IsCameraCut = true;
|
task->IsCameraCut = true;
|
||||||
task->Resize(probeResolution, probeResolution);
|
task->Resize(probeResolution, probeResolution);
|
||||||
task->Render.Bind(onRender);
|
task->Render.Bind(OnRender);
|
||||||
|
|
||||||
// Init render targets
|
// Init render targets
|
||||||
_probe = GPUDevice::Instance->CreateTexture(TEXT("ProbesUpdate.Probe"));
|
_probe = GPUDevice::Instance->CreateTexture(TEXT("ProbesUpdate.Probe"));
|
||||||
if (_probe->Init(GPUTextureDescription::NewCube(probeResolution, _output->Format(), GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews, 0)))
|
if (_probe->Init(GPUTextureDescription::NewCube(probeResolution, probeFormat, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews, 0)))
|
||||||
return true;
|
return true;
|
||||||
_tmpFace = GPUDevice::Instance->CreateTexture(TEXT("ProbesUpdate.TmpFace"));
|
_tmpFace = GPUDevice::Instance->CreateTexture(TEXT("ProbesUpdate.TmpFace"));
|
||||||
if (_tmpFace->Init(GPUTextureDescription::New2D(probeResolution, probeResolution, 0, _output->Format(), GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews)))
|
if (_tmpFace->Init(GPUTextureDescription::New2D(probeResolution, probeResolution, 0, probeFormat, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Mark as ready
|
// Mark as ready
|
||||||
@@ -400,7 +406,7 @@ bool fixFarPlaneTreeExecute(Actor* actor, const Vector3& position, float& farPla
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
|
void ProbesRenderer::OnRender(RenderTask* task, GPUContext* context)
|
||||||
{
|
{
|
||||||
ASSERT(_current.Type != EntryType::Invalid && _updateFrameNumber == 0);
|
ASSERT(_current.Type != EntryType::Invalid && _updateFrameNumber == 0);
|
||||||
switch (_current.Type)
|
switch (_current.Type)
|
||||||
@@ -426,6 +432,7 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
|
|||||||
// Init
|
// Init
|
||||||
float customCullingNear = -1;
|
float customCullingNear = -1;
|
||||||
const int32 probeResolution = _current.GetResolution();
|
const int32 probeResolution = _current.GetResolution();
|
||||||
|
const PixelFormat probeFormat = _current.GetFormat();
|
||||||
if (_current.Type == EntryType::EnvProbe)
|
if (_current.Type == EntryType::EnvProbe)
|
||||||
{
|
{
|
||||||
auto envProbe = (EnvironmentProbe*)_current.Actor.Get();
|
auto envProbe = (EnvironmentProbe*)_current.Actor.Get();
|
||||||
@@ -433,8 +440,9 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
|
|||||||
float radius = envProbe->GetScaledRadius();
|
float radius = envProbe->GetScaledRadius();
|
||||||
float nearPlane = Math::Max(0.1f, envProbe->CaptureNearPlane);
|
float nearPlane = Math::Max(0.1f, envProbe->CaptureNearPlane);
|
||||||
|
|
||||||
// Fix far plane distance
|
// Adjust far plane distance
|
||||||
float farPlane = Math::Max(radius, nearPlane + 100.0f);
|
float farPlane = Math::Max(radius, nearPlane + 100.0f);
|
||||||
|
farPlane *= farPlane < 10000 ? 10 : 4;
|
||||||
Function<bool(Actor*, const Vector3&, float&)> f(&fixFarPlaneTreeExecute);
|
Function<bool(Actor*, const Vector3&, float&)> f(&fixFarPlaneTreeExecute);
|
||||||
SceneQuery::TreeExecute<const Vector3&, float&>(f, position, farPlane);
|
SceneQuery::TreeExecute<const Vector3&, float&>(f, position, farPlane);
|
||||||
|
|
||||||
@@ -457,10 +465,10 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
|
|||||||
_task->CameraCut();
|
_task->CameraCut();
|
||||||
|
|
||||||
// Resize buffers
|
// Resize buffers
|
||||||
bool resizeFailed = _output->Resize(probeResolution, probeResolution);
|
bool resizeFailed = _output->Resize(probeResolution, probeResolution, probeFormat);
|
||||||
|
resizeFailed |= _probe->Resize(probeResolution, probeResolution, probeFormat);
|
||||||
|
resizeFailed |= _tmpFace->Resize(probeResolution, probeResolution, probeFormat);
|
||||||
resizeFailed |= _task->Resize(probeResolution, probeResolution);
|
resizeFailed |= _task->Resize(probeResolution, probeResolution);
|
||||||
resizeFailed |= _probe->Resize(probeResolution, probeResolution);
|
|
||||||
resizeFailed |= _tmpFace->Resize(probeResolution, probeResolution);
|
|
||||||
if (resizeFailed)
|
if (resizeFailed)
|
||||||
LOG(Error, "Failed to resize probe");
|
LOG(Error, "Failed to resize probe");
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Graphics/PixelFormat.h"
|
||||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||||
#include "Engine/Level/Actor.h"
|
#include "Engine/Level/Actor.h"
|
||||||
|
|
||||||
@@ -18,7 +19,6 @@ class RenderTask;
|
|||||||
class ProbesRenderer
|
class ProbesRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum class EntryType
|
enum class EntryType
|
||||||
{
|
{
|
||||||
Invalid = 0,
|
Invalid = 0,
|
||||||
@@ -46,10 +46,10 @@ public:
|
|||||||
|
|
||||||
bool UseTextureData() const;
|
bool UseTextureData() const;
|
||||||
int32 GetResolution() const;
|
int32 GetResolution() const;
|
||||||
|
PixelFormat GetFormat() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum amount of time between two updated of probes
|
/// Minimum amount of time between two updated of probes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -67,7 +67,6 @@ public:
|
|||||||
static Delegate<const Entry&> OnFinishBake;
|
static Delegate<const Entry&> OnFinishBake;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if resources are ready to render probes (shaders or textures may be during loading).
|
/// Checks if resources are ready to render probes (shaders or textures may be during loading).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -86,7 +85,6 @@ public:
|
|||||||
static void Release();
|
static void Release();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register probe to baking service.
|
/// Register probe to baking service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -102,6 +100,5 @@ public:
|
|||||||
static void Bake(SkyLight* probe, float timeout = 0);
|
static void Bake(SkyLight* probe, float timeout = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void OnRender(RenderTask* task, GPUContext* context);
|
||||||
static void onRender(RenderTask* task, GPUContext* context);
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user