实时DXT压缩

                                                                               实时DXt压缩算法

JMP van Waveren 
id Software,Inc.


NVIDIA公司

2008年2月7日

©2008,id Software,Inc.

翻译此文,我觉得对于理解Doom3和rage的dxt压缩算法,有很大的帮助,尽管翻译的地方有所失误,

(注,原文写的更好,强烈建议看原文)

使用今天的图形硬件,普通地图可以存储在几种压缩格式中,

这些格式在渲染过程中在硬件上即时解压缩。

对使用现有纹理压缩格式的几个对象空间和正切空间法线贴图进行评估。

虽然这些格式的解压缩在渲染过程中在硬件中实时发生,

但是使用现有的压缩器可能需要大量时间的压缩。

提出了两种高度优化的切线空间法线贴图压缩算法,

可以在CPU和GPU上实现实时性能。


 

介绍

   凹凸映射使用纹理来扰乱表面法线,以使对象更具有几何复杂的外观,

而不增加几何图元的数量。

如Blinn [ 1 ] 最初描述的,凹凸贴图在计算表面的照明之前,

使用凹凸贴图高度场的梯度来扰动表面衍生(方向向量)方向上的内插表面法线。

通过改变表面法线,表面被点亮,好像它具有更多的细节,

结果也被认为比用于描述表面的几何图元具有更多的细节。

正态映射是凹凸映射的应用,由Peercy等引入 [ 2 ]。

虽然凹凸贴图扰乱了对象的现有表面法线,但是正常映射完全取代了法线。

普通地图是存储法线的纹理。

这些法线通常存储为具有三个组件的单位长度向量:X,Y和Z.正常映射比凹凸贴图具有显着的性能优势,因为计算表面照明所需的操作更少。

通常的映射通常在两个品种中找到:对象空间和正切空间法线映射。

它们在测量和存储法线的坐标系中不同。对象空间法则映射相对于整个对象的位置和方向存储法线。

切线空间法线相对于三角形顶点的内插切线空间存储。

虽然物体空间法线可以是单位球体上的任何地方,

但正切空间法线仅在表面前方的单位半球上,

因为法线总是指向表面。

对象空间法线贴图(左)
和切线空间中相同法线贴图(右)的示例。

正常并不一定必须存储为具有组件X,Y和Z的向量。然而,从其他表示形式的渲染通常以性能成本来存储。例如,通常可以存储为角度对(俯仰,偏航)。然而,该表示具有内插或滤波不能正常工作的问题,因为存在可能不存在用于表示局部旋转的角度的简单变化的方向。在内插,滤波或计算该物体的表面照明之前,角度对必须转换为不同的表示,如矢量,这需要昂贵的三角函数。

尽管法线贴图可以存储为浮点纹理,但是通常将法线贴图存储为有符号或无符号整数纹理,因为法向矢量的分量取值范围很广(通常为[-1,+1] ),并且在不浪费浮点指数的任何位的情况下,在整个范围内具有相同的精度是有益的。例如,要将法线贴图存储为每个分量8位的无符号整数纹理,X,Y和Z分量将从[-1,+1]范围内的实数值重新整数到[0, 255]。这样,实值向量[0,0,1]被转换成整数向量[128,128,255],当被解释为RGB空间中的一个点时,是紫色/蓝色主要在切线空间法线贴图 为了呈现存储为无符号整数纹理的法线贴图,矢量分量首先从一个整数值映射到硬件中的浮点范围[0,+1]。

    例如,在每个分量具有8位的纹理的情况下,通过与255分割将整数范围[0,255]映射到浮点范围[0,+1]。然后,组件通常从[0,+1]范围在片段程序渲染过程中通过在与2相乘后减1后范围为[-1,+1]范围。当使用有符号整数纹理时,从整数值到浮点数范围[-1,+1]直接在硬件中执行。矢量分量首先从整数值映射到硬件中的浮点范围[0,+1]。例如,在每个分量具有8位的纹理的情况下,通过与255分割将整数范围[0,255]映射到浮点范围[0,+1]。然后,组件通常从[0,+1]范围在片段程序渲染过程中通过在与2相乘后减1后范围为[-1,+1]范围。当使用有符号整数纹理时,从整数值到浮点数范围[-1,+1]直接在硬件中执行。矢量分量首先从整数值映射到硬件中的浮点范围[0,+1]。例如,在每个分量具有8位的纹理的情况下,通过与255分割将整数范围[0,255]映射到浮点范围[0,+1]。然后,组件通常从[0,+1]范围在片段程序渲染过程中通过在与2相乘后减1后范围为[-1,+1]范围。当使用有符号整数纹理时,从整数值到浮点数范围[-1,+1]直接在硬件中执行。

    是否使用有符号或无符号整数纹理,一个根本的问题是不可能从二进制整数到浮点范围[-1,+1] 导出线性映射,使得值-1,和+1表示准确。在先前的NVIDIA实现中使用的带符号整数纹理的硬件映射并不完全代表+1。对于n位无符号整数分量,整数0映射到-1,整数2 n-1映射到0,最大整数值2 n -1映射到1 - 2 1-n。换句话说,值-1和0被精确地表示,但值+1不是。用于DirectX 10类硬件的映射是非线性的。对于n位有符号整数分量,整数-2 n-1映射到-1,整数-2 n-1 +1也映射到-1,整数0映射到0,整数2 n-1 -1映射到+1。换句话说,值-1,0和+1都被精确地表示,但值-1表示两次。

旧硬件不支持签名纹理。此外,从二进制整数到范围[-1,+1]的映射可能是硬件特定的。一些实现可能选择不完全代表+1,而传统的OpenGL映射指定-1和+1可以被精确地表示,但是0不能。其他实现可以选择非线性映射,或允许超出范围[-1,+1]的值,使得可以精确地表示所有三个值-1,0和+1。为了覆盖最广泛的硬件范围,没有任何硬件特定的依赖关系,这里使用的所有法线图被假设存储为无符号整数纹理。从[0,+1]到[-1,+1]范围内的映射在片段程序中通过在乘以2之后减1来执行。这可能导致附加的片段程序指令,当使用带符号的纹理时,可以将其简单地删除。这里使用的映射与传统的OpenGL映射相同,这导致值-1和+1的精确表示,但不是0。

整数法线贴图通常可以按照每个法向量16(5:6:5),24(8:8:8),48(16:16:16)或96(32:32:32)位存储。然而,今天的大部分普通地图都不存在每个法向量不超过24(8:8:8)位。重要的是要认识到实际上接近单位长度的相对较少的8:8:8位向量。例如,在RGB空间中为深蓝色的整数向量[0,0,64]不表示单位长度的法向量(长度为0.5而不是1.0)。下图显示了比单位长度小于特定百分比的可表示的8:8:8位向量的百分比。

例如,如果法向量不被认为是单位长度大于5%的可接受的话,那么只有大约15%的可表示的8:8:8位向量可用于表示法向量。如5:6:5位那样精确度较低的位,接近单位长度的可表示向量的数量迅速减少。

为了显着增加可以使用的向量的数量,可以将每个法向量存储为不一定是单位长度的方向。然后,这个方向需要在片段程序中进行归一化。然而,仍然有一些浪费,因为只有83%的所有8:8:8位向量表示唯一的方向。例如,整数向量[0,0,32],[0,0,64]和[0,0,96]都指定完全相同的方向(它们是彼此的倍数)。此外,独特的标准化方向不是均匀分布在单位球体上。对于[-1,+1] x [-1,+1] x [-1,+1]向量空间的边界框的四个对角线的方向,有更多的表示方式,到坐标轴。例如,在向量[1,1,1]周围的15度半径内表示的方向比在向量[0,0,1]周围15度半径内的方向表示三倍。下图显示了投射到单位球体上的所有可表示的8:8:8位矢量的分布。载体密度较低的区域为绿色,密度较高的区域为红色。

8:8:8位向量
投影在单位球体上的分布

在今天的图形硬件上,普通地图也可以以多种压缩格式存储,在渲染过程中实时解压缩。由于减少的带宽要求,压缩的法线贴图不仅要求显卡内存少得多,而且通常还会比未压缩的法线贴图快。各种不同的方式来利用现有的纹理压缩格式的正常地图压缩,已被建议在文献[ 789 ]。这些正常的地图压缩技术中的几个以及它们的扩展在第2节和第3节进行了评估。

虽然这些格式的解压缩是在硬件中实时完成的,但对这些格式的压缩可能需要相当长的时间。现有压缩机设计为高质量离线压缩,而不是实时压缩[ 202122 ]。然而,实时压缩对于从不同格式的代码转换法线图,动态生成的法线贴图的压缩以及压缩的法线贴图渲染目标来说是非常有用的。在第4节和第5节中,提出了两种高度优化的切线空间法线贴图压缩算法,可用于实现CPU和GPU的实时性能。

对象空间正常图

对象空间法则映射相对于整个对象的位置和方向存储法线。物体空间中的常规可以在整个单位球体上的任何地方,并且通常存储为具有三个组件的向量:X,Y和Z.可以使用常规颜色纹理压缩技术存储对象空间法线贴图,但是这些技术可能不会有效,因为法线贴图不具有与颜色纹理相同的属性。

2.1对象空间DXT1

DXT1 [ 34 ],也被称为在DirectX 10 BC1 [ 5 ],是用于颜色纹理一种有损压缩格式,以8:1的固定压缩比为2:1。DXT1格式设计用于在渲染过程中对显卡硬件进行实时解压缩。DXT1压缩是块截断编码(BTC)[ 6 ]的一种形式,其中图像被划分为非重叠块,并且每个块中的像素被量化为有限数量的值。4×4像素块中的像素的颜色值通过RGB颜色空间在一行上的等距点近似。该行由两个端点定义,对于4x4块中的每个像素,2位索引存储在该行上的一个等距点上。通过颜色空间的线的端点被量化为16位5:6:5 RGB格式,并且通过插值生成一个或两个中间点。DXT1格式允许通过根据终点的顺序切换到不同的模式,其中仅生成一个中间点并指定一个附加颜色,这是黑色和完全透明的。

虽然DXT1格式是为颜色纹理设计的,但此格式也可用于存储法线贴图。为了将法线贴图压缩成DXT1格式,法线向量的X,Y和Z分量映射到颜色纹理的RGB通道。特别是对于DXT1压缩,每个法向量分量从[-1,+1]范围映射到整数范围[0,255]。在光栅化期间,DXT1格式在硬件中解压缩,并且整数范围[0,255]映射到硬件中的浮点范围[0,1]。在片段程序中,范围[0,1]将必须映射回范围[-1,+1]以执行法向量的照明计算。以下片段程序显示了如何使用单个指令实现此转换。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = normal.z 

[0,1]
#input.w = 0
 
MAD正常,输入,2.0,-1.0

将法线贴图压缩成DXT1格式通常会导致质量相当差。有明显的阻塞和条带伪影。每4×4块只能编码四个不同的法向量,这通常不足以准确地表示块中的所有原始法向量。因为每个块中的法线在一行上用等距点近似,所以也不可能对每个4×4块的四个不同的法向量编码都是单位长度。每4x4块只有两个法向量可以一次接近单位长度,通常一个压缩器通过向量空间来选择一个最小化一些误差度量的一条线,使得这些向量实际上不接近单位长度。

右侧的DXT1压缩法线贴图
与左侧的原始法线贴图相比,显示出明显的块状伪影。

为了提高质量,可以将每个法向量编码为不一定是单位长度的方向。然后,该方向必须在片段程序中重新归一化。以下片段程序显示了法向量如何重新归一化。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = normal.z 

[0,1]
#input.w = 0
 
MAD正常,输入,2.0,-1.0
DP3标尺,正常,正常
RSQ scale.x,scale.x
MUL正常,正常,scale.x

编码方向使压缩机更自由,因为压缩机不必担心向量的大小,并且可以通过正常空间将所有可表示向量的大部分百分比用于线路的终点。然而,这种增加的自由使压缩成为一个更难的问题。

DXT1压缩的法线贴图与
右侧的原始法线贴图相比右侧重新归一化。

以上图片显示,尽管质量好一点,质量一般还是比较差。无论是否在片段程序中重新规范化,DXT1压缩对象空间法线贴图的质量一般不被认为是可以接受的。

2.2对象空间DXT5

所述DXT5格式[ 34 ],也被称为在DirectX 10 BC3 [ 5 ],存储三个颜色通道中的相同的方式DXT1确实,但没有1位alpha通道。代替1位alpha通道,DXT5格式存储与DXT1色彩通道相似的单独的Alpha通道。4x4块中的alpha值通过α空间在一行上的等距点近似。通过α空间的线的端点存储为8位值,并且基于端点的顺序,通过插值生成4或6个中间点。对于4个中间点的情况,生成两个附加点,一个完全不透明,另一个用于完全透明。对于4x4块中的每个像素,3位索引通过alpha空间或两个附加点中的一个存储到该行上的等距点之一,用于完全不透明或完全透明。使用相同数量的位来将alpha通道编码为三个DXT1颜色通道。因此,与三维颜色空间相反,α通道以比每个颜色通道更高的精度被存储,因为α空间是一维的。

     此外,总共有8个样本表示4×4块中的α值,而不是4个样本来表示颜色值。由于额外的Alpha通道,DXT5格式消耗DXT1格式的内存量的两倍。使用相同数量的位来将alpha通道编码为三个DXT1颜色通道。因此,与三维颜色空间相反,α通道以比每个颜色通道更高的精度被存储,因为α空间是一维的。

   此外,总共有8个样本表示4×4块中的α值,而不是4个样本来表示颜色值。由于额外的Alpha通道,DXT5格式消耗DXT1格式的内存量的两倍。使用相同数量的位来将alpha通道编码为三个DXT1颜色通道。因此,与三维颜色空间相反,α通道以比每个颜色通道更高的精度被存储,因为α空间是一维的。此外,总共有8个样本表示4×4块中的α值,而不是4个样本来表示颜色值。由于额外的Alpha通道,DXT5格式消耗DXT1格式的内存量的两倍。总共有8个样本来表示4×4块中的α值,而不是4个样本来表示颜色值。由于额外的Alpha通道,DXT5格式消耗DXT1格式的内存量的两倍。总共有8个样本来表示4×4块中的α值,而不是4个样本来表示颜色值。由于额外的Alpha通道,DXT5格式消耗DXT1格式的内存量的两倍。

  DXT5格式设计用于具有平滑alpha通道的颜色纹理。但是,此格式也可用于存储对象空间法线贴图。特别地,可以通过使用DXT5格式并将其中一个组件移动到Alpha通道来实现更好质量的法线贴图压缩。通过将其中一个组件移动到Alpha通道,该组件以更高的精度存储。此外,通过仅对DXT5格式的DXT1块中的两个组件进行编码,这些组件的存储准确度通常也会得到改善。对于对象空间法线图,由于法向量可以指向任何方向,因此所有元素都可以以相似的频率发生,所以没有明确的优点将任何特定的组件移动到alpha通道。

   当对象空间法线贴图在特定方向上确实具有最多的向量时,将与该方向最正交的轴线映射到阿尔法通道显然是一个好处。然而,由于每个编码需要不同的片段程序,所以通常在每个法线贴图上改变编码是不切实际的。以下片段程序假设Z组件移动到alpha通道。片段程序显示了组件如何从范围[0,1]映射到范围[-1,+1],而Z组件也从alpha通道移回原位。因为每个编码都需要一个不同的片段程序。以下片段程序假设Z组件移动到alpha通道。片段程序显示了组件如何从范围[0,1]映射到范围[-1,+1],而Z组件也从alpha通道移回原位。因为每个编码都需要一个不同的片段程序。以下片段程序假设Z组件移动到alpha通道。片段程序显示了组件如何从范围[0,1]映射到范围[-1,+1],而Z组件也从alpha通道移回原位。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = 0
#input.w = normal.z 

[0,1]
 
MAD normal,input.xywz,2.0,-1.0

就像DXT1一样,没有重新规范化,这种格式导致片段程序中的最小开销。质量明显优于对象空间法向贴图的DXT1压缩。然而,仍然存在明显的阻塞和条纹伪像。

右侧的DXT5压缩法线贴图
与左侧原始法线贴图相比较。

使用第三个通道来存储比如从[ 24 ] 的YCoCg-DXT5压缩完成的比例因子并不能提高质量。单个组件的动态范围通常太大,或者不同的组件跨越不同的范围,而组合的动态范围只有一个比例因子。

就像对象空间法线图的DXT1压缩一样,通过将法向量编码为不一定是单位长度的方向,可以提高质量。以下片段程序显示如何执行swizzle和重新归一化。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = 0
#input.w = normal.z 

[0,1]
 
MAD normal,input.xywz,2.0,-1.0
DP3标尺,正常,正常
RSQ scale.x,scale.x
MUL正常,正常,scale.x

编码方向给予压缩机更多的自由度,因为压缩器可以忽略向量的大小,并且可以通过正常空间将所有可表示向量的更大百分比用于线的端点。使用DXT5格式的DXT1块和alpha通道对法线矢量进行编码,其中Alpha通道的端点不存储量化。因此,线的端点的潜在搜索空间可能非常大,并且高质量压缩可能需要相当长的时间。

DXT5压缩的法线贴图与
右侧的原始法线贴图相比右侧重新归一化。

在当前硬件上,片段程序中重新归一化的DXT5格式导致对象空间法线贴图的最佳质量压缩。

切线 - 空间正常图

切线空间法向量相对于三角形顶点的内插切线空间存储。因为动态范围较低,切线空间法线贴图的压缩通常比对象空间法线贴图的效果更好。向量只在表面前面的单位半球(法向量从不指向对象)。此外,大多数正常向量接近单位半球的尖端,Z接近1。

与使用对象空间法线图相比,使用切线空间法线贴图本身可以被认为是一种压缩形式。使用局部变换来改变矢量分量的频域,从而降低其存储要求。该变换确实需要将切向量存储在三角形顶点处,并且因此成本。然而,与正常地图的存储要求相比,切线向量的存储要求相对较小。

通过仅存储单位长度法向量的X和Y分量以及导出Z分量,可以改善切线空间法线贴图的压缩。法向量总是向上指向表面,Z总是为正。此外,法向量是单位长度,因此,可以如下导出Z。

Z = sqrt(1-X * X-Y * Y)

从X和Y重建Z的问题是它是一个非线性运算,并在双线性滤波下分解。当在XY平面中的两个法线之间进行插值时,这个问题最为显着。理想地,使用法向量的球面插值来放大法线贴图,其中内插样本以恒定速度跟随单位球体上的最短大弧。三分法法线图的双线性滤波,在片段程序中进行重新归一化,不会以恒定速度产生球面插值,但至少内插样本遵循最短的大弧。然而,使用双分量法线贴图,其中Z从X和Y导出,内插样本不再必须跟随单位球上的最短大弧。例如,预计下图中两个向量之间的插值将跟随虚线。然而,相反,内插样本在单位球上上升的弧上。

幸运的是,现实世界的正常地图通常与邻近XY平面的邻近矢量不具有很多尖锐的正常边界,大多数法线指向直线。因此,在导出Z分量之前,双线性或三线性过滤双分量法线图时通常不会有明显的伪影。

仅存储X和Y分量本质上是沿Z轴的法向量向XY平面的正投影。为了重构原始法向量,通过从X和Y中导出Z分量,可以使用返回到单位半球的投影。代替该正投影,也可以使用立体投影。对于立体投影,X和Y分量如下划分一个加Z,其中(pX,pY)是法向量的投影。

pX = X /(1 + Z)
pY = Y /(1 + Z)

通过将立体投影向量投影到单位半球上来重建原始法向量,如下。

denom = 2 /(1 + pX * pX + pY * pY)
X = pX * denom
Y = pY * denom
Z = denom  -  1

使用立体投影的优点是内插法线矢量在双线性或三线性滤波下表现更好。内插的法向量仍然不在最短的大弧上,但是它们更接近,并且在单位半球上具有更少的上升趋势。

立体投影还导致pX和pY分量的更均匀分布与单位半球上的角度。虽然这似乎是可取的,但实际上并不是这样,因为大多数正切空间的法向量靠近单位半球的尖端。因此,使用正交投影实际上有一个优点,其导致Z接近1的向量的更多表示。下面讨论的压缩技术使用正投影,因为对于大多数正常映射,其导致更好的质量压缩。

3.1切线空间DXT1

使用正切空间法线图,只有X和Y分量必须以DXT1格式存储,Z分量可以在片段程序中导出。以下片段程序显示如何从X和Y派生Z。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = 0
#input.w = 0
 
MAD正常,输入,2.0,-1.0
DP4_SAT normal.z,正常,正常;
MAD正常,正常,{1,1,-1,0},{0,0,1,0};
RSQ temp,normal.z;
MUL normal.z,temp;

以下图像显示右侧的XY_ DXT1压缩法线贴图,位于左侧原始法线贴图旁边。DXT1压缩的法线贴图显示明显的阻塞和条纹伪影。

XY_ DXT1压缩的法线贴图
与左侧原始法线贴图相比较。

尽管起初似乎这种压缩应该产生优质的质量,但通常可以通过存储所有三个组件并在片段程序中重新归一化来实现更好的质量压缩,就像对象空间法线图一样。当只有X和Y分量以DXT1格式存储时,通过导出Z分量来自动归一化重构法线矢量。当X和Y分量由于DXT1压缩而失真,其中所有点通过XY空间放置在直线上时,导出的Z中的误差可能相当大。

下面显示的用于重新归一化DXT1压缩法线的片段程序与用于具有重新归一化的DXT1压缩对象空间法线贴图相同。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = normal.z 

[0,1]
#input.w = 0
 
MAD正常,输入,2.0,-1.0
DP3标尺,正常,正常
RSQ scale.x,scale.x
MUL正常,正常,scale.x

以下图像显示了右侧重新归一化的DXT1压缩法线贴图,在左侧的原始法线贴图旁边。

DXT1压缩的法线贴图与
右边的正规化法相比,左边是原来的法线贴图。

无论哪种方式,无论是在DXT1中存储两个组件并导出Z,还是将DXT1格式中的所有三个组件存储在片段程序中的重新归一化,质量相当差。

3.2切线空间DXT5

就像对象空间法线图一样,所有三个组件都可以以DXT5格式存储。通常在存储_YZX数据时可以获得最佳结果。换句话说,X分量被移动到alpha通道。这种技术也被称为RxGB压缩,并被用于电脑游戏DOOM III。通过将X分量移动到alpha通道,X和Y分量被分别编码。这提高了质量,因为X和Y组件在最大动态范围内最独立。Z始终为正,通常接近1,因此,将Z分量与Y分量存储在DXT5格式的DXT1部分中会导致Y分量几乎不失真。存储所有三个组件会导致片段程序中的最小开销,如下所示。

#input.x = 0
#input.y = normal.y 

[0,1]
#input.z = normal.z 

[0,1]
#input.w = normal.x 

[0,1]
 
MAD normal,input.wyzx,2.0,-1.0

以下图像显示,虽然质量优于DXT1压缩,但仍然有明显的条带伪像。

右侧的DXT5压缩法线贴图
与左侧原始法线贴图相比较。

就像对象空间法线图一样,可以通过存储不一定是单位长度的方向来改善质量。通过将X组件移动到DXT5 alpha通道也可以实现最佳质量。以下片段程序显示了如何在将X组件从alpha通道移回到原位后如何重新归一化方向。

#input.x = normal.x 

[0,1]
#input.y = normal.y 

[0,1]
#input.z = 0
#input.w = normal.z 

[0,1]
 
MAD normal,input.wyzx,2.0,-1.0
DP3标尺,正常,正常
RSQ scale.x,scale.x
MUL正常,正常,scale.x

以下图像显示,在片段程序中具有重新归一化的编码方向减少了带状伪像,但是它们仍然非常显着。

DXT5压缩的法线贴图与
右侧的原始法线贴图相比右侧重新归一化。

对于大多数正切空间的法线贴图,仅通过将X和Y组件存储在DXT5格式中并获得Z即可实现更好的质量压缩。这也称为DXT5nm压缩,并且在当今的电脑游戏中是最受欢迎的。以下片段程序显示了Z是如何从X和Y组件导出的。

#input.x = 0
#input.y = normal.y 

[0,1]
#input.z = 0
#input.w = normal.x 

[0,1]
 
MAD normal,input.wyzx,2.0,-1.0
DP4_SAT normal.z,正常,正常;
MAD正常,正常,{1,1,-1,0},{0,0,1,0};
RSQ temp,normal.z;
MUL normal.z,temp;

以下图像显示仅存储X和Y并导出Z,进一步减少了带状伪像。

DXT5压缩的法线贴图只在
右边的X和Y 与左边原来的法线贴图相比较。

当使用XY_ DXT1,_YZX DXT5或_Y_X DXT5压缩用于切线空间法线贴图时,至少有一个可用于存储比例因子的备用通道,可用于对抗与YCoCg-DXT5类似的量化误差压缩机从[ 24 ]。然而,尝试升级组件以对抗量化误差不会提高质量(通常PSNR改善小于0.1 dB)。组件只有在动态范围较小时才能进行放大。虽然大多数法线指向直线,并且大多数XY向量的幅度相对较小,但XY分量的动态范围实际上仍然相当大。即使所有的法线都不会从直线偏离45度以上,那么每个X或Y分量仍然可以映射到范围[-cos(45°)+ + cos(45°)],其中cos(45°)≅0.707。换句话说,即使是从直线向下偏离小于45度的角度范围的50%,每个部件仍然可以覆盖超过最大动态范围的70%。一方面,这是一件好事,因为对于正切空间法向量的分量,这意味着动态范围的最大部分涵盖最常发生的值。另一方面,这意味着由于动态范围相对较大而难以升级组件。因为对于正切空间法向矢量的分量,这意味着动态范围的最大部分涵盖最常发生的值。另一方面,这意味着由于动态范围相对较大而难以升级组件。因为对于正切空间法向矢量的分量,这意味着动态范围的最大部分涵盖最常发生的值。另一方面,这意味着由于动态范围相对较大而难以升级组件。

在_Y_X DXT5压缩切线空间法线图的情况下,有两个未使用的通道,其中一个通道也可用于存储偏置以使动态范围居中。这显着增加了4x4块的数量,可以对这些块进行放大(通常,所有4x4块中的75%以上的块通常使用至少为2的比例因子)。然而,即使使用偏差来增加缩放的4×4块的数量对提高质量没有太大的帮助。真正的问题是DXT1块的四个采样点根本不足以准确地表示4x4块中法线的所有Y分量。引入更多的采样点将显着提高质量,但这在DXT5格式中显然是不可能的。

代替存储偏差和比例,备用信道之一,也可用于存储正常矢量的旋转在绕Z轴的4×4块,如[建议的1112 ]。可以使用这样的旋转来找到XY向量的更紧密的边界框。特别是使用_Y_X DXT5压缩这样的旋转可以用来确保具有最大动态范围的轴映射到阿尔法通道,这样被更精确地压缩。为了能够将具有最大动态范围的轴映射到Alpha通道,可能需要高达180度的旋转。该旋转可以作为5位通道之一中的整个4x4块的常数值存储。代替存储旋转角度,可以存储角度的余弦,使得余弦不必在片段程序中计算,其中矢量需要旋转回其原始位置。在[0,180]度范围内进行旋转的正弦值总是为正值,因此可以如下从片段程序中的余弦中导出。

正弦= sqrt(1  - 余弦*余弦)

在4×4块中旋转法线的PSNR改善是显着的,通常在2至3dB的范围内。不幸的是,相邻的4×4块可能需要非常不同的旋转,并且在双线性或三线性滤波下,对于具有不同旋转的两个4×4块之间的边界处的滤波纹迹样本,可能出现可见的伪像。在旋转施加到X和Y分量之前,分别对X,Y和旋转进行过滤。这样,滤波的旋转被施加到经过滤的X和Y分量,其与首先旋转回其原始位置的滤波X和Y分量不同。换句话说,除非法线贴图只是点采样,使用旋转也不是提高DXT1或DXT5法线贴图质量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值