chandragon's picture

How to render text on the screen

I feel a bit of shame asking such a basic thing, but how do I render text on the screen ?
I searched for classes that could do that and found on internet that many people use a "TextPrinter" instance, but I don't find that class in OpenTK.Graphics.
I read in a post of this forum that it would be in "OpenTK.Compatibility", but I don't have it, has it been removed from the newer versions of OpenTK ? is there any substitute for the TextPrinter ?
Thanks for the answers !


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
David's picture


Here is a modified version of Chandragon's code, with the projection working. Hope this can help ppl landing on that thread.

Just create and instance of MyTextWriter and call Update/AddText whenever the text change. Call Draw in the drawing loop.

class MyTextWriter
            private readonly Font TextFont = new Font(FontFamily.GenericSansSerif, 8);
            private readonly Bitmap TextBitmap;
            private List<PointF> _positions;
            private List<string> _lines;
            private List<Brush> _colours;
            private int _textureId;
            private Size _clientSize;
            public void Update(int ind, string newText)
                if (ind < _lines.Count)
                    _lines[ind] = newText;
            public MyTextWriter(Size ClientSize, Size areaSize)
                _positions = new List<PointF>();
                _lines = new List<string>();
                _colours = new List<Brush>();
                TextBitmap = new Bitmap(areaSize.Width, areaSize.Height);
                this._clientSize = ClientSize;
                _textureId = CreateTexture();
            private int CreateTexture()
                int textureId;
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (float)TextureEnvMode.Replace);//Important, or wrong color on some computers
                Bitmap bitmap = TextBitmap;
                GL.GenTextures(1, out textureId);
                GL.BindTexture(TextureTarget.Texture2D, textureId);
                BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
                //    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest);
                //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest);
                return textureId;
            public void Dispose()
                if (_textureId > 0)
            public void Clear()
            public void AddLine(string s, PointF pos, Brush col)
            public void UpdateText()
                if (_lines.Count > 0)
                    using (Graphics gfx = Graphics.FromImage(TextBitmap))
                        gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                        for (int i = 0; i < _lines.Count; i++)
                            gfx.DrawString(_lines[i], TextFont, _colours[i], _positions[i]);
                    System.Drawing.Imaging.BitmapData data = TextBitmap.LockBits(new Rectangle(0, 0, TextBitmap.Width, TextBitmap.Height),
                        System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, TextBitmap.Width, TextBitmap.Height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
            public void Draw()
                Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, _clientSize.Width, _clientSize.Height, 0, -1, 1);
                GL.LoadMatrix(ref ortho_projection);
                GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.DstColor);
                GL.BindTexture(TextureTarget.Texture2D, _textureId);
                GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
                GL.TexCoord2(1, 0); GL.Vertex2(TextBitmap.Width, 0);
                GL.TexCoord2(1, 1); GL.Vertex2(TextBitmap.Width, TextBitmap.Height);
                GL.TexCoord2(0, 1); GL.Vertex2(0, TextBitmap.Height);
the Fiddler's picture

Thanks for the book page, this is a question that gets asked a lot. I will add the code to the sample browser.

juanfhj's picture

Hi fictiveLaark,

I managed to use your code, but the text background is always black. Can you show me where I can change that? THanks

c2woody's picture

Hope you already did the obvious and searched the code for Color.Black.

thorrablot's picture

Thanks for posting the code - this works pretty well, except I found I had to fall back to TextRenderingHint.SingleBitPerPixelGridFit (no AA) or the text looked really awful when overlaid on background images.

Has anyone tried support for BitmapFonts in OpenTK, e.g.

puklaus's picture

Why this excellent font library and routines isnt any more in core of otk? I liked these a lot, my bitmap font rendering system sucks
when comparing to them, and when I tried some dynamic texts on that one example, it does not work the way I needed (was calculating
wrong bboxes or so, dont remember but havent tested it so much, maybe I write wrong my code already).

praveendm's picture

Hi David,
Thanx for the code.
This works perfectly fine on 32 bit machine but when I compile on 64 bit machine, only white screen is displayed. Am I missing something??

Dread_Boy's picture

I used the class you provided, but I can't get it working.

How I tried to use it:

class Game : GameWindow
TextWriter text_writer;
public Game()
: base(1280, 720, GraphicsMode.Default, "A Dusty Path")
VSync = VSyncMode.On;
text_writer = new TextWriter(new Size(1280, 720), new Size(1280, 720));
text_writer.AddLine("Prva vrsta", new PointF(0, 0), Brushes.Red);
text_writer.AddLine("Druga vrsta", new PointF(100, 200), Brushes.Blue);
text_writer.Update(1, "2. vrstica");
protected override void OnRenderFrame(FrameEventArgs e)

I'm not sure what areaSize actually does but as far as I can understand it controls the size of bitmap created from text. My project is empty except these two snippets, default methods and GL.ClearColor(1f, 1f, 1f, 1f); in Onload method. Can anybody help me please?

AltSoftLab's picture
Dread_Boy wrote:

Can anybody help me please?

You can use QuickFont or AltSketch.QuickFont basically to render text

Gottn's picture

I got this code working, only problem is that i get a trasparent black background behind the text. I tried to set gfx.Clear color to Color.Transparent, inside the UpdateText-function but nothing changed. I would like to know if there is a way to change the background color behind the text.