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: