我正在寻找一种在WebGL中绘制更好质量(任意)文本的方法。目前,我在2D画布上使用位图字体渲染,并将它们放入WebGL上下文中。
此处描述了此方法http://delphic.me.uk/webgltext.html
这是我现在知道的在WebGL中绘制任意unicode文本的唯一解决方案。这种方法的问题是这些是位图字体,并且在较小的字体大小上看起来很块。我主要使用的字体大小为18,与桌面质量字体相比,结果相当块状。
我知道threeJS有一个字体库可以生成更好看的文字,但是我不想使用threeJS,因为我有自己的包装器,它可以正常工作,我不需要添加额外的三个开销。
那么如何在WebGL中创建质量更好的文本呢?有没有方法在Javascript中提取文本形状以提高质量?
答案 0 :(得分:30)
使用Fonts一段时间之后,我可以看到6种在WebGL中进行字体处理的方法,都有优点和缺点:
这也称为" On Demand Dynamic Textures"。将文本字形仅渲染到(屏幕外)画布,并将其作为WebGL纹理显示在屏幕上,如下所述:http://delphic.me.uk/webgltext.html
游戏帝国时代III 使用此方法。
如果您希望为有限的字符集和固定字符大小(游戏)提供最佳质量的最高速度,最好创建自己的位图,其中包含您要使用的字符,并根据需要将它们blit到屏幕上。你可以在互联网上找到很多这些字符位图。
这既快速又简单,但限制了您可以使用的语言和字符,但您不会在游戏中担心这一点。
通常字体纹理图集看起来像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倍。
答案 1 :(得分:3)
查看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
其他解决方案:
将文本渲染到您的位图并获得更高的分辨率,然后将其绘制到分辨率或更小的分辨率。
使用曲线渲染器。 (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html)
答案 2 :(得分:0)
Pixi.js同意上述有关SDF的建议。
https://github.com/PixelsCommander/pixi-sdf-text
他们说(对于浏览器来说,这是一个出色的游戏项目)
SDF是在WebGL中绘制文本的最有效方法。它使用特殊的栅格地图集和GLSL着色器在GPU上以非常高效的方式绘制矢量可缩放文本。
this来自MapBox,至少在某个时候也做到了。