chandragon's picture

How to render text on the screen

Hi
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 !


Comments

Comment viewing options

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

You probably need to enable alpha-blending.

Gottn's picture

EDIT: I got it working now change the last parameter in this function GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.DstAlpha); From BlendingFactorDest.DstColor to BlendingFactorDest.DstAlpha.

bjthm's picture

Is it possible to make the background of the text transparent? I tried to adjust the parameters of the BlendFunction, but i cannot get the right thing.

the Fiddler's picture

Have you called GL.Enable(EnableCap.Blending)?

bjthm's picture

yes, i have called GL.Enable(EnableCap.Blending), but it did not work.
The code rewritten from David’s MyTextwriter class is liste below.
Thanks for your reply.

Public Class TextWriter
    Private TextFont As Font = New Font(FontFamily.GenericSansSerif, 8) '字体
    Private TextBitmap As Bitmap 'TextBitmap用于承载所绘制文本
    Private _positions As New List(Of PointF) '各行文本在TextBitMap中的位置(左上角为原点)
    Private _lines As New List(Of String) '各行文本的内容
    Private _colours As New List(Of Brush) '各行文本的颜色
    Private _textureId As Integer '纹理ID
    Private _clientSize As Size '绘图区域
 
    '更新TextBitmap中的第ind行文本
    Public Sub Update(ind As Integer, newText As String)
        If ind < _lines.Count Then
            _lines(ind) = newText
            UpdateText()
        End If
    End Sub
 
    '初始化函数 ClientSize表示绘图区大小,areaSize表示Bitmap的大小,font为字体
    Public Sub New(ClientSize As Size, areaSize As Size, font As Font)
        _positions = New List(Of PointF)
        _lines = New List(Of String)
        _colours = New List(Of Brush)
        TextFont = font
        TextBitmap = New Bitmap(areaSize.Width, areaSize.Height)
        _clientSize = ClientSize
        _textureId = CreateTexture()
    End Sub
 
    Private Function CreateTexture() As Integer
        Dim textureId As Integer
        GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, TextureEnvMode.Replace) 'Important, or wrong color on some computers
        Dim bitmap As Bitmap = TextBitmap
        GL.GenTextures(1, textureId)
        GL.BindTexture(TextureTarget.Texture2D, textureId)
        Dim data As BitmapData = 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, TextureMinFilter.Linear)
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureMagFilter.Linear)
        'GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, All.Nearest)
        'GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, All.Nearest)
        GL.Finish()
        bitmap.UnlockBits(data)
        Return textureId
    End Function
 
    Public Sub Dispose()
        If _textureId > 0 Then
            GL.DeleteTexture(_textureId)
        End If
    End Sub
 
    Public Sub Clear()
        _lines.Clear()
        _positions.Clear()
        _colours.Clear()
    End Sub
 
    '在Bitmap中增加一行文本
    Public Sub AddLine(s As String, pos As PointF, col As Brush)
        _lines.Add(s)
        _positions.Add(pos)
        _colours.Add(col)
        UpdateText()
    End Sub
 
    Public Sub UpdateText()
        If _lines.Count > 0 Then
            Dim gfx As Drawing.Graphics = Drawing.Graphics.FromImage(TextBitmap)
            gfx.Clear(Color.White) 
            gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit
            For i As Integer = 0 To _lines.Count - 1
                gfx.DrawString(_lines(i), TextFont, _colours(i), _positions(i))
            Next	
 
            Dim data As BitmapData = TextBitmap.LockBits(New Rectangle(0, 0, TextBitmap.Width, TextBitmap.Height), 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)
            TextBitmap.UnlockBits(data)
            gfx.Dispose()
        End If
    End Sub
 
    ''' <summary>
    ''' 绘制文本
    ''' 坐标原点在左上角,向右为X正方向,向下为Y正方向
    ''' width为宽度(像素),height为高度(像素)
    ''' </summary>
    Public Sub Draw(x As Single, y As Integer, width As Single, height As Single)
        Dim ortho_projection As Matrix4
        GL.PushMatrix()
        GL.LoadIdentity()
        ortho_projection = Matrix4.CreateOrthographicOffCenter(0, _clientSize.Width, _clientSize.Height, 0, -1, 1)
        GL.MatrixMode(MatrixMode.Projection)
        GL.PushMatrix()
        GL.LoadMatrix(ortho_projection)
        GL.Enable(EnableCap.Blend)
        GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.DstAlpha) ' BlendingFactorDest.DstColor
 
        GL.Enable(EnableCap.Texture2D)
        GL.BindTexture(TextureTarget.Texture2D, _textureId)
        GL.Begin(PrimitiveType.Quads)
        GL.TexCoord2(0, 0) : GL.Vertex2(x, y)
        GL.TexCoord2(1, 0) : GL.Vertex2(x + width, y)
        GL.TexCoord2(1, 1) : GL.Vertex2(x + width, y + height)
        GL.TexCoord2(0, 1) : GL.Vertex2(x, y + height)
        GL.End()
        GL.PopMatrix()
        GL.Disable(EnableCap.Blend)
        GL.Disable(EnableCap.Texture2D)
        GL.MatrixMode(MatrixMode.Modelview)
        GL.PopMatrix()
    End Sub
End Class
the Fiddler's picture

You are setting the background to white:

gfx.Clear(Color.White)

This means that alpha blending will not work. Have you tried any other blending modes?

You could also try with a transparent background:

gfx.Clear(Color.Transparent)

This should make alpha blending work.

mtronic's picture

Hello

After updating opentk to 1.1.2 I've been getting an InvalidValue exception from the line

GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, TextBitmap.Width, TextBitmap.Height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

in UpdateText() from the example solution. I noticed that the TexSubImage2D function is deprecated, but I dont know enough about opengl yet to update it.. Can anyone help?

the Fiddler's picture

Did you update from 1.1.1 to 1.1.2 or from 1.0 to 1.1.2?

mtronic's picture

ah, from 1.0

the Fiddler's picture

Can you please run the "Text Rendering" example? You can find this in OpenTK.sln -> OpenTK.Examples, under OpenGL -> Text Rendering.

Does that also fail with an InvalidValue error? (It would help if you run it in debug mode, which turns GL errors into exceptions.)