OpenGL:滚动文本的别名

时间:2013-08-31 17:01:04

标签: opengl

我正在使用OpenGL制作新版画。使用纹理四边形绘制角色。纹理是从使用FreeType2渲染的位图创建的。

滚动是通过根据传递的时间和给定的速度计算dx并更新我的“世界x”:x += dx来完成的。由于我无法影响时间,dx必须采用0.5等浮点值。

舍入到整数确实不起作用,无论你采用何种方式,它都会产生非常明显的抖动。我已经尝试在每次迭代时舍入“世界x”值,使用“世界x”保持浮动,但使用glTranslate2f而不是GL_NEAREST舍入给GL_LINEAR的值。无论如何,在较小的像素尺寸下,始终存在不可接受的抖动,因此不能选择舍入。

这意味着我们必须使用浮点值进行渲染并使用抗锯齿(假设GL_LINEAR)。现在的问题是,在较小的像素大小下,字符似乎会增长和缩小,具体取决于abs(x - (int)x):接近0.5或接近0.0。这种增长和萎缩可以被视为一种“边缘闪烁”。

我怎样才能让这种感知成长和萎缩消失?也许我必须深入了解着色器并实现我自己的抗锯齿算法?还有其他想法吗?

2 个答案:

答案 0 :(得分:2)

您必须实现某种子像素渲染。你在X方向上滚动,所以我建议你在X维度上渲染,比如目标宽度的4倍(过采样)。然后在片段着色器中执行像素覆盖积分,即您总结覆盖屏幕像素的所有纹素,并通过过采样因子进行归一化(即除)。根据输出帧缓冲格式,您可能必须在之后应用伽马校正。

答案 1 :(得分:1)

因为你没有提供"small example"你的问题,所以很难确定究竟发生了什么。

无论如何,可能的原因:

在freetype中,下一个字符的偏移量存储为分数。如果您正在渲染这样的字符(伪代码)

float x = startX, y = startY;
for(c in charactersToRender){
    Glyph glyph = getGlyph(c);
    renderGlyphAtIntegerPos(round(x), round(y))
    x += glyph.advance;//advance is float.
}
当您使用小小的步骤移动文本时,单个字母将来回摆动。为了防止这种情况,您必须将下一个字母的偏移量计算为整数值。

float textStartX, textStartY;
int x = 0, y = 0;
for(c in charactersToRender){
    Glyph glyph = getGlyph(c);
    renderGlyphAtIntegerPos(x + round(textStartX), y + round(textStartY))
    x += round(glyph.advance);//advance is float.
}

当字符“增长和缩小”时,如果你使用纹理过滤器,那么它可能对你有帮助

  1. 将整个文本字符串渲染到纹理上,然后滚动纹理。
  2. 或者在所有字母位图中添加1个像素边框,并使用包含边框的渲染字母(如果位图不透明则不可能)。
  3. 原因是如果您的字母紧密排列,那么触及位图边框的像素可能最终会被分数子像素偏移切断。 Antialising MIGHT对此有所帮助,但这并不能保证。向位图添加边框将阻止这种情况,但您仍需要启用纹理过滤器。

    仅当您的字形位图具有触及位图边框的像素时,才会改善文本。否则就没有效果。

    是的,写一个着色器会有所帮助。但是,如果我是你,我会使用更大的字体或避免使用小数文本偏移,或者不希望使用小数偏移呈现的文本可读。