Troika: 改进文本抗锯齿的快速想法

创建于 2021-06-17  ·  7评论  ·  资料来源: protectwise/troika

我不确定您最近是否更新了抗锯齿代码,因为我使用的是旧版本,但是在找到一种对着色器绘制的圆圈进行抗锯齿的好方法之后,我也想在您的文本上尝试一下,因为文本是基于 SDF 的,而圆的抗锯齿也是基于距离的。

在我当前版本的 Troika 中,您为 aa 距离执行return length(fwidth(vTroikaGlyphUV * vTroikaGlyphDimensions)) * 0.5; 。 这有一个伪影,当从一个角度观看时,最左边和最右边的边缘会出现一些明显的模糊:
image

我将其更改为标量; 距离,就像在我的圈子代码中一样: return fwidth(distance) * 0.5;troikaGetFragDistValue传入的距离如下: float distance = troikaGetFragDistValue(); float aaDist = troikaGetAADist(distance);
这样做我不会得到模糊的伪影:
image

可以增加0.5因子以获得更平滑的抗锯齿。 例如0.8
image

我想也许你和我一样不知道这种方法,所以想我会分享它。 我的“实现”确实有一些奇怪的工件(见下文),也许这就是你选择其他方法的原因。 此外,我不确定您如何在着色器代码中使用 aaDist 变量,因此您可能更擅长实现此功能。 例如,由于这种变化,也许有一些代码应该更改或删除,这可以进一步改进我的“实现”。

image

我在 bgolus 的帖子中找到了这种方法: https ://forum.unity.com/threads/antialiasing-circle-shader.432119/ 那里有更多信息。 他还说,您可以使用length(vec2(dFdx(distance), dFdy(distance)))而不是fwidth(distance)来获得更高的精度,尽管我不确定这是否可以忽略不计。

所有7条评论

感谢您的建议! 我肯定会调查这个,因为我也注意到倾斜角度的那些模糊边缘并且想消除它们。

从理论上讲,我认为distance的变化和vTroikaGlyphUV * vTroikaGlyphDimensions的变化应该是等价的,因为它们都代表了字体空间单位的距离,但是我必须有一些细微的差别被忽视了。 如果我可以避免您展示的工件,那么我很乐意整合您的更改。 :)

伟大的! 更改就像那一行一样简单(并传入该距离参数以适应它)。 如果您仍然想要原始代码,我可以在明天工作时发送。

从理论上讲,我认为距离的变化和 vTroikaGlyphUV * vTroikaGlyphDimensions 的变化应该是等价的,因为它们都代表字体空间单位的距离

我不完全理解衍生品是如何相同的。 distance是我猜的 SDF 距离,但另一个是缩放的 uv 位置。 我没有查看代码以及它们的比较方式,但感觉它们的衍生产品应该不同。 据我所知, fwidth只是将作为参数传入的特定输入值与相邻片段中的相同特定输入值的差异,这是可能的,因为相邻片段同时并行执行。 我今天早些时候用gl_FragColor.rgb = vec3(fwidth(gl_FragColor.x + gl_FragColor.g + gl_FragColor.b));进行了一个测试,看看它是否像边缘检测/索贝尔过滤器一样渲染边缘,试图稍微确认一下这个事实,它确实做到了。

感谢您的讨论,这些东西有时会破坏我的大脑。 ;)

当我说它们是“等价的”时,我的意思是它们都代表相同单位的距离,但你是对的,它们并不完全相同。

备份,我们在这里想要的是片段之间的_潜在_变化率。 像您建议的那样使用distance变量中的更改通常是准确的,但在某些情况下它会非常不准确。 这是因为从中采样该值的 SDF 是_non-uniform_; 它弯曲并在字形上切换其变化方向。 因此,相邻片段之间的distance的导数最终可能会变得太小,甚至为零,例如距离字段在字形路径之间从增加变为减少的位置,或者太大,例如在显示文本时在小尺寸和片段网格覆盖在不可预测的位置的 SDF。 我怀疑这至少可以解释您所看到的一些文物。

那么我们如何在不使用distance的情况下确定_潜在_变化率? 好吧,您所说的“缩放的 uv 位置”本质上是字形矩形内的 x/y 坐标,使用与distance相同的单位。 x/y 的导数为我们提供了片段之间的潜在移动速率。 总体而言,这比使用distance提供了更好的结果,因为它基于字形中的 _uniform_ 变化率,因此我们不会得到伪影,并且在小尺寸下更准确。

但是,正如您所看到的,它在斜角处分解。 在这些情况下,垂直方向的潜在 x/y 变化率与水平方向的变化率大不相同。 因此,我们最终对一个方向的潜在变化率使用单个值,该值在一个方向上太大而在另一个方向上太小,根据 SDF 在该片段的实际变化方向给出模糊和/或断断续续的线条。

所以,是的,倾斜情况肯定有改进的余地,但仅使用distance的导数本身是不够的。 当然,我对改进这一点的想法持开放态度。 一种可能性是尝试检测场景(斜角的大文本大小,靠近路径)并仅在这种情况下使用distance导数。

是啊,这东西想想就让人费解,哈哈。 我可以看到距离场不太平滑,是的。

那些有问题的像素可能只是因为那里的片段有一些奇怪的距离值。

从远处看它并不是令人难以置信的波涛汹涌,但你肯定可以看到紫外线更好。 也许在距离变量和依赖于相机距离的 UV 之间进行插值会很好; 就像在靠近时选择更多的 fwidth(distance),在远离时选择更多的 fwidth(uv)。

为了比较(没有在完全相同的相机位置和方向捕获两者,但我认为它无论如何都很好地显示了差异):
距离(0.8 因子):
image
紫外线:
image

我注意到此修改显着改善了自定义文本转换的结果。 这是一些文本,使用createDerivedMaterial修改为遵循曲线(请参阅此技术)。 这使用当前的三驾马车三文本着色器:

image

这是相同的屏幕截图,但@asbjornlystruptroikaGetAADist的修改:

image

在第二张照片中,你可以看到极度拉伸的“GREAT!” 比较清脆。

有趣的是:我还发现将常数调整为 0.25(从 0.5)也会产生很好的清晰边缘:

return length(fwidth(vTroikaGlyphUV * vTroikaGlyphDimensions)) * 0.25;

谢谢@canadaduane ,我绝对可以看到拉伸部分的改进。 我还可以看到 HELLO 中的 L 之间出现了丑陋的伪影,在采用此更改之前,我们肯定需要弄清楚这一点。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Ocelyn picture Ocelyn  ·  13评论

arpu picture arpu  ·  43评论

lojjic picture lojjic  ·  18评论

lojjic picture lojjic  ·  11评论

stephencorwin picture stephencorwin  ·  39评论