我正在将一些旧的OpenGL 1.2位图字体渲染代码移植到现代OpenGL(至少OpenGL 3.2+),我想知道我是否可以使用GLSL着色器来实现我手动完成的工作。
当我想绘制字符串“123”,缩放到特定大小时,我使用下面的精灵执行以下步骤。
我将精灵画到屏幕上,用GL_NEAREST缩放2倍。然而,为了获得黑色轮廓,我实际上画了几次精灵。
精灵被绘制到屏幕后,我通过glCopyTexSubImage2D将屏幕复制到纹理。
最终结果是一种更具视觉吸引力的缩放像素精灵形式。当将小像素精灵升级到任意尺寸时,仅使用GL_NEAREST(右下角)或仅使用GL_LINEAR(左下角)会产生我不喜欢的效果。使用GL_NEAREST加倍像素,然后使用GL_LINEAR进行剩余缩放,得到我更喜欢的结果(顶部)。
我非常确定GLSL可以做黑色轮廓(从而使我不必进行大量绘制),但它是否也可以组合GL_NEAREST和GL_LINEAR缩放?
答案 0 :(得分:1)
你可以实现" 2x最近邻扩频的效果,接着是线性采样"通过假装从放大的纹理中采样4个纹素的邻域,而实际上从原始纹理中采样它们。然后,您必须手动实施双线性插值。如果您的目标是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);