mieki256's diary



2024/02/25() [n年前の日記]

#1 [basic] FreeBASICとOpenGLで文字描画をしてみる

_昨日、 FreeBASIC + OpenGL で、二値のbitmapを描画する glBitmap() を利用してみた。その glBitmap() を使ってビットマップフォントの文字描画をしてみたい。

環境は Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。

文字は等幅フォント、かつ、0/1の二値とする。ASCIIコード 0x20 - 0x7f まで対応。

動作結果 :

先に動作結果を載せておく。

glbitmapfont_test1_ss.gif


ということで、FreeBASIC + OpenGL で、ビットマップフォントを使って文字描画できると分かった。

ソース :

先にファイル一式を置いておく。

_glbitmap_font_20240225.zip
  • プログラム部分の License は CC0 / Public Domain。
  • 内包しているフォントデータについては各フォントのライセンスを確認のこと。


各ソースも一応載せておく。

以下は、文字描画を担当する部分。

_glbitmapfont.bi

ビットマップフォントデータが配列の形で入っていて、文字描画を担当する glDrawBitmapText() というサブルーチンも入ってる。

処理をしているところだけ抜き出して貼っておく。
#include once "fbgfx.bi"
Using FB
#include once "GL/gl.bi"
#include once "GL/glu.bi"

' ...

Type glbitmapfontinfo
    w As GLsizei
    h As GLsizei
    clen As Integer
    adrs As UByte Ptr
End Type

Const GLBITMAPFONT_COURR18     = 0
Const GLBITMAPFONT_PET2015     = 1
Const GLBITMAPFONT_PROFONT     = 2
Const GLBITMAPFONT_SHNM8X16R   = 3
Const GLBITMAPFONT_SHNM8X16RX2 = 4
Const GLBITMAPFONT_TER_U24B    = 5

Const GLBITMAPFONT_MAX = 6

Dim Shared glBitmapFontInfoTbl( GLBITMAPFONT_MAX - 1 ) As glbitmapfontinfo => { _
  ( FONT_COURR18_PNG_WIDTH, FONT_COURR18_PNG_HEIGHT, FONT_COURR18_PNG_CHR_LEN, @font_courR18_png(0, 0)), _
  ( FONT_PET2015_PNG_WIDTH, FONT_PET2015_PNG_HEIGHT, FONT_PET2015_PNG_CHR_LEN, @font_pet2015_png(0, 0)), _
  ( FONT_PROFONT_PNG_WIDTH, FONT_PROFONT_PNG_HEIGHT, FONT_PROFONT_PNG_CHR_LEN, @font_profont_png(0, 0)), _
  ( FONT_SHNM8X16R_PNG_WIDTH, FONT_SHNM8X16R_PNG_HEIGHT, FONT_SHNM8X16R_PNG_CHR_LEN, @font_shnm8x16r_png(0, 0)), _
  ( FONT_SHNM8X16RX2_PNG_WIDTH, FONT_SHNM8X16RX2_PNG_HEIGHT, FONT_SHNM8X16RX2_PNG_CHR_LEN, @font_shnm8x16rx2_png(0, 0)), _
  ( FONT_TER_U24B_PNG_WIDTH, FONT_TER_U24B_PNG_HEIGHT, FONT_TER_U24B_PNG_CHR_LEN, @font_ter_u24b_png(0, 0)) _
  }

Sub glDrawBitmapText(ByVal text As string, ByVal kind As Integer)
    Dim As GLfloat xorig, yorig, xmove, ymove
    Dim As GLsizei w, h
    Dim As Integer clen
    Dim As ubyte ptr adrs

    If kind < 0 Then kind = 0
    If kind > GLBITMAPFONT_MAX - 1 Then kind = GLBITMAPFONT_MAX - 1

    w = glBitmapFontInfoTbl(kind).w
    h = glBitmapFontInfoTbl(kind).h
    clen = glBitmapFontInfoTbl(kind).clen
    adrs = glBitmapFontInfoTbl(kind).adrs

    xorig = 0
    yorig = 0
    xmove = w
    ymove = 0

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)

    Dim As Integer slen = Len(text)
    For i As Integer = 0 To slen - 1
        Dim As Integer c = text[i]
        If c = 0 Then Exit For

        If c < &H20 Or c > &H7f Then c = &H20
        c -= &H20
        glBitmap(w, h, xorig, yorig, xmove, ymove, adrs + clen * c)
    Next i
End Sub


使用サンプルは以下。カーソルキーの上下でフォント種類を切り替えることができるようにしておいた。

_glbitmapfont_test1.bas
#include once "fbgfx.bi"
Using FB
#include once "GL/gl.bi"
#include once "GL/glu.bi"

#include "glbitmapfont.bi"

ChDir ExePath()

Const SCRW = 480
Const SCRH = 270
ScreenRes SCRW, SCRH, 32, ,GFX_OPENGL

' get window size
Dim shared As Integer scr_w, scr_h, sdepth
ScreenInfo scr_w, scr_h, sdepth

' OpenGL Config
glViewport 0, 0, scr_w, scr_h
glMatrixMode(GL_PROJECTION)
glLoadIdentity()

glOrtho(0, scr_w, scr_h, 0, 5.0, -5.0)
' gluPerspective 45.0, w/h, 0.1, 100.0

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

glClearColor(0, 0, 0, 1)
glShadeModel(GL_SMOOTH)

glDisable(GL_DEPTH_TEST)
' glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

Dim As Boolean running = True

Dim fontlist(GLBITMAPFONT_MAX - 1) As Integer => { _
  GLBITMAPFONT_COURR18, _
  GLBITMAPFONT_PET2015, _
  GLBITMAPFONT_PROFONT, _
  GLBITMAPFONT_SHNM8X16R, _
  GLBITMAPFONT_SHNM8X16RX2, _
  GLBITMAPFONT_TER_U24B _
  }

Dim As Integer fontkind = 0
Dim As Integer fontmax = UBound(fontlist) + 1

' main loop
While running

    ' ESC or Q key to exit
    Dim As String k = inkey$
    If k = Chr$(27) Or k = "q" Or k = Chr$(255) + "k" Then
        running = False
    ElseIf k = Chr$(255) + "H" Then
        ' up key
        fontkind = (fontkind + 1) Mod fontmax
    ElseIf k = Chr$(255) + "P" Then
        ' down key
        fontkind = (fontkind + fontmax - 1) Mod fontmax
    End If

    ' clear screen
    glClear(GL_COLOR_BUFFER_BIT)

    ' draw text
    glColor4f(1, 1, 1, 1)  ' set color
    glRasterPos2f(32, 64)  ' set position
    glDrawBitmapText("Hello World", fontlist(fontkind))

    flip  ' double buffer flip
    sleep 10
Wend

  • #include "glbitmapfont.bi" をして、glDrawBitmapText() を呼び出せば使える。
  • glColor4f() で色を、glRasterPos2f() で描画位置を指定して、glDrawBitmapText() で文字列を描画する。

フォントデータの作り方 :

今回は、以下のビットマップフォント画像を元にしてフォントデータを作ってる。それぞれ、ASCIIコード 0x20 - 0x7f を、16 x 6 個並べた画像になっている。

_font_courR18.png
_font_pet2015.png
_font_profont.png
_font_shnm8x16r.png
_font_shnm8x16rx2.png
_font_ter-u24b.png

この画像を、FreeBASIC の配列の形に変換する。Pythonスクリプトを書いて変換した。

_fontpng2bitsbas.py
  • 動作には Pillow が必要。
  • Python 3.10.10 + Pillow 10.2.0 で動作確認した。
  • License : CC0 / Public Domain

使い方は以下。
python fontpng2bitsbas.py -i image.png

python fontpng2bitsbas.py -i image.png > image.bi

以下のような変換結果が得られる。UByte の二次元配列の中に、ASCIIコード 0x20 - 0x7f 分の bitmap font データが、1bit = 1dot の状態で入っている。

_font_courR18.bi
_font_pet2015.bi
_font_profont.bi
_font_shnm8x16r.bi
_font_shnm8x16rx2.bi
_font_ter-u24b.bi

これらをコピペして、glbitmapfont.bi を作成した。

各フォントの入手先やライセンスは、以下を参照のこと。

_readme.md

余談 :

glut (freeglut) を使える環境なら、glut にビットマップフォント描画機能( glutBitmapCharacter() ) があるので、そちらを使えば済む。

_グラフィックス科学演習 / Graphics Science Seminar

以上、1 日分です。

過去ログ表示

Prev - 2024/02 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project