monolithic kernel

プラグイン無しでOpenGLを用いた描画を行う

HSPからOpenGLを使う方法のメモ。プラグインは使わないのでコンテストのHSPTV部門でも利用可能です。

文章では説明しづらいので以下サンプルのソースコード。HSPTV部門での利用を想定して定数の演算を最適化しています。pfd_nの値は一部0になるので更なる最適化も可能だとは思いますが、そこは本質ではないので割愛。

#uselib "gdi32"
#func SwapBuffers "SwapBuffers" int
#cfunc ChoosePixelFormat "ChoosePixelFormat" int, var
#func SetPixelFormat "SetPixelFormat" int, int, var
#uselib "opengl32"
#cfunc wglCreateContext "wglCreateContext" int
#func wglMakeCurrent "wglMakeCurrent" int, int
#func wglDeleteContext "wglDeleteContext" int
#cfunc wglGetCurrentDC "wglGetCurrentDC"
#func glClear "glClear" int
#func glFinish "glFinish"
#func glBegin "glBegin" int
#func glEnd "glEnd"
#func glVertex2d "glVertex2d" double, double
#func glColor3d "glColor3d" double, double, double
#uselib "user32"
#cfunc GetDC "GetDC" int
#func ReleaseDC "ReleaseDC" int, int
#define GL_TRIANGLES 0x0004
#define GL_COLOR_BUFFER_BIT 0x00004000
#define PFD_DOUBLEBUFFER 0x00000001
#define PFD_DRAW_TO_WINDOW 0x00000004
#define PFD_SUPPORT_OPENGL 0x00000020
#define PFD_TYPE_RGBA 0
#define PFD_MAIN_PLANE 0
// screen 0のDCを取得する。
// システム変数hdcの値は内部バッファのDCなので利用できない。
hdc_ = GetDC(hwnd)
// PIXELFORMATDESCRIPTOR構造体の値を定義する。
#const pfd_nSize 40
#const pfd_nVersion 1
#const pfd_dwFlags (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER)
#const pfd_iPixelType PFD_TYPE_RGBA
#const pfd_cColorBits 24
#const pfd_cRedBits 0
#const pfd_cRedShift 0
#const pfd_cGreenBits 0
#const pfd_cGreenShift 0
#const pfd_cBlueBits 0
#const pfd_cBlueShift 0
#const pfd_cAlphaBits 0
#const pfd_cAlphaShift 0
#const pfd_cAccumBits 0
#const pfd_cAccumRedBits 0
#const pfd_cAccumGreenBits 0
#const pfd_cAccumBlueBits 0
#const pfd_cAccumAlphaBits 0
#const pfd_cDepthBits 0
#const pfd_cStencliBits 0
#const pfd_cAuxBuffers 16
#const pfd_iLayerType PFD_MAIN_PLANE
#const pfd_bReserved 0
#const pfd_dwLayerMask 0
#const pfd_dwVisibleMask 0
#const pfd_dwDamageMask 0
// PIXELFORMATDESCRIPTOR構造体を初期化する。
#const pfd_0 ((pfd_nVersion << 16) | pfd_nSize)
#const pfd_1 (pfd_dwFlags)
#const pfd_2 ((pfd_cRedShift << 24) | (pfd_cRedBits << 16) | (pfd_cColorBits << 8) | pfd_iPixelType)
#const pfd_3 ((pfd_cBlueShift << 24) | (pfd_cBlueBits << 16) | (pfd_cGreenShift << 8) | pfd_cGreenBits)
#const pfd_4 ((pfd_cAccumRedBits << 24) | (pfd_cAccumBits << 16) | (pfd_cAlphaShift << 8) | pfd_cAlphaBits)
#const pfd_5 ((pfd_cDepthBits << 24) | (pfd_cAccumAlphaBits << 16) | (pfd_cAccumBlueBits << 8) | pfd_cAccumGreenBits)
#const pfd_6 ((pfd_bReserved << 24) | (pfd_iLayerType << 16) | (pfd_cAuxBuffers << 8) | pfd_cStencliBits)
#const pfd_7 (pfd_dwLayerMask)
#const pfd_8 (pfd_dwVisibleMask)
#const pfd_9 (pfd_dwDamageMask)
pfd = pfd_0, pfd_1, pfd_2, pfd_3, pfd_4, pfd_5, pfd_6, pfd_7, pfd_8, pfd_9
#undef pfd_0
#undef pfd_1
#undef pfd_2
#undef pfd_3
#undef pfd_4
#undef pfd_5
#undef pfd_6
#undef pfd_7
#undef pfd_8
#undef pfd_9
// ピクセルフォーマットを設定する。
SetPixelFormat hdc_, ChoosePixelFormat(hdc_, pfd), pfd
// コンテキストを生成し、設定する。
hrc = wglCreateContext(hdc_)
wglMakeCurrent hdc_, hrc
onexit *close
*main
// バッファをクリアする。
glClear GL_COLOR_BUFFER_BIT
// 描画を行う。
glBegin GL_TRIANGLES
glColor3d 1
glVertex2d , 1
glColor3d , 1
glVertex2d -1, -1
glColor3d , , 1
glVertex2d 1, -1
glEnd
// 描画を終了する。
glFinish
SwapBuffers wglGetCurrentDC()
await 30
goto *main
*close
// コンテキストを元に戻し、破棄する。
wglMakeCurrent hdc_
wglDeleteContext hrc
ReleaseDC hwnd, hdc_
end

このコードは最小限なので本格的に開発する場合にはgl.hあたりから定義をとってくる必要があります。

実際にプログラムに利用した例としては、2007年のコンテストに応募したameのソースコードが参考になるかもしれません。

追記

  • 2010/12/10
    • デバイスコンテキストのリークを修正

Related articles