Page 1 of 1

Most important include files for DX8 (+ simple examples)

Posted: Fri Sep 02, 2005 7:13 pm
by traumatic
I don't exactly know why but there still seem to be a lot of people having
difficulties converting the DX( 8 ) SDK includes for PureBasic. At least my-
self got a lot of requests recently (you know who you are ;)), so here you are:

http://files.connection-refused.org/pbdx8.zip

Note: These aren't all headers, only some most necessary ones.
I hope this is useful to someone in some way. Have fun! :)

Re: Most important include files for DX8

Posted: Sun Sep 04, 2005 2:04 pm
by traumatic
Here's a simple example:

Code: Select all

;
; DX8 - Simple Example: Triangle
;


XIncludeFile "include/dx8.h.pb" ; http://forums.purebasic.com/english/viewtopic.php?t=16652


Structure MYVERTEX
    x.f : y.f : z.f
    rhw.f
    color.l
EndStructure

#D3DFVF_MYVERTEX = #D3DFVF_XYZRHW | #D3DFVF_DIFFUSE

Dim Vertices.MYVERTEX(2)
Vertices(0)\x = 150.0 : Vertices(0)\y =  50.0 : Vertices(0)\z = 0.5 : Vertices(0)\rhw = 1.0 : Vertices(0)\color = $ffff0000
Vertices(1)\x = 250.0 : Vertices(1)\y = 250.0 : Vertices(1)\z = 0.5 : Vertices(1)\rhw = 1.0 : Vertices(1)\color = $ff00ff00
Vertices(2)\x =  50.0 : Vertices(2)\y = 250.0 : Vertices(2)\z = 0.5 : Vertices(2)\rhw = 1.0 : Vertices(2)\color = $ff00ffff


;
; INIT Direct3D8, setup and fill vertexbuffer
;
Procedure D3D8_Init(hWnd.l)
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8

  If OpenLibrary(0, "d3d8.dll")
    *F = IsFunction(0, "Direct3DCreate8")
    If *F
      d3d = CallFunctionFast(*F, #D3D_SDK_VERSION)
    EndIf

    d3ddm.D3DDISPLAYMODE
    If d3d\GetAdapterDisplayMode(#D3DADAPTER_DEFAULT, @d3ddm) <> #D3D_OK
      Debug "ERR @ GetAdapterDisplayMode"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    d3dpp.D3DPRESENT_PARAMETERS
    ZeroMemory_(@d3dpp, SizeOf(d3dpp))
    d3dpp\Windowed   = #True
    d3dpp\SwapEffect = #D3DSWAPEFFECT_DISCARD
    d3dpp\BackBufferFormat = d3ddm\Format

    If d3d\CreateDevice(#D3DADAPTER_DEFAULT, #D3DDEVTYPE_HAL, hWnd, #D3DCREATE_SOFTWARE_VERTEXPROCESSING, @d3dpp, @d3dDevice) <> #D3D_OK
      Debug "ERR @ CreateDevice"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    ;   
    Shared VB.IDirect3DVertexBuffer8
   
    If d3dDevice\CreateVertexBuffer(3*SizeOf(MYVERTEX), 0, #D3DFVF_MYVERTEX, #D3DPOOL_DEFAULT, @VB) <> #D3D_OK
      Debug "ERR @ CreateVertexBuffer"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    *pVertices.b
    If VB\Lock(0, SizeOf(MYVERTEX)*3, @*pVertices, 0) <> #D3D_OK
      Debug "ERR @ Lock"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    CopyMemory(Vertices(0), *pVertices, SizeOf(MYVERTEX)*3)
    VB\Unlock()
   
    ProcedureReturn #True
  Else
    Debug "ERR opening d3d8.dll"
    ProcedureReturn #False
  EndIf
EndProcedure



;
; CLEANUP
;
Procedure D3D8_Close()
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8
  If d3dDevice <> #Null
    d3dDevice\Release()
    d3dDevice = #Null
  EndIf
  If d3d <> #Null
    d3d\Release()
    d3d = #Null
  EndIf
  CloseLibrary(0)
EndProcedure


;
; MAIN
;
D3D8_Init(OpenWindow(0, 0, 0, 640, 480, #PB_Window_SystemMenu, "Direct3D8"))

Repeat
  d3dDevice\Clear(0, #Null, #D3DCLEAR_TARGET, $FF000040, 1.0, 0)
  d3dDevice\BeginScene()

  d3dDevice\SetStreamSource(0, VB, SizeOf(MYVERTEX))
  d3dDevice\SetVertexShader(#D3DFVF_MYVERTEX)
  d3dDevice\DrawPrimitive(#D3DPT_TRIANGLELIST, 0, 1)
 
  d3dDevice\EndScene()
  d3dDevice\Present(#Null, #Null, #Null, #Null)
Until WaitWindowEvent() = #PB_Event_CloseWindow

D3D8_Close()
End

Re: Most important include files for DX8

Posted: Sun Sep 04, 2005 4:58 pm
by traumatic
...I was asked "Why do you use RHW? What's that?"

I've choosen to use transformed vertices because of their simplicity.
Anyway, here's the same example, this time slightly adjusted to show
how to setup the needed matrices in order to display the triangle in
model space.

(BTW: rhw = reciprocal of homogeneous W) :)

Code: Select all

XIncludeFile "include/dx8.h.pb"

#PI  = 3.14159265

Structure VECTOR3
  x.f
  y.f
  z.f
EndStructure



Structure MATRIX
  _11.f : _12.f : _13.f : _14.f
  _21.f : _22.f : _23.f : _24.f
  _31.f : _32.f : _33.f : _34.f
  _41.f : _42.f : _43.f : _44.f
EndStructure



;----------------------------------------------------------------------

; vector math


; normalize
Procedure VectorNormalize(*v.VECTOR3)
  len.f = 1/Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z) 
  *v\x * len : *v\y * len : *v\z * len
  ProcedureReturn *v
EndProcedure

; dotproduct
Procedure.f VectorDot(*v1.VECTOR3, *v2.VECTOR3) 
  ProcedureReturn *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z 
EndProcedure 

; crossproduct
Procedure VectorCross(*out.VECTOR3, *v1.VECTOR3, *v2.VECTOR3)
  *out\x = (*v1\y * *v2\z) - (*v1\z * *v2\y)
  *out\y = (*v1\z * *v2\x) - (*v1\x * *v2\z)
  *out\z = (*v1\x * *v2\y) - (*v1\y * *v2\x)
  ProcedureReturn *out
EndProcedure

; subtraction
Procedure VectorSubstract(*out.VECTOR3, *a.VECTOR3, *b.VECTOR3)
  *out\x = *a\x - *b\x
  *out\y = *a\y - *b\y
  *out\z = *a\z - *b\z
  ProcedureReturn *out
EndProcedure


; matrix math (look ma! no d3dx needed! ;))

;
; Builds a left-handed perspective projection matrix
;
Procedure MatrixLookAtLH(*out.MATRIX, *eye.VECTOR3, *at.VECTOR3, *up.VECTOR3)
  ; zaxis = normal(At - Eye)  
  VectorSubstract(zaxis.VECTOR3, *at, *eye)
  VectorNormalize(zaxis.VECTOR3)

  ; xaxis = normal(cross(Up, zaxis))  
  VectorCross(xaxis.VECTOR3, *up, zaxis)
  VectorNormalize(xaxis)

  ; yaxis = cross(zaxis, xaxis)  
  VectorCross(yaxis.VECTOR3, zaxis, xaxis)
  
  xdot.f = VectorDot(xaxis, *eye)
  ydot.f = VectorDot(yaxis, *eye)
  zdot.f = VectorDot(zaxis, *eye)  
  
  *out\_11 = xaxis\x : *out\_12 = yaxis\x : *out\_13 = zaxis\x : *out\_14 = 0.0
  *out\_21 = xaxis\y : *out\_22 = yaxis\y : *out\_23 = zaxis\y : *out\_24 = 0.0
  *out\_31 = xaxis\z : *out\_32 = yaxis\z : *out\_33 = zaxis\z : *out\_34 = 0.0
  *out\_41 = -xdot   : *out\_42 = -ydot   : *out\_43 = -zdot   : *out\_44 = 1.0
  ProcedureReturn *out
EndProcedure


;
; Builds a left-handed perspective projection matrix based on a field of view (FOV).
;
Procedure MatrixPerspectiveFovLH(*out.MATRIX, fov.f, aspect.f, zn.f, zf.f)
  h.f = Cos(fov/2) / Sin(fov/2)
  w.f= h / aspect

  *out\_11 = 2*zn/w : *out\_12 = 0.0    : *out\_13 = 0.0            : *out\_14 = 0.0
  *out\_21 = 0.0    : *out\_22 = 2*zn/h : *out\_23 = 0.0            : *out\_24 = 0.0
  *out\_31 = 0.0    : *out\_32 = 0.0    : *out\_33 = zf/(zf-zn)     : *out\_34 = 1.0
  *out\_41 = 0.0    : *out\_42 = 0.0    : *out\_43 = zn*zf/(zn-zf)  : *out\_44 = 0.0
  ProcedureReturn *out
EndProcedure


;
; Builds a matrix using the specified offsets.
;
Procedure MatrixTranslation(*out.MATRIX, x.f, y.f, z.f)
  *out\_11 = 1.0 : *out\_12 = 0.0 : *out\_13 = 0.0  : *out\_14 = 0.0
  *out\_21 = 0.0 : *out\_22 = 1.0 : *out\_23 = 0.0  : *out\_24 = 0.0
  *out\_31 = 0.0 : *out\_32 = 0.0 : *out\_33 = 1.0  : *out\_34 = 0.0
  *out\_41 = x   : *out\_42 = y   : *out\_43 = z    : *out\_44 = 1.0
  ProcedureReturn *out
EndProcedure


;----------------------------------------------------------------------


Structure MYVERTEX
    x.f : y.f : z.f
    color.l
EndStructure

#D3DFVF_MYVERTEX = #D3DFVF_XYZ | #D3DFVF_DIFFUSE



Dim Vertices.MYVERTEX(2)
Vertices(0)\x =  0.0 : Vertices(0)\y =  1.0 : Vertices(0)\z = 0.0 : Vertices(0)\color = $ffff0000
Vertices(1)\x =  1.0 : Vertices(1)\y = -1.0 : Vertices(1)\z = 0.0 : Vertices(1)\color = $ff00ff00
Vertices(2)\x = -1.0 : Vertices(2)\y = -1.0 : Vertices(2)\z = 0.0 : Vertices(2)\color = $ff00ffff


;
; INIT Direct3D8, setup and fill vertexbuffer
;
Procedure D3D8_Init(hWnd.l)
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8

  If OpenLibrary(0, "d3d8.dll")
    *F = IsFunction(0, "Direct3DCreate8")
    If *F
      d3d = CallFunctionFast(*F, #D3D_SDK_VERSION)
    EndIf

    d3ddm.D3DDISPLAYMODE
    If d3d\GetAdapterDisplayMode(#D3DADAPTER_DEFAULT, @d3ddm) <> #D3D_OK
      Debug "ERR @ GetAdapterDisplayMode"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    d3dpp.D3DPRESENT_PARAMETERS
    ZeroMemory_( @d3dpp, SizeOf(d3dpp) )
    d3dpp\Windowed   = #True
    d3dpp\SwapEffect = #D3DSWAPEFFECT_DISCARD
    d3dpp\BackBufferFormat = d3ddm\Format


    If d3d\CreateDevice( #D3DADAPTER_DEFAULT, #D3DDEVTYPE_HAL, hWnd, #D3DCREATE_SOFTWARE_VERTEXPROCESSING, @d3dpp, @d3dDevice ) <> #D3D_OK
      Debug "ERR @ CreateDevice"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    ;   
    Shared VB.IDirect3DVertexBuffer8
   
    If d3dDevice\CreateVertexBuffer(3*SizeOf(MYVERTEX), #D3DUSAGE_WRITEONLY, #D3DFVF_MYVERTEX, #D3DPOOL_MANAGED, @VB) <> #D3D_OK
      Debug "ERR @ CreateVertexBuffer"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    *pVertices.b
    If VB\Lock(0, SizeOf(MYVERTEX)*3, @*pVertices, 0) <> #D3D_OK
      Debug "ERR @ Lock"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf


    CopyMemory(Vertices(0), *pVertices, SizeOf(MYVERTEX)*3)
    VB\Unlock()
   
    ProcedureReturn #True
  Else
    Debug "ERR opening d3d8.dll"
    ProcedureReturn #False
  EndIf
EndProcedure



;
; CLEANUP
;
Procedure D3D8_Close()
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8
  If d3dDevice <> #Null
    d3dDevice\Release()
    d3dDevice = #Null
  EndIf
  If d3d <> #Null
    d3d\Release()
    d3d = #Null
  EndIf
  CloseLibrary(0)
EndProcedure


;
; MAIN
;
D3D8_Init(OpenWindow(0, 0, 0, 640, 480, #PB_Window_SystemMenu, "Direct3D8"))

d3dDevice\SetRenderState(#D3DRS_LIGHTING, #False)


; setup view- and procection-matrix
eye.VECTOR3 : eye\z = -1.5
up.VECTOR3  : up\y  = 1.0
MatrixLookAtLH(@view_matrix.MATRIX, @eye, @at.VECTOR3, @up)
d3dDevice\SetTransform(#D3DTS_VIEW, @view_matrix)

MatrixPerspectiveFovLH(@matProj.MATRIX, #PI/4, 640/480, 1.0, 100.0)
d3dDevice\SetTransform(#D3DTS_PROJECTION, @matProj)

; Set world-matrix
MatrixTranslation(@matWorld.MATRIX, 0.0, 0.0, 0.0)
d3dDevice\SetTransform(#D3DTS_WORLD, @matWorld)

Repeat
  d3dDevice\Clear(0, #Null, #D3DCLEAR_TARGET, $FF000040, 1.0, 0)
  d3dDevice\BeginScene()

 
    d3dDevice\SetStreamSource(0, VB, SizeOf(MYVERTEX))
    d3dDevice\SetVertexShader(#D3DFVF_MYVERTEX)
    
    d3dDevice\DrawPrimitive(#D3DPT_TRIANGLELIST, 0, 1)
 
  d3dDevice\EndScene()  
  d3dDevice\Present(#Null, #Null, #Null, #Null)
Until WaitWindowEvent() = #PB_Event_CloseWindow


D3D8_Close()
End 
...and just in case someone thinks I'm drunk and talking to myself:
The mentionend questions arrive via PM yet I thought it's nice post
the answers publically for everyone to see.

Posted: Sun Sep 04, 2005 5:05 pm
by Dare2
Thank you! :)

Posted: Sun Sep 04, 2005 5:07 pm
by Polo
Thanks 8) !

Posted: Mon Sep 05, 2005 1:18 am
by Dreglor
Can some one tell me why Directx8 (or 9 if you wish) requires the dll for runtime?

in c++ its a static lib thats linked from what i understand it comes from the sdk

shouldn't the one function (Direct3dCreate) be in the those static libs

Posted: Mon Sep 05, 2005 7:15 am
by traumatic
Dreglor, the only difference is static vs. dynamic binding.
The DLL is needed in both cases of course.

If you'd take the dll-importer and generate a library from that, everything
was the same. There's just no static library supplied with PB, that's all.

Out of curiosity: Why do you care at all? Is there any problem I don't see?

Posted: Tue Mar 07, 2006 2:23 pm
by traumatic
"Compress-me-with-UPX-and-I'm-4.096-Bytes-PB-4.0-Version-for-the-fun-of-it" :D

Warning: Bad code ahead, don't try this at home

Code: Select all

XIncludeFile "include/dx8.h.pb" ; http://purebasic.fr/english/viewtopic.php?t=16652


Structure MYVERTEX
    x.f : y.f : z.f
    rhw.f
    color.l
EndStructure

#D3DFVF_MYVERTEX = #D3DFVF_XYZRHW | #D3DFVF_DIFFUSE


;
; Don't we all LOVE macros?
;
Macro FillVertex(v, a, b, c, d, e)
  v\x = a : v\y = b : v\z = c : v\rhw = d : v\color = e
EndMacro


Prototype.l D3DCreate8(version.l = #D3D_SDK_VERSION)


Procedure D3D8_WindowProc(hWnd, Msg, wParam, lParam)
  ProcedureReturn DefWindowProc_(hWnd, Msg, wParam, lParam)
EndProcedure

;
; D3D8_CreateWindow()
;
; Saves executable size compared to PB's OpenWindow()
;
;
Procedure D3D8_CreateWindow(width.l, height.l, Caption.s, Proc.l)

  wc.WNDCLASS

  ClassName.s = "pbD3D8"
  hInstance.l = GetModuleHandle_(0);


  ; Set up and register window class
  wc\style = #CS_HREDRAW | #CS_VREDRAW
  wc\lpfnWndProc = Proc
  wc\cbClsExtra = 0
  wc\cbWndExtra = SizeOf(LONG)
  wc\hInstance = hInstance
  wc\hIcon = LoadIcon_(0,#IDI_WINLOGO); #Null
  wc\hCursor = LoadCursor_(#Null, #IDC_ARROW)
  wc\hbrBackground = GetStockObject_(#BLACK_BRUSH)
  wc\lpszMenuName = #Null
  wc\lpszClassName = @ClassName

  If RegisterClass_(wc) = 0
    ProcedureReturn 0
  EndIf

  ScreenWidth.l  = width
  ScreenHeight.l = height

  hWnd.l = CreateWindowEx_(#WS_EX_TOPMOST, ClassName, Caption, #WS_OVERLAPPEDWINDOW, 0, 0, ScreenWidth, ScreenHeight,#Null, #Null, hInstance, #Null)
  If hWnd = 0 
    ProcedureReturn 0
  EndIf

  ShowWindow_(hWnd, #SW_SHOW)

  ProcedureReturn hWnd         
EndProcedure

;
; INIT Direct3D8, setup and fill vertexbuffer
;
Procedure D3D8_Init(hWnd.l)
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8
  
  Dim Vertices.MYVERTEX(2)
  FillVertex(Vertices(0), 150.0,  50.0, 0.5, 1.0, $ffff0000)
  FillVertex(Vertices(1), 250.0, 250.0, 0.5, 1.0, $ff00ff00)
  FillVertex(Vertices(2),  50.0, 250.0, 0.5, 1.0, $ff00ffff)


  If OpenLibrary(0, "d3d8.dll")
    d3dCreate.D3DCreate8 = GetFunction(0, "Direct3DCreate8")
    If d3dCreate
      d3d = d3dCreate()
    EndIf
      

    d3ddm.D3DDISPLAYMODE
    If d3d\GetAdapterDisplayMode(#D3DADAPTER_DEFAULT, @d3ddm) <> #D3D_OK
      Debug "ERR @ GetAdapterDisplayMode"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    d3dpp.D3DPRESENT_PARAMETERS
    ZeroMemory_(@d3dpp, SizeOf(d3dpp))
    d3dpp\Windowed   = #True
    d3dpp\SwapEffect = #D3DSWAPEFFECT_DISCARD
    d3dpp\BackBufferFormat = d3ddm\Format

    If d3d\CreateDevice(#D3DADAPTER_DEFAULT, #D3DDEVTYPE_HAL, hWnd, #D3DCREATE_SOFTWARE_VERTEXPROCESSING, @d3dpp, @d3dDevice) <> #D3D_OK
      Debug "ERR @ CreateDevice"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    ;   
    Shared VB.IDirect3DVertexBuffer8
   
    If d3dDevice\CreateVertexBuffer(3*SizeOf(MYVERTEX), 0, #D3DFVF_MYVERTEX, #D3DPOOL_DEFAULT, @VB) <> #D3D_OK
      Debug "ERR @ CreateVertexBuffer"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf

    *pVertices.b
    If VB\Lock(0, SizeOf(MYVERTEX)*3, @*pVertices, 0) <> #D3D_OK
      Debug "ERR @ Lock"
      CloseLibrary(0)
      ProcedureReturn #False
    EndIf


    CopyMemory_(*pVertices, Vertices(0), SizeOf(MYVERTEX)*3)
    VB\Unlock()
   
    ProcedureReturn #True
  Else
    Debug "ERR opening d3d8.dll"
    ProcedureReturn #False
  EndIf
EndProcedure



;
; CLEANUP
;
Procedure D3D8_Close()
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8
  If d3dDevice <> #Null
    d3dDevice\Release()
    d3dDevice = #Null
  EndIf
  If d3d <> #Null
    d3d\Release()
    d3d = #Null
  EndIf
  CloseLibrary(0)
EndProcedure


;
; MAIN
;
D3D8_Init(D3D8_CreateWindow(640, 480, "Direct3D8", @D3D8_WindowProc()))

Repeat
  d3dDevice\Clear(0, #Null, #D3DCLEAR_TARGET, $FF000040, 1.0, 0)
  d3dDevice\BeginScene()

  d3dDevice\SetStreamSource(0, VB, SizeOf(MYVERTEX))
  d3dDevice\SetVertexShader(#D3DFVF_MYVERTEX)
  d3dDevice\DrawPrimitive(#D3DPT_TRIANGLELIST, 0, 1)
 
  d3dDevice\EndScene()
  d3dDevice\Present(#Null, #Null, #Null, #Null)

Until GetAsyncKeyState_(#VK_ESCAPE)

D3D8_Close()
End 
[ESC] to quit...

Posted: Tue Mar 07, 2006 3:03 pm
by Fred
Nice one ;). After seeing your demo, i was expecting more than a single triangle :lol:

Posted: Tue Mar 07, 2006 3:08 pm
by traumatic
lol, considering the unpacked exe is just about 6kb, there's actually loads
of space left to fill! UPX didn't even know WHAT to compress... :P

Posted: Tue Mar 07, 2006 4:02 pm
by traumatic
Ok, I couldn't resist and also removed the last remaining PB functions
(the library ones)... 3.584 Bytes :P

Code: Select all

;
; DX8 - Simple Example: Triangle
;

XIncludeFile "include/dx8.h.pb" ; http://purebasic.fr/english/viewtopic.php?t=16652


Structure MYVERTEX
    x.f : y.f : z.f
    rhw.f
    color.l
EndStructure

#D3DFVF_MYVERTEX = #D3DFVF_XYZRHW | #D3DFVF_DIFFUSE


;
; Don't we all LOVE macros?
;
Macro FillVertex(v, a, b, c, d, e)
  v\x = a : v\y = b : v\z = c : v\rhw = d : v\color = e
EndMacro


Prototype.l D3DCreate8(version.l = #D3D_SDK_VERSION)


Procedure D3D8_WindowProc(hWnd, Msg, wParam, lParam)
  ProcedureReturn DefWindowProc_(hWnd, Msg, wParam, lParam)
EndProcedure

;
; D3D8_CreateWindow()
;
; Saves executable size compared to PB's OpenWindow()
;
;
Procedure D3D8_CreateWindow(width.l, height.l, Caption.s, Proc.l)

  wc.WNDCLASS

  ClassName.s = "pbD3D8"
  hInstance.l = GetModuleHandle_(0);


  ; Set up and register window class
  wc\style = #CS_HREDRAW | #CS_VREDRAW
  wc\lpfnWndProc = Proc
  wc\cbClsExtra = 0
  wc\cbWndExtra = SizeOf(LONG)
  wc\hInstance = hInstance
  wc\hIcon = LoadIcon_(0,#IDI_WINLOGO); #Null
  wc\hCursor = LoadCursor_(#Null, #IDC_ARROW)
  wc\hbrBackground = GetStockObject_(#BLACK_BRUSH)
  wc\lpszMenuName = #Null
  wc\lpszClassName = @ClassName

  If RegisterClass_(wc) = 0
    ProcedureReturn 0
  EndIf

  ScreenWidth.l  = width
  ScreenHeight.l = height

  hWnd.l = CreateWindowEx_(#WS_EX_TOPMOST, ClassName, Caption, #WS_OVERLAPPEDWINDOW, 0, 0, ScreenWidth, ScreenHeight,#Null, #Null, hInstance, #Null)
  If hWnd = 0 
    ProcedureReturn 0
  EndIf

  ShowWindow_(hWnd, #SW_SHOW)

  ProcedureReturn hWnd         
EndProcedure

;
; INIT Direct3D8, setup and fill vertexbuffer
;
Procedure D3D8_Init(hWnd.l)
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8, hDll.l
  
  Dim Vertices.MYVERTEX(2)
  FillVertex(Vertices(0), 150.0,  50.0, 0.5, 1.0, $ffff0000)
  FillVertex(Vertices(1), 250.0, 250.0, 0.5, 1.0, $ff00ff00)
  FillVertex(Vertices(2),  50.0, 250.0, 0.5, 1.0, $ff00ffff)


  hDll.l = LoadLibrary_("d3d8.dll")
  If hDll
    d3dCreate.D3DCreate8 = GetProcAddress_(hDll, "Direct3DCreate8")
    If d3dCreate
      d3d = d3dCreate()
    EndIf
      

    d3ddm.D3DDISPLAYMODE
    If d3d\GetAdapterDisplayMode(#D3DADAPTER_DEFAULT, @d3ddm) <> #D3D_OK
      Debug "ERR @ GetAdapterDisplayMode"
      FreeLibrary_(hDll)
      ProcedureReturn #False
    EndIf

    d3dpp.D3DPRESENT_PARAMETERS
    ZeroMemory_(@d3dpp, SizeOf(d3dpp))
    d3dpp\Windowed   = #True
    d3dpp\SwapEffect = #D3DSWAPEFFECT_DISCARD
    d3dpp\BackBufferFormat = d3ddm\Format

    If d3d\CreateDevice(#D3DADAPTER_DEFAULT, #D3DDEVTYPE_HAL, hWnd, #D3DCREATE_SOFTWARE_VERTEXPROCESSING, @d3dpp, @d3dDevice) <> #D3D_OK
      Debug "ERR @ CreateDevice"
      FreeLibrary_(hDll)
      ProcedureReturn #False
    EndIf

    ;   
    Shared VB.IDirect3DVertexBuffer8
   
    If d3dDevice\CreateVertexBuffer(3*SizeOf(MYVERTEX), 0, #D3DFVF_MYVERTEX, #D3DPOOL_DEFAULT, @VB) <> #D3D_OK
      Debug "ERR @ CreateVertexBuffer"
      FreeLibrary_(hDll)
      ProcedureReturn #False
    EndIf

    *pVertices.b
    If VB\Lock(0, SizeOf(MYVERTEX)*3, @*pVertices, 0) <> #D3D_OK
      Debug "ERR @ Lock"
      FreeLibrary_(hDll)
      ProcedureReturn #False
    EndIf


    CopyMemory_(*pVertices, Vertices(0), SizeOf(MYVERTEX)*3)
    VB\Unlock()
   
    ProcedureReturn #True
  Else
    Debug "ERR opening d3d8.dll"
    ProcedureReturn #False
  EndIf
EndProcedure



;
; CLEANUP
;
Procedure D3D8_Close()
  Shared d3d.IDirect3D8, d3dDevice.IDirect3DDevice8, hDll.l
  If d3dDevice <> #Null
    d3dDevice\Release()
    d3dDevice = #Null
  EndIf
  If d3d <> #Null
    d3d\Release()
    d3d = #Null
  EndIf
  FreeLibrary_(hDll)
EndProcedure


;
; MAIN
;
D3D8_Init(D3D8_CreateWindow(640, 480, "Direct3D8", @D3D8_WindowProc()))

Repeat
  d3dDevice\Clear(0, #Null, #D3DCLEAR_TARGET, $FF000040, 1.0, 0)
  d3dDevice\BeginScene()

  d3dDevice\SetStreamSource(0, VB, SizeOf(MYVERTEX))
  d3dDevice\SetVertexShader(#D3DFVF_MYVERTEX)
  d3dDevice\DrawPrimitive(#D3DPT_TRIANGLELIST, 0, 1)
 
  d3dDevice\EndScene()
  d3dDevice\Present(#Null, #Null, #Null, #Null)

Until GetAsyncKeyState_(#VK_ESCAPE)

D3D8_Close()
End 
Well, yes... this is silly I know ;)