GL_LINEAR具体使用什么算法?

What algorithm does GL_LINEAR use exactly?

refpages 说 "Returns the weighted average of the four texture elements that are closest to the specified texture coordinates." 它们的权重究竟是多少?那么 3D 纹理呢,它是否仍然只使用 4 个纹素进行插值或更多?

2D纹理中使用了4个样本,这意味着双线性插值所以3x 线性插值.权重是目标纹素与其 4 个邻居的归一化距离。

所以例如你想要

处的纹素
(s,t)=(0.21,0.32)

但是纹素附近的纹理有坐标:

(s0,t0)=(0.20,0.30)
(s0,t1)=(0.20,0.35) 
(s1,t0)=(0.25,0.30) 
(s1,t1)=(0.25,0.35)

权重是:

ws = (s-s0)/(s1-s0) = 0.2
wt = (t-t0)/(t1-t0) = 0.4

所以在 s 方向

线性插值文本元素
c0 = texture(s0,t0) + (texture(s1,t0)-texture(s0,t0))*ws
c1 = texture(s0,t1) + (texture(s1,t1)-texture(s0,t1))*ws

最后 t 方向:

c = c0 + (c1-c0)*wt

其中 texture(s,t) returns 纹理颜色在 s,t 而坐标对应于精确的纹理并且 c 是最终的插值纹理颜色。

实际上,s,t 坐标乘以纹理分辨率 (xs,ys),将它们转换为纹素单位。在那之后 s-s0t-t0 已经归一化,所以不需要除以 s1-s0t1-t0 因为它们等于一。所以:

s=s*xs; s0=floor(s); s1=s0+1; ws=s-s0;
t=t*ys; t0=floor(t); t1=t0+1; wt=t-t0;
c0 = texture(s0,t0) + (texture(s1,t0)-texture(s0,t0))*ws;
c1 = texture(s0,t1) + (texture(s1,t1)-texture(s0,t1))*ws;
c = c0 + (c1-c0)*wt;

我以前从未使用过3D 纹理,但在这种情况下它使用了 8 个文本元素,它被称为 三线性插值,即 2x 双线性插值 只需取 2 个最近的纹理并使用 双线性插值 计算每个纹理,然后根据基于u 以完全相同的方式坐标...所以

u=u*zs; u0=floor(u); u1=u0+1; wu=u-u0;
c = cu0 + (cu1-cu0)*wu;

其中 zs 是纹理的数量,cu0 双线性插值 u0 和 [=32] 处的纹理的结果=] 在 u1。同样的原则也适用于 mipmaps...

所有坐标可能都偏移了 0.5 纹素,并且根据您的钳位设置,分辨率倍增可以用 xs-1 而不是 xs 来完成...

除了 Spektre 的回答中概述的双线性插值外,您还应该了解 GL_LINEAR 插值的 精度。许多 GPU(例如 Nvidia、AMD)使用定点算法进行插值,纹理中的 R、G、B、A 值之间只有约 255 个不同的值。

例如,这里是显示 GPU 如何进行插值的伪代码:

float interpolate_red(float red0, float red1, float f) {
    int g = (int)(f*256)
    return (red0*(256-g) + red1*g)/256;
}

如果您的纹理用于着色并包含 GL_UNSIGNED_BYTE 值,那么它可能适合您。但是,如果您的纹理是用于某些其他计算的查找 table 并且它包含 GL_UNSIGNED_SHORT 或 GL_FLOAT 值,那么这种精度损失对您来说可能是个问题。在这种情况下,您应该使用(浮点)或(双)精度计算的中间值使查找 table 更大。