我的问题是针对金属的,因为我不知道答案是否会针对其他API改变。

到目前为止,我相信我的理解是:


mipmapped纹理已预先计算了“细节级别”,其中通过以某种有意义的方式对原始纹理进行下采样来创建较低的细节级别。
Mipmap级别以细节级别递减表示,其中级别0
大多数GPU实现三线性过滤,即为每个样本选择两个相邻的mipmap级别,使用双线性过滤从每个级别中采样,然后进行线性处理混合这些样本。

我不太了解的是如何选择这些mipmap级别。在Metal标准库的文档中,我看到可以采样,无论是否指定lod_options类型的实例。我假设该参数会更改mipmap级别的选择方式,显然2D纹理有三种lod_options


bias(float value)
level(float lod)
gradient2d(float2 dPdx, float2 dPdy)

不幸的是,文档没有费心地解释这些选项的作用。我可以猜测到bias()会偏向某些自动选择的细节级别,但是偏见value是什么意思呢?它的运作规模是多少?同样,lodlevel()如何转换为离散的mipmap级别?并且,在假设gradient2d()使用纹理坐标的渐变的情况下进行操作,如何使用该渐变选择mipmap级别?

更重要的是,如果我省略lod_options,mipmap级别如何然后选择?这取决于执行的函数类型吗?

而且,如果sample()函数的默认no-lod-options指定的操作是执行gradient2D()之类的操作(至少在片段着色器中),它是利用简单的屏幕空间导数还是直接与光栅化器和插值一起工作纹理坐标来计算精确的梯度?

最后,设备与设备之间这种行为的一致性如何?我读了一篇老文章(在DirectX 9中是古老的文章),其中提到了复杂的设备特定的mipmap选择,但是我不知道在新的体系结构上是否可以更好地定义mipmap选择。

#1 楼

如今,跨设备的Mip选择已经非常标准化了-各向异性过滤的一些实质性细节除外,这仍然需要各个GPU制造商来定义(其确切细节通常不会公开记录)。

在OpenGL规范的第8.14节“纹理最小化”中可以详细了解有关Mip选择的好地方。我认为它在Metal中的工作方式相同。 (考虑到它们可以同时制造硬件和API,Apple可能已经进行了某些更改。但是我怀疑它们已经做到了。)我将在此处进行总结。

默认的mip选择(不使用任何lod_options修改器)使用纹理坐标的屏幕空间渐变来选择Mip级别。从本质上讲,它会尝试选择产生尽可能接近纹理像素与像素的1:1映射的mip级别。例如,如果渐变每个像素的长度为4像素,它将选择2级的Mip(级别0大小的1/4,因此每个像素为1个贴图像素)。 >使用三线性过滤时,由于通常不会精确地按1:1映射,因此它会选择两个最接近的级别并在它们之间进行线性插值,因此您可以在摄影机或场景中的对象之间的mip级别之间进行平滑过渡四处走动。

从数学上讲是精确的:取纹理坐标的屏幕空间渐变,按纹理大小缩放比例(以“像素像素像素”为单位),取其长度,取两者中的较长者(X和Y)梯度,并计算其对数底数2。在OpenGL规范中,此数量称为$ \ lambda $;它通常也称为纹理LOD(细节级别)。它只是整数mip级别索引的连续版本。因此,使用的mip级别是最接近$ \ lambda $的两个整数,并且使用$ \ lambda $的小数部分进行混合。例如,如果$ \ lambda = 2.8 $,GPU将采样纹理的2级和3级,然后混合到3%的80%和2级的20%。

如果启用了各向异性过滤,而不是简单地使用两个梯度中的较长者,而是使用它们的比率来设置各向异性样品的数量。例如,如果X梯度比Y梯度长4倍,则将使用4个aniso样本,它们的位置沿X梯度隔开。每个将是一个三线性样本,使用一个$ \ lambda $,它对应于X梯度的长度的1/4(即,降低两个mip级别,因为$ \ log_2(1/4)= -2 $)。 >
现在,关于修改器选项:



bias在使用$ m来选择mip级别之前,对$ \ lambda $应用偏移量。因此,例如,偏差+1将使其使用比通常高一级的mips进行三线性滤波。偏置-1将使mips降低一级,依此类推。

level完全覆盖了根据屏幕空间渐变自动计算$ \ lambda $的能力,并允许您输入自己的值$ \ lambda $(aka lod)直接。

gradient2d允许您输入自己的渐变矢量,该渐变矢量替代纹理坐标的隐式屏幕空间渐变。其余的mip选择和采样过程将正常进行,但梯度会发生变化。这使您可以自定义各向异性过滤。

在除片段着色器之外的其他类型的着色器中,没有“屏幕空间渐变”的概念,因此后两个操作通常是唯一允许的操作-尝试使用隐式渐变会产生编译错误。我不太肯定Metal是如何做到的,但这是我与其他API一起使用的期望。