块压缩

从 Windows 8.1 开始,Direct2D 支持多个块压缩像素格式。 此外,Windows 8.1 还包含新的 Windows 映像组件 (WIC) DDS 编解码器,用于以 DDS 文件格式加载和存储块压缩图像。 块压缩是减少位图内容使用的图形内存量的技术。 通过使用块压缩,应用可以减少相同分辨率图像的内存消耗和加载时间。 或者,你的应用可以使用更多或更高的分辨率图像,同时仍占用相同的 GPU 内存占用。

Direct3D 应用程序长时间使用块压缩,Windows 8.1 也可用于主流和 Direct2D 应用程序开发人员。

本主题介绍块压缩的工作原理以及如何在 WIC 和 Direct2D 中使用它。

关于块压缩

块压缩(BC)是指用于减小纹理大小的一类压缩技术。 Direct3D 11 支持最多 7 种不同的 BC 格式,具体取决于功能级别。 在 Windows 8.1 Direct2D 中,引入了对 BC1、BC2 和 BC3 格式的支持,这些格式适用于所有功能级别。

块压缩的工作原理

块压缩格式都使用相同的基本技术来减少颜色数据占用的空间。 本部分总结了最简单的算法 BC1。 有关更详细的说明,请参阅 块压缩

首先,图像分为 4 个像素的块。 每个块单独压缩。

注意

这意味着图像的宽度和高度必须是 4 像素的倍数,才能将其块压缩。

 

此示例图像显示图像中的 4x4 像素块。

示例图像显示图像中的 4x4 像素块。

接下来,在 4 到 4 块内,选择两种“引用”颜色,并编码为两个 16 位值(5 位红色、6 位绿色、5 位蓝色)。 这些颜色的选择严重影响图像质量,这是非平常的。 两种中间颜色是通过在 RGB 颜色空间中的两种参考颜色之间线性内插来计算的。 这总共产生 4 种不同的可能颜色;为每个颜色分配一个两位索引值。 但是,请注意,只有两种终结点颜色需要存储,因为内插是固定的。

在此图中,颜色 0 和 3 被选为块的“参考”颜色,而颜色 1 和 2 是使用线性内插计算的。

关系图,显示用于表示块的 4 个颜色值的计算。

最后,块中的每个像素都映射到以前计算过的四种颜色之一,并且每个像素都使用两位索引值进行编码。

用于表示这 16 像素的数据总量为:

16 bits [to define a reference color] * 2 + 2 bits * 16 [number of pixels] = 64 bits

这会导致每个像素的平均密度为 4 位。 为了进行比较,常见的DXGI_FORMAT_B8G8R8A8_UNORM像素格式每像素消耗 32 位。

此图显示,每个像素都编码为 2 位索引。 整个块编码为 64 位。

计算 4 个颜色值来表示块。

有一些变体支持 alpha 数据和不同数量的颜色通道。 BC6H 和 BC7 使用不同的算法来支持高动态范围(HDR)内容,并分别提高图像质量。

DirectDraw Surface (DDS) 文件格式

块压缩数据通常存储在 DirectDraw Surface (DDS) 文件中。 如果你是 Direct3D 开发人员,则可能熟悉 DDS 文件。 请注意,Direct2D 仅支持某些 DDS 功能;有关详细信息,请参阅 DDS 要求

块压缩的优点

块压缩格式不同于常见的行业图像压缩格式,例如 JPEG,因为 BC 格式原生受现代 GPU 支持。 这意味着,无需任何解码或解压缩,即可将块压缩图像直接加载到 GPU 上。 BC 格式平均每像素消耗 4 到 8 位;与每个像素 BGRA 位图的典型未压缩 32 位相比,这会导致内存节省 75% 到 87.5%。 此外,由于没有解码步骤,因此与 JPEG 等格式相比,加载 BC 图像的时间会显著减少。

何时使用块压缩

如果要减少位图的内存消耗,或者希望减少解码和加载时间,应考虑在应用中使用块压缩图像,而不是 JPEG 等其他格式。

但是,块压缩不适用于所有情况,需要一些权衡。 首先,块压缩算法是丢失的。 块压缩非常适用于自然摄影内容,但可以将不需要的视觉项目引入具有锐利、高对比度边界的图像,例如计算机生成的屏幕截图。 在使用压缩图像资产之前,应确保块压缩图像资产具有可接受的图像质量。

其次,块压缩的 DDS 文件通常消耗的磁盘空间比可比的 JPEG 映像更多。 这反过来又会增加应用的包大小和网络带宽要求。

使用块压缩

本部分介绍如何在 Direct2D 应用中生成和使用块压缩资产。

概述

块压缩的 DDS 文件是运行时优化的格式,这意味着它们专门针对应用运行时的性能进行了优化。 建议继续使用现有资产创建和编辑管道,并且仅在将资源导入应用程序项目或生成时转换为块压缩格式。

DDS 要求

DDS 文件格式旨在支持 Direct3D 中使用的各种功能。 Direct2D 仅使用这些功能的子集。 因此,在创建用于 Direct2D 的 DDS 映像时,必须牢记以下限制:

  • 仅允许以下 DXGI_FORMAT 值:
    • DXGI_FORMAT_BC1_UNORM
    • DXGI_FORMAT_BC2_UNORM
    • DXGI_FORMAT_BC3_UNORM
  • 必须使用预乘的 alpha 数据。 这包括使用显式定义预乘 alpha(DXT1、DXT2、DXT4)的格式的旧 DDS 文件,以及使用具有DDS_ALPHA_MODE_OPAQUE和DDS_ALPHA_MODE_PREMULTIPLIED值的DDS_HEADER_DX10结构的 DDS 文件。
  • X 和 Y 尺寸必须是 4 像素的倍数。
  • 不允许使用卷纹理、立方体贴图、mipmap 或纹理数组。 应仅使用单个帧源图像。

生成块压缩资产

有多种 DDS 创作工具可用于创建或转换块压缩的 DDS 文件。 请注意,并非所有工具都支持将 DDS 文件与 Direct2D 配合使用的要求,如上一部分所述。

从 Visual Studio 2013 开始,可以将现有视觉资产(如 JPEG 和 PNG)转换为正确的 DDS 块压缩格式,作为生成过程的自动部分。 这是使用映像内容任务自定义生成步骤完成的。

有关如何为项目设置此项的信息,请参阅:如何:导出纹理以用于 Direct2D 或 Javascipt Apps

Direct2D API

Direct2D 在 Windows 8.1 中更新,以支持以下像素格式:

  • DXGI_FORMAT_BC1_UNORM
  • DXGI_FORMAT_BC2_UNORM
  • DXGI_FORMAT_BC3_UNORM

对于上述格式,必须使用预乘 alpha。 此外,这些格式仅可用于源,而不是目标。 例如,这意味着可以使用 BC1 创建 Direct2D 位图,但不能创建设备上下文。

Windows 8.1 中更新了以下方法以支持 BC 格式:

请注意,CreateBitmapFromWicBitmapIWICBitmapSource 作为接口;但是,在 Windows 8.1 WIC 中,不支持从 IWICBitmapSource获取块压缩数据,并且没有对应于DXGI_FORMAT_BC1_UNORM等的 WIC 像素格式。相反,CreateBitmapFromWicBitmap 确定 IWICBitmapSource 是否是有效的 DDS IWICBitmapFrameDecode,并直接加载块压缩的数据。 可以在 D2D1_BITMAP_PROPERTIES1 结构中显式指定像素格式,或者允许 Direct2D 自动确定正确的格式。

Windows 映像组件 API

Windows 映像组件 (WIC) 在 Windows 8.1 中添加新的 DDS 编解码器。 此外,它还添加了支持访问特定于 DDS 的数据的新接口,包括块压缩的像素数据:

阻止压缩 WIC 像素格式

Windows 8.1 中没有新的 WIC 块压缩像素格式。 相反,如果从 DDS 解码器获取 IWICBitmapFrameDecode 并调用 CopyPixels,则会收到标准未压缩的像素,如 WICPixelFormat32bppPBGRA。 可以使用 IWICDdsFrameDecode::CopyBlocks 从 DDS 文件中获取内存缓冲区形式的原始块压缩数据。

多帧 DDS 访问

DDS 文件格式允许将多个相关图像存储在单个文件中。 例如,DDS 文件可能包含多维数据集地图、卷纹理或纹理数组,所有这些数组都可以被 mipmapp 应用。 在 Direct3D 中,这些多个图像作为子资源公开。 在 WIC 中,多个图像作为帧公开(IWICBitmapFrameDecodeIWICBitmapFrameEncode)。

WIC 仅支持帧的单维数组的概念,而 DDS 支持三个独立的维度(尽管在任何一个文件中只能使用两个)。 WIC 提供了方便的方法,可帮助在 DDS 子资源与 WIC 帧之间进行映射。 对于解码,IWICDdsDecoder::GetFrame 允许指定子资源的数组索引、mip 级别和切片索引,并返回正确的 WIC 帧。

对于编码,IWICDdsEncoder::CreateNewFrame 在创建新帧时计算生成的数组索引、mip 级别和切片索引。 必须先调用 IWICDdsEncoder::SetParameters 才能定义特定于 DDS 的文件参数。

如何:导出纹理以用于 Direct2D 或 Javascipt 应用

DDS 参考

块压缩