Files
UnrealEngineUWP/Engine/Plugins/Experimental/MeshModelingToolset/Source/ModelingComponents/Private/AssetUtils/Texture2DUtil.cpp
charles bloom 05b4b19678 Float16Color use VectorStoreHalf/VectorLoadHalf
add SSE2 half conversions

#rb alexander.suvorov
#fyi rod.bogart

[CL 16135278 by charles bloom in ue5-main branch]
2021-04-27 20:41:39 -04:00

149 lines
5.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AssetUtils/Texture2DUtil.h"
#include "ExplicitUseGeometryMathTypes.h" // using UE::Geometry::(math types)
using namespace UE::Geometry;
static bool ReadTexture_PlatformData(
UTexture2D* TextureMap,
FImageDimensions& Dimensions,
TImageBuilder<FVector4f>& DestImage)
{
// Read from PlatformData
// UBlueprintMaterialTextureNodesBPLibrary::Texture2D_SampleUV_EditorOnly() shows how to read from PlatformData
// without converting formats if it's already uncompressed. And can read PF_FloatRGBA. Would make sense to do
// that when possible, and perhaps is possible to convert to PF_FloatRGBA instead of using TC_VectorDisplacementmap?
//
// Note that the current code cannot run on a background thread, UpdateResource() will call FlushRenderingCommands()
// which will check() if it's on the Game Thread
check(TextureMap->PlatformData);
int32 Width = TextureMap->PlatformData->Mips[0].SizeX;
int32 Height = TextureMap->PlatformData->Mips[0].SizeY;
Dimensions = FImageDimensions(Width, Height);
DestImage.SetDimensions(Dimensions);
int64 Num = Dimensions.Num();
// convert built platform texture data to uncompressed RGBA8 format
TextureCompressionSettings InitialCompressionSettings = TextureMap->CompressionSettings;
bool bWasSRGB = TextureMap->SRGB;
#if WITH_EDITOR
TextureMipGenSettings InitialMipGenSettings = TextureMap->MipGenSettings;
#endif
TextureMap->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
TextureMap->SRGB = false;
#if WITH_EDITOR
TextureMap->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
#endif
TextureMap->UpdateResource();
// lock texture and represet as FColor
const FColor* FormattedImageData = reinterpret_cast<const FColor*>(TextureMap->PlatformData->Mips[0].BulkData.LockReadOnly());
// maybe could be done more quickly by row?
for (int32 i = 0; i < Num; ++i)
{
FColor ByteColor = FormattedImageData[i];
DestImage.SetPixel(i, FVector4f(ByteColor.ReinterpretAsLinear()));
}
// restore built platform texture data to initial state
TextureMap->PlatformData->Mips[0].BulkData.Unlock();
TextureMap->CompressionSettings = InitialCompressionSettings;
TextureMap->SRGB = bWasSRGB;
#if WITH_EDITOR
TextureMap->MipGenSettings = InitialMipGenSettings;
#endif
TextureMap->UpdateResource();
return true;
}
#if WITH_EDITOR
static bool ReadTexture_SourceData(
UTexture2D* TextureMap,
FImageDimensions& Dimensions,
TImageBuilder<FVector4f>& DestImage)
{
FTextureSource& TextureSource = TextureMap->Source;
int32 Width = TextureSource.GetSizeX();
int32 Height = TextureSource.GetSizeY();
Dimensions = FImageDimensions(Width, Height);
DestImage.SetDimensions(Dimensions);
int64 Num = Dimensions.Num();
TArray64<uint8> SourceData;
TextureMap->Source.GetMipData(SourceData, 0, 0, 0);
ETextureSourceFormat SourceFormat = TextureSource.GetFormat();
int32 BytesPerPixel = TextureSource.GetBytesPerPixel();
const uint8* SourceDataPtr = SourceData.GetData();
// code below is derived from UBlueprintMaterialTextureNodesBPLibrary::Texture2D_SampleUV_EditorOnly()
if ((SourceFormat == TSF_BGRA8 || SourceFormat == TSF_BGRE8))
{
check(BytesPerPixel == sizeof(FColor));
for (int32 i = 0; i < Num; ++i)
{
const uint8* PixelPtr = SourceDataPtr + (i * BytesPerPixel);
FColor PixelColor = *((FColor*)PixelPtr);
FLinearColor FloatColor = (TextureMap->SRGB) ?
FLinearColor::FromSRGBColor(PixelColor) :
PixelColor.ReinterpretAsLinear();
DestImage.SetPixel(i, FVector4f(FloatColor));
}
}
else if ((SourceFormat == TSF_RGBA16 || SourceFormat == TSF_RGBA16F))
{
check(BytesPerPixel == sizeof(FFloat16Color));
for (int32 i = 0; i < Num; ++i)
{
const uint8* PixelPtr = SourceDataPtr + (i * BytesPerPixel);
DestImage.SetPixel(i, FVector4f( ((const FFloat16Color*)PixelPtr)->GetFloats() ));
}
}
else if (SourceFormat == TSF_G8)
{
check(BytesPerPixel == 1);
for (int32 i = 0; i < Num; ++i)
{
const uint8* PixelPtr = SourceDataPtr + (i * BytesPerPixel);
uint8 PixelColor = *PixelPtr;
float PixelColorf = float(PixelColor) / 255.0f;
FLinearColor FloatColor = (TextureMap->SRGB) ?
FLinearColor::FromSRGBColor(FColor(PixelColor, PixelColor, PixelColor, 255)) :
FLinearColor(PixelColorf, PixelColorf, PixelColorf, 1.0);
DestImage.SetPixel(i, FVector4f(FloatColor));
}
}
return true;
}
#endif
bool UE::AssetUtils::ReadTexture(
UTexture2D* TextureMap,
FImageDimensions& Dimensions,
TImageBuilder<FVector4f>& DestImage,
bool bPreferPlatformData)
{
if (ensure(TextureMap) == false) return false;
#if WITH_EDITOR
bool bHasVTData = TextureMap->GetPlatformData()->VTData != nullptr;
bool bHasMips = TextureMap->GetPlatformData()->Mips.Num() != 0;
ensure(bHasVTData != bHasMips); // should be one or the other
if (TextureMap->Source.IsValid() && (bPreferPlatformData == false || bHasMips == false))
{
return ReadTexture_SourceData(TextureMap, Dimensions, DestImage);
}
#endif
return ReadTexture_PlatformData(TextureMap, Dimensions, DestImage);
}