WebGL中更好的文本质量
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL中更好的文本质量相关的知识,希望对你有一定的参考价值。
我正在寻找一种在WebGL中绘制更好质量(任意)文本的方法。目前我在2D画布上使用位图字体渲染并将它们放入WebGL上下文中。
这个方法在这里描述http://delphic.me.uk/webgltext.html
这是我现在知道的在WebGL中绘制任意unicode文本的唯一解决方案。这种方法的问题是这些是位图字体,并且在较小的字体大小上看起来很块。我大多使用18的字体大小,与桌面质量字体相比,结果相当块。
我知道threeJS有一个字体库可以生成更好看的文本,但是我不想使用threeJS,因为我有自己的包装器,它可以正常工作,我不需要增加额外的三个开销。
那么如何在WebGL中创建更高质量的文本呢?有没有方法在javascript中提取文本形状以提高质量?
使用Fonts一段时间后,我可以看到在WebGL中使用6种字体的方法,所有这些方法都有优点和缺点:
Font as Geometry
- 获取像谷歌那样的开源字体(Open Sans和Roboto非常受欢迎)
- 使用OpenType或类似(https://nodebox.github.io/opentype.js/)读出字体的曲线
- 三角形曲线。我最喜欢的是Earcut,因为它非常快https://github.com/mapbox/earcut
- 将每个字符的多边形绘制为普通的WebGL三角形。
Advantages
- 非常快,如果你有很多文字并需要全功能字体,这是你最好的选择。通过矩阵操作在GPU上完成字体缩放。
Disadvantages
- 渲染字体的质量取决于WebGL浏览器启用的抗锯齿功能。 Safari做8x8 AA看起来不错,但所有其他浏览器只使用4x4,这可能看起来很块。此外,移动浏览器根本不启用AA,使得移动设备上的字体看起来非常模糊。
Canvas
这也称为“按需动态纹理”。将文本字形仅渲染到(屏幕外)画布,并将其作为WebGL纹理显示在屏幕上,如下所述:http://delphic.me.uk/webgltext.html
Advantages
- 体面的品质。
Disadvantages
- 速度,取决于您需要在多长时间内呈现的文本可以正常工作。特别是如果你只需要渲染静态文本。
游戏Age of Empires III使用这种方法。
Bitmap Fonts
如果您希望以最佳质量获得最大速度以获得有限的字符集和固定字符大小(游戏),则最好创建自己的位图,其中包含您要使用的字符,并根据需要将它们显示在屏幕上。您可以在互联网上找到相当多的这些字符位图。
这既快速又简单,但限制了您可以使用的语言和字符,但您不会介意在游戏中使用它。
好处:
- 简单易懂
- 创造纹理图集的琐碎
- 可以使用彩色字体
缺点
- 放大时看起来非常模糊
- 必须预渲染所有使用的字形
- 每个字体大小需要纹理
- 需要texture bin packing才能获得最佳纹理效果。 Example
Signed-Distance Field Fonts
Valve的Chris Green撰写了关于使用纹理符号距离字段的“书”。你想阅读2007 SIGGRAPH白皮书"Improved Alpha-Tested Magnification for Vector Textures and Special Effects
通常字体纹理图集看起来像this。 SDF纹理看起来像like。是的,当“按原样”渲染时,SDF纹理图集看起来很模糊。那是因为8位通道编码为:
- 0 - > -1.0(外)
- 255 - > +1.0(内部)
好处:
- 单个纹理可用于将字体非常小(6像素)缩放到非常大(200像素+)而不会有任何质量损失,
- 抗锯齿通常是“免费的”。
缺点:
- 必须预渲染所有使用的字形,
- 由于S-L-O-W预处理(约15秒),预处理SDF纹理通常是“离线”的,
- 没有多少人了解如何生成高质量的抗锯齿。由于人们在纹理空间而不是屏幕空间进行插值,因此
smoothstep()
和fwidth()
等黑客会给出质量较差的缩放结果。 WebGL的fwidth()
使用错误的常量也没有帮助。 - 单通道SDF不会像Valve在他们的论文中暗示的那样保留边缘。他们的解决方案是使用多通道SDF,但没有提供任何细节。见Chlumsky Viktor Master thesis或他的开源msdfgen
- 如果以小尺寸使用SDF字体,则需要“单元格填充”或几个像素的边框。
- 仅支持单色字体
总而言之,如果你有多种字体,那么SDF字体在两种尺寸(仅需要1)和质量(在小尺寸和大尺寸上看起来都很棒)都是一个巨大的胜利
SDF演示
- Michaelangel007的SDF vs Bitmap shadertoy演示
- Konstantin Käfer's MapboxGL SDF Demo
- SDF subpixel antialiasing demo
- Multi-Channel SDF shadertoy by P Malin
- Multi-Channel SDF Texture
Fonts on the GPU
人们正在探索在GPU上存储三次曲线,并通过智能片段着色器完成所有渲染的繁重工作来完全绕过纹理。
此blog截至2017年2月的字体渲染摘要。
Advantages
- 正常和大尺寸的高品质雕文
Disadvantages
- 高着色器成本和复杂性
- 有小尺寸的质量问题
GPU字体演示
- 将Dobbie的Vector Texture
Canvas Overlay
对于我当前的项目,我使用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。
其他方案:
- 将文本渲染到您的位图和更高的分辨率,并绘制它们或更小的分辨率。
- 使用曲线渲染器。 (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html)
Pixi.js同意上面针对SDF的建议。
https://github.com/PixelsCommander/pixi-sdf-text
他们说(并且他们是浏览器的优秀游戏项目)
SDF是在WebGL中绘制文本的最有效方式。它使用特殊类型的栅格图集和GLSL着色器在GPU上以非常高效的方式绘制矢量可伸缩文本。
this来自MapBox,至少在某些时候也是如此。
以上是关于WebGL中更好的文本质量的主要内容,如果未能解决你的问题,请参考以下文章