0

我正在用 OpenGL 制作一个新贴纸。字符是使用带纹理的四边形绘制的。纹理是从使用 FreeType2 渲染的位图创建的。

滚动是通过根据dx经过的时间和给定的速度计算 a 并更新我的 "world x":来完成的x += dx。由于我无法影响经过的时间,dx因此必须采用浮点值,例如0.5.

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

这意味着我们必须使用浮点值进行渲染并使用抗锯齿(比方说GL_LINEAR)。现在的问题是,在小像素尺寸下,字符似乎会增长和缩小,具体取决于abs(x - (int)x):near to0.5或 near to 0.0。这种增长和缩小可以被视为一种“边缘闪烁”。

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

4

2 回答 2

2

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

于 2013-08-31T17:17:49.470 回答
1

因为您没有提供问题的“小例子”,所以很难弄清楚到底发生了什么。

无论如何,可能的原因:

在 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 个像素边框,并渲染包含边框的字母(如果位图不透明,则不可能)。

原因是,如果你的字母被紧紧地挤在一起,那么接触位图边框的像素最终可能会被小数子像素偏移量截断。抗锯齿可能会对此有所帮助,但这并不能保证。为位图添加边框可以防止这种情况发生,但您仍然需要启用纹理过滤器。

只有当您的字形位图具有触摸位图边框的像素时,这才会改善文本。否则不会有效果。

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

于 2013-08-31T17:41:59.103 回答