Skip to content

Instantly share code, notes, and snippets.

@mirichi
Created December 11, 2016 05:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirichi/77f97a820ea7ede24650ab87821e15bb to your computer and use it in GitHub Desktop.
Save mirichi/77f97a820ea7ede24650ab87821e15bb to your computer and use it in GitHub Desktop.
ffiによる三角形描画
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