Add support for baking env probes in cooked game
This commit is contained in:
@@ -64,6 +64,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
data.AddRootEngineAsset(TEXT("Shaders/Histogram"));
|
data.AddRootEngineAsset(TEXT("Shaders/Histogram"));
|
||||||
data.AddRootEngineAsset(TEXT("Shaders/Lights"));
|
data.AddRootEngineAsset(TEXT("Shaders/Lights"));
|
||||||
data.AddRootEngineAsset(TEXT("Shaders/MultiScaler"));
|
data.AddRootEngineAsset(TEXT("Shaders/MultiScaler"));
|
||||||
|
data.AddRootEngineAsset(TEXT("Shaders/ProbesFilter"));
|
||||||
data.AddRootEngineAsset(TEXT("Shaders/PostProcessing"));
|
data.AddRootEngineAsset(TEXT("Shaders/PostProcessing"));
|
||||||
data.AddRootEngineAsset(TEXT("Shaders/MotionBlur"));
|
data.AddRootEngineAsset(TEXT("Shaders/MotionBlur"));
|
||||||
data.AddRootEngineAsset(TEXT("Shaders/BitonicSort"));
|
data.AddRootEngineAsset(TEXT("Shaders/BitonicSort"));
|
||||||
|
|||||||
@@ -176,33 +176,7 @@ bool Texture::LoadFile(const StringView& path, bool generateMips)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto initData = New<InitData>();
|
auto initData = New<InitData>();
|
||||||
|
initData->FromTextureData(textureData, generateMips);
|
||||||
initData->Format = textureData.Format;
|
|
||||||
initData->Width = textureData.Width;
|
|
||||||
initData->Height = textureData.Height;
|
|
||||||
initData->ArraySize = 1;
|
|
||||||
if (generateMips)
|
|
||||||
initData->Mips.Resize(MipLevelsCount(textureData.Width, textureData.Height));
|
|
||||||
else
|
|
||||||
initData->Mips.Resize(textureData.GetMipLevels());
|
|
||||||
|
|
||||||
for (int32 mipIndex = 0; mipIndex < textureData.GetMipLevels(); mipIndex++)
|
|
||||||
{
|
|
||||||
auto& mip = initData->Mips[mipIndex];
|
|
||||||
auto& data = *textureData.GetData(0, mipIndex);
|
|
||||||
|
|
||||||
mip.Data.Copy(data.Data);
|
|
||||||
mip.RowPitch = data.RowPitch;
|
|
||||||
mip.SlicePitch = data.DepthPitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (generateMips)
|
|
||||||
{
|
|
||||||
for (int32 mipIndex = textureData.GetMipLevels(); mipIndex < initData->Mips.Count(); mipIndex++)
|
|
||||||
{
|
|
||||||
initData->GenerateMip(mipIndex, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Init(initData);
|
return Init(initData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -886,3 +886,43 @@ bool TextureBase::InitData::GenerateMip(int32 mipIndex, bool linear)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureBase::InitData::FromTextureData(const TextureData& textureData, bool generateMips)
|
||||||
|
{
|
||||||
|
Format = textureData.Format;
|
||||||
|
Width = textureData.Width;
|
||||||
|
Height = textureData.Height;
|
||||||
|
ArraySize = textureData.GetArraySize();
|
||||||
|
if (generateMips)
|
||||||
|
Mips.Resize(MipLevelsCount(textureData.Width, textureData.Height));
|
||||||
|
else
|
||||||
|
Mips.Resize(textureData.GetMipLevels());
|
||||||
|
|
||||||
|
for (int32 mipIndex = 0; mipIndex < textureData.GetMipLevels(); mipIndex++)
|
||||||
|
{
|
||||||
|
auto& mip = Mips[mipIndex];
|
||||||
|
auto& data = *textureData.GetData(0, mipIndex);
|
||||||
|
mip.Data.Allocate(data.Data.Length() * ArraySize);
|
||||||
|
mip.RowPitch = data.RowPitch;
|
||||||
|
mip.SlicePitch = data.Data.Length();
|
||||||
|
|
||||||
|
byte* dst = mip.Data.Get();
|
||||||
|
for (int32 arrayIndex = 0; arrayIndex < ArraySize; arrayIndex++)
|
||||||
|
{
|
||||||
|
auto& d = *textureData.GetData(arrayIndex, mipIndex);
|
||||||
|
ASSERT(data.RowPitch == d.RowPitch);
|
||||||
|
ASSERT(data.Data.Length() == d.Data.Length());
|
||||||
|
Platform::MemoryCopy(dst, d.Data.Get(), d.Data.Length());
|
||||||
|
dst += data.Data.Length();
|
||||||
|
ASSERT((int32)(dst - mip.Data.Get()) <= mip.Data.Length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generateMips)
|
||||||
|
{
|
||||||
|
for (int32 mipIndex = textureData.GetMipLevels(); mipIndex < Mips.Count(); mipIndex++)
|
||||||
|
{
|
||||||
|
GenerateMip(mipIndex, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API TextureBase : public BinaryAss
|
|||||||
/// <param name="linear">True if use linear filer, otherwise point filtering.</param>
|
/// <param name="linear">True if use linear filer, otherwise point filtering.</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
bool GenerateMip(int32 mipIndex, bool linear = false);
|
bool GenerateMip(int32 mipIndex, bool linear = false);
|
||||||
|
|
||||||
|
void FromTextureData(const TextureData& textureData, bool generateMips = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -84,16 +84,12 @@ void EnvironmentProbe::SetCustomProbe(CubeTexture* probe)
|
|||||||
|
|
||||||
void EnvironmentProbe::Bake(float timeout)
|
void EnvironmentProbe::Bake(float timeout)
|
||||||
{
|
{
|
||||||
#if COMPILE_WITH_PROBES_BAKING
|
|
||||||
ProbesRenderer::Bake(this, timeout);
|
ProbesRenderer::Bake(this, timeout);
|
||||||
#else
|
|
||||||
LOG(Warning, "Baking probes is not supported.");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvironmentProbe::SetProbeData(GPUContext* context, GPUTexture* data)
|
void EnvironmentProbe::SetProbeData(GPUContext* context, GPUTexture* data)
|
||||||
{
|
{
|
||||||
// Remove any probe asset
|
// Remove probe asset (if used)
|
||||||
_isUsingCustomProbe = false;
|
_isUsingCustomProbe = false;
|
||||||
_probe = nullptr;
|
_probe = nullptr;
|
||||||
|
|
||||||
@@ -128,11 +124,14 @@ void EnvironmentProbe::SetProbeData(TextureData& data)
|
|||||||
_probe = nullptr;
|
_probe = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid id = Guid::New();
|
// Remove probe texture (if used)
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_probeTexture);
|
||||||
|
|
||||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||||
// Create asset file
|
// Create asset file
|
||||||
const String path = GetScene()->GetDataFolderPath() / TEXT("EnvProbes/") / GetID().ToString(Guid::FormatType::N) + ASSET_FILES_EXTENSION_WITH_DOT;
|
const String path = GetScene()->GetDataFolderPath() / TEXT("EnvProbes/") / GetID().ToString(Guid::FormatType::N) + ASSET_FILES_EXTENSION_WITH_DOT;
|
||||||
AssetInfo info;
|
AssetInfo info;
|
||||||
|
Guid id = Guid::New();
|
||||||
if (FileSystem::FileExists(path) && Content::GetAssetInfo(path, info))
|
if (FileSystem::FileExists(path) && Content::GetAssetInfo(path, info))
|
||||||
id = info.ID;
|
id = info.ID;
|
||||||
if (AssetsImportingManager::Create(AssetsImportingManager::CreateCubeTextureTag, path, id, &data))
|
if (AssetsImportingManager::Create(AssetsImportingManager::CreateCubeTextureTag, path, id, &data))
|
||||||
@@ -141,14 +140,6 @@ void EnvironmentProbe::SetProbeData(TextureData& data)
|
|||||||
return;
|
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.");
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check if has loaded probe and it has different ID
|
// Check if has loaded probe and it has different ID
|
||||||
if (_probe && _probe->GetID() != id)
|
if (_probe && _probe->GetID() != id)
|
||||||
{
|
{
|
||||||
@@ -159,6 +150,19 @@ void EnvironmentProbe::SetProbeData(TextureData& data)
|
|||||||
|
|
||||||
// Link probe texture
|
// Link probe texture
|
||||||
_probe = Content::LoadAsync<CubeTexture>(id);
|
_probe = Content::LoadAsync<CubeTexture>(id);
|
||||||
|
#else
|
||||||
|
// Create virtual asset
|
||||||
|
if (!_probe || !_probe->IsVirtual())
|
||||||
|
_probe = Content::CreateVirtualAsset<CubeTexture>();
|
||||||
|
auto initData = New<TextureBase::InitData>();
|
||||||
|
initData->FromTextureData(data);
|
||||||
|
if (_probe->Init(initData))
|
||||||
|
{
|
||||||
|
Delete(initData);
|
||||||
|
LOG(Error, "Cannot load generated env probe!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvironmentProbe::UpdateBounds()
|
void EnvironmentProbe::UpdateBounds()
|
||||||
@@ -175,10 +179,8 @@ void EnvironmentProbe::Draw(RenderContext& renderContext)
|
|||||||
(renderContext.View.Flags & ViewFlags::Reflections) != 0 &&
|
(renderContext.View.Flags & ViewFlags::Reflections) != 0 &&
|
||||||
renderContext.View.Pass & DrawPass::GBuffer)
|
renderContext.View.Pass & DrawPass::GBuffer)
|
||||||
{
|
{
|
||||||
#if COMPILE_WITH_PROBES_BAKING
|
|
||||||
if (UpdateMode == ProbeUpdateMode::Realtime)
|
if (UpdateMode == ProbeUpdateMode::Realtime)
|
||||||
ProbesRenderer::Bake(this, 0.0f);
|
ProbesRenderer::Bake(this, 0.0f);
|
||||||
#endif
|
|
||||||
if ((_probe != nullptr && _probe->IsLoaded()) || _probeTexture != nullptr)
|
if ((_probe != nullptr && _probe->IsLoaded()) || _probeTexture != nullptr)
|
||||||
{
|
{
|
||||||
renderContext.List->EnvironmentProbes.Add(this);
|
renderContext.List->EnvironmentProbes.Add(this);
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ CubeTexture* SkyLight::GetSource() const
|
|||||||
|
|
||||||
void SkyLight::Bake(float timeout)
|
void SkyLight::Bake(float timeout)
|
||||||
{
|
{
|
||||||
#if COMPILE_WITH_PROBES_BAKING
|
|
||||||
ProbesRenderer::Bake(this, timeout);
|
ProbesRenderer::Bake(this, timeout);
|
||||||
#else
|
|
||||||
LOG(Warning, "Baking probes is not supported.");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyLight::SetProbeData(TextureData& data)
|
void SkyLight::SetProbeData(TextureData& data)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if COMPILE_WITH_PROBES_BAKING
|
|
||||||
|
|
||||||
#include "ProbesRenderer.h"
|
#include "ProbesRenderer.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "ReflectionsPass.h"
|
#include "ReflectionsPass.h"
|
||||||
@@ -602,5 +600,3 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
|
|||||||
_current.Type = EntryType::Invalid;
|
_current.Type = EntryType::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if COMPILE_WITH_PROBES_BAKING
|
|
||||||
|
|
||||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||||
#include "Engine/Level/Actor.h"
|
#include "Engine/Level/Actor.h"
|
||||||
|
|
||||||
@@ -107,5 +105,3 @@ private:
|
|||||||
|
|
||||||
static void onRender(RenderTask* task, GPUContext* context);
|
static void onRender(RenderTask* task, GPUContext* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -15,10 +15,5 @@ public class Renderer : EngineModule
|
|||||||
|
|
||||||
options.PrivateDependencies.Add("Graphics");
|
options.PrivateDependencies.Add("Graphics");
|
||||||
options.PrivateDependencies.Add("Content");
|
options.PrivateDependencies.Add("Content");
|
||||||
|
|
||||||
if (options.Target.IsEditor)
|
|
||||||
{
|
|
||||||
options.PublicDefinitions.Add("COMPILE_WITH_PROBES_BAKING");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user