您可以通过假装从放大后的纹理中采样 4 纹理邻域,而实际上从原始纹理中采样它们来实现“2 倍最近邻放大后线性采样”的效果。然后你必须手动实现双线性插值。如果您的目标是 OpenGL 4+,textureGather() 会很有用,但请牢记this issue。在下面我提出的解决方案中,我将使用 4 个texelFetch() 调用,而不是textureGather(),因为textureGather() 会使事情变得相当复杂。
假设您有一个未缩放的纹理,其字形周围已经存在黑色边框。假设您在该纹理中有一个标准化的纹理坐标 vec2 pn = ...,其中 pn.x 和 pn.y 介于 0 和 1 之间。下面的代码应该可以达到预期的效果,尽管我还没有测试过:
ivec2 origTexSize = textureSize(sampler, 0);
int upscaleFactor = 2;
// Floating point texel coordinate into the upscaled texture.
vec2 ptu = pn * vec2(origTexSize * upscaleFactor);
// Decompose "ptu - 0.5" into the integer and fractional parts.
vec2 ptuf;
vec2 ptui = modf(ptu - 0.5, ptuf);
// Integer texel coordinates into the upscaled texture.
ivec2 ptu00 = ivec2(ptui);
ivec2 ptu01 = ptu00 + ivec2(0, 1);
ivec2 ptu10 = ptu00 + ivec2(1, 0);
ivec2 ptu11 = ptu00 + ivec2(1, 1);
// Integer texel coordinates into the original texture.
ivec2 pt00 = clamp(ptu00 / upscaleFactor, ivec2(0), origTexSize - 1);
ivec2 pt01 = clamp(ptu01 / upscaleFactor, ivec2(0), origTexSize - 1);
ivec2 pt10 = clamp(ptu10 / upscaleFactor, ivec2(0), origTexSize - 1);
ivec2 pt11 = clamp(ptu11 / upscaleFactor, ivec2(0), origTexSize - 1);
// Sampled colours.
vec4 clr00 = texelFetch(sampler, pt00, 0);
vec4 clr01 = texelFetch(sampler, pt01, 0);
vec4 clr10 = texelFetch(sampler, pt10, 0);
vec4 clr11 = texelFetch(sampler, pt11, 0);
// Bilinear interpolation.
vec4 clr0x = mix(clr00, clr01, ptuf.y);
vec4 clr1x = mix(clr10, clr11, ptuf.y);
vec4 clrFinal = mix(clr0x, clr1x, ptuf.x);