9

在使用混合模式时加入两条抗锯齿线时遇到问题,我在它们加入的点处有所下降。通过混合模式,我的意思是我通过计算线条颜色与背景颜色的比率来绘制抗锯齿线条,因此当像素的比率为例如 70% 时,新像素为 0.7*线条颜色 + 0.3*背景颜色。我的线条抗锯齿功能基本上是由错误函数制成的(尽管我认为大多数抗锯齿功能也会出现同样的问题),如下所示:

0.5+0.5erf(-x)

因此,当两条线相遇时,一条接一条地绘制,你会得到一个下降,两条线的连接处下降到它应该处于的强度的 75%,因为在那一点上,第一条线保留了 50% 的背景,并且然后在绘制第二条线后剩下 50% 的 50% 应该留下 0%:

1 - (0.5erfc(-x) * 0.5erfc(x))

我只能假设这是绘制带有连接线的抗锯齿光栅图形的常见问题,因此它必须有一个通用的解决方案,但我不知道这是什么。谢谢!

另外:为了清楚线条是如何绘制的,线条的宽度是使用高斯函数 (e^-x*x) 制作的,并且两端使用凸起的误差函数进行四舍五入。您可以通过在 WolframAlpha 中输入 '0.5erfc(-x-5) * 0.5erfc(x-5) * e^(-y*y)' 来查看 10 px 长水平线的示例。

4

4 回答 4

1

如果您将混合线段视为线段,则通常无法制作由混合线段组成的好看的连续线 - 如果您只是想到有一条线然后以相同角度绘制下一条线段的情况,然后以 90 度角。一条线的像素颜色取决于它与下一条线的连接角度

然后你需要考虑的是末端有角度的部分。

要绘制它,请查找有关斜角线连接斜接的文献(斜接可能更容易)。

于 2012-12-25T23:04:33.823 回答
0

如果你用混合来绘制相邻的线,这是一个非常不可能的问题。

考虑这一点的一个好方法是理想形状的距离函数。像素强度映射(通过某些函数)到形状的距离。有两条完美的线条,这只是最低限度。

不幸的是,这意味着您需要到可能影响像素的每条线的距离。这就是一些文本光栅化器所做的。

或者你只是不加权线。它们按像素打开或关闭。然后你让超级采样处理剩下的事情。这就是像 flash 或 svg 这样的软件矢量渲染器所做的。

于 2013-02-04T08:01:58.000 回答
0

thang的想法可能是一个很好的起点:简而言之,控制“画笔”的中心而不是边缘。理想情况下,通过这种方法,您会看到漂亮的圆形端点。

然而,事实不会这么美好。问题是您首先将一条线与目标曲面进行 alpha 混合,然后在该曲面上对第二条线进行 alpha 混合,该曲面上已经有一条线“烧入”。最终结果将是在两个半透明像素相互重叠的角落处出现更胖的斑点(例如,如果您尝试在 Gimp 中绘制连接线段,您可能会在实际中观察到这种效果)。

我认为在此设置上使用这种简单的一次一行的方法无法解决此问题(因此您需要使用折线算法或超级采样朝着其他建议的方向发展)。但是,根据您的目标,您可能有一个可行的解决方案。

这是将您的图形对象预渲染到具有 alpha 的单独表面。在这一点上,您可以组合各个线的 alpha(例如从目标像素和绘制的像素中获取最大的),这将为您提供预期的结果(角落上没有脂肪团)。

缺点是您需要一个单独的表面,当对象完成时,您必须在目标上进行 blit:这需要额外的内存和处理时间。

如果您只需要渲染到一些平面(单色)目标,您可以解决这个问题:那么您根本不需要执行适当的 alpha 混合,并且可以就地进行组合 alpha 计算。如果背景很容易计算(例如坐标网格),则此解决方案可能是可行的,因此总的来说,当您可以轻松获得背景的原始像素值时,您可以结合它(确实这也可以如果你将渲染的背景保留在一个单独的表面中,但你又在内存中有另一个表面,所以可能没有任何结果)。

如果您的问题属于其他性质,如果您将这些渲染的单独表面保留在周围,这也可能是可行的,这实际上是您预渲染线条对象,然后仅将它们用作纹理或瓷砖。

于 2013-07-05T18:46:55.217 回答
0

最终我找到了这个问题的答案。直接在主图像上直接绘制一条线,这是没有明智的方法的,因为您不希望将线条混合在一起,而是希望将它们加在一起然后得到线条总和的结果融入主图。

但是,如果您必须将所有这些线绘制到一个单独的缓冲区,然后将整个缓冲区混合到主缓冲区中,那将很笨拙,这是我在提出这个问题之前考虑并认为不合适的。值得庆幸的是,从那以后我完全改变了我的方法,而不是使用一个缓冲区来绘制一个又一个元素,而是使用逐像素方法,其中每个像素都是通过遍历要绘制的元素列表直接计算的,为了并行化(使用 OpenCL)。因此,不必使用额外的缓冲区,我只需要一个可以容纳一些额外像素值的小数组,并且在我要绘制的元素列表中,我有用作括号的元素,例如,而不是:

image => (blend) line1 => (blend) line2 => (blend) line3

我可以有:

image => (blend) [0 => (add) line1 => (add) line2 => (add) line3]

这是通过为括号的每个深度级别设置一个值数组来替换单个像素值的使用来完成的,因此在这种情况下,v[0]您将拥有来自 的像素image,然后您将从v[1]0 开始并将每一行添加到它,当添加所有行时,括号的关闭将v[1]被混合v[0],并且正确的结果像素值将在那里。

就是这样,它非常简单,如果您不允许自己在 Photoshop 中使用相当于一组图层,这只是一个问题。

于 2016-05-21T13:09:32.790 回答