Add real-time environment probes support

This commit is contained in:
Wojciech Figat
2022-07-18 14:50:41 +02:00
parent 3dbff3cab7
commit 60f868a08b
7 changed files with 124 additions and 50 deletions

View File

@@ -4,6 +4,7 @@
#include "Engine/Platform/FileSystem.h"
#include "Engine/Graphics/RenderView.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/Textures/GPUTexture.h"
#include "Engine/Graphics/Textures/TextureData.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Renderer/ProbesRenderer.h"
@@ -13,18 +14,21 @@
#include "Engine/ContentImporters/AssetsImportingManager.h"
#include "Engine/Serialization/Serialization.h"
#include "Engine/Level/Scene/Scene.h"
#include "Engine/Graphics/Graphics.h"
EnvironmentProbe::EnvironmentProbe(const SpawnParams& params)
: Actor(params)
, _radius(3000.0f)
, _isUsingCustomProbe(false)
, _probe(nullptr)
{
_sphere = BoundingSphere(Vector3::Zero, _radius);
BoundingBox::FromSphere(_sphere, _box);
}
EnvironmentProbe::~EnvironmentProbe()
{
SAFE_DELETE_GPU_RESOURCE(_probeTexture);
}
float EnvironmentProbe::GetRadius() const
{
return _radius;
@@ -45,19 +49,9 @@ float EnvironmentProbe::GetScaledRadius() const
return _radius * _transform.Scale.MaxValue();
}
bool EnvironmentProbe::HasProbe() const
GPUTexture* EnvironmentProbe::GetProbe() const
{
return _probe != nullptr;
}
bool EnvironmentProbe::HasProbeLoaded() const
{
return _probe != nullptr && _probe->IsLoaded();
}
CubeTexture* EnvironmentProbe::GetProbe() const
{
return _probe;
return _probe ? _probe->GetTexture() : _probeTexture;
}
bool EnvironmentProbe::IsUsingCustomProbe() const
@@ -74,9 +68,7 @@ void EnvironmentProbe::SetupProbeData(const RenderContext& renderContext, ProbeD
CubeTexture* EnvironmentProbe::GetCustomProbe() const
{
if (IsUsingCustomProbe())
return GetProbe();
return nullptr;
return _isUsingCustomProbe ? _probe : nullptr;
}
void EnvironmentProbe::SetCustomProbe(CubeTexture* probe)
@@ -99,6 +91,34 @@ void EnvironmentProbe::Bake(float timeout)
#endif
}
void EnvironmentProbe::SetProbeData(GPUContext* context, GPUTexture* data)
{
// Remove any probe asset
_isUsingCustomProbe = false;
_probe = nullptr;
// Allocate probe texture manually
if (!_probeTexture)
{
_probeTexture = GPUTexture::New();
#if !BUILD_RELEASE
_probeTexture->SetName(GetNamePath());
#endif
}
if (_probeTexture->Width() != data->Width() || _probeTexture->Format() != data->Format())
{
auto desc = data->GetDescription();
desc.Usage = GPUResourceUsage::Default;
desc.Flags = GPUTextureFlags::ShaderResource;
if (_probeTexture->Init(desc))
return;
_probeTexture->SetResidentMipLevels(_probeTexture->MipLevels());
}
// Copy probe texture data
context->CopyResource(_probeTexture, data);
}
void EnvironmentProbe::SetProbeData(TextureData& data)
{
// Remove custom probe (if used)
@@ -109,7 +129,6 @@ void EnvironmentProbe::SetProbeData(TextureData& data)
}
Guid id = Guid::New();
#if COMPILE_WITH_ASSETS_IMPORTER
// Create asset file
const String path = GetScene()->GetDataFolderPath() / TEXT("EnvProbes/") / GetID().ToString(Guid::FormatType::N) + ASSET_FILES_EXTENSION_WITH_DOT;
@@ -121,6 +140,9 @@ void EnvironmentProbe::SetProbeData(TextureData& data)
LOG(Error, "Cannot import generated env probe!");
return;
}
// Remove probe texture
SAFE_DELETE_GPU_RESOURCE(_probeTexture);
#else
// TODO: create or reuse virtual texture and use it
LOG(Error, "Changing probes at runtime in game is not supported.");
@@ -151,10 +173,16 @@ void EnvironmentProbe::Draw(RenderContext& renderContext)
{
if (Brightness > ZeroTolerance &&
(renderContext.View.Flags & ViewFlags::Reflections) != 0 &&
renderContext.View.Pass & DrawPass::GBuffer &&
HasProbeLoaded())
renderContext.View.Pass & DrawPass::GBuffer)
{
renderContext.List->EnvironmentProbes.Add(this);
#if COMPILE_WITH_PROBES_BAKING
if (UpdateMode == ProbeUpdateMode::Realtime)
ProbesRenderer::Bake(this, 0.0f);
#endif
if ((_probe != nullptr && _probe->IsLoaded()) || _probeTexture != nullptr)
{
renderContext.List->EnvironmentProbes.Add(this);
}
}
}
@@ -189,7 +217,7 @@ void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj)
SERIALIZE_MEMBER(Radius, _radius);
SERIALIZE(CubemapResolution);
SERIALIZE(Brightness);
SERIALIZE(AutoUpdate);
SERIALIZE(UpdateMode);
SERIALIZE(CaptureNearPlane);
SERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
SERIALIZE_MEMBER(ProbeID, _probe);
@@ -203,10 +231,18 @@ void EnvironmentProbe::Deserialize(DeserializeStream& stream, ISerializeModifier
DESERIALIZE_MEMBER(Radius, _radius);
DESERIALIZE(CubemapResolution);
DESERIALIZE(Brightness);
DESERIALIZE(AutoUpdate);
DESERIALIZE(UpdateMode);
DESERIALIZE(CaptureNearPlane);
DESERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
DESERIALIZE_MEMBER(ProbeID, _probe);
// [Deprecated on 18.07.2022, expires on 18.07.2022]
if (modifier->EngineBuild <= 6332)
{
const auto member = stream.FindMember("AutoUpdate");
if (member != stream.MemberEnd() && member->value.IsBool() && member->value.GetBool())
UpdateMode = ProbeUpdateMode::WhenMoved;
}
}
bool EnvironmentProbe::HasContentLoaded() const
@@ -248,7 +284,7 @@ void EnvironmentProbe::OnTransformChanged()
UpdateBounds();
if (AutoUpdate && IsDuringPlay())
if (IsDuringPlay() && UpdateMode == ProbeUpdateMode::WhenMoved)
{
Bake(1.0f);
}