为什么使用双线性过滤放大/放大边框纹理时,它们会得到相同的颜色?

时间:2018-07-08 03:38:47

标签: opengl shader

与双线性过滤一样,采样颜色是基于4个最接近纹理像素的加权平均值计算的,那么为什么角纹理像素在放大时会得到相同的颜色?

例如:

在这种情况下(下图),当将3x3图像放大/缩放为5x5像素图像(使用双线性过滤)时,“红色”像素的角也获得完全相同的颜色,而“绿色”边框也完全相同?

3x3 pixel to 5x5 pixel scaling

在某些文档中,说明了角纹理像素以相同的颜色扩展以提供4个相邻的纹理像素,这解释了为什么“红色”纹理像素在5x5图像中获得相同的颜色,但是边框“绿色”纹理像素如何得到相同的颜色(如果是根据4个最接近的纹理像素的加权平均值计算的话)

2 个答案:

答案 0 :(得分:4)

在使用双线性纹理采样时,纹理中的纹理像素不会被视为彩色正方形,而是被视为连续色域的样本。这是红绿色棋盘格的此字段,其中概述了纹理边框:

Continuous Color Field

圆圈代表纹理像素,即纹理的样本位置。样本之间的颜色通过双线性插值计算。作为一种特殊情况,两个相邻纹理像素之间的插值是简单的线性插值。当x01之间时,则:color = (1 - x) * leftColor + x * rightColor

插值方案仅定义在样本之间的区域中发生的事情,即,甚至不到达纹理的边缘。 OpenGL用于确定缺失区域的是纹理或采样器的环绕模式。如果使用GL_CLAMP_TO_EDGE,将像上面的示例一样重复从边缘开始的纹素值。这样,我们就为任意纹理坐标定义了颜色字段。

现在,当我们渲染5x5图像时,将在像素中心评估片段的颜色。如下图所示,其中片段评估位置用黑点标记:

Fragment Evaluation Positions

假设您绘制的全屏四边形具有0到1的纹理坐标,则片段评估位置处的纹理坐标是顶点纹理坐标的插值。现在,我们可以将片段之前的色域覆盖起来,我们将找到双线性采样器产生的颜色:

Color Field and Fragment Positions

我们可以看到几件事:

  1. 中央片段与红色纹理像素完全重合,因此获得完美的红色。
  2. 边缘上的中央片段恰好落在两个绿色样本之间(其中一个样本是纹理外部的虚拟样本)。因此,它们获得了完美的绿色。这是由于换行模式。其他包装模式会产生不同的颜色。则插值为:color = (1 - t) * outsideColor + t * insideColor,其中t = 3 * (0.5 / 5 + 0.5 / 3) = 0.8是插值参数。
  3. 角部片段也是来自四种纹理颜色的插值(纹理中有1种真实纹理,外部有3种虚拟外观)。同样,由于环绕模式,这些将获得完美的红色。
  4. 所有其他颜色都是红色和绿色的某种插值。

答案 1 :(得分:2)

您正在错误地查看双线性插值。将其视为从目标像素位置到源像素位置的映射。因此,对于每个目标像素,都有一个与之相对应的源坐标。源坐标决定了4个相邻像素以及分配给它们的双线性权重。

让我们用左上角的(0,0)为像素编号。

目标图像中的像素(0,0)映射到源图像中的坐标(0,0)。源图像中的四个相邻像素为(0,0),(1、0),(0,1)和(1,1)。我们通过简单的数学计算双线性权重:特定像素在X方向上的权重为1 - (pixel.x - source.x),其中source是源坐标。 Y也是如此。因此,四个相邻像素中的每个像素的双线性权重分别为(分别为上述顺序):( 1,1),(0,0),(0,0)和(0,0)。

简而言之,因为目标像素精确地映射到了源像素,所以它精确地获得了源像素的值。这是应该的。