mieki256's diary



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

#1 [basic] FreeBASICで画像を拡大描画する方法を勉強中。その2

FreeBASICで、QVGA(320x240)サイズの画像バッファにCPUで描画して、それをデスクトップ画面全体に拡大表示したい。

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

まずは画像バッファに描画する方法を調べないといかんのだけど、ざっとググっても方法が見つからなくて、さては FreeBASICは画像バッファに描画できないのかなと…。だとしたら、画面表示で使ってるバッファに一旦描画して、それを拡大するしかないのかなと、そのあたりを試し始めた。

ちなみに後で再度調べたら、各描画命令の最初の引数に書き込みたい画像バッファのポインタを渡すだけで目的は果たせる模様。調べ方が足りなかった。

OpenGLで画面全体に拡大表示 :

OpenGL で画面全体に拡大表示する方法でどうにかできないか試してみた。線、円、画像を描画するところはCPUで処理して、最後の拡大表示だけ OpenGL を使う。

この方法は整数倍しかできないので、元解像度とデスクトップ解像度の組み合わせによっては、画面全体に表示できない状態になる。

そこで、元解像度とは別に、デスクトップ画面の1/Nのサイズになる解像度を決めてしまって、そのサイズ内で、描画範囲を指定する view() を使って、実際に描画する範囲を元解像度で固定してしまう方法でどうにかしようと試みた。

ソースは以下。元解像度は320x240にして、それをデスクトップ解像度に拡大する。

_gl_scaling.bas
#define NO_BLUR 1  'change to 1
'Const SCRW = 320 : Const SCRH = 180
Const SCRW = 320 : Const SCRH = 240

#include "fbgfx.bi"
Using fb

' set screen depth
Dim As Integer sdepth = 32
Select Case Command(1)
Case "8"  : sdepth = 8
Case "16" : sdepth = 16
Case "32" : sdepth = 32
End Select

' get desktop size
Dim As Integer dispw, disph
ScreenInfo dispw, disph

' get scale (Integer)
Dim As Integer dscale = Int(disph / SCRH)
If dscale > (dispw / SCRW) Then dscale = Int(dispw / SCRW)

' ge true screen size
Dim As Integer tscrw, tscrh
tscrw = dispw / dscale
tscrh = disph / dscale

If (tscrw * dscale) <> dispw Then tscrw += (dispw - (tscrw * dscale))
If (tscrh * dscale) <> disph Then tscrh += (disph - (tscrh * dscale))

screencontrol(SET_GL_2D_MODE, OGL_2D_MANUAL_SYNC)
screencontrol(SET_GL_SCALE, dscale)

ScreenRes tscrw, tscrh, sdepth, , GFX_OPENGL Or GFX_NO_FRAME

#if (NO_BLUR = 1)
#include "GL/gl.bi"
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
#endif

Dim As Double angle = 0.0
Dim As Boolean running = True

Const PI = 3.1415926535897932

' Main Loop

Do
    If Inkey <> "" Then running = False

    ' set true screen view size
    view (0, 0) - (tscrw - 1, tscrh - 1), RGB(0, 0, 0)

    ' set draw area size
    Dim As Integer ox, oy
    ox = (tscrw - SCRW) * 0.5
    oy = (tscrh - SCRH) * 0.5
    view (ox, oy) - (SCRW - 1 + ox, SCRH - 1 + oy), RGB(30, 60, 120)

    ' clear screen
    Color RGB(255, 255, 255), RGB(30, 60, 120)
    cls
    
    Circle (SCRW \ 2, SCRH \ 2), (SCRH \ 2 - 1), RGB(0, 255, 0)

    Dim As Integer x, y, r
    r = SCRH / 4
    x = (SCRW / 2 - r - 1) * Cos(angle * PI / 180.0) + (SCRW / 2)
    y = (SCRH / 2 - r - 1) * Sin(angle * PI / 180.0) + (SCRH / 2)
    Circle (x, y), r, RGB(0, 255, 255)

    Draw String (0, 0), Str(SCRW) & "x" & SCRH & " (" & tscrw & "x" & tscrh & ")x" & dscale, RGB(255, 255, 255)

    angle += 1.0

    sleep 10
    flip()  ' change double buffer
Loop While running

fbc gl_scaling.bas でコンパイル。gl_scaling.exe を実行した結果は以下。




OpenGL を使っているからキャプチャ時に黒画面が入ってしまっているけれど、実際の動作画面では瞬時に切り替わってる。デスクトップ画面全体に表示することはできてないけれど、元解像度がそれなりの大きさで拡大表示されてることぐらいは分かるかなと…。

昨日もメモしたけれど、肝は以下。
#include "fbgfx.bi"
Using fb

' ...

screencontrol(SET_GL_2D_MODE, OGL_2D_MANUAL_SYNC)
screencontrol(SET_GL_SCALE, dscale)

ScreenRes tscrw, tscrh, sdepth, , GFX_OPENGL Or GFX_NO_FRAME

#include "GL/gl.bi"
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

Do
    ' ...

    sleep 10
    flip()  ' change double buffer
Loop While running

  • ScreenControl() で、SET_GL_2D_MODE や SET_GL_SCALE を設定。
  • SET_GL_SCALE で拡大率を整数で指定。
  • ScreenRes の最後で、GFX_OPENGL を指定。
  • OpenGL利用時は flip() でダブルバッファを切り替えるけど、必ずループの中で呼ばないとハングアップする。

以上、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