简单来说,textureGrad()是什么?

时间:2018-10-24 18:37:50

标签: opengl graphics glsl

我在此阅读了khronos wiki

但是我不明白它在说什么。 TextureGrad到底做什么?

我认为它对多个mipmap级别进行采样,并使用为其提供的显式导数向量来计算一些颜色混合。但是我不确定。

1 个答案:

答案 0 :(得分:3)

对纹理进行采样时,需要特定的纹理坐标来对纹理数据进行采样。为了简单起见,我将假设一个2D纹理,因此纹理坐标是2D向量(s,t)。 (解释与其他维度类似)。

如果要对三角形进行纹理映射,通常使用两种策略之一来获取纹理坐标:

  1. 纹理坐标是模型的一部分。每个顶点都包含2D纹理坐标作为顶点属性。在栅格化过程中,这些纹理坐标将在图元上进行插值。
  2. 您指定一个数学映射。例如,您可以定义一些将3D对象坐标映射到某些2D纹理坐标的函数。例如,您可以定义一些投影,然后将纹理投影到表面上,就像真实的投影仪将图像投影到某些真实对象上一样。

无论哪种情况,光栅化时生成的每个片段通常都具有不同的纹理坐标,因此屏幕上的每个绘制像素将获得纹理的不同部分。

关键是:每个片段都具有2D像素坐标(x,y)和2D纹理坐标(s,t),因此我们基本上可以将此关系解释为数学函数:

(s,t) = T(x,y)

由于这是2D像素位置向量(x,y)中的向量函数,因此我们还可以沿x方向(向右)和y方向(向上)构建偏导数),告诉他们沿这些方向使用纹理坐标的变化率

dTdx中的dTdytextureGrad就是这样。

那GPU需要做什么呢?

当您要实际过滤纹理时(与简单的点采样相比),您需要了解纹理空间中的 pixel footrpint 。每个单个片段代表屏幕上一个像素的面积,您将使用纹理中的单个颜色值来代表整个像素(撇开多重采样)。像素覆盖区现在表示像素在纹理空间中的实际尺寸。我们可以通过不是针对像素中心而是针对4个像素角插值texcoords来计算它。生成的texcoords将在纹理空间中形成梯形。

当您最小化纹理时,几个纹理像素被映射到同一像素(因此,像素空间在纹理空间中很大)。放大时,每个像素将仅代表相应纹理像素的一小部分(因此占用空间很小)。

纹理足迹告诉您:

  • 如果纹理被缩小或放大(GL在每种情况下具有不同的滤镜设置)
  • 每个像素将映射多少个纹理像素,所以哪个mipmap级别合适
  • 像素覆盖区中有多少各向异性。屏幕上的每个像素和纹理空间中的每个纹理像素基本上是一个正方形,但是像素覆盖区可能会明显偏离正方形,并且可能比宽度或过渡距离高得多(尤其是在透视失真较大的情况下)。经典的双线性或三线性纹理滤镜始终使用正方形滤镜足迹,但各向异性纹理滤镜将使用此信息来 实际上会生成一个与足迹像素足迹更匹配的过滤器足迹(以避免混入不应真正属于像素的texel数据)。

我们将使用片段中心的偏导数作为像素足迹的近似值,而不是计算所有像素角的纹理坐标。

下图显示了几何关系:

diagram of pixel footprint in texture space

这表示纹理空间中四个相邻像素(2x2)的足迹,因此均匀网格为纹理像素,而四个梯形则代表4个像素足迹。 现在计算实际导数将意味着我们具有如上所述的或多或少的显式公式T(x,y)。 GPU通常使用另一种近似值: 只需查看每个2x2像素块中相邻片段的实际texcoords(无论如何将要计算),然后通过有限差分来近似估算占位面积-只需减去相邻像素的实际texcoords彼此的碎片。 结果显示为图中的平行四边形。

在硬件中,这已实现为始终在同一扭曲/波前/ SIMD-Group中并行阴影2x2像素四边形。 GLSL derivative functions like dFdx and dFdy只需减去相邻片段的实际值即可工作。标准的texture函数仅在内部对纹理坐标参数使用此机制。 textureGrad函数绕过了这一点,并允许您指定自己的值,这意味着您可以控制GPU在进行实际的过滤/ mipmap级别选择时所采用的像素尺寸。