如何在OpenGL的2D场景中绘制平滑的线条而不使用GL_LINE_SMOOTH?

11

由于GL_LINE_SMOOTH不受硬件加速支持,也不能在所有GFX卡上使用,那么在2D模式下如何绘制平滑线条,使其看起来与GL_LINE_SMOOTH一样好呢?

编辑2: 我目前的解决方案是从两个四边形绘制一条直线,从边缘向零透明度淡化,并且这两个四边形之间的颜色即为线条颜色。对于基本平滑线条渲染来说,它已经足够好用并且不需要使用纹理,因此非常快速。


你有没有排除使用带纹理的四边形或带颜色渐变的四边形?这对我来说似乎是一个可能的解决方案,尽管听起来Edvard已经涵盖了这个领域。 - Tim
@Tim,嗯,我不确定仅有着色的四边形是否能像平滑线一样正常工作,它可能会变得过于锐利...好吧,我得测试一下。 - Rookie
@Tim,我刚刚测试了一下,就像我预期的那样,它太锐利(或者说太模糊),但是对于我当前的目的来说,它可以很好地工作!线条厚度 1.7 看起来非常适合我的当前厚度为 1.1 的平滑线条。 - Rookie
4
你说你不想使用全屏抗锯齿技术。那么,在性能方面,什么解决方案最好呢?但是,请注意,抗锯齿技术恰好是为实现你所需效果而设计的。同时,你也不想使用着色器。那么,到底你希望得到什么效果呢? - Nicol Bolas
@NicolBolas,我不想要全屏抗锯齿,因为据我所知它速度很慢。目前使用彩色四边形的效果还不错。 - Rookie
3个回答

12

所以,你想要平滑的线条,但不想使用以下任何一种技术:

  • 线条平滑。
  • 全屏抗锯齿。
  • 着色器。

好的。

你最好使用 Valve 的Alpha-Tested Magnification 技术。对于你的需求,基本思路是创建一个纹理来表示距离线条的距离,其中纹理中心的距离为 1.0。这可能可以是一维纹理。

然后使用文献中描述的技术(包括抗锯齿版本在内)绘制代表您的线条的四边形。显然,你需要使用 alpha 混合 (因此它不是无序的)。使用线宽来控制它变成适当颜色的距离,从而使您能够制作窄或宽线条。


使用着色器完成上面的过程与上述方法几乎相同,只是没有使用纹理。顶点着色器将距离传递并插值。对于四边形的左侧,顶点着色器传递 0。对于右侧,它传递 1。您将这个值乘以 2,减去 1,并取绝对值。

这就是您距离线条的距离(线条是四边形的中心)。然后按照 Valve 的算法使用该距离即可。


我知道那种技术,但它并不是我正在寻找的,而且需要更多的内存。我的当前解决方案是使用带有颜色的四边形,速度快且不占用额外的纹理内存。 - Rookie
4
@Rookie:你所说的“更多内存”是指4KB(可能是GPU可以分配的最小内存)。你不需要为每行都创建一个纹理,只需要创建一个纹理即可。正如先前所述,这可以是一个一维纹理;它也不必特别大。一个16x1 GL_LUMINANCE8 纹理就足够了。我相信你不会错过那4K内存的。 - Nicol Bolas

3
打开全屏抗锯齿并使用四边形是我的首选。

我认为全屏抗锯齿对于一个游戏来说有点过度杀伤力,因为除了这些线条之外,游戏并没有渲染任何其他的抗锯齿效果,而这些线条只是游戏的一小部分。顺便问一下,你为什么需要纹理四边形和全屏抗锯齿两者都要?难道纹理四边形不足以满足需求吗? - Rookie
但是,如果您使用具有1像素完全不透明和相邻的2个像素完全透明的纹理,四边形不会看起来像平滑的线条吗?我还没有测试过,但我不知道为什么不行...因为在我的纹理测试中,我已经在纹理中画了一条直线,然后旋转了纹理四边形顶点,当它被旋转时,该线确实看起来像平滑的线条,就好像它具有抗锯齿效果。 - Rookie
问题在于,超过3个像素宽度的四边形需要另一个纹理来避免线条看起来过于平滑,还有1像素的问题。 - Edvard Pedersen
但是我能否只对我渲染的四边形进行FSAA呢?否则它将变得非常密集,因为我至少需要8倍抗锯齿,也许需要16倍才能使线看起来像使用GL_LINE_SMOOTH一样。 - Rookie
在渲染之前,您启用了多重采样。实际上,您只能为线启用它。 - Luca
显示剩余4条评论

1

目前我使用2或3个四边形来完成这个任务,这是最简单的方法。

  • 如果线条粗细<=1像素,则只需要2个四边形。
  • 如果线条粗细>1像素,则需要在中间添加第三个四边形。
  • 如果线条粗细>=1像素,则淡出边缘四边形的厚度不能改变。

在下面的图像中,您可以看到带有蓝色边框的四边形。白色表示完全不透明,黑色表示零不透明度(=完全透明)。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接