签名距离字段(的SDF)是作为一个快速的解决方案由Valve实现与分辨率无关的字体呈现在本文中。
我已经可以使用Valve解决方案了,但是我想保留转角处的清晰度。Valve指出,他们的方法可以通过使用第二个纹理通道与基础纹理通道“与”来实现锐角,但缺乏解释如何生成第二个通道。
实际上,本文遗漏了许多实现细节。
我想知道你们中的任何人都可以指出一个方向,以使SDF字体具有尖角。
签名距离字段(的SDF)是作为一个快速的解决方案由Valve实现与分辨率无关的字体呈现在本文中。
我已经可以使用Valve解决方案了,但是我想保留转角处的清晰度。Valve指出,他们的方法可以通过使用第二个纹理通道与基础纹理通道“与”来实现锐角,但缺乏解释如何生成第二个通道。
实际上,本文遗漏了许多实现细节。
我想知道你们中的任何人都可以指出一个方向,以使SDF字体具有尖角。
Answers:
亚当·西蒙斯(Adam Simmons)在这方面做了一些有趣的工作。我具体不知道他是如何实现的,但是他的基于SDF的矢量渲染是我在Valve以外的实践中所见过最清晰的。http://twitter.com/adamjsimmons/status/611677036545863680
编辑:请参阅我的其他答案与具体解决方案。
实际上,一年多以前,我已经为硕士论文解决了这个确切的问题。在Valve论文中,他们表明您可以AND两个距离字段来实现这一点,只要您只有一个凸角即可。对于凹角,还需要“或”运算。这个家伙实际上开发了一些晦涩的系统,可以使用四个纹理通道在两个操作之间进行切换。
但是,有一种简单得多的运算可以根据情况简化AND和OR运算,这是我论文的主要思想:3 的中值。因此,基本上,您恰好使用了三个通道(对于RGB来说是理想的),它们是完全可以互换的,并使用中值运算将它们组合在一起(从三个值中选择中间值)。
为了适应抗锯齿,我们不仅使用布尔值,还使用浮点值,并且AND运算变为最小值,而OR则变为两个值的最大值。三个的中位数确实可以做到这两者:如果a < b,对于(a,a,b),中位数是最小值,而对于(a,b,b),则最大值是最大值。
渲染过程仍然非常简单。整个片段着色器(包括抗锯齿)可以如下所示:
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纹理与单色纹理之间的差异。
很抱歉,等待时间很长,但很明显,尽管我已答应的文章已基本完成,但发布过程仍需要一些时间。因此,我改用我的新多通道距离场构造算法msdfgen准备了一个开源程序,您可以立即尝试。
它在GitHub上可用:https : //github.com/Chlumsky/msdfgen
(我对此并不陌生,所以请让我知道存储库是否有问题。)
有人还询问它如何与更大的单色距离场进行比较,因此这是质量差异的预告片。但是,它实际上取决于特定的字体,我不会说它总是值得额外的数据。
我绝不是这个主题的专家,但是,如果您使用双向滤镜,定向双三次滤镜而不是标准双线性滤镜,则至少在理论上可以在单色伪SDF中保留尖角。除了节省内存的明显好处之外,您还可以使用多个通道来放置多色SDF贴花纸。
另外,如果您不介意使用第二个通道,那么您也可以尝试使用一个通道作为“水平距离”通道,而另一个通道作为“垂直距离”通道,并使用拉普拉斯差(DoL)能量金字塔来压缩纹理,从而避免冗余信息不会被记录。
第三个也是最后一个理论解决方案是通过数组集寻址对六角形采样纹理进行实验。
不幸的是,我目前无法测试我的想法,也无法找到描述或测试与我的想法相似的任何文档。我将链接所有获得我的信息/想法的相关文章。