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.