top of page
Search
deaconrzb

Rendering text with OpenTK and FreeType: A cross-platform solution



Contrary to what you might expect, rendering a simple string is quite difficult with a low-level library like OpenGL. But basically, you iterate through the string, rendering a textured quad for each character.




OpenTK text renderer



Then, when the application loads, create a VAO for each character, containing the vertex positions (size of the quad) and it's texture co-ordinates. This font is monospaced so the vertex positions are simply:


OpenGL and OpenTK do not support any built-in text rendering. Essentially, they are too "low-level" for that. Nevertheless, many applications, such as yours, require text rendering, and significant work has been done to find efficient ways to render text via OpenGL (and OpenTK as well, of course). One popular technique is based on "distance fields," made famous by a 2007 SIGGRAPH paper, from Chris Green. In my own applications, I have implemented support for text rendering on top of OpenTK using techniques based on distance fields, and have been very pleased by the overall quality, performance, and flexibility of this approach:


One possibility would be to use FreeType library to load a TrueType Font to texture objects.SharpFont provides Cross-platform FreeType bindings for C#.The source can be found at GitHub - Robmaister/SharpFont.(x64 SharpFont.dll and freetype6.dll from MonoGame.Dependencies)


This article shall help to get a quick overview about the text rendering options for OpenGL/OpenTK, espeially for the MONO/.NET programming languages. I want to share my findings and help programmers, which are looking for a solution, that fits their needs.


Let's start with a short discussion about the INNOVATIVE approach: This method requires a powerful GPU and a considerable amout of texture buffer memory on the one hand but it relieves the CPU remarkable on the other hand. Currently there is exactly one known implementation: GLyphy. IMO this will definitively be the approach of the future. Future because GLyphy detected various implementation errors in Mesa, almost all video drivers and pixel shaders it has been tested for. And they have to be fixed before it can be used widely.


On X11 the Mono wrapper for Pango or Cairo's Pango calls could be a good alternative to Mono's System.Drawing.Graphics namespace (Windows GDI replica). Cairo offers Cairo.Context.ShowText() and Cairo.Context.TextExtents() as an equivalent to System.Drawing.Graphics.DrawString() and System.Drawing.Graphics.MeasureString(). But i didn't find code "ready to use" that implements the required functionality for application in the context of OpenTK.


The practice 1.b. (glyphs to intermediate texture bitmap, excerpts to final texture bitmap) is a little bit "reinventing the wheel". Because to render the glyphs of a font to an (intermediate) bitmap is the same thing that Windows GDI or X11 font server already do.


Cons: A lot of effort for creation and management of the (intermediade) font bitmaps. As well as for extraction of glyph texture's excerpts and combination to a string. Program initialization requires font bitmap initialization and consumes runtime.


The practice 1.c. (bitmap-font to intermediate texture bitmap, excerpts to final texture bitmap) is similar to practice 1.b, but it doesn't provide the same fonts as the Windows GDI or X11 font server already do - it provides fonts from specific bitmap font files. This practice is typically used by games.


Cons: A lot of effort for creation and management of the font bitmaps. As well as for extraction of glyph texture's excerpts and combination to a string. Specific font files are required. Program initialization requires font bitmap initialization but is much faster than 1.b.


Description: The creation of font bitmaps can be completely separated (by time, by resources, by location) from their usage. Artificial or texture fonts are easy to achieve. Most of the fonts are monospaced, but proportional fonts are possible - they need the glyph widths in addition to the bitmap provided by the font file.


I've found the 'missing piece' to use FreeType instead of Mono's GDI implementation (System.Drawing.Graphics class) within the articles Rendering FreeType/2 with OpenGL and Rendering AltNETType (= .NET FreeType port) with OpenGL. They led me to the FtFont class that joins ideas from OpenGL 3.3+ text..., freetype-gl and FreeType Fonts.


Instead using TextPrinter, the whole OpenTK community recommends to write an own text printer. But TextPrinter is still present, produces very good output quality and is open source (can be copied and used, even if it would be removed from OpenTK.Compatibility.dll in remote future).


The sample programs FreeTypeGlyphWise-Test and FreeTypeLineWise-Test will also take a closer look to the aspect 'write an own text printer' and are faster than the TextRenderer technology.


During the work on the sample solution FreeTypeLineWise-Test i've been faced with residues as well and solved it with two extra scan-lines within the intermediate bitmap, one obove and one below the glyphs. I think the extraction of glyph texture's excerpt from the intermediate bitmap, that is done with glTexCoord2() on a coordinate range 0.0 ... 1.0, has insufficient precisition and causes the problems. Probably extra scan-lines within the intermediate bitmap would solve the problem for QuickFont too.


The FreeTypeLineWise-Test sample advances the FtFont class to support string rendering instead character rendering (that is mapping the text glyph texture by glyph texture to the viewport). The output quality using FtFont class' second version is excellent as well.


The FreeTypeDynamic-Test sample advances the FreeTypeLineWise-Test sample and FtFont class to support dynamic glyph appending to the glyph texture. The output quality using FtFont class' third version is excellent as well.


The next image shows a sample output with FtFont class' third version and seven coloured different fonts. The quality is excellent. No off-color pixel, no residues. The glypht positioning has been reworked, now the text output complies with the font metrics.


The next image shows a sample output with TexLib and seven different fonts. The quality is varying. The delivered bitmap font big-outline has cut-off ascenders and descenders, the other font bitmaps are created quick and dirty and show only black text. The acquisition of ready-to-use high quality font bitmap files seems to be a problem. The limitation of TexLib to 16 x 16 glyps is a restriction.


The next image shows a sample output with TextRenderer (first red text line) compared to TextPrinter (second red line) and QuickFont (third red line). The quality is excellent. No off-color pixel, no residues.


There is a very interesting article Texts Rasterization Exposures about text rendering detalis written for the Anti-Grain Geometry (AGG) library. The text rendering detalis that are discussed, are namely:


The subsequent image shows gray-scale anti-aliased text with color fidelity (on the left) and sub-pixel positioned text with brightness fidelity (on the right), zommed to 400%. Both texts have been rendered with WPF (.NET 4.5) and have different pixel set on different positions.


This is the first version from 21. November 2015.The second version is from 13. January 2016 (improved TextRenderer and new FreeType samples FreeTypeGlyphWise and FreeTypeLineWise; text improvements).The third version is from 04. July 2016 (text fixes and improvements; additional links).The fourth version is from 03. October 2018 (text fixes and improvements; additional links).The fifth version is from 27. October 2018 (new FreeTypeDanamic and FreeType sample; text improvements).


Libdrawtext uses freetype2 for glyph rasterization. If you would rather avoidhaving freetype2 as a dependency, you can optionally compile libdrawtext without it,and use pre-rendered glyphmaps. Glyphmaps can be generated by the includedfont2glyphmap tool, or by calling dtx_save_glyphmap.


Copyright (C) 2011-2016 JohnTsiombikas. You may freely use, modify and/or redistribute libdrawtext,under the terms of the GNU Lesser General Public License (LGPL) version 3 (or atyour option, any later version published by the Free Software Foundation). SeeCOPYING, and COPYING.LESSER for details.


OpenTK exposes this through NativeWindow in the form of its Context property and its MakeCurrent() method. Context is an IGraphicsContext, and includes low-level OpenGL operations like MakeCurrent() and MakeNoneCurrent() and SwapBuffers().


When creating a NativeWindow, you pass a NativeWindowSettings object to describe what kind of OpenGL context you need. To enable compatibility mode, you change the ContextProfile of the NativeWindowSettings:


I promised to enhance the scroll behavior. Here it is. You can influence the text in various ways. When the zoom factor turns negative you can even see upside down characters. Also the drift can turn negative; if so the wave moves to the left, but its peaks drift to the right.Weirdly enough it is a lot of fun playing with the sliders and watching the wave change. Of course, we could still create far more complex movements. This source code here is providing the full basics. The rest is up to you.


Oh, I used to write so called intros with scrolling text slogans at the bottom on the Commodore Amiga. The hardware was pretty much unalterable and you could easily work with the Blitter and Copper. The vertical blank beam on the monitor was my timer. These days are over. No more Assembler. And who cares about high and low byte these days?


I have to admit that using C# in combination with WPF is not the best approach for moving text around. You should directly talk to graphic cards for such. Anyway, it started with a short benchmark test and ended up with this example program. If you program properly, then you can make WPF do the job without any flickering. 2ff7e9595c


0 views0 comments

Recent Posts

See All

Download do WSJT-Z

Como baixar e usar o WSJT-Z para comunicação digital de rádio amador Se você está interessado em explorar o mundo dos modos digitais para...

Comments


bottom of page