版权声明:本文为CSDN博主「繁弱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
在目前所做的一个大世界项目的开发中,整体场景的制作会涉及到很多的方方面面,也会有很多问题产生,每个方面都需要理一个比较清晰易懂的标准出来,让整个项目组有关的人员能快速达成共识,也减少沟通的成本。
比如项目中发现对于 贴图格式的设置和使用 还是有些错误,故可能会逐步整理一些类似这样有关的说明给项目美术人员看看,顺便解答自己的一些疑惑,文中分为三个版本,分别是
- 太长不看版:直接看结果,那种贴图用哪个格式
- 美术版:除了结果,稍微介绍一下每种格式的细节
- 程序版:主要解答我自己以下几个疑问,如果你也有这些疑问,可以看看
- NormalMap 是如何选择使用
BC3还是BC5压缩的? - 普通 Texture 导入进来,引擎会不会自动判断是否有 alpha 通道,从而选择使用
BC1还是BC3? - 当然第二个问题很容易看出来,引擎确实会,但它执行逻辑的地方在哪里?
- 引擎真正执行压缩的地方在哪里?使用的什么来执行压缩?
太长不看版
-
BaseColor 等就一般使用
BC1或者BC3(有 alpha 用BC3,没有就用BC1),一般勾选sRGB,如果 错误 导入进来 alpha,可以勾选Compress Without Alpha,在引擎里面禁用掉 -
NormalMap 使用
BC5,也就是选项里的Normalmap选项,取消勾选sRGB -
MSRA 使用
Masks模式,并且取消勾选sRGB -
HDR 环境贴图使用
BC6,推荐使用HDR Comressed,也就是使用BC6压缩,如果选择HDR,它的 format 是floatRGBA一个通道32bit,非常大 -
单通道的贴图 可以使用
Alpha或者GrayScale,GrayScale 相当于不压缩,使用G8的 format,也就是 一个 Pixel 是 8 bit,4*4 16 个 pixel 占 128 bits,Alpha 使用BC4压缩 4*4 16 个 pixel 占 64bits,小一半,所以 GrayScale 适合本身不是很大的贴图,否则比较大,还是使用 Alpha 选项,BC4压缩一下 -
LUT 就不需要自己选了,选一下引擎的
LoopUpTable的texture group,它会自动帮你设置好,默认引擎的配置是不压缩的
美术版
BaseColor(Default DXT1/DXT5 BC1/BC3)
如果导入的 BaseColor 贴图带了 alpha,但其实不需要,可以勾选 Compress Without Alpha,避免把 alpha 压进来
DXT1/BC1: 有 8:1 的压缩比,24bit*16 变成 64 bit(6:1),(32bits*16 / 64 = 8,所以 8:1)
NormalMap
Normal map BC5,并且没有 sRGB,根据系统配置可以强制选择 BC3 压缩
具体逻辑在 Texture.cpp FName GetDefaultTextureFormatName()
FString UseDXT5NormalMapsString;
if (EngineSettings.GetString(TEXT("SystemSettings"), TEXT("Compat.UseDXT5NormalMaps"), UseDXT5NormalMapsString))
{
bUseDXT5NormalMap = FCString::ToBool(*UseDXT5NormalMapsString);
}
...
else if (FormatSettings.CompressionSettings == TC_Normalmap)
{
TextureFormatName = bUseDXT5NormalMap ? NameDXT5n : NameBC5;
}
...
如果导入不小心带了 alpha ,也可以勾选 Without Alpha 去掉
Masks(MSRA: Metal,Specular,Roughness,Ao )
另外那张 metal, specular, roughness, ao 等等的贴图 MSRA,这类不是用来存储 color 或者 vector,而是独立的 4 种信息(相当于 4 种 GrayScale),都可以归类为 Mask,使用 (Mask,no sRGB),实际使用的是 DXT5,也就是 BC3 的压缩,每个 4*4 的块压缩为 128 bits,所以基本能看到比选择 default BC1 的 texture size 大一倍,注意 128 bits 里面 64bits 用于 rgb color,64 bits 用于 alpha,所以这四个里面选择也是把 比较重要 的那个放在 Alpha Channel 里面
Alpha/GrayScale
同样 Masks 模式,这张 Heightmap
自动检查到没有 alpha,所以使用了 DXT1
但能看到这种模式下由于压缩带来的 锯齿 很严重,所以换用别的压缩模式 (GrayScale,R8) 的 format,适合本身就是 8 bits 灰度,由于 R8 是直接没压缩的,所以适合不止单通道、本身也不是很大的那种 texture,否则还是用压缩 BC4 吧
这里 注意 原本是 RGBA8 的 贴图,进来强行只使用 单通道,选择 Alpha 或者 GrayScale 是 不可以 的,原来不是单通道,切换到 Alpha 或者 GrayScale 会变成 BGRA8.
HDR (RGB, no sRGB) / HDR Compressed (RGB, BC6H, DX11)
HDR 环境贴图使用 BC6,如果选择 HDR , 它的 format 是 floatRGBA 一个通道 32 bit,非常大,推荐使用 HDR Comressed,也就是使用 BC6 压缩
BC7 (DX11, optional A)
特别重要的使用 BC7,4:1 压缩比,相比 BC1,两倍占用,alpha 也可以有
Others
其他的类型的 用法都包含在名字里了
- Displacement Map (8 / 16bit):
G8,单通道的 置换贴图 - Vector Displacement Map (RGB8):
BGRA8,支持四个通道的置换贴图 - User Interface 2D (RGBA):
BGRA8,UI 上的贴图都选这个,注意复用,不要太大 - Distance Field Font (R8):用于 SDF Font 的 贴图,只用存单通道距离就行,所以
G8就够
合理 使用 TextureGroup
配置好 group,可以减少美术出错几率,只要一开始配置好 config,后面所有贴图资源的 format 都可以统一管理
程序版
在 Texture 修改属性之后,一般会调用到 Texture 的 UpdateResource();
里面会调用
CachePlatformData();重新生成 DDC(生成压缩纹理),ClearAllCachedCookedPlatformData();清理 cook data
而 压缩的逻辑就在 CachePlatformData()
GetBuildSettingsForRunningPlatform() 获取各种配置和 压缩 format,出来判断 DDC 的 key 是否已经有了,如果没有,就重新cache 生成
里面会调用
GetTextureBuildSettings,获取 texture 的各种配置,就是 那个窗口的配的各种属性CurrentPlatform->GetTextureFormats,各个平台选择各自需要的压缩格式
- Android:
FAndroidTargetPlatform::GetTextureFormats
- Windows:
GenericWindowsTargetPlatform.h,调用 Default, -
FName GetDefaultTextureFormatName,这里就是 官方解释 压缩格式的文档里写明的格式
FTexturePlatformData::Cache如果 DDC 里没有找到,开始 Cache 。
先找到 ITextureCompressorModule 纹理压缩的 module 作为 Compressor 压缩器,由 Compressor 生成 task,这里可以异步
Compressor 里面根据不同的 format,分给不同的 format 压缩器,比如 DXT 格式就是 FTextureFormatDXT
const ITextureFormat* TextureFormat = nullptr;
ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();
if (TPM)
{
TextureFormat = TPM->FindTextureFormat(BuildSettings.TextureFormatName);
}
然后 DXT 的 format 里再处理,比如上面如果是 AutoDXT 的 format,这里就是再根据是否有 Alpha 选择使用 DXT1 还是 DXT5
然后同样这个方法,下面就执行 Compress,DXT 目前默认使用 NVTT,Nvidia 的一个纹理压缩器,压缩之后返回是否成功,如果成功,就缓存到到 DDC 里面
那大概这样。