diff --git a/Source/Engine/Graphics/TextureBase.cs b/Source/Engine/Graphics/TextureBase.cs
index 3c22df929..997dd5261 100644
--- a/Source/Engine/Graphics/TextureBase.cs
+++ b/Source/Engine/Graphics/TextureBase.cs
@@ -47,6 +47,16 @@ namespace FlaxEngine
///
public int ArraySize;
+ ///
+ /// If checked, the engine will generate automatic-mips based on the latest provided mip.
+ ///
+ public bool GenerateMips;
+
+ ///
+ /// If checked, the generated mips will use linear filter, otherwise it will use point filter. Linear filter is supported only for formats compatible with Color32.
+ ///
+ public bool GenerateMipsLinear;
+
///
/// The mips levels data.
///
@@ -108,7 +118,7 @@ namespace FlaxEngine
}
// Convert data to internal storage (don't allocate memory but pin the managed arrays)
- InternalInitData t = new InternalInitData
+ var t = new InternalInitData
{
Format = initData.Format,
Width = initData.Width,
@@ -116,6 +126,12 @@ namespace FlaxEngine
ArraySize = initData.ArraySize,
MipLevels = initData.Mips.Length,
};
+ if (initData.GenerateMips)
+ {
+ t.GenerateMips = 1;
+ if (initData.GenerateMipsLinear)
+ t.GenerateMips |= 2;
+ }
var emptyArray = Utils.GetEmptyArray();
fixed (byte* data13 = (initData.Mips.Length > 13 ? initData.Mips[13].Data : emptyArray))
fixed (byte* data12 = (initData.Mips.Length > 12 ? initData.Mips[12].Data : emptyArray))
@@ -173,6 +189,7 @@ namespace FlaxEngine
public int Height;
public int ArraySize;
public int MipLevels;
+ public int GenerateMips;
public int Data00RowPitch;
public int Data01RowPitch;
diff --git a/Source/Engine/Graphics/Textures/TextureBase.cpp b/Source/Engine/Graphics/Textures/TextureBase.cpp
index 2f68b4956..5c885071f 100644
--- a/Source/Engine/Graphics/Textures/TextureBase.cpp
+++ b/Source/Engine/Graphics/Textures/TextureBase.cpp
@@ -11,6 +11,7 @@
#include "Engine/Debug/Exceptions/InvalidOperationException.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Content/Factories/BinaryAssetFactory.h"
+#include "Engine/Threading/Threading.h"
TextureMipData::TextureMipData()
: RowPitch(0)
@@ -151,11 +152,13 @@ BytesContainer TextureBase::GetMipData(int32 mipIndex, int32& rowPitch, int32& s
bool TextureBase::GetTextureData(TextureData& result, bool copyData)
{
+ PROFILE_CPU_NAMED("Texture.GetTextureData");
if (!IsVirtual() && WaitForLoaded())
{
LOG(Error, "Asset load failed.");
return true;
}
+ auto dataLock = LockData();
// Setup description
result.Width = _texture.TotalWidth();
@@ -202,7 +205,7 @@ bool TextureBase::Init(InitData* initData)
// Validate state
if (!IsVirtual())
{
- Log::InvalidOperationException();
+ LOG(Error, "Texture must be virtual.");
return true;
}
if (initData->Format == PixelFormat::Unknown ||
@@ -214,6 +217,7 @@ bool TextureBase::Init(InitData* initData)
Log::ArgumentOutOfRangeException();
return true;
}
+ ScopeLock lock(Locker);
// Release texture
_texture.UnloadTexture();
@@ -243,6 +247,7 @@ bool TextureBase::Init(InitData* initData)
bool TextureBase::Init(void* ptr)
{
+ PROFILE_CPU_NAMED("Texture.Init");
struct InternalInitData
{
PixelFormat Format;
@@ -250,6 +255,7 @@ bool TextureBase::Init(void* ptr)
int32 Height;
int32 ArraySize;
int32 MipLevels;
+ int32 GenerateMips;
int32 DataRowPitch[14];
int32 DataSlicePitch[14];
byte* Data[14];
@@ -261,8 +267,9 @@ bool TextureBase::Init(void* ptr)
initData->Width = initDataObj->Width;
initData->Height = initDataObj->Height;
initData->ArraySize = initDataObj->ArraySize;
- initData->Mips.Resize(initDataObj->MipLevels);
+ initData->Mips.Resize(initDataObj->GenerateMips ? MipLevelsCount(initDataObj->Width, initDataObj->Height) : initDataObj->MipLevels);
+ // Copy source mips data
for (int32 mipIndex = 0; mipIndex < initDataObj->MipLevels; mipIndex++)
{
auto& mip = initData->Mips[mipIndex];
@@ -271,6 +278,12 @@ bool TextureBase::Init(void* ptr)
mip.Data.Copy(initDataObj->Data[mipIndex], mip.SlicePitch * initData->ArraySize);
}
+ // Generate mips
+ for (int32 mipIndex = initDataObj->MipLevels; mipIndex < initData->Mips.Count(); mipIndex++)
+ {
+ initData->GenerateMip(mipIndex, initDataObj->GenerateMips & 2);
+ }
+
return Init(initData);
}
@@ -462,7 +475,7 @@ bool TextureBase::InitData::GenerateMip(int32 mipIndex, bool linear)
break;
}
default:
- LOG(Error, "Unsupported texture data format {0} for mip map generation.", (int32)Format);
+ LOG(Error, "Unsupported texture data format {0}.", (int32)Format);
return true;
}
}
diff --git a/Source/Engine/Graphics/Textures/TextureBase.h b/Source/Engine/Graphics/Textures/TextureBase.h
index 2bb0042df..babe5a055 100644
--- a/Source/Engine/Graphics/Textures/TextureBase.h
+++ b/Source/Engine/Graphics/Textures/TextureBase.h
@@ -43,7 +43,7 @@ DECLARE_ASSET_HEADER(TextureBase);
/// Index of the mip.
/// True if use linear filer, otherwise point filtering.
/// True if failed, otherwise false.
- bool GenerateMip(int32 mipIndex, bool linear);
+ bool GenerateMip(int32 mipIndex, bool linear = false);
};
protected: