我正在使用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
。这种增长和萎缩可以被视为一种“边缘闪烁”。
我怎样才能让这种感知成长和萎缩消失?也许我必须深入了解着色器并实现我自己的抗锯齿算法?还有其他想法吗?
答案 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.
}
当字符“增长和缩小”时,如果你使用纹理过滤器,那么它可能对你有帮助
原因是如果您的字母紧密排列,那么触及位图边框的像素可能最终会被分数子像素偏移切断。 Antialising MIGHT对此有所帮助,但这并不能保证。向位图添加边框将阻止这种情况,但您仍需要启用纹理过滤器。
仅当您的字形位图具有触及位图边框的像素时,才会改善文本。否则就没有效果。
是的,写一个着色器会有所帮助。但是,如果我是你,我会使用更大的字体或避免使用小数文本偏移,或者不希望使用小数偏移呈现的文本可读。