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
[ ツッコむ ]
以上、1 日分です。