原文: More ASTC in ARM Mali GPUs - High Dynamic Range and 3D
ARM Mali GPU 中更多 关于ASTC的特性 – 高动态范围和 3D
作者 seanellis / 2013 年 7 月 8 日上午 10:06 /
ARM 的 ASTC 已作为全新的行业标准纹理压缩方案被 Khronos 采用。正如我上一篇博文中所述,ASTC 同时支持高动态范围和 3D 纹理压缩。我想我该花点时间来演示这些功能如何运作,以及它们能够实现的精彩效果。
高动态范围 一般(低动态范围或 LDR)彩色图像将屏幕上的颜色亮度表示为相对较低动态范围(0 最低亮度到 1 最高亮度)中的值。超出此范围的值毫无意义,因为你无法得到比黑色更暗的颜色,也无法让显示器发出比最大亮度更亮的光线。
然而,在决定屏幕上像素最终颜色的计算中,常常会出现你希望表示超出此范围的亮度的情况。例如,直射表面的光线可能会造成两倍于最高亮度的效果,而后再由表面上相对较暗的颜色向下调节。如果只能以 0 到 1 范围表示值,则无论照射表面的光线有多强,表面的亮度都不会超过其基础颜色。对于简单的照明来讲,这很容易做,因为你可以在计算中将任何旧的亮度分配给你的光线。更加高级的照明技巧通常使用纹理来提供光线强度和颜色,如果我们只有低动态范围纹理,这会成为问题。仅缩放纹理值对明亮颜色是可行的,但由于亮度步进之间的线性间隔,它会在较暗的区域中产生恼人的条带效果,看上去很糟糕。类似地,如果纹理呈现的是带有光线和阴影的场景或包含光源的场景,使用 LDR 会导致问题,要么偏向明亮区域而丢失昏暗区域的精确度,要么保持阴影的准确性却消除了明亮区域。
我们需要的是这样的表示方式,允许更大的动态范围,同时又在昏暗区域使用较小的步进值呈现颜色。这就是高动态范围 (HDR) 纹理。
HDR 图像(以 3.56bpp 的 ASTC 压缩,使用三种不同的曝光度显示)
在 OpenGL® ES 中,可以使用 16 位浮点值指定 HDR 纹理,但对于典型的 RGB 纹理而言,这相当于 48 bpp。由于大多数设计师对仅 24 bpp 的典型纹理占用的空间大小已经不满,这种翻一倍的空间是个大缺陷。显然,我们需要压缩。
支持 HDR 正如你所记得的,ASTC 可以针对图像中的各个纹素块使用不同的编码模式,确保根据该块的内容选择效用最高的模式。在以前的博文中,我们探讨了 LDR 编码方案,但 ASTC 也包含很多 HDR 编码模式,可以修改颜色存储和插值的方式。如果块中包含的一组像素值含有合适分布的明暗纹素,或者值超出 0 到 1 范围的纹素,就会以伪对数 12 位表示存储颜色,它们可以在解码器中轻松转换为真正的浮点形式。这种表示的优点在于可以将用于 LDR 值的相同线性插值应用到对数值上,正好得到我们需要同时以最小视觉失真表示明亮和昏暗值的那种值间隔。需要的额外步骤是,在编码期间将传入的浮点纹素值转换为伪对数值,然后在解码期间最终再转回为浮点值。编码经过选择,因此这些函数非常简单。转换之后,ASTC 以对待 LDR 值相同的方式处理这些值,这可节省硅面积,并能提供 LDR 模式可用的所有选择灵活性。
纹理创建者可以决定是否希望 HDR 或 LDR 在两个情形中访问相同的颜色格式和比特率。当然,许多情形中 HDR 图像包含的信息要多于 LDR 图像,因此更高的比特率才适当。我们对 HDR 图像的实验表明,以 8bpp 的相同比特率比较时,ASTC 的表现基本上与 BC6H 相当,后者是目前事实上的 HDR 压缩标准。然而,HDR 内容中有些类别(光线图是其中一种)可从低比特率获益,因此有必要在可行时启用。
3D 纹理 OpenGL、OpenGL ES 和 DirectX API 对 3D 纹理的支持已经有一些时候了,但它们似乎并未获得大家的热爱。原因不难了解 - 它们有些庞大。256×256 RGB 纹理目前属于小尺寸,未压缩时占用 192KiB 空间。要在 3D 中获得相同的像素分辨率,则需要 256x256x256 个纹素,占用空间达到了令人堪忧的 48MiB。对于大多数应用来说,这就是 3D 专业人士所说的太大。显然,需要压缩不是为了支持 3D 纹理,而是为了启用它们。
到目前为止,压缩方案对 3D 的支持有些不足,它们只是压缩 2D 切面。在我们的 256x256x256 案例中,我们只是把它视作 256 个独立切面,每个大小为 256×256 像素,单独压缩每个切面,然后再粘贴为阵列。这种方式有两大缺点:一个是性能,另一个则是质量。
性能问题的体现取决于你观看 3D 纹理的方式。如果表面显示的方向与切面编码的方向平行,则一个纹素解码操作仅需要访问单个切面中的数据块。你也很有可能在同一块中或缓存中找到附近的像素。
不过,如果你的表面是以垂直方向映射的,你将需要访问许多纹理块,这会影响带宽并加大纹理缓存负荷。这会导致很大的性能依赖,不在于复杂度或内容结构等可控制的方面,而在于无法预料的视角上。这真讨厌。
第二个问题是,在 3D 纹理中,我们通常会表示真实的体积数据,纹理中的特征实际上是三维的。因此纹理中的值在切面之间是关联的,这就是压缩算法可以利用的地方。如果你分割切面,就会妨碍压缩,这就导致给定比特率下较低的质量。
ASTC 中的 3D 模式引入了全新的理念 – 每个 128 位压缩数据块现在涵盖一个 3D 足迹,从 3x3x3 像素到 6x6x6 像素,之间采用常见的精细步进值。这对应于从每像素 4.7 到 0.56 位的比特率。既然块是立方体(或近似于立方体,也允许 4x4x5 这样的尺寸),那么无论从哪个方向观看它们的外观都是相似的。这基本上完全消除了切面方式中看到的巨大性能变化。
我们利用 ASTC 以 2 bpp 进行了 3D 体积纹理编码实验。这对应于 8×8 像素块的切面,或者使用 4x4x4 像素块的 3D 原始编码。3D 编码提供的原始质量提升大约为 2dB,表明压缩算法可以利用层面之前的额外关联来产生质量的大幅提升。
对于不同颜色区域边界清楚的 3D 纹理,我们也看到我们定义纹理分区的方式的优势。通过将它实现为函数而不是表,可以轻松地以 X、Y 和 Z 来定义函数,而不仅仅是 X 和 Y(一旦你认识到这是可行的)。这给予我们一个额外硬件成本绝对最小的 3D 分区表,而不会要求很大的 ROM。
3D 块确实需要修改像素权重阵列的排放,但这可完美融入到 128 位块结构中,而且重用了 2D 案例中的许多功能单元。例如,另一种小技巧是使用单一插值而不是三线性插值在权重之间插值,来计算有效权重。这可将涉及的工作量减少到与 2D 双线性插值相同,我们也可重新利用相同的插值硬件,节省功耗和面积。
然后,转到明显的问题上:是的,这是另一种独立选择,所以 ASTC 也支持 3D HDR 纹理!当然,你还有别的期待吗?
玩一玩 Mali 开发者中心提供了 ASTC 评估编解码器,支持 LDR、HDR 和 3D 纹理压缩。
你有 HDR 或 3D 纹理的新颖应用吗?为何不在评论中分享下呢?