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 まで対応。
環境は Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。
文字は等幅フォント、かつ、0/1の二値とする。ASCIIコード 0x20 - 0x7f まで対応。
◎ 動作結果 :
先に動作結果を載せておく。

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

ということで、FreeBASIC + OpenGL で、ビットマップフォントを使って文字描画できると分かった。
◎ ソース :
先にファイル一式を置いておく。
_glbitmap_font_20240225.zip
各ソースも一応載せておく。
以下は、文字描画を担当する部分。
_glbitmapfont.bi
ビットマップフォントデータが配列の形で入っていて、文字描画を担当する glDrawBitmapText() というサブルーチンも入ってる。
処理をしているところだけ抜き出して貼っておく。
使用サンプルは以下。カーソルキーの上下でフォント種類を切り替えることができるようにしておいた。
_glbitmapfont_test1.bas
_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
使い方は以下。
以下のような変換結果が得られる。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
_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
_グラフィックス科学演習 / Graphics Science Seminar
[ ツッコむ ]
以上です。