# -*- mode: nim; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2017/09/16 00:00:00 +0900> # # OpenGLが利用できそうか確認するサンプル # Google Gemini に作ってもらった # # Windows11 x64 25H2 + Nim 2.2.8 64bit import winim/lean import opengl import std/monotimes # 必要な情報をまとめる構造体 type AppWindow = object hwnd: HWND hdc: HDC hrc: HGLRC # --- 1. ウィンドウプロシージャ(イベント処理) --- proc windowProc( hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM ): LRESULT {.stdcall.} = case uMsg of WM_DESTROY: PostQuitMessage(0) return 0 of WM_KEYDOWN: if wParam == VK_ESCAPE: PostMessage(hwnd, WM_CLOSE, 0, 0) return 0 else: return DefWindowProc(hwnd, uMsg, wParam, lParam) # --- 2. ウィンドウとOpenGLの初期化 --- proc initWindow(width, height: int): AppWindow = let hInstance = GetModuleHandle(nil) let className = "NimGLWindow" var wc: WNDCLASS wc.lpfnWndProc = windowProc wc.hInstance = hInstance wc.lpszClassName = className wc.hCursor = LoadCursor(0, IDC_ARROW) RegisterClass(addr wc) let hwnd = CreateWindowEx( 0, className, "Nim OpenGL - Single EXE Framework", WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, width.int32, height.int32, 0, 0, hInstance, nil, ) # OpenGL初期化 let hdc = GetDC(hwnd) var pfd: PIXELFORMATDESCRIPTOR pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR).uint16 pfd.nVersion = 1 pfd.dwFlags = PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER pfd.iPixelType = PFD_TYPE_RGBA pfd.cColorBits = 32 let pixFormat = ChoosePixelFormat(hdc, addr pfd) SetPixelFormat(hdc, pixFormat, addr pfd) let hrc = wglCreateContext(hdc) wglMakeCurrent(hdc, hrc) loadExtensions() # モダンな関数を使えるようにロード result = AppWindow(hwnd: hwnd, hdc: hdc, hrc: hrc) # --- 3. 描画ロジック(アスペクト比補正付き) --- proc render(app: AppWindow, angle: float32) = # ウィンドウサイズの取得 var rect: RECT GetClientRect(app.hwnd, addr rect) let w = (rect.right - rect.left).float32 let h = (rect.bottom - rect.top).float32 # ビューポートと投影行列の設定(引き伸ばし防止) glViewport(0, 0, w.int32, h.int32) glMatrixMode(GL_PROJECTION) glLoadIdentity() let aspect = if h != 0: w / h else: 1.0 if w >= h: glOrtho(-aspect, aspect, -1.0, 1.0, -1.0, 1.0) else: glOrtho(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect, -1.0, 1.0) # モデルビュー行列のリセットと描画 glMatrixMode(GL_MODELVIEW) glLoadIdentity() glClearColor(0.1, 0.2, 0.3, 1.0) glClear(GL_COLOR_BUFFER_BIT) # 回転の適用 glRotatef(angle, 0, 0, 1) # 三角形の描画 glBegin(GL_TRIANGLES) glColor3f(1.0, 0.0, 0.0) glVertex2f(0.0, 0.8) glColor3f(0.0, 1.0, 0.0) glVertex2f(-0.8, -0.8) glColor3f(0.0, 0.0, 1.0) glVertex2f(0.8, -0.8) glEnd() # --- 4. メインループ --- proc mainLoop(app: AppWindow) = var msg: MSG var angle: float32 = 0.0 let rotationSpeed: float32 = 90.0 # 1秒間に90度 var lastTicks = getMonoTime().ticks while true: if PeekMessage(addr msg, 0, 0, 0, PM_REMOVE) != 0: if msg.message == WM_QUIT: break TranslateMessage(addr msg) DispatchMessage(addr msg) else: # デルタタイム計算 (.ticks を使用) let currentTicks = getMonoTime().ticks let dt = (currentTicks - lastTicks).float32 / 1_000_000_000.0 lastTicks = currentTicks angle += rotationSpeed * dt # if angle > 360.0: # angle -= 360.0 render(app, angle) SwapBuffers(app.hdc) Sleep(15) # --- 5. メイン --- proc main() = let app = initWindow(800, 600) # 使用中のOpenGLのバージョンを表示 # echo "Vendor: ", $glGetString(GL_VENDOR) # echo "Renderer: ", $glGetString(GL_RENDERER) # echo "Version: ", $glGetString(GL_VERSION) mainLoop(app) main()