【转载】UE4 场景流程规范-纹理压缩(美术版/程序版/太长不看版)

1,088 阅读6分钟

版权声明:本文为CSDN博主「繁弱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:blog.csdn.net/zzgyy123/ar…

在目前所做的一个大世界项目的开发中,整体场景的制作会涉及到很多的方方面面,也会有很多问题产生,每个方面都需要理一个比较清晰易懂的标准出来,让整个项目组有关的人员能快速达成共识,也减少沟通的成本。

比如项目中发现对于 贴图格式的设置和使用 还是有些错误,故可能会逐步整理一些类似这样有关的说明给项目美术人员看看,顺便解答自己的一些疑惑,文中分为三个版本,分别是

  • 太长不看版:直接看结果,那种贴图用哪个格式
  • 美术版:除了结果,稍微介绍一下每种格式的细节
  • 程序版:主要解答我自己以下几个疑问,如果你也有这些疑问,可以看看
  1. NormalMap 是如何选择使用 BC3 还是 BC5 压缩的?
  2. 普通 Texture 导入进来,引擎会不会自动判断是否有 alpha 通道,从而选择使用 BC1 还是 BC3
  3. 当然第二个问题很容易看出来,引擎确实会,但它执行逻辑的地方在哪里?
  4. 引擎真正执行压缩的地方在哪里?使用的什么来执行压缩?

image.png

太长不看版

  1. BaseColor 等就一般使用 BC1 或者 BC3(有 alpha 用 BC3,没有就用 BC1),一般勾选 sRGB,如果 错误 导入进来 alpha,可以勾选 Compress Without Alpha,在引擎里面禁用掉

  2. NormalMap 使用 BC5,也就是选项里的 Normalmap 选项,取消勾选 sRGB

  3. MSRA 使用 Masks 模式,并且取消勾选 sRGB

  4. HDR 环境贴图使用 BC6,推荐使用 HDR Comressed,也就是使用 BC6 压缩,如果选择 HDR ,它的 format 是 floatRGBA 一个通道 32bit,非常大

  5. 单通道的贴图 可以使用 Alpha 或者 GrayScaleGrayScale 相当于不压缩,使用 G8 的 format,也就是 一个 Pixel 是 8 bit,4*4 16 个 pixel 占 128 bits,Alpha 使用 BC4 压缩 4*4 16 个 pixel 占 64bits,小一半,所以 GrayScale 适合本身不是很大的贴图,否则比较大,还是使用 Alpha 选项,BC4 压缩一下

  6. LUT 就不需要自己选了,选一下引擎的 LoopUpTabletexture group,它会自动帮你设置好,默认引擎的配置是不压缩的

美术版

BaseColor(Default DXT1/DXT5 BC1/BC3)

如果导入的 BaseColor 贴图带了 alpha,但其实不需要,可以勾选 Compress Without Alpha,避免把 alpha 压进来

image.png

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 去掉

image.png

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 里面

image.png

Alpha/GrayScale

同样 Masks 模式,这张 Heightmap

image.png

自动检查到没有 alpha,所以使用了 DXT1

但能看到这种模式下由于压缩带来的 锯齿 很严重,所以换用别的压缩模式 (GrayScale,R8) 的 format,适合本身就是 8 bits 灰度,由于 R8 是直接没压缩的,所以适合不止单通道、本身也不是很大的那种 texture,否则还是用压缩 BC4

image.png

这里 注意 原本是 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()

image.png

GetBuildSettingsForRunningPlatform() 获取各种配置和 压缩 format,出来判断 DDC 的 key 是否已经有了,如果没有,就重新cache 生成

里面会调用

  1. GetTextureBuildSettings,获取 texture 的各种配置,就是 那个窗口的配的各种属性
  2. CurrentPlatform->GetTextureFormats,各个平台选择各自需要的压缩格式
  • Android:FAndroidTargetPlatform::GetTextureFormats

image.png

  • Windows:GenericWindowsTargetPlatform.h,调用 Default
    • FName GetDefaultTextureFormatName,这里就是 官方解释 压缩格式的文档里写明的格式

image.png

  1. FTexturePlatformData::Cache 如果 DDC 里没有找到,开始 Cache 。

先找到 ITextureCompressorModule 纹理压缩的 module 作为 Compressor 压缩器,由 Compressor 生成 task,这里可以异步

image.png

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

image.png

然后同样这个方法,下面就执行 Compress,DXT 目前默认使用 NVTT,Nvidia 的一个纹理压缩器,压缩之后返回是否成功,如果成功,就缓存到到 DDC 里面

image.png

那大概这样。

Reference