-
-
Save mirichi/77f97a820ea7ede24650ab87821e15bb to your computer and use it in GitHub Desktop.
ffiによる三角形描画
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ffi' | |
width = 320 | |
height = 240 | |
# 構造体にアクセサを生やす拡張 | |
class << FFI::Struct | |
def layout_ex *args | |
layout *args | |
args.each_slice(2) do |member, type| | |
define_method(member) do | |
self[member] | |
end | |
define_method("#{member}=".to_sym) do |v| | |
self[member] = v | |
end | |
end | |
end | |
# コールバックじゃないことを明示したいのでfunctionメソッドを作る | |
alias_method(:function, :callback) | |
end | |
module FFI::Library | |
# enum時についでに定数を定義する拡張 | |
def enum_ex *args | |
args.each do |member| | |
self.const_set(member, member) if member.is_a?(Symbol) | |
end | |
enum args | |
end | |
end | |
module WinAPI | |
extend FFI::Library | |
ffi_lib 'gdi32', 'ole32', 'user32', 'kernel32' | |
ffi_convention(:stdcall) | |
ULONG_PTR = FFI::TypeDefs[:uintptr_t] | |
LONG_PTR = FFI::TypeDefs[:intptr_t] | |
ULONG = FFI::TypeDefs[:ulong] | |
LONG = FFI::TypeDefs[:long] | |
UINT = FFI::TypeDefs[:uint] | |
INT = FFI::TypeDefs[:int] | |
BYTE = FFI::TypeDefs[:uchar] | |
WORD = FFI::TypeDefs[:ushort] | |
DWORD = FFI::TypeDefs[:uint] | |
BOOL = FFI::TypeDefs[:int] | |
POINTER = FFI::TypeDefs[:pointer] | |
VOID = FFI::TypeDefs[:void] | |
LPVOID = FFI::TypeDefs[:pointer] | |
LPCSTR = FFI::TypeDefs[:pointer] | |
LPCTSTR = FFI::TypeDefs[:pointer] | |
HWND = HICON = HCURSOR = HBRUSH = HINSTANCE = HMENU = HMODULE = HANDLE = ULONG_PTR | |
LPARAM = LONG_PTR | |
WPARAM = ULONG_PTR | |
LRESULT = LONG_PTR | |
HRESULT = LONG | |
ATOM = WORD | |
WINBOOL = BOOL | |
WNDPROC = callback(:WindowProc, [HWND, UINT, WPARAM, LPARAM], LRESULT) | |
class WNDCLASSEX < FFI::Struct | |
layout_ex :cbSize, UINT, | |
:style, UINT, | |
:lpfnWndProc, WNDPROC, | |
:cbClsExtra, INT, | |
:cbWndExtra, INT, | |
:hInstance, HINSTANCE, | |
:hIcon, HICON, | |
:hCursor, HCURSOR, | |
:hbrBackground, HBRUSH, | |
:lpszMenuName, LPCSTR, | |
:lpszClassName, LPCSTR, | |
:hIconSm, HICON | |
end | |
class POINT < FFI::Struct | |
layout_ex :x, LONG, | |
:y, LONG | |
end | |
class MSG < FFI::Struct | |
layout_ex :hwnd, HWND, | |
:message, UINT, | |
:wParam, WPARAM, | |
:lParam, LPARAM, | |
:time, DWORD, | |
:pt, POINT | |
end | |
class RECT < FFI::Struct | |
layout_ex :left, LONG, | |
:top, LONG, | |
:right, LONG, | |
:bottom, LONG | |
end | |
LPRECT = RECT.ptr | |
attach_function :GetModuleHandle, :GetModuleHandleA, [ LPCSTR ], HMODULE | |
attach_function :RegisterClassEx, :RegisterClassExA, [ WNDCLASSEX.ptr ], ATOM | |
attach_function :AdjustWindowRect, [ LPRECT, DWORD, WINBOOL ], WINBOOL | |
attach_function :CreateWindowEx, :CreateWindowExA, [ DWORD, LPCTSTR, LPCTSTR, DWORD, UINT, UINT, INT, INT, HWND, HMENU, HINSTANCE, LPVOID ], HWND | |
attach_function :DefWindowProc, :DefWindowProcA, [ HWND, UINT, WPARAM, LPARAM ], LRESULT | |
attach_function :DestroyWindow, [ HWND ], BOOL | |
attach_function :PostQuitMessage, [ INT ], VOID | |
attach_function :GetMessage, :GetMessageA, [ MSG.ptr, HWND, UINT, UINT ], BOOL | |
attach_function :TranslateMessage, [ MSG.ptr ], BOOL | |
attach_function :DispatchMessage, :DispatchMessageA, [ MSG.ptr ], BOOL | |
attach_function :SetCursor, [ HCURSOR ], HCURSOR | |
attach_function :LoadCursor, :LoadCursorA, [ HINSTANCE, LPCSTR ], HCURSOR | |
# 使いそうな定数の定義 | |
CS_VREDRAW = 0x0001 | |
CS_HREDRAW = 0x0002 | |
CS_DBLCLKS = 0x0008 | |
CS_OWNDC = 0x0020 | |
CS_CLASSDC = 0x0040 | |
CS_PARENTDC = 0x0080 | |
CS_NOCLOSE = 0x0200 | |
CS_SAVEBITS = 0x0800 | |
CS_BYTEALIGNCLIENT = 0x1000 | |
CS_BYTEALIGNWINDOW = 0x2000 | |
CS_GLOBALCLASS = 0x4000 | |
CS_IME = 0x00010000 | |
CS_DROPSHADOW = 0x00020000 | |
COLOR_SCROLLBAR = 0 | |
COLOR_BACKGROUND = 1 | |
COLOR_ACTIVECAPTION = 2 | |
COLOR_INACTIVECAPTION = 3 | |
COLOR_MENU = 4 | |
COLOR_WINDOW = 5 | |
COLOR_WINDOWFRAME = 6 | |
COLOR_MENUTEXT = 7 | |
COLOR_WINDOWTEXT = 8 | |
COLOR_CAPTIONTEXT = 9 | |
COLOR_ACTIVEBORDER = 10 | |
COLOR_INACTIVEBORDER = 11 | |
COLOR_APPWORKSPACE = 12 | |
COLOR_HIGHLIGHT = 13 | |
COLOR_HIGHLIGHTTEXT = 14 | |
COLOR_BTNFACE = 15 | |
COLOR_BTNSHADOW = 16 | |
COLOR_GRAYTEXT = 17 | |
COLOR_BTNTEXT = 18 | |
COLOR_INACTIVECAPTIONTEXT = 19 | |
COLOR_BTNHIGHLIGHT = 20 | |
COLOR_3DDKSHADOW = 21 | |
COLOR_3DLIGHT = 22 | |
COLOR_INFOTEXT = 23 | |
COLOR_INFOBK = 24 | |
COLOR_HOTLIGHT = 26 | |
COLOR_GRADIENTACTIVECAPTION = 27 | |
COLOR_GRADIENTINACTIVECAPTION = 28 | |
COLOR_MENUHILIGHT = 29 | |
COLOR_MENUBAR = 30 | |
COLOR_DESKTOP = COLOR_BACKGROUND | |
COLOR_3DFACE = COLOR_BTNFACE | |
COLOR_3DSHADOW = COLOR_BTNSHADOW | |
COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT | |
COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT | |
COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT | |
WS_OVERLAPPED = 0x00000000 | |
WS_POPUP = 0x80000000 | |
WS_CHILD = 0x40000000 | |
WS_MINIMIZE = 0x20000000 | |
WS_VISIBLE = 0x10000000 | |
WS_DISABLED = 0x08000000 | |
WS_CLIPSIBLINGS = 0x04000000 | |
WS_CLIPCHILDREN = 0x02000000 | |
WS_MAXIMIZE = 0x01000000 | |
WS_CAPTION = 0x00C00000 | |
WS_BORDER = 0x00800000 | |
WS_DLGFRAME = 0x00400000 | |
WS_VSCROLL = 0x00200000 | |
WS_HSCROLL = 0x00100000 | |
WS_SYSMENU = 0x00080000 | |
WS_THICKFRAME = 0x00040000 | |
WS_GROUP = 0x00020000 | |
WS_TABSTOP = 0x00010000 | |
WS_MINIMIZEBOX = 0x00020000 | |
WS_MAXIMIZEBOX = 0x00010000 | |
WS_TILED = WS_OVERLAPPED | |
WS_ICONIC = WS_MINIMIZE | |
WS_SIZEBOX = WS_THICKFRAME | |
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) | |
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW | |
WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU) | |
WS_CHILDWINDOW = (WS_CHILD) | |
CW_USEDEFAULT = 0x80000000 | |
WM_NULL = 0x0000 | |
WM_CREATE = 0x0001 | |
WM_DESTROY = 0x0002 | |
WM_MOVE = 0x0003 | |
WM_SIZE = 0x0005 | |
WM_ACTIVATE = 0x0006 | |
WA_INACTIVE = 0 | |
WA_ACTIVE = 1 | |
WA_CLICKACTIVE = 2 | |
WM_SETFOCUS = 0x0007 | |
WM_KILLFOCUS = 0x0008 | |
WM_ENABLE = 0x000A | |
WM_SETREDRAW = 0x000B | |
WM_SETTEXT = 0x000C | |
WM_GETTEXT = 0x000D | |
WM_GETTEXTLENGTH = 0x000E | |
WM_PAINT = 0x000F | |
WM_CLOSE = 0x0010 | |
WM_QUIT = 0x0012 | |
WM_ERASEBKGND = 0x0014 | |
WM_SYSCOLORCHANGE = 0x0015 | |
WM_SHOWWINDOW = 0x0018 | |
WM_WININICHANGE = 0x001A | |
WM_SETTINGCHANGE = WM_WININICHANGE | |
WM_DEVMODECHANGE = 0x001B | |
WM_ACTIVATEAPP = 0x001C | |
WM_FONTCHANGE = 0x001D | |
WM_TIMECHANGE = 0x001E | |
WM_CANCELMODE = 0x001F | |
WM_SETCURSOR = 0x0020 | |
WM_MOUSEACTIVATE = 0x0021 | |
WM_CHILDACTIVATE = 0x0022 | |
WM_QUEUESYNC = 0x0023 | |
IDC_ARROW = 32512 | |
IDC_IBEAM = 32513 | |
IDC_WAIT = 32514 | |
IDC_CROSS = 32515 | |
IDC_UPARROW = 32516 | |
IDC_SIZE = 32640 | |
IDC_ICON = 32641 | |
IDC_SIZENWSE = 32642 | |
IDC_SIZENESW = 32643 | |
IDC_SIZEWE = 32644 | |
IDC_SIZENS = 32645 | |
IDC_SIZEALL = 32646 | |
IDC_NO = 32648 | |
IDC_HAND = 32649 | |
IDC_APPSTARTING = 32650 | |
IDC_HELP = 32651 | |
end | |
hInstance = WinAPI::GetModuleHandle(nil) | |
def wndproc(hWnd, msg, wParam, lParam) | |
case msg | |
when WinAPI::WM_CLOSE | |
WinAPI::DestroyWindow(hWnd) | |
when WinAPI::WM_DESTROY | |
WinAPI::PostQuitMessage(0) | |
else | |
return WinAPI::DefWindowProc(hWnd, msg, wParam, lParam) | |
end | |
return 0 | |
end | |
wcex = WinAPI::WNDCLASSEX.new | |
wcex.cbSize = WinAPI::WNDCLASSEX.size | |
wcex.style = WinAPI::CS_HREDRAW | WinAPI::CS_VREDRAW | |
wcex.lpfnWndProc = method(:wndproc) | |
wcex.cbClsExtra = 0 | |
wcex.cbWndExtra = 0 | |
wcex.hInstance = hInstance | |
wcex.hIcon = 0 | |
wcex.hIconSm = 0 | |
wcex.hCursor = 0 | |
wcex.hbrBackground = WinAPI::COLOR_WINDOW | |
wcex.lpszMenuName = nil | |
wcex.lpszClassName = FFI::MemoryPointer.from_string("test") | |
atom = WinAPI::RegisterClassEx(wcex) | |
rect = WinAPI::RECT.new | |
rect.top = 0 | |
rect.left = 0 | |
rect.right = width | |
rect.bottom = height | |
WinAPI::AdjustWindowRect(rect, WinAPI::WS_OVERLAPPED | WinAPI::WS_CAPTION | WinAPI::WS_SYSMENU | WinAPI::WS_MINIMIZEBOX, 0) | |
# ウィンドウ作成 | |
hWnd = WinAPI::CreateWindowEx(0, "test", "Test Window", | |
WinAPI::WS_OVERLAPPED | WinAPI::WS_CAPTION | WinAPI::WS_SYSMENU | WinAPI::WS_MINIMIZEBOX | WinAPI::WS_VISIBLE, | |
WinAPI::CW_USEDEFAULT, WinAPI::CW_USEDEFAULT, | |
rect.right - rect.left, rect.bottom - rect.top, | |
0, 0, hInstance, nil ); | |
# カーソル設定 | |
WinAPI::SetCursor(WinAPI::LoadCursor(0, FFI::Pointer.new(WinAPI::IDC_ARROW))) | |
# COMインターフェイス基本クラス | |
class COM < FFI::Struct | |
class << self | |
# 自身の構造体レイアウトを設定し、VTableクラスを参照してメソッドを定義する | |
def init | |
vtbl = self.const_get(:VTable) | |
layout_ex :lpVtbl, vtbl.ptr | |
vtbl.members.each do |member| | |
define_method(member) do |*args| | |
self[:lpVtbl][member].call(self, *args) | |
end | |
end | |
end | |
end | |
end | |
module D3D9 | |
extend FFI::Library | |
ffi_lib 'd3d9', 'ole32' | |
ffi_convention(:stdcall) | |
ULONG_PTR = FFI::TypeDefs[:uintptr_t] | |
LONG_PTR = FFI::TypeDefs[:intptr_t] | |
ULONG = FFI::TypeDefs[:ulong] | |
LONG = FFI::TypeDefs[:long] | |
UINT = FFI::TypeDefs[:uint] | |
INT = FFI::TypeDefs[:int] | |
BYTE = FFI::TypeDefs[:uchar] | |
WORD = FFI::TypeDefs[:ushort] | |
DWORD = FFI::TypeDefs[:uint] | |
FLOAT = FFI::TypeDefs[:float] | |
BOOL = FFI::TypeDefs[:int] | |
POINTER = FFI::TypeDefs[:pointer] | |
VOID = FFI::TypeDefs[:void] | |
LPVOID = FFI::TypeDefs[:pointer] | |
LPCSTR = FFI::TypeDefs[:pointer] | |
LPCTSTR = FFI::TypeDefs[:pointer] | |
HWND = HICON = HCURSOR = HBRUSH = HINSTANCE = HMENU = HMODULE = HANDLE = HMONITOR = ULONG_PTR | |
LPARAM = LONG_PTR | |
WPARAM = ULONG_PTR | |
LRESULT = LONG_PTR | |
HRESULT = LONG | |
ATOM = WORD | |
WINBOOL = BOOL | |
D3DCOLOR = DWORD | |
D3DMULTISAMPLE_TYPE = enum_ex( | |
:D3DMULTISAMPLE_NONE , 0, | |
:D3DMULTISAMPLE_NONMASKABLE , 1, | |
:D3DMULTISAMPLE_2_SAMPLES , 2, | |
:D3DMULTISAMPLE_3_SAMPLES , 3, | |
:D3DMULTISAMPLE_4_SAMPLES , 4, | |
:D3DMULTISAMPLE_5_SAMPLES , 5, | |
:D3DMULTISAMPLE_6_SAMPLES , 6, | |
:D3DMULTISAMPLE_7_SAMPLES , 7, | |
:D3DMULTISAMPLE_8_SAMPLES , 8, | |
:D3DMULTISAMPLE_9_SAMPLES , 9, | |
:D3DMULTISAMPLE_10_SAMPLES , 10, | |
:D3DMULTISAMPLE_11_SAMPLES , 11, | |
:D3DMULTISAMPLE_12_SAMPLES , 12, | |
:D3DMULTISAMPLE_13_SAMPLES , 13, | |
:D3DMULTISAMPLE_14_SAMPLES , 14, | |
:D3DMULTISAMPLE_15_SAMPLES , 15, | |
:D3DMULTISAMPLE_16_SAMPLES , 16, | |
:D3DMULTISAMPLE_FORCE_DWORD , 0x7fffffff | |
) | |
D3DFORMAT = enum_ex( | |
:D3DFMT_UNKNOWN , 0, | |
:D3DFMT_D24S8 , 75 | |
) | |
D3DSWAPEFFECT = enum_ex( | |
:D3DSWAPEFFECT_DISCARD , 1, | |
:D3DSWAPEFFECT_FLIP , 2, | |
:D3DSWAPEFFECT_COPY , 3, | |
:D3DSWAPEFFECT_FORCE_DWORD , 0xFFFFFFFF | |
) | |
D3DDEVTYPE = enum_ex( | |
:D3DDEVTYPE_HAL , 1, | |
:D3DDEVTYPE_REF , 2, | |
:D3DDEVTYPE_SW , 3, | |
:D3DDEVTYPE_NULLREF , 4, | |
:D3DDEVTYPE_FORCE_DWORD , 0xffffffff | |
) | |
D3DPRIMITIVETYPE = enum_ex( | |
:D3DPT_POINTLIST , 1, | |
:D3DPT_LINELIST , 2, | |
:D3DPT_LINESTRIP , 3, | |
:D3DPT_TRIANGLELIST , 4, | |
:D3DPT_TRIANGLESTRIP , 5, | |
:D3DPT_TRIANGLEFAN , 6, | |
:D3DPT_FORCE_DWORD , 0x7fffffff | |
) | |
class D3DPRESENT_PARAMETERS < FFI::Struct | |
layout_ex :BackBufferWidth, UINT, | |
:BackBufferHeight, UINT, | |
:BackBufferFormat, D3DFORMAT, | |
:BackBufferCount, UINT, | |
:MultiSampleType, D3DMULTISAMPLE_TYPE, | |
:MultiSampleQuality, DWORD, | |
:SwapEffect, D3DSWAPEFFECT, | |
:hDeviceWindow, HWND, | |
:Windowed, WINBOOL, | |
:EnableAutoDepthStencil, WINBOOL, | |
:AutoDepthStencilFormat, D3DFORMAT, | |
:Flags, DWORD, | |
:FullScreen_RefreshRateInHz, UINT, | |
:PresentationInterval, UINT | |
end | |
class D3DVIEWPORT9 < FFI::Struct | |
layout_ex :X, DWORD, | |
:Y, DWORD, | |
:Width, DWORD, | |
:Height, DWORD, | |
:MinZ, FLOAT, | |
:MaxZ, FLOAT | |
end | |
class D3DRECT < FFI::Struct | |
layout_ex :x1, LONG, | |
:y1, LONG, | |
:x2, LONG, | |
:y2, LONG | |
end | |
class RECT < FFI::Struct | |
layout_ex :left, LONG, | |
:top, LONG, | |
:right, LONG, | |
:bottom, LONG | |
end | |
# 定数 | |
D3D_SDK_VERSION = 32 | |
D3DPRESENT_INTERVAL_IMMEDIATE = 0x80000000 | |
D3DADAPTER_DEFAULT = 0 | |
D3DCREATE_MIXED_VERTEXPROCESSING = 0x00000080 | |
D3DCLEAR_TARGET = 0x00000001 | |
D3DCLEAR_ZBUFFER = 0x00000002 | |
D3DCLEAR_STENCIL = 0x00000004 | |
D3DFVF_RESERVED0 = 0x0001 | |
D3DFVF_POSITION_MASK = 0x400E | |
D3DFVF_XYZ = 0x0002 | |
D3DFVF_XYZRHW = 0x0004 | |
D3DFVF_XYZB1 = 0x0006 | |
D3DFVF_XYZB2 = 0x0008 | |
D3DFVF_XYZB3 = 0x000a | |
D3DFVF_XYZB4 = 0x000c | |
D3DFVF_XYZB5 = 0x000e | |
D3DFVF_XYZW = 0x4002 | |
D3DFVF_NORMAL = 0x0010 | |
D3DFVF_PSIZE = 0x0020 | |
D3DFVF_DIFFUSE = 0x0040 | |
D3DFVF_SPECULAR = 0x0080 | |
D3DFVF_TEXCOUNT_MASK = 0x0f00 | |
D3DFVF_TEXCOUNT_SHIFT = 8 | |
D3DFVF_TEX0 = 0x0000 | |
D3DFVF_TEX1 = 0x0100 | |
D3DFVF_TEX2 = 0x0200 | |
D3DFVF_TEX3 = 0x0300 | |
D3DFVF_TEX4 = 0x0400 | |
D3DFVF_TEX5 = 0x0500 | |
D3DFVF_TEX6 = 0x0600 | |
D3DFVF_TEX7 = 0x0700 | |
D3DFVF_TEX8 = 0x0800 | |
D3DFVF_LASTBETA_UBYTE4 = 0x1000 | |
D3DFVF_LASTBETA_D3DCOLOR = 0x8000 | |
D3DFVF_RESERVED2 = 0x6000 | |
# IDirect3DDevice9 | |
class IDirect3DDevice9 < COM | |
# IDirect3DDevice9 | |
class VTable < FFI::Struct | |
layout :QueryInterface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:AddRef, function([ IDirect3DDevice9.ptr ], ULONG), | |
:Release, function([ IDirect3DDevice9.ptr ], ULONG), | |
:TestCooperativeLevel, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetAvailableTextureMem, function([ IDirect3DDevice9.ptr ], UINT), | |
:EvictManagedResources, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetDirect3D, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetDeviceCaps, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetDisplayMode, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetCreationParameters, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetCursorProperties, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetCursorPosition, function([ IDirect3DDevice9.ptr ], VOID), | |
:ShowCursor, function([ IDirect3DDevice9.ptr ], WINBOOL), | |
:CreateAdditionalSwapChain, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetSwapChain, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetNumberOfSwapChains, function([ IDirect3DDevice9.ptr ], UINT), | |
:Reset, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:Present, function([ IDirect3DDevice9.ptr, RECT.ptr, RECT.ptr, HWND, LPVOID ], HRESULT), | |
:GetBackBuffer, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetRasterStatus, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetDialogBoxMode, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetGammaRamp, function([ IDirect3DDevice9.ptr ], VOID), | |
:GetGammaRamp, function([ IDirect3DDevice9.ptr ], VOID), | |
:CreateTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateVolumeTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateCubeTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateVertexBuffer, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateIndexBuffer, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateRenderTarget, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateDepthStencilSurface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:UpdateSurface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:UpdateTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetRenderTargetData, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetFrontBufferData, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:StretchRect, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:ColorFill, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateOffscreenPlainSurface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetRenderTarget, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetRenderTarget, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetDepthStencilSurface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetDepthStencilSurface, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:BeginScene, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:EndScene, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:Clear, function([ IDirect3DDevice9.ptr, DWORD, D3DRECT.ptr, DWORD, D3DCOLOR, FLOAT, DWORD ], HRESULT), | |
:SetTransform, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetTransform, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:MultiplyTransform, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetViewport, function([ IDirect3DDevice9.ptr, D3DVIEWPORT9.ptr ], HRESULT), | |
:GetViewport, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetMaterial, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetMaterial, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetLight, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetLight, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:LightEnable, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetLightEnable, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetClipPlane, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetClipPlane, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetRenderState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetRenderState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateStateBlock, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:BeginStateBlock, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:EndStateBlock, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetClipStatus, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetClipStatus, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetTexture, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetTextureStageState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetTextureStageState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetSamplerState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetSamplerState, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:ValidateDevice, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetPaletteEntries, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetPaletteEntries, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetCurrentTexturePalette, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetCurrentTexturePalette, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetScissorRect, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetScissorRect, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetSoftwareVertexProcessing, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetSoftwareVertexProcessing, function([ IDirect3DDevice9.ptr ], WINBOOL), | |
:SetNPatchMode, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetNPatchMode, function([ IDirect3DDevice9.ptr ], FLOAT), | |
:DrawPrimitive, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:DrawIndexedPrimitive, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:DrawPrimitiveUP, function([ IDirect3DDevice9.ptr, D3DPRIMITIVETYPE, UINT, LPVOID, UINT ], HRESULT), | |
:DrawIndexedPrimitiveUP, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:ProcessVertices, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateVertexDeclaration, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetVertexDeclaration, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetVertexDeclaration, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetFVF, function([ IDirect3DDevice9.ptr, DWORD ], HRESULT), | |
:GetFVF, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateVertexShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetVertexShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetVertexShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetVertexShaderConstantF, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetVertexShaderConstantF, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetVertexShaderConstantI, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetVertexShaderConstantI, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetVertexShaderConstantB, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetVertexShaderConstantB, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetStreamSource, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetStreamSource, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetStreamSourceFreq, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetStreamSourceFreq, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetIndices, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetIndices, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreatePixelShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetPixelShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetPixelShader, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetPixelShaderConstantF, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetPixelShaderConstantF, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetPixelShaderConstantI, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetPixelShaderConstantI, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:SetPixelShaderConstantB, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:GetPixelShaderConstantB, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:DrawRectPatch, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:DrawTriPatch, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:DeletePatch, function([ IDirect3DDevice9.ptr ], HRESULT), | |
:CreateQuery, function([ IDirect3DDevice9.ptr ], HRESULT) | |
end | |
# VTable構造体を定義してからinitを呼ぶとメソッドが定義される | |
init | |
end | |
# IDirect3D9インターフェイス | |
class IDirect3D9 < COM | |
# Idirect3D9のメンバ定義 | |
class VTable < FFI::Struct | |
layout :QueryInterface, function([ IDirect3D9.ptr ], HRESULT), # できてないので呼ぶとコケる | |
:AddRef, function([ IDirect3D9.ptr ], ULONG), | |
:Release, function([ IDirect3D9.ptr ], ULONG), | |
:RegisterSoftwareDevice, function([ ], HRESULT), | |
:GetAdapterCount, function([ ], UINT), | |
:GetAdapterIdentifier, function([ ], HRESULT), | |
:GetAdapterModeCount, function([ ], UINT), | |
:EnumAdapterModes, function([ ], HRESULT), | |
:GetAdapterDisplayMode, function([ ], HRESULT), | |
:CheckDeviceType, function([ ], HRESULT), | |
:CheckDeviceFormat, function([ ], HRESULT), | |
:CheckDeviceMultiSampleType, function([ ], HRESULT), | |
:CheckDepthStencilMatch, function([ ], HRESULT), | |
:CheckDeviceFormatConversion, function([ ], HRESULT), | |
:GetDeviceCaps, function([ ], HRESULT), | |
:GetAdapterMonitor, function([ ], HMONITOR), | |
:CreateDevice, function([ IDirect3D9.ptr, UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS.ptr, LPVOID ], HRESULT) | |
end | |
# VTable構造体を定義してからinitを呼ぶとメソッドが定義される | |
init | |
end | |
attach_function :Direct3DCreate9, [ UINT ], IDirect3D9.ptr | |
attach_function :CoInitialize, [ LPVOID ], HRESULT | |
# マクロ | |
def self.D3DCOLOR_ARGB(a,b,c,d) | |
((a & 0xff) << 24) + ((b & 0xff) << 16) + ((c & 0xff) << 8) + (d & 0xff) | |
end | |
def self.D3DCOLOR_XRGB(r,g,b) | |
D3DCOLOR_ARGB(0xff,r,g,b) | |
end | |
end | |
D3D9::CoInitialize(nil) | |
d3d9 = D3D9::Direct3DCreate9(D3D9::D3D_SDK_VERSION) # IDirect3D9インターフェイスが返る | |
# D3DPRESENT_PARAMETERS構造体 | |
d3dpp = D3D9::D3DPRESENT_PARAMETERS.new | |
d3dpp.BackBufferWidth = 0 | |
d3dpp.BackBufferHeight = 0 | |
d3dpp.BackBufferFormat = D3D9::D3DFMT_UNKNOWN | |
d3dpp.BackBufferCount = 2 | |
d3dpp.MultiSampleType = D3D9::D3DMULTISAMPLE_NONE | |
d3dpp.MultiSampleQuality = 0 | |
d3dpp.SwapEffect = D3D9::D3DSWAPEFFECT_DISCARD | |
d3dpp.hDeviceWindow = hWnd | |
d3dpp.Windowed = 1 | |
d3dpp.EnableAutoDepthStencil = 1 | |
d3dpp.AutoDepthStencilFormat = D3D9::D3DFMT_D24S8 | |
d3dpp.Flags = 0 | |
d3dpp.FullScreen_RefreshRateInHz = 0 | |
d3dpp.PresentationInterval = D3D9::D3DPRESENT_INTERVAL_IMMEDIATE | |
# CreateDevice | |
# IDirect3DDevice9**型の引数は一手間かかる | |
mp = FFI::MemoryPointer.new(D3D9::IDirect3DDevice9.ptr) | |
hr = d3d9.CreateDevice(D3D9::D3DADAPTER_DEFAULT, | |
D3D9::D3DDEVTYPE_HAL, | |
hWnd, | |
D3D9::D3DCREATE_MIXED_VERTEXPROCESSING, | |
d3dpp, | |
mp) | |
d3ddevice = D3D9::IDirect3DDevice9.new(mp.read_pointer) | |
# D3DVIEWPORT9 | |
vp = D3D9::D3DVIEWPORT9.new | |
vp.X = 0 | |
vp.Y = 0 | |
vp.Width = width | |
vp.Height = height | |
vp.MinZ = 0.0 | |
vp.MaxZ = 1.0 | |
# ビューポート設定 | |
hr = d3ddevice.SetViewport(vp) | |
# 背景色塗りつぶし | |
d3ddevice.Clear(0, nil, D3D9::D3DCLEAR_TARGET, D3D9::D3DCOLOR_XRGB(0,0,0), 1.0, 0 ) | |
# 三角形用の構造体定義 | |
module D3D9 | |
class D3DVERTEX < FFI::Struct | |
layout_ex :x, FLOAT, | |
:y, FLOAT, | |
:z, FLOAT, | |
:rhw, FLOAT, | |
:diffuse, D3DCOLOR | |
end | |
end | |
vp = FFI::MemoryPointer.new(D3D9::D3DVERTEX, 3) # 頂点構造体用メモリをまとめて取得 | |
v = Array.new(3){|i|D3D9::D3DVERTEX.new(vp[i])} # アドレスを計算してD3DVERTEX構造体を生成 | |
v[0].x = 150 | |
v[0].y = 50 | |
v[0].z = 0 | |
v[0].rhw = 1 | |
v[0].diffuse = 0xffff0000 | |
v[1].x = 200 | |
v[1].y = 150 | |
v[1].z = 0 | |
v[1].rhw = 1 | |
v[1].diffuse = 0xff00ff00 | |
v[2].x = 100 | |
v[2].y = 150 | |
v[2].z = 0 | |
v[2].rhw = 1 | |
v[2].diffuse = 0xff0000ff | |
# 描画開始 | |
d3ddevice.BeginScene() | |
# 頂点情報の形を指定 | |
d3ddevice.SetFVF(D3D9::D3DFVF_XYZRHW | D3D9::D3DFVF_DIFFUSE) | |
# 描画 | |
d3ddevice.DrawPrimitiveUP(D3D9::D3DPT_TRIANGLELIST, 1, vp, D3D9::D3DVERTEX.size) | |
# 描画終了 | |
d3ddevice.EndScene() | |
# 画面に反映 | |
d3ddevice.Present(nil, nil, 0, nil) | |
# ウィンドウメッセージ構造体作成 | |
msg = WinAPI::MSG.new | |
# メッセージループ | |
loop do | |
if WinAPI::GetMessage(msg, 0, 0, 0) == 0 | |
break | |
end | |
WinAPI::TranslateMessage(msg) | |
WinAPI::DispatchMessage(msg) | |
end | |
p d3ddevice.Release | |
p d3d9.Release |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment