2014-03-14 14:13:41 -04:00
|
|
|
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "Core.h"
|
|
|
|
|
#include "ModuleInterface.h"
|
|
|
|
|
#include "ModuleManager.h"
|
|
|
|
|
#include "TargetPlatform.h"
|
|
|
|
|
#include "TextureCompressorModule.h"
|
|
|
|
|
#include "PixelFormat.h"
|
|
|
|
|
#include "ImageCore.h"
|
|
|
|
|
|
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogTextureFormatUncompressed, Log, All);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Macro trickery for supported format names.
|
|
|
|
|
*/
|
|
|
|
|
#define ENUM_SUPPORTED_FORMATS(op) \
|
|
|
|
|
op(BGRA8) \
|
|
|
|
|
op(G8) \
|
|
|
|
|
op(VU8) \
|
|
|
|
|
op(RGBA16F) \
|
2014-05-22 09:13:12 -04:00
|
|
|
op(XGXR8) \
|
|
|
|
|
op(RGBA8)
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
#define DECL_FORMAT_NAME(FormatName) static FName GTextureFormatName##FormatName = FName(TEXT(#FormatName));
|
|
|
|
|
ENUM_SUPPORTED_FORMATS(DECL_FORMAT_NAME);
|
|
|
|
|
#undef DECL_FORMAT_NAME
|
|
|
|
|
|
|
|
|
|
#define DECL_FORMAT_NAME_ENTRY(FormatName) GTextureFormatName##FormatName ,
|
|
|
|
|
static FName GSupportedTextureFormatNames[] =
|
|
|
|
|
{
|
|
|
|
|
ENUM_SUPPORTED_FORMATS(DECL_FORMAT_NAME_ENTRY)
|
|
|
|
|
};
|
|
|
|
|
#undef DECL_FORMAT_NAME_ENTRY
|
|
|
|
|
|
|
|
|
|
#undef ENUM_SUPPORTED_FORMATS
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Uncompressed texture format handler.
|
|
|
|
|
*/
|
|
|
|
|
class FTextureFormatUncompressed : public ITextureFormat
|
|
|
|
|
{
|
|
|
|
|
virtual bool AllowParallelBuild() const OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual uint16 GetVersion(FName Format) const OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void GetSupportedFormats(TArray<FName>& OutFormats) const OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
for (int32 i = 0; i < ARRAY_COUNT(GSupportedTextureFormatNames); ++i)
|
|
|
|
|
{
|
|
|
|
|
OutFormats.Add(GSupportedTextureFormatNames[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-23 20:04:50 -04:00
|
|
|
|
|
|
|
|
virtual FTextureFormatCompressorCaps GetFormatCapabilities() const OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
return FTextureFormatCompressorCaps(); // Default capabilities.
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
virtual bool CompressImage(
|
|
|
|
|
const FImage& InImage,
|
|
|
|
|
const struct FTextureBuildSettings& BuildSettings,
|
|
|
|
|
bool bImageHasAlphaChannel,
|
|
|
|
|
FCompressedImage2D& OutCompressedImage
|
|
|
|
|
) const OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
if (BuildSettings.TextureFormatName == GTextureFormatNameG8)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::G8, BuildSettings.bSRGB);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_G8;
|
|
|
|
|
OutCompressedImage.RawData = Image.RawData;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (BuildSettings.TextureFormatName == GTextureFormatNameVU8)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_V8U8;
|
|
|
|
|
|
|
|
|
|
uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices;
|
|
|
|
|
OutCompressedImage.RawData.Empty(NumTexels * 2);
|
|
|
|
|
OutCompressedImage.RawData.AddUninitialized(NumTexels * 2);
|
|
|
|
|
const FColor* FirstColor = Image.AsBGRA8();
|
|
|
|
|
const FColor* LastColor = FirstColor + NumTexels;
|
|
|
|
|
int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData();
|
|
|
|
|
|
|
|
|
|
for (const FColor* Color = FirstColor; Color < LastColor; ++Color)
|
|
|
|
|
{
|
|
|
|
|
*Dest++ = (int32)Color->R - 128;
|
|
|
|
|
*Dest++ = (int32)Color->G - 128;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (BuildSettings.TextureFormatName == GTextureFormatNameBGRA8)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_B8G8R8A8;
|
|
|
|
|
OutCompressedImage.RawData = Image.RawData;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-05-22 09:13:12 -04:00
|
|
|
else if (BuildSettings.TextureFormatName == GTextureFormatNameRGBA8)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_B8G8R8A8;
|
|
|
|
|
|
|
|
|
|
// swizzle each texel
|
|
|
|
|
uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices;
|
|
|
|
|
OutCompressedImage.RawData.Empty(NumTexels * 4);
|
|
|
|
|
OutCompressedImage.RawData.AddUninitialized(NumTexels * 4);
|
|
|
|
|
const FColor* FirstColor = Image.AsBGRA8();
|
|
|
|
|
const FColor* LastColor = FirstColor + NumTexels;
|
|
|
|
|
int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData();
|
|
|
|
|
|
|
|
|
|
for (const FColor* Color = FirstColor; Color < LastColor; ++Color)
|
|
|
|
|
{
|
|
|
|
|
*Dest++ = (int32)Color->R;
|
|
|
|
|
*Dest++ = (int32)Color->G;
|
|
|
|
|
*Dest++ = (int32)Color->B;
|
|
|
|
|
*Dest++ = (int32)Color->A;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
else if (BuildSettings.TextureFormatName == GTextureFormatNameXGXR8)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_B8G8R8A8;
|
|
|
|
|
|
|
|
|
|
// swizzle each texel
|
|
|
|
|
uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices;
|
|
|
|
|
OutCompressedImage.RawData.Empty(NumTexels * 4);
|
|
|
|
|
OutCompressedImage.RawData.AddUninitialized(NumTexels * 4);
|
|
|
|
|
const FColor* FirstColor = Image.AsBGRA8();
|
|
|
|
|
const FColor* LastColor = FirstColor + NumTexels;
|
|
|
|
|
int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData();
|
|
|
|
|
|
|
|
|
|
for (const FColor* Color = FirstColor; Color < LastColor; ++Color)
|
|
|
|
|
{
|
|
|
|
|
*Dest++ = (int32)Color->B;
|
|
|
|
|
*Dest++ = (int32)Color->G;
|
|
|
|
|
*Dest++ = (int32)Color->A;
|
|
|
|
|
*Dest++ = (int32)Color->R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (BuildSettings.TextureFormatName == GTextureFormatNameRGBA16F)
|
|
|
|
|
{
|
|
|
|
|
FImage Image;
|
|
|
|
|
InImage.CopyTo(Image, ERawImageFormat::RGBA16F, false);
|
|
|
|
|
|
|
|
|
|
OutCompressedImage.SizeX = Image.SizeX;
|
|
|
|
|
OutCompressedImage.SizeY = Image.SizeY;
|
|
|
|
|
OutCompressedImage.PixelFormat = PF_FloatRGBA;
|
|
|
|
|
OutCompressedImage.RawData = Image.RawData;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogTextureFormatUncompressed, Warning,
|
|
|
|
|
TEXT("Cannot convert uncompressed image to format '%s'."),
|
|
|
|
|
*BuildSettings.TextureFormatName.ToString()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Module for uncompressed texture formats.
|
|
|
|
|
*/
|
|
|
|
|
static ITextureFormat* Singleton = NULL;
|
|
|
|
|
|
|
|
|
|
class FTextureFormatUncompressedModule : public ITextureFormatModule
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual ~FTextureFormatUncompressedModule()
|
|
|
|
|
{
|
|
|
|
|
delete Singleton;
|
|
|
|
|
Singleton = NULL;
|
|
|
|
|
}
|
|
|
|
|
virtual ITextureFormat* GetTextureFormat()
|
|
|
|
|
{
|
|
|
|
|
if (!Singleton)
|
|
|
|
|
{
|
|
|
|
|
Singleton = new FTextureFormatUncompressed();
|
|
|
|
|
}
|
|
|
|
|
return Singleton;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_MODULE(FTextureFormatUncompressedModule, TextureFormatUncompressed);
|
|
|
|
|
|