问题描述
我正在寻找一种在WebGL中绘制更好质量(任意)文本的方法。目前我在2D画布上使用位图字体渲染并将它们放入WebGL上下文中。
I am searching a method to draw better quality (arbitrary) text inside WebGL. Currently I am using bitmap font rendering on a 2D canvas and blitting them into the WebGL context.
此方法在此描述
这是唯一的我现在知道的在WebGL中绘制任意unicode文本的解决方案。这种方法的问题是这些是位图字体,并且在较小的字体大小上看起来很块。我大多使用字体大小为18,与桌面质量字体相比,结果相当块状。
This is the only solution for drawing arbitrary unicode text inside WebGL I know of right now. The problem with this method is that these are bitmap fonts and look blocky on smaller font sizes. I mostly use a font size of 18 and the result is quite blocky compared to desktop quality fonts.
我知道threeJS有一个字体库,可生成更好看的文字,但是我不想使用threeJS,因为我有自己的包装器,它可以正常工作,我不需要添加额外的三JS开销。
I know that threeJS has a font library which generates better looking text, however I do not want to use threeJS as I have my own wrapper which is working fine for what I need and don't want to add the additional overhead of threeJS.
所以如何在WebGL中创建更高质量的文本?有没有方法在Javascript中提取文本形状以提高质量?
So how to create better quality text in WebGL ? Are there methods to extract text shapes in Javascript to improve quality ?
推荐答案
使用字体一段时间之后,我可以看到6在WebGL中做字体的方法,都有优点和缺点:
After working with Fonts for some time, I can see 6 ways to do fonts in WebGL, all with advantages and disadvantages:
- 获取一个类似Google的开源字体(和非常受欢迎)
- 使用OpenType或类似内容()
- 对字符曲线进行三角测量。我最喜欢的是Earcut,因为它非常快
- 将每个字符的多边形绘制为普通的WebGL三角形。
- Get an open source font like the ones from Google (Open Sans and Roboto are very popular)
- Read out the curves of the font using OpenType or similar (https://nodebox.github.io/opentype.js/)
- Triangulate the characters curves. My favorite for this is Earcut as it is very fast https://github.com/mapbox/earcut
- Draw the polygons for each character as normal WebGL triangles.
优点
- 非常快,如果你有很多文字并需要全功能字体,这是你最好的选择。通过矩阵操作在GPU上完成字体缩放。
- 渲染字体的质量取决于WebGL浏览器启用的抗锯齿功能。 Safari执行8x8 AA看起来不错,但所有其他浏览器只使用4x4,这可能看起来很块。此外,移动浏览器根本不启用AA,使得移动设备上的字体看起来非常块状。
- 体面质量。
- 速度,取决于您需要在多长时间内呈现的文本数量。特别是如果你只需要渲染静态文本。
- 简单易懂
- 创建纹理图集的琐碎
- 可以使用彩色字体
- 放大时看起来非常模糊
- 必须预渲染所有字形已使用
- 每个字体大小需要纹理
- 需要,以获得最佳纹理效果。
- Looks horribly blurry when scaled up
- Must pre-render all glyphs that are used
- Requires a texture per font size
- Requires texture bin packing for optimal texture usage. Example
- 0 - > -1.0(外部)
- 255 - > +1.0(内部)
- 单个纹理可用于将字体非常小(6像素)缩放到非常巨大的(200像素+)没有任何质量损失,
- 抗锯齿通常是免费。
- 必须预渲染所有使用的字形,
- 由于SLOW预处理(约15秒),预处理SDF纹理通常是离线,
- 没有多少人了解如何生成高质量的抗锯齿。诸如
smoothstep()
和fwidth()
之类的黑客会因为人物在纹理空间中进行插值而导致质量不佳的缩放结果屏幕空间。 WebGL的fwidth()
使用错误的常量也没有帮助。 - 单通道SDF不会将边缘保留为Valve在他们的论文中暗示过。他们的解决方案是使用多通道SDF,但没有提供任何细节。见Chlumsky Viktor 或他的开源
- 需要单元格填充如果小尺寸使用SDF字体,则为几个像素的边框。
- 仅支持单色字体
- Must pre-render all glyphs that are used,
- Pre-processing the SDF texture is normally done "offline" due to the S-L-O-W preprocessing (~15 seconds),
- Not many people understand how to generate quality anti-aliasing. Hacks such as
smoothstep()
andfwidth()
give poor quality scaled results due to people interpolating in texture space instead of screenspace. It also doesn't help that WebGL'sfwidth()
uses the wrong constant. - Single Channel SDF's doesn't preserve edges as Valve hinted at in their paper. Their solution was to using a multi-channel SDF but didn't provide any details. See Chlumsky Viktor Master thesis or his open source msdfgen
- Requires "cell padding" or a border of a few pixels if SDF fonts are used at small sizes.
- Only monochrome fonts are supported
- Michaelangel007的 shadertoy demo
- Michaelangel007's SDF vs Bitmap shadertoy demo
- Konstantin Käfer's MapboxGL SDF Demo
- SDF subpixel antialiasing demo
- Multi-Channel SDF shadertoy by P Malin
- Multi-Channel SDF Texture
- 正常和大尺寸的高品质标志符号
- 高着色器成本和复杂性
- 小尺寸质量问题
- Will Dobbie的
- Will Dobbie's Vector Texture
这也称为On Demand Dynamic Textures。将文本字形仅渲染到(屏幕外)画布并将其作为WebGL纹理显示在屏幕上,如下所述:
This is also called "On Demand Dynamic Textures". Render only the text glyphs to the (offscreen) canvas and blit it to the screen as a WebGL texture, as described here: http://delphic.me.uk/webgltext.html
游戏帝国时代III 使用这种方法。
如果你想获得最佳速度和最佳速度对于有限的字符集和固定字符大小(游戏)的质量,最好创建自己的位图,其中包含您想要使用的字符,并根据需要将它们显示在屏幕上。您可以在互联网上找到相当多的这些字符位图。
If you want max speed with best quality for a limited set of characters and a fixed character size (Game), it is probably best to create your own bitmap featuring the characters you want to use and blit them to the screen as needed. You can find quite a few of these character bitmaps predone on the internet.
这是快速而简单的,但限制了您可以使用的语言和字符,但您不会介意例如,在游戏中。
This is fast and easy, but limits the languages and characters you can use but you would not mind this in a Game for example.
Valve的Chris Green写了关于使用纹理的符号距离字段的书。您需要阅读2007 SIGGRAPH白皮书
Chris Green of Valve wrote the "book" on using Signed-Distance Fields for textures. You'll want to read the 2007 SIGGRAPH whitepaper "Improved Alpha-Tested Magnification for Vector Textures and Special Effects
通常字体纹理图集看起来像 .SDF纹理看起来像。是的,当按原样呈现时,SDF纹理图集看起来很模糊。这是因为8位通道编码为:
Normally a font texture atlas looks like this. A SDF texture looks like. Yes, the SDF texture atlas looks blurry when rendered "as-is". That's because the 8-bit channel has been encoded as:
这就是说,如果你有多种字体,那么SDF字体在两种尺寸(仅需要1)和质量(在小尺寸和大尺寸上看起来都很棒)都可以获得巨大的胜利。
That all said, if you have multiple fonts then SDF fonts can be a huge win in both size (only need 1) and quality (looks fantastic at both small and large sizes)
人们正在探索在GPU上存储三次曲线,并通过智能片段着色器完成所有渲染的繁重工作来完全绕过纹理。
People are exploring storing the cubic curves on the GPU and bypassing the texture entirely via having a smart fragment shader do all the heavy lifting of rendering.
这有截至2017年2月的字体渲染摘要。
This blog has a summary of Font Rendering as of February 2017.
对于我当前的项目,我使用HTML5 2D画布渲染文本和其他2D基元,并使用WebgGL画布上的透明度覆盖它。我对速度感到惊讶,它在速度和质量方面都比其他所有方法都要好。
For my current project I use an HTML5 2D canvas to render text and other 2D primitives and overlay it using transparency over the WebgGL canvas. I was surprised at the resulting speed, it beats all other methods described here in speed and quality is very good.
只要你的文字是静态2D而你不是需要任何3D转换,这将是我的建议。在我的项目中,这比我之前使用的方法(Font as Geometry)快了约2倍。
As long as your text is static 2D and you do not need any 3D transformations, this would be my recommendation. In my project this is about 2 times faster than the previous method I used (Font as Geometry).
这篇关于WebGL中更好的文本质量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!