Reputation: 10103
The refpages say "Returns the weighted average of the four texture elements that are closest to the specified texture coordinates." How exactly are they weighted? And what about 3D textures, does it still only use 4 texels for interpolation or more?
Upvotes: 6
Views: 1672
Reputation: 1690
As well as the bilinear interpolation outlined in Spektre's answer, you should be aware of the precision of GL_LINEAR interpolation. Many GPUs (e.g. Nvidia, AMD) do the interpolation using fixed point arithmetic with only ~255 distinct values between the R,G,B,A values in the texture.
For example, here is pseudo code showing how GPUs might do the interpolation:
float interpolate_red(float red0, float red1, float f) {
int g = (int)(f*256)
return (red0*(256-g) + red1*g)/256;
}
If your texture is for coloring and contains GL_UNSIGNED_BYTE values then it is probably OK for you. But if your texture is a lookup table for some other calculation and it contains GL_UNSIGNED_SHORT or GL_FLOAT values then this loss of precision could be a problem for you. In which case you should make your lookup table bigger with in-between values calculated with (float) or (double) precision.
Upvotes: 1
Reputation: 51873
in 2D textures are 4 samples used which means bi-linear interpolation so 3x linear interpolation. The weight is the normalized distance of target texel to its 4 neighbors.
So for example you want the texel at
(s,t)=(0.21,0.32)
but the texture nearby texels has coordinates:
(s0,t0)=(0.20,0.30)
(s0,t1)=(0.20,0.35)
(s1,t0)=(0.25,0.30)
(s1,t1)=(0.25,0.35)
the weights are:
ws = (s-s0)/(s1-s0) = 0.2
wt = (t-t0)/(t1-t0) = 0.4
so linear interpolate textels at s
direction
c0 = texture(s0,t0) + (texture(s1,t0)-texture(s0,t0))*ws
c1 = texture(s0,t1) + (texture(s1,t1)-texture(s0,t1))*ws
and finally in t
direction:
c = c0 + (c1-c0)*wt
where texture(s,t)
returns texel color at s,t
while the coordinate corresponds to exact texel and c
is the final interpolated texel color.
In reality the s,t
coordinates are multiplied by the texture resolution (xs,ys
) which converts them to texel units. after that s-s0
and t-t0
is already normalized so no need to divide by s1-s0
and t1-t0
as they are booth equal to one. so:
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;
I never used 3D textures before but in such case it use 8 textels and it is called tri-linear interpolation which is 2x bi-linear interpolation simply take 2 nearest textures and compute each with bi-linear interpolation and the just compute the final texel by linear interpolation based on the u
coordinate in the exact same way ... so
u=u*zs; u0=floor(u); u1=u0+1; wu=u-u0;
c = cu0 + (cu1-cu0)*wu;
where zs
is count of textures, cu0
is result of bi-linear interpolation in texture at u0
and cu1
at u1
. This same principle is used also for mipmaps...
All the coordinates may have been offseted by 0.5 texel and also the resolution multiplication can be done with xs-1
instead of xs
based on your clamp settings ...
Upvotes: 3