【问题标题】:Why do we need texture filtering in OpenGL?为什么我们需要在 OpenGL 中进行纹理过滤?
【发布时间】:2020-02-21 07:44:15
【问题描述】:

在将纹理映射到几何体时,我们可以在GL_NEARESTGL_LINEAR 之间选择过滤方法。

the examples 中,我们有一个被纹素包围的纹理坐标,如下所示:

并解释了每种算法如何选择片段的颜色,例如根据与纹理坐标的距离线性插值所有相邻的纹素。

每个纹理坐标本质上不是映射到屏幕上的像素的片段位置吗?那么这些坐标是如何小于本质上是像素并且与片段大小相同的纹素呢?

【问题讨论】:

  • 一般 3D 屏幕像素不会映射到单个测试的像素 - 透视图甚至会扭曲平面。或者想象一下球体。所以屏幕像素不会恰好命中一个纹素,您需要一种方法在具有分数坐标的纹理上的某个点产生一些颜色,因此需要进行过滤。

标签: opengl textures fragment-shader texture-mapping


【解决方案1】:

可以将(2D)纹理视为函数t(u, v),其输出是“颜色”值。这是一个纯函数,因此对于相同的 uv 值,它将返回相同的值。该值来自存储在内存中的查找表,由uv 索引,而不是通过某种计算。

纹理“映射”是将表面上的特定位置与纹理空间中的特定位置相关联的过程。也就是说,您将表面位置“映射”到纹理中的位置。因此,纹理函数t 的输入通常称为“纹理坐标”。一些表面位置可能映射到纹理上的相同位置,而一些纹理位置可能没有映射到它们的表面位置。这一切都取决于映射

实际的纹理图像不是平滑函数;它是一个离散函数。它在纹素位置 (0, 0) 处有一个值,在 (1, 0) 处有另一个值,但在 (0.5, 0) 处的纹理值是未定义的。在图像空间中,uv 是整数。

您的纹理部分放大图片不正确。纹素“之间”没有,因为“纹素之间”是不可能的。整数行上没有介于 0 和 1 之间的数字。

但是,从表面到纹理函数的任何有用映射都需要在连续空间中进行,而不是在离散空间中进行。毕竟,每个片段都不太可能精确地落在映射到纹理中精确整数的位置上。毕竟,尤其是在基于着色器的渲染中,着色器可以发明任意映射。 “映射”可以基于光的方向(投影纹理)、片段相对于某个表面的高度,或者用户可能想要的任何东西。对于片段着色器来说,纹理只是一个函数t(u, v),可以对其求值以产生一个值。

所以我们真的希望该函数处于连续空间中。

过滤的目的是通过在离散纹素之间发明值来创建连续函数t。这允许您声明 uv 是浮点值,而不是整数。我们还可以对纹理坐标进行归一化,这样它们就在 [0, 1] 范围内,而不是基于纹理的大小。

【讨论】:

    【解决方案2】:

    纹理过滤不决定片段应该是什么颜色。这就是片段着色器所做的。但是,片段着色器可能会在给定位置对纹理进行采样以获得颜色。它可以直接返回该颜色,也可以对其进行处理(例如添加阴影等)

    纹理过滤发生在采样时。纹理坐标不一定是完美的像素位置。例如,纹理可以是您在透视图中显示的 3D 模型的材质。那么一个片段可能覆盖多个纹理像素,也可能覆盖更少。或者它可能没有与纹理网格对齐。在所有情况下,您都需要某种过滤。

    对于以原始大小呈现精灵而没有任何变形的应用程序,通常不需要过滤,因为屏幕像素到纹素的映射是 1:1。

    【讨论】:

      猜你喜欢
      • 2016-09-17
      • 2015-10-10
      • 1970-01-01
      • 2012-09-09
      • 2019-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      相关资源
      最近更新 更多