我正在寻找一种在WebGL中绘制更好质量(任意)文本的方法。目前我在2D画布上使用位图字体渲染并将它们放入WebGL上下文中。
这个方法在这里描述http://delphic.me.uk/webgltext.html
这是我现在知道的在WebGL中绘制任意unicode文本的唯一解决方案。这种方法的问题是这些是位图字体,并且在较小的字体大小上看起来很块。我大多使用18的字体大小,与桌面质量字体相比,结果相当块。
我知道threeJS有一个字体库可以生成更好看的文本,但是我不想使用threeJS,因为我有自己的包装器,它可以正常工作,我不需要增加额外的三个开销。
那么如何在WebGL中创建更高质量的文本呢?有没有方法在Javascript中提取文本形状以提高质量?
使用Fonts一段时间后,我可以看到在WebGL中使用6种字体的方法,所有这些方法都有优点和缺点:
这也称为“按需动态纹理”。将文本字形仅渲染到(屏幕外)画布,并将其作为WebGL纹理显示在屏幕上,如下所述:http://delphic.me.uk/webgltext.html
游戏Age of Empires III使用这种方法。
如果您希望以最佳质量获得最大速度以获得有限的字符集和固定字符大小(游戏),则最好创建自己的位图,其中包含您要使用的字符,并根据需要将它们显示在屏幕上。您可以在互联网上找到相当多的这些字符位图。
这既快速又简单,但限制了您可以使用的语言和字符,但您不会介意在游戏中使用它。
Valve的Chris Green撰写了关于使用纹理符号距离字段的“书”。你想阅读2007 SIGGRAPH白皮书"Improved Alpha-Tested Magnification for Vector Textures and Special Effects
通常字体纹理图集看起来像this。 SDF纹理看起来像like。是的,当“按原样”渲染时,SDF纹理图集看起来很模糊。那是因为8位通道编码为:
smoothstep()
和fwidth()
等黑客会给出质量较差的缩放结果。 WebGL的fwidth()
使用错误的常量也没有帮助。总而言之,如果你有多种字体,那么SDF字体在两种尺寸(仅需要1)和质量(在小尺寸和大尺寸上看起来都很棒)都是一个巨大的胜利
人们正在探索在GPU上存储三次曲线,并通过智能片段着色器完成所有渲染的繁重工作来完全绕过纹理。
此blog截至2017年2月的字体渲染摘要。
对于我当前的项目,我使用HTML5 2D画布渲染文本和其他2D基元,并使用WebgGL画布上的透明度覆盖它。我对速度和速度感到惊讶,它在速度和质量方面都非常好。
只要您的文本是静态2D并且您不需要任何3D转换,这将是我的建议。在我的项目中,这比我之前使用的方法(Font as Geometry)快了约2倍。
查看three.js的源代码提出了一个解决方案。
这是three.js字体创建https://github.com/mrdoob/three.js/blob/master/src/extras/FontUtils.js的代码
它在右上方说
* For Text operations in three.js (See TextGeometry)
*
* It uses techniques used in:
*
* typeface.js and canvastext
* For converting fonts and rendering with javascript
* http://typeface.neocracy.org
*
* Triangulation ported from AS3
* Simple Polygon Triangulation
* http://actionsnippet.com/?p=1462
*
* A Method to triangulate shapes with holes
* http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
Typeface.js provides the font data and there's an online form to convert truetype fonts。
其他方案:
Pixi.js同意上面针对SDF的建议。
https://github.com/PixelsCommander/pixi-sdf-text
他们说(并且他们是浏览器的优秀游戏项目)
SDF是在WebGL中绘制文本的最有效方式。它使用特殊类型的栅格图集和GLSL着色器在GPU上以非常高效的方式绘制矢量可伸缩文本。
this来自MapBox,至少在某些时候也是如此。