带有标志距离字段字体的尖角


49

签名距离字段(的SDF)是作为一个快速的解决方案由Valve实现与分辨率无关的字体呈现在本文中

我已经可以使用Valve解决方案了,但是我想保留转角处的清晰度。Valve指出,他们的方法可以通过使用第二个纹理通道与基础纹理通道“与”来实现锐角,但缺乏解释如何生成第二个通道。

实际上,本文遗漏了许多实现细节。

我想知道你们中的任何人都可以指出一个方向,以使SDF字体具有尖角。


事实上,亚当已经在shadertoy上发布了源代码。这是链接:shadertoy.com/view/ltXSDB
Felipe Lira

你让我激动。他确实将bezier内容发布在shadertoy上,但未将纹理距离字段内容发布!
艾伦·沃尔夫

@AlanWolfe我认为他只是为按程序设置贝塞尔曲线所做的。我不确定将其集成到ttf render lib中所需的工作。有空的时候我会看看。
费利佩·里拉

看起来他在实际存储和检索纹理距离方面有一些魔力。在没有纹理的情况下,shadertoy示例缺少方程式的该部分。
艾伦·沃尔夫

有点迟到了,但是从reddit的这种旧的线程有一吨关于改进SDF渲染清晰度的各种方法的信息:reddit.com/r/gamedev/comments/2879jd/...
Necrolis

Answers:


7

亚当·西蒙斯(Adam Simmons)在这方面做了一些有趣的工作。我具体不知道他是如何实现的,但是他的基于SDF的矢量渲染是我在Valve以外的实践中所见过最清晰的。http://twitter.com/adamjsimmons/status/611677036545863680


当然,我并没有全部的细节,但是在我看来,这个人只是使​​用伪距场来代替常规场,这在2006年Qin,McCool和Kaplan的论文中已经得到证明,“实时纹理映射矢量字形”,在Valve文件中也有提及。它仅影响轮廓的斜角,无助于改善角的外观。我怀疑它看起来很锐利的原因是因为他使用了不切实际的大距离场纹理。我可能是错的。
Detheroc

69

编辑:请参阅我的其他答案与具体解决方案。

实际上,一年多以前,我已经为硕士论文解决了这个确切的问题。在Valve论文中,他们表明您可以AND两个距离字段来实现这一点,只要您只有一个凸角即可。对于凹角,还需要“或”运算。这个家伙实际上开发了一些晦涩的系统,可以使用四个纹理通道在两个操作之间进行切换。

但是,有一种简单得多的运算可以根据情况简化AND和OR运算,这是我论文的主要思想:3 的中值。因此,基本上,您恰好使用了三个通道(对于RGB来说是理想的),它们是完全可以互换的,并使用中值运算将它们组合在一起(从三个值中选择中间值)。

为了适应抗锯齿,我们不仅使用布尔值,还使用浮点值,并且AND运算变为最小值,而OR则变为两个值的最大值。三个的中位数确实可以做到这两者:如果a < b,对于(aab),中位数是最小值,而对于(abb),则最大值是最大值。

渲染过程仍然非常简单。整个片段着色器(包括抗锯齿)可以如下所示:

int main() {
    // Bilinear sampling of the distance field
    vec3 s = texture2D(sdf, p).rgb;
    // Acquire the signed distance
    float d = median(s.r, s.g, s.b) - 0.5;
    // Weight between inside and outside (anti-aliasing)
    float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);
    // Combining the background and foreground color
    gl_FragColor = mix(outsideColor, insideColor, w);
}

因此,与原始方法的唯一区别是在采样纹理后立即计算中值。但是,您将必须实现中值函数,只需执行4分钟/最大操作即可

当然,现在的问题是,如何建立这样的三通道距离场?这是棘手的部分。我一开始采用的最明显的方法是将输入形状/字形分解为三个分量,然后从每个分量中生成常规距离场。分解的规则并不那么复杂。首先,内部至少有3个通道中的2个通道的区域。然后,如果您将其想象为RGB颜色通道,则凸角必须由辅助颜色制成,并且其两个主要成分继续向外延伸。凹角是相反的:两个辅助色围住它们共同的主色,并且两个边向内连续的位置之间的楔形是白色。我还发现在某些情况下需要填充以防止其他两种原色或两种原色接触(例如,在“ N”的中间笔划中)

下图是程序根据我的论文生成的示例分解:

字形的多通道分解

但是这种方法有一些缺点。其中之一是特殊效果(例如轮廓和阴影)将不再正常工作。Fortunatelly,我还想出了第二种更为优雅的方法,它可以直接生成距离场,甚至支持所有图形效果。它也包含在我的论文中,也已经有1年多的历史了。我现在不打算提供更多详细信息,因为我目前正在写一篇详细描述第二种技术的论文,但是一旦完成,我将在此处发布。

无论如何,这是质量差异的一个例子。每张图像的纹理分辨率都相同,但是左边的使用常规纹理,中间的使用普通距离场,右边的使用我的三通道距离场。性能开销只是采样RGB纹理与单色纹理之间的差异。

在此处输入图片说明


5
伟大的第一答案,欢迎来到Computer Graphics SE!:)您的论文可以公开发表吗?(或者是在完成所述论文之后?)如果这样的话,链接到该文档也可能非常有帮助。
马丁·恩德

它应该是公开可用的,但似乎学校尚未提出。无论如何,我不希望现在就散布它,因为我正在写的文章将真正更好地解释重要部分并集中于如何实现它,并且它应该很快完成。
Detheroc

@Detheroc完成本文后,请在此处和gamedev Q上进行通知。解释对我来说还不是100%清晰。我建议逐步在图像中显示构图。
工程师

1
希望能够复制您当前的结果,即使它们不如您将来的结果好,也可以+1以分享您可以提供的所有详细信息。非常令人兴奋。您是否考虑过任何一种技术在射线行进(球面跟踪)中的应用?在体积纹理或类似纹理中……
艾伦·沃尔夫


43

很抱歉,等待时间很长,但很明显,尽管我已答应的文章已基本完成,但发布过程仍需要一些时间。因此,我改用我的新多通道距离场构造算法msdfgen准备了一个开源程序,您可以立即尝试。

它在GitHub上可用:https : //github.com/Chlumsky/msdfgen

(我对此并不陌生,所以请让我知道存储库是否有问题。)

有人还询问它如何与更大的单色距离场进行比较,因此这是质量差异的预告片。但是,它实际上取决于特定的字体,我不会说它总是值得额外的数据。

多通道距离场16x16 单色距离场32x32


3

很有趣!我是阀门签名定距纸的作者。抱歉,实施细节有点稀疏。我仅将两个通道的示例作为将来的工作-我没有生成器。我想过要生成一个高分辨率的sdf,然后根据sdf的倾斜角度进行分段是一种合理的策略。但是从来没有。对于您的应用所需的放大倍数,必须权衡使用任何高分辨率的具有相同内存占用量的单通道数据的多通道方案。


0

我绝不是这个主题的专家,但是,如果您使用双向滤镜,定向双三次滤镜而不是标准双线性滤镜,则至少在理论上可以在单色伪SDF中保留尖角。除了节省内存的明显好处之外,您还可以使用多个通道来放置多色SDF贴花纸。

另外,如果您不介意使用第二个通道,那么您也可以尝试使用一个通道作为“水平距离”通道,而另一个通道作为“垂直距离”通道,并使用拉普拉斯差(DoL)能量金字塔来压缩纹理,从而避免冗余信息不会被记录。

第三个也是最后一个理论解决方案是通过数组集寻址对六角形采样纹理进行实验。

不幸的是,我目前无法测试我的想法,也无法找到描述或测试与我的想法相似的任何文档。我将链接所有获得我的信息/想法的相关文章。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.