GL_LINEAR使用什么算法?

时间:2017-04-18 21:20:20

标签: opengl textures linear-interpolation

refpages说"返回最接近指定纹理坐标的四个纹理元素的加权平均值。"它们究竟是如何加权的?那3D纹理呢,它仍然只使用4个纹素进行插值或更多?

2 个答案:

答案 0 :(得分:1)

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)返回s,t处的texel颜色,而坐标对应于精确的纹素,c是最终的插值纹素颜色。

实际上,s,t坐标乘以纹理分辨率(xs,ys),将其转换为纹素单位。之后s-s0t-t0已经标准化,因此无需除以s1-s0t1-t0,因为它们的展位等于1。这样:

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个textels,它被称为三线性插值,它是2x 双线性插值< / strong>简单地采用2个最近的纹理,并使用双线性插值计算每个纹理,然后通过基于u坐标的线性插值以完全相同的方式计算最终纹素...所以

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

其中zs是纹理数量,cu0是<{1}}纹理中双线性插值的结果,而u0cu1的结果1}}。同样的原则也适用于 mipmap ...

所有坐标可能已被0.5纹素格式化,并且根据您的钳位设置,分辨率乘法可以使用u1代替xs-1 ...

答案 1 :(得分:0)

除了在 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 值,那么它可能适合您。但是,如果您的纹理是用于其他计算的查找表,并且它包含 GL_UNSIGNED_SHORT 或 GL_FLOAT 值,那么这种精度损失对您来说可能是个问题。在这种情况下,您应该使用 (float) 或 (double) 精度计算的中间值使查找表更大。