• Welcome to Jose's Read Only Forum 2023.
 

DirectX 9 Examples

Started by José Roca, August 28, 2011, 04:32:48 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

 
This sample demonstrates how to perform multi-texturing under Direct3D by either modulating or adding two textures together in one rendering pass.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_MultiTexture.bas
' Contents: DX9 example
' Description: This sample demonstrates how to perfrom multitexturing with Direct3D.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_multitexture.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_4.htm#dx9_multitexture
' Control Keys: F1 - Toggle between modulating or adding the two textures.
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Multitexturing"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_TEX2

TYPE Vertex
   x   AS SINGLE
   y   AS SINGLE
   z   AS SINGLE
   tu1 AS SINGLE
   tv1 AS SINGLE
   tu2 AS SINGLE
   tv2 AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu1_, tv1_, tu2_, tv2_)
   v.x = x_ : v.y = y_ : v.z = z_
   v.tu1 = tu1_ : v.tv1 = tv1_ : v.tu2 = tu2_ : v.tv2 = tv2_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture_0 AS IDirect3DTexture9
   INSTANCE m_pTexture_1 AS IDirect3DTexture9
   INSTANCE m_bModulate AS LONG
   INSTANCE m_quadVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bModulate = %TRUE
      DIM m_quadVertices(3) AS INSTANCE Vertex
      FillVertex(m_quadVertices(0), -1.0!,  1.0!,  0.0!,  0.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(1),  1.0!,  1.0!,  0.0!,  1.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(2), -1.0!, -1.0!,  0.0!,  0.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(3),  1.0!, -1.0!,  0.0!,  1.0!,  1.0!,  1.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      ' // Loads the textures
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\dx9_multitexture.bmp", m_pTexture_0)
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\dx9_multitexture_checker.bmp", m_pTexture_1)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      ' // Creates a vertex buffer
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, %D3DUSAGE_WRITEONLY, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
      m_pVertexBuffer.Unlock

      ' // Sets a device render-state parameter
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      ' // This is how you find out how many texture stages your hardware will support
      LOCAL caps AS D3DCAPS9
      m_pD3DDevice.GetDeviceCaps(caps)
      LOCAL dwMaxTextureBlendStages AS DWORD
      dwMaxTextureBlendStages = caps.MaxTextureBlendStages

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL matWorld AS D3DXMATRIX
      D3DXMatrixTranslation(matWorld, 0.0!, 0.0!, 4.0!)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      ' // STAGE 0
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      m_pD3DDevice.SetTextureStageState(0, %D3DTSS_TEXCOORDINDEX, 0)
      m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLOROP, %D3DTOP_MODULATE)   ' // Modulate...
      m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG1, %D3DTA_TEXTURE)   ' // the texture for this stage with...
      m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG2, %D3DTA_DIFFUSE)   ' // the diffuse color of the geometry.

      ' // STAGE 1
      m_pD3DDevice.SetSamplerState(1, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(1, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      m_pD3DDevice.SetTextureStageState(1, %D3DTSS_TEXCOORDINDEX, 1)

      IF ISTRUE m_bModulate THEN
         m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLOROP, %D3DTOP_MODULATE)   ' // Modulate...
      ELSE
         m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLOROP, %D3DTOP_ADD)        ' // or Add...
      END IF

      m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLORARG1, %D3DTA_TEXTURE)      ' // the texture for this stage with...
      m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLORARG2, %D3DTA_CURRENT)      ' // the current argument passed down from stage 0

      ' // Set the two textures to be used by our stages...
      m_pD3DDevice.SetTexture(0, m_pTexture_0)
      m_pD3DDevice.SetTexture(1, m_pTexture_1)

      ' // Render our quad with two sets of texture coordinates...
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pTexture_0 = NOTHING
            m_pTexture_1 = NOTHING
            m_pVertexBuffer = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  IF m_bModulate = 0 THEN m_bModulate = -1 ELSE m_bModulate = 0
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to create dynamic textures through the use of an off-screen rendering surface under Direct3D.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_OffscreenRendering.bas
' Contents: DX9 example
' Description: Demonstrates how to create dynamic textures through off-screen rendering.
' As a demonstration, a spinning textured cube is rendered to an off-screen surface, which
' is in turn, used to create a dynamic texture. The dynamic texture is then used to
' texture a second spinning cube, which will be rendered to the application's window.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_offscreen_rendering.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_6.htm#dx9_lighting
' Control Keys: Left Mouse Button  - Spin the large, black cube.
'               Right Mouse Button - Spin the textured cube being rendered into the p-buffer.
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Off-Screen Rendering"

%RENDERTOSURFACE_WIDTH = 256
%RENDERTOSURFACE_HEIGHT = 256

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTestTexture AS IDirect3DTexture9
   INSTANCE m_pRenderToSurface AS ID3DXRenderToSurface
   INSTANCE m_pDynamicTexture AS IDirect3DTexture9
   INSTANCE m_pTextureSurface AS IDirect3DSurface9
   INSTANCE m_matProjection_window AS D3DXMATRIX
   INSTANCE m_matProjection_offscreenSurface AS D3DXMATRIX
   INSTANCE m_cubeVertices () AS Vertex
   INSTANCE m_fSpinX_L AS SINGLE
   INSTANCE m_fSpinY_L AS SINGLE
   INSTANCE m_fSpinX_R AS SINGLE
   INSTANCE m_fSpinY_R AS SINGLE

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      DIM m_cubeVertices(23) AS INSTANCE Vertex
      FillVertex(m_cubeVertices( 0), -1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 1),  1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices( 2), -1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices( 3),  1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices( 4), -1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices( 5), -1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices( 6),  1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 7),  1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices( 8), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 9),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(10), -1.0!,  1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(11),  1.0!,  1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(12), -1.0!, -1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(13), -1.0!, -1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(14),  1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(15),  1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(16),  1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(17),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(18),  1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(19),  1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(20), -1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(21), -1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(22), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(23), -1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG

      ' // Loads the texture
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\test.bmp", m_pTestTexture)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      ' // Creates a vertex buffer
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_cubeVertices) - LBOUND(m_cubeVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_cubeVertices(0)), nSize
      m_pVertexBuffer.Unlock

      ' // Sets a device render-state parameter
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(m_matProjection_window, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, m_matProjection_window)

      ' // Create our dynamic texture for use by the "render to" surface...
      hr = D3DXCreateTexture(m_pD3DDevice, _
                             %RENDERTOSURFACE_WIDTH, _
                             %RENDERTOSURFACE_HEIGHT, _
                             1, _
                             %D3DUSAGE_RENDERTARGET, _
                             %D3DFMT_A8R8G8B8, _
                             %D3DPOOL_DEFAULT, _
                             m_pDynamicTexture)
      IF FAILED(hr) THEN
         MessageBox(%NULL,"Failed to create a texture with the D3DUSAGE_RENDERTARGET usage flag set!", _
               "ERROR", %MB_OK OR %MB_ICONEXCLAMATION)
         METHOD = hr
         EXIT METHOD
      END IF

      ' // Create an off-screen "render to" surface...
      LOCAL desc AS D3DSURFACE_DESC
      m_pDynamicTexture.GetSurfaceLevel(0, m_pTextureSurface)
      m_pTextureSurface.GetDesc(desc)
      hr = D3DXCreateRenderToSurface(m_pD3DDevice, _
                                     desc.Width, _
                                     desc.Height, _
                                     desc.Format, _
                                     %TRUE, _
                                     %D3DFMT_D16, _
                                     m_pRenderToSurface)

      IF FAILED(hr) THEN
         MessageBox(%NULL,"Failed to create the off-screen render surface!", _
               "ERROR", %MB_OK OR %MB_ICONEXCLAMATION)
         METHOD = hr
         EXIT METHOD
      END IF

      ' // We'll need to create a second projection matrix, which take in account
      ' // the off-screen surface's dimensions.
      D3DXMatrixPerspectiveFovLH(m_matProjection_offscreenSurface, _
                                 D3DXToRadian(45.0!), _
                                 %RENDERTOSURFACE_WIDTH / %RENDERTOSURFACE_HEIGHT, _
                                 0.1!, 100.0!)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG
      LOCAL matWorld AS D3DXMATRIX
      LOCAL matTranslation AS D3DXMATRIX
      LOCAL matRotation AS D3DXMATRIX

      ' //-------------------------------------------------------------------------
      ' // Use the "render to" surface for off-screen rendering
      ' //-------------------------------------------------------------------------

      m_pRenderToSurface.BeginScene(m_pTextureSurface, BYVAL %NULL)

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      ' // We'll need to change the projection matrix on the device, to match the
      ' // off-screen surface's dimensions, or the cube will look wrong.
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, m_matProjection_offscreenSurface)

      ' // Let the user spin the cube about with the right mouse button, so our
      ' // dynamic texture will show motion.
      D3DXMatrixTranslation(matTranslation, 0.0!, 0.0!, 5.0!)
      D3DXMatrixRotationYawPitchRoll(matRotation, D3DXToRadian(m_fSpinX_R), D3DXToRadian(m_fSpinY_R), 0.0!)
      D3DXMatrixMultiply(matWorld, matRotation, matTranslation)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Now the render the cube to the off-screen surface
      m_pD3DDevice.SetTexture(0, m_pTestTexture)
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)

      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  0, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  4, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  8, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 12, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 16, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 20, 2)

      m_pRenderToSurface.EndScene(0)

      ' //-------------------------------------------------------------------------
      ' // Use the Direct3D device for regular rendering...
      ' //-------------------------------------------------------------------------

      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,1.0!,1.0!), 1.0!, 0)

      ' // Change the projection matrix back, so it matches the window's size.
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, m_matProjection_window)

      ' // Let the user spin the cube about with the left mouse button.
      D3DXMatrixTranslation(matTranslation, 0.0!, 0.0!, 5.0!)
      D3DXMatrixRotationYawPitchRoll(matRotation, D3DXToRadian(m_fSpinX_L), D3DXToRadian(m_fSpinY_L), 0.0!)
      D3DXMatrixMultiply(matWorld, matRotation, matTranslation)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      ' // Finally, we'll use the dynamic texture like a regular static texture.
      m_pD3DDevice.SetTexture(0, m_pDynamicTexture)
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)

      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  0, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  4, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  8, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 12, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 16, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 20, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pRenderToSurface = NOTHING
            m_pDynamicTexture = NOTHING
            m_pTextureSurface = NOTHING
            m_pTestTexture = NOTHING
            m_pVertexBuffer = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   ' ====================================================================================
   ' Processes mouse
   ' ====================================================================================
   METHOD ProcessMouse (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      STATIC ptLastMousePosit_L AS POINT
      STATIC ptCurrentMousePosit_L AS POINT
      STATIC bMousinm_L AS LONG

      STATIC ptLastMousePosit_R AS POINT
      STATIC ptCurrentMousePosit_R AS POINT
      STATIC bMousinm_R AS LONG

      SELECT CASE wMsg

         CASE %WM_LBUTTONDOWN
            ptLastMousePosit_L.x = LO(WORD, lParam)
            ptCurrentMousePosit_L.x = LO(WORD, lParam)
            ptLastMousePosit_L.y = HI(WORD, lParam)
            ptCurrentMousePosit_L.y = HI(WORD, lParam)
            bMousinm_L = %TRUE

         CASE %WM_LBUTTONUP
            bMousinm_L = %FALSE

         CASE %WM_RBUTTONDOWN
            ptLastMousePosit_R.x = LO(WORD, lParam)
            ptCurrentMousePosit_R.x = LO(WORD, lParam)
            ptLastMousePosit_R.y = HI(WORD, lParam)
            ptCurrentMousePosit_R.y = HI(WORD, lParam)
            bMousinm_R = %TRUE

         CASE %WM_RBUTTONUP
            bMousinm_R = %FALSE

         CASE %WM_MOUSEMOVE
            ptCurrentMousePosit_L.x = LO(WORD, lParam)
            ptCurrentMousePosit_L.y = HI(WORD, lParam)
            ptCurrentMousePosit_R.x = LO(WORD, lParam)
            ptCurrentMousePosit_R.y = HI(WORD, lParam)

            IF bMousinm_L THEN
               m_fSpinX_L = m_fSpinX_L - (ptCurrentMousePosit_L.x - ptLastMousePosit_L.x)
               m_fSpinY_L = m_fSpinY_L - (ptCurrentMousePosit_L.y - ptLastMousePosit_L.y)
            END IF

            IF bMousinm_R THEN
               m_fSpinX_R = m_fSpinX_R - (ptCurrentMousePosit_R.x - ptLastMousePosit_R.x)
               m_fSpinY_R = m_fSpinY_R - (ptCurrentMousePosit_R.y - ptLastMousePosit_R.y)
            END IF

            ptLastMousePosit_L.x = ptCurrentMousePosit_L.x
            ptLastMousePosit_L.y = ptCurrentMousePosit_L.y
            ptLastMousePosit_R.x = ptCurrentMousePosit_R.x
            ptLastMousePosit_R.y = ptCurrentMousePosit_R.y

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_LBUTTONDOWN, %WM_LBUTTONUP, %WM_RBUTTONDOWN, %WM_RBUTTONUP, %WM_MOUSEMOVE
         pDX9.ProcessMouse hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to setup point lighting with Direct3D. The sample also demonstrates how the tessellation or triangle count of a mesh effects lighting.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_PointLight.bas
' Contents: DX9 example
' Description: Demonstrates how to setup point lighting with Direct3D. The sample also
' demonstrates how the tessellation or triangle count of a mesh effects lighting.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_point_light.cpp by Kevin Harris, 02/17/05, available at
' http://www.codesampler.com/dx9src/dx9src_5.htm#dx9_point_light
' Control Keys: v - Decrease the mesh's tessellation or vertex count
'               V - Increase the mesh's tessellation or vertex count
'               w - Toggle wire-frame mode
'
'               r  - Decrease Range
'               R  - Increase Range
'               F1 - Decrease Attenuation0
'               F2 - Increase Attenuation0
'               F3 - Decrease Attenuation1
'               F4 - Increase Attenuation1
'               F5 - Decrease Attenuation2
'               F6 - Increase Attenuation2
'
'               Up   - Move the point light up
'               Down - Move the point light down
'
' NOTE: Please refer to the DirectX 9.0c Documentation for the more
'       information concerning the Attenuation, and Range controls.
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Point Lighting"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_NORMAL OR %D3DFVF_DIFFUSE

TYPE Vertex
   ' Position of vertex in 3D space
   x       AS SINGLE
   y       AS SINGLE
   z       AS SINGLE
   ' Normal for lighting calculations
   nx      AS SINGLE
   ny      AS SINGLE
   nz      AS SINGLE
   ' Diffuse color of vertex
   diffuse AS DWORD
END TYPE

' enum LightTypes
%LIGHT_TYPE_DIRECTIONAL = 0
%LIGHT_TYPE_SPOT        = 1
%LIGHT_TYPE_POINT       = 2

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pMeshVertices AS IDirect3DVertexBuffer9
   INSTANCE m_pSphereMesh AS ID3DXMesh                   ' // A mesh to represent a point light
   INSTANCE m_light0 AS D3DLIGHT9
   INSTANCE m_meshMaterial AS D3DMATERIAL9
   INSTANCE m_sphereMaterial AS D3DMATERIAL9

   INSTANCE m_bRenderInWireFrame AS LONG
   INSTANCE m_fLightPositionY AS SINGLE
   INSTANCE m_fAttenuation0 AS SINGLE
   INSTANCE m_fAttenuation1 AS SINGLE
   INSTANCE m_fAttenuation2 AS SINGLE
   INSTANCE m_fRange AS SINGLE
   INSTANCE m_nMeshVertCount AS LONG
   INSTANCE m_nNumVerts AS LONG

   ' ====================================================================================
   ' Initializes values
   ' ====================================================================================
   CLASS METHOD Create
      m_bRenderInWireFrame = %FALSE
      m_fLightPositionY    = 2.0!
      m_fAttenuation0      = 0.0!
      m_fAttenuation1      = 0.5!
      m_fAttenuation2      = 0.0!
      m_fRange             = 10.0!
      m_nMeshVertCount     = 0
      m_nNumVerts          = 64
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Init lighting
   ' =====================================================================================
   METHOD initLighting

      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
      m_pD3DDevice.LightEnable(0, %TRUE)

      ' // Set up our material...
      m_meshMaterial.Diffuse.r = 1.0!
      m_meshMaterial.Diffuse.g = 1.0!
      m_meshMaterial.Diffuse.b = 1.0!
      m_meshMaterial.Diffuse.a = 1.0!
      m_meshMaterial.Ambient.r = 1.0!
      m_meshMaterial.Ambient.g = 1.0!
      m_meshMaterial.Ambient.b = 1.0!
      m_meshMaterial.Ambient.a = 1.0!
      m_pD3DDevice.SetMaterial(m_meshMaterial)

      ' // Set up our point light...
      m_light0.Diffuse.r    = 1.0!
      m_light0.Diffuse.g    = 1.0!
      m_light0.Diffuse.b    = 1.0!
      m_light0.Diffuse.a    = 1.0!
      m_light0.Type         = %D3DLIGHT_POINT
      LOCAL v AS D3DXVECTOR3
      v.x = 0.0! : v.y = m_fLightPositionY : v.z = 0.0!
      TYPE SET m_light0.Position     = v
      m_light0.Attenuation0 = m_fAttenuation0
      m_light0.Attenuation1 = m_fAttenuation1
      m_light0.Attenuation2 = m_fAttenuation2
      m_light0.Range        = m_fRange
      m_pD3DDevice.SetLight(0, m_light0)

      ' // Enable some dim, grey ambient lighting...
      ' //m_pD3DDevice.SetRenderState(%D3DRS_AMBIENT,
      ' //                            %D3DCOLOR_COLORVALUE(0.25!, 0.25!, 0.25!, 1.0!))

      ' // Set up a yellow emissive material so our little sphere, which
      ' // represents our light, will appear to glow yellow.
      m_sphereMaterial.Emissive.r = 1.0!
      m_sphereMaterial.Emissive.g = 1.0!
      m_sphereMaterial.Emissive.b = 0.0!
      m_sphereMaterial.Emissive.a = 1.0!

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Create simple mesh
   ' =====================================================================================
   METHOD createSimpleMesh (BYVAL nNumVertsAlongX AS LONG, BYVAL nNumVertsAlongZ AS LONG, _
                              BYVAL fMeshLengthAlongX AS SINGLE, BYVAL fMeshLengthAlongZ AS SINGLE) AS LONG

      LOCAL nMeshVertCount AS LONG
      nMeshVertCount = (nNumVertsAlongX-1) * (nNumVertsAlongZ-1) * 6

      ' // Compute position deltas for moving down the X, and Z axis during mesh creation
      LOCAL dX, dZ AS SINGLE
      dX = 1.0! / (nNumVertsAlongX - 1)
      dZ = 1.0! / (nNumVertsAlongZ - 1)

      m_pD3DDevice.CreateVertexBuffer(nMeshVertCount * SIZEOF(Vertex), _
                                      %D3DUSAGE_WRITEONLY, %FVF_Flags, _
                                      %D3DPOOL_MANAGED, m_pMeshVertices, %NULL)

      LOCAL i, x, z AS LONG
      LOCAL v AS Vertex PTR

      m_pMeshVertices.Lock(0, 0, v, 0)

      ' // These are all the same...
      FOR i = 0 TO nMeshVertCount - 1
         ' // Mesh tesselation occurs in the X,Z plane, so Y is always zero
         @v[i].nx = 0.0!
         @v[i].ny = 1.0!
         @v[i].nz = 0.0!
         @v[i].diffuse = D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!)
      NEXT

      ' //
      ' // Create all the vertex points required by the mesh...
      ' //
      ' // Note: Mesh tesselation occurs in the X,Z plane.
      ' //

      ' // For each row of our mesh...
      i = 0
      FOR z = 0 TO nNumVertsAlongZ - 2
         ' // Fill the row with quads which are composed of two triangles each...
         FOR x = 0 TO nNumVertsAlongX - 2
            ' // First triangle of the current quad
            ' // 1 ___ 2
            ' //  |  /|
            ' //  |/__|
            ' // 0

            ' // 0
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1

            ' // 1
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // 2
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // Second triangle of the current quad
            ' //   ___ 1
            ' //  |  /|
            ' //  |/__|
            ' // 0     2

            ' // 0
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1

            ' // 1
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // 2
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1
         NEXT
      NEXT

      m_pMeshVertices.Unlock

      METHOD = nMeshVertCount

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG
      LOCAL matProj AS D3DXMATRIX

      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      LOCAL mView AS D3DXMATRIX
      LOCAL v1, v2, v3 AS D3DXVECTOR3
      v1.x = 0.0! : v1.y = 4.0! : v1.z = -14.0!   ' // Camera position
      v2.x = 0.0! : v2.y = 0.0! : v2.z =   0.0!   ' // Look-at point
      v3.x = 0.0! : v3.y = 1.0! : v3.z =   0.0!   ' // Up vector
      D3DXMatrixLookAtLH(mView, v1, v2, v3)
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, mView)

      ME.initLighting

      ' // Create a custom mesh to test lighting on.
      m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)

      ' // Create a sphere mesh to represent our light's position.
      D3DXCreateSphere(m_pD3DDevice, 0.1!, 20, 20, m_pSphereMesh, BYVAL %NULL)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      LOCAL matWorld AS D3DXMATRIX
      LOCAL matTrans AS D3DXMATRIX
      LOCAL matRotate AS D3DXMATRIX

      ' // Set up our light and apply a material...

      m_light0.Position.y   = m_fLightPositionY
      m_light0.Attenuation0 = m_fAttenuation0
      m_light0.Attenuation1 = m_fAttenuation1
      m_light0.Attenuation2 = m_fAttenuation2
      m_light0.Range        = m_fRange

      m_pD3DDevice.SetLight(0, m_light0)
      m_pD3DDevice.LightEnable(0, %TRUE)
      m_pD3DDevice.SetMaterial(m_meshMaterial)

      ' // Render a tesselated mesh of variable resolution so we can see how its
      ' // tessleation alters our attempt to light it.

      D3DXMatrixTranslation(matTrans, -5.0!, 0.0!, -5.0!)
      D3DXMatrixRotationZ(matRotate, D3DXToRadian(0.0!))
      D3DXMatrixMultiply(matWorld, matRotate, matTrans)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pD3DDevice.SetStreamSource(0, m_pMeshVertices, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, m_nMeshVertCount / 3)

      ' // Render a little yellow sphere to represent out light's current position
      ' // in 3D space.

      m_pD3DDevice.LightEnable(0, %FALSE)
      m_pD3DDevice.SetMaterial(m_sphereMaterial)

      D3DXMatrixTranslation(matWorld, m_light0.Position.x, _
                            m_light0.Position.y, m_light0.Position.z)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
      m_pSphereMesh.DrawSubset(0)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pMeshVertices = NOTHING
            m_pSphereMesh = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_CHAR
            SELECT CASE wParam
               CASE ASC("v")
                  m_nNumVerts = m_nNumVerts - 1
                  ' // Don't let the mesh's resolution get too low!
                  IF m_nNumVerts <= 1 THEN m_nNumVerts = 2
                  ' // Release the old mesh so we can create a new one.
                  m_pMeshVertices = NOTHING
                  m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)
               CASE ASC("V")
                  m_nNumVerts = m_nNumVerts + 1
                  ' // Release the old mesh so we can create a new one.
                  m_pMeshVertices = NOTHING
                  m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)
               CASE ASC("r")
                  m_fRange = m_fRange - 1.0!
               CASE ASC("R")
                  m_fRange = m_fRange + 1.0!
               CASE ASC("w"), ASC("W")
                  m_bRenderInWireFrame = IIF&(m_bRenderInWireFrame = 0, -1, 0)
                  IF ISTRUE m_bRenderInWireFrame THEN
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_WIREFRAME)
                  ELSE
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_SOLID)
                  END IF
            END SELECT

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  m_fAttenuation0 = m_fAttenuation0 - 0.01!
                  IF m_fAttenuation0 < 0.0! THEN m_fAttenuation0 = 0.0!
               CASE %VK_F2
                  m_fAttenuation0 = m_fAttenuation0 + 0.01!
               CASE %VK_F3
                  m_fAttenuation1 = m_fAttenuation1 - 0.01!
                  IF m_fAttenuation1 < 0.0! THEN m_fAttenuation1 = 0.0!
               CASE %VK_F3
                  m_fAttenuation1 = m_fAttenuation1+ 0.01!
               CASE %VK_F5
                  m_fAttenuation2 = m_fAttenuation2 - 0.01!
                  IF m_fAttenuation2 < 0.0! THEN m_fAttenuation2 = 0.0!
               CASE %VK_F6
                  m_fAttenuation2 = m_fAttenuation2 + 0.01!
               CASE %VK_UP
                  m_fLightPositionY = m_fLightPositionY + 0.1!
               CASE %VK_DOWN
                  m_fLightPositionY = m_fLightPositionY - 0.1!
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_CHAR, %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
This sample demonstrates how to use the 6 primitive types available under Direct3D: point list, line list, line strip, triangle list, triangle strip, and triangle fan.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_PrimitiveTypes.bas
' Contents: DX9 example
' Description: Demonstrates how to use the 6 primitive types available under Direct3D:
' point list, line list, line strip, triangle list, triangle strip, and triangle fan.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_primitive_types.cpp by Kevin Harris, 06/06/05, available at
' http://www.codesampler.com/dx9src/dx9src_2.htm#dx9_primitive_types
' Control Keys: F1 - Switch the primitive type to be rendered.
'               F2 - Toggle wire-frame mode.
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Primitive Types"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_DIFFUSE

TYPE Vertex
   x       AS SINGLE
   y       AS SINGLE
   z       AS SINGLE
   dwColor AS DWORD
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, dwColor_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.dwColor = dwColor_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pPointList AS IDirect3DVertexBuffer9
   INSTANCE m_pLineStrip AS IDirect3DVertexBuffer9
   INSTANCE m_pLineList AS IDirect3DVertexBuffer9
   INSTANCE m_pTriangleList AS IDirect3DVertexBuffer9
   INSTANCE m_pTriangleStrip AS IDirect3DVertexBuffer9
   INSTANCE m_pTriangleFan AS IDirect3DVertexBuffer9
   INSTANCE m_bRenderInWireFrame AS LONG
   INSTANCE m_currentPrimitive AS LONG
   INSTANCE m_pointList () AS Vertex
   INSTANCE m_lineList () AS Vertex
   INSTANCE m_lineStrip () AS Vertex
   INSTANCE m_triangleList () AS Vertex
   INSTANCE m_triangleStrip () AS Vertex
   INSTANCE m_triangleFan () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create

      m_currentPrimitive = %D3DPT_TRIANGLEFAN

      '// We'll store the vertex data in simple arrays until we're ready to load
      '// them into actual Direct3D Vertex Buffers. Seeing the vertices laid out
      '// like this should make it easier to understand how vertices need to be
      '// passed to be considered valid for each primitive type.

      DIM m_pointList(4) AS INSTANCE Vertex

      FillVertex(m_pointList(0),  0.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_pointList(1),  0.5!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_pointList(2), -0.5!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_pointList(3),  0.0!, -0.5!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
      FillVertex(m_pointList(4),  0.0!,  0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))

      DIM m_lineList(5) AS INSTANCE Vertex

      FillVertex(m_lineList(0), -1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_lineList(1),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_lineList(2),  0.5!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_lineList(3),  0.5!, -1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_lineList(4),  1.0!, -0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_lineList(5), -1.0!, -0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))

      DIM m_lineStrip(5) AS INSTANCE Vertex

      FillVertex(m_lineStrip(0),  0.5!,  0.5!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_lineStrip(1),  1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_lineStrip(2),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_lineStrip(3), -1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
      FillVertex(m_lineStrip(4),  0.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
      FillVertex(m_lineStrip(5),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))

      DIM m_triangleList(5) AS INSTANCE Vertex

      FillVertex(m_triangleList(0), -1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_triangleList(1),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleList(2),  1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_triangleList(3), -0.5!, -1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleList(4),  0.0!, -0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
      FillVertex(m_triangleList(5),  0.5!, -1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))

      DIM m_triangleStrip(7) AS INSTANCE Vertex

      FillVertex(m_triangleStrip(0), -2.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_triangleStrip(1), -1.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleStrip(2), -1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_triangleStrip(3),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleStrip(4),  0.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
      FillVertex(m_triangleStrip(5),  1.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))
      FillVertex(m_triangleStrip(6),  1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_triangleStrip(7),  2.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))

      DIM m_triangleFan(5) AS INSTANCE Vertex

      FillVertex(m_triangleFan(0),  0.0!, -1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
      FillVertex(m_triangleFan(1), -1.0!, -0.0!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleFan(2), -0.5!,  0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
      FillVertex(m_triangleFan(3),  0.0!,  1.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
      FillVertex(m_triangleFan(4),  0.5!,  0.5!,  0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
      FillVertex(m_triangleFan(5),  1.0!,  0.0!,  0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))

   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG
      LOCAL matProj AS D3DXMATRIX

      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 1.0!, 1.0!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_NONE)

      ' // Point List
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      pVertices = 0
      nSize = (UBOUND(m_pointList) - LBOUND(m_pointList) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pPointList, %NULL)
      m_pPointList.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_pointList(0)), nSize
      m_pPointList.Unlock

      ' // Line List
      pVertices = 0
      nSize = (UBOUND(m_lineList) - LBOUND(m_lineList) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pLineList, %NULL)
      m_pLineList.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_lineList(0)), nSize
      m_pLineList.Unlock

      ' // Line Strip
      pVertices = 0
      nSize = (UBOUND(m_lineStrip) - LBOUND(m_lineStrip) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pLineStrip, %NULL)
      m_pLineStrip.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_lineStrip(0)), nSize
      m_pLineStrip.Unlock

      ' // Triangle List
      pVertices = 0
      nSize = (UBOUND(m_triangleList) - LBOUND(m_triangleList) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pTriangleList, %NULL)
      m_pTriangleList.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_triangleList(0)), nSize
      m_pTriangleList.Unlock

      ' // Triangle Strip
      pVertices = 0
      nSize = (UBOUND(m_triangleStrip) - LBOUND(m_triangleStrip) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pTriangleStrip, %NULL)
      m_pTriangleStrip.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_triangleStrip(0)), nSize
      m_pTriangleStrip.Unlock

      ' // Triangle Fan
      pVertices = 0
      nSize = (UBOUND(m_triangleFan) - LBOUND(m_triangleFan) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pTriangleFan, %NULL)
      m_pTriangleFan.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_triangleFan(0)), nSize
      m_pTriangleFan.Unlock

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL mWorld AS D3DXMATRIX
      D3DXMatrixTranslation(mWorld, 0.0!, 0.0!, 5.0!)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, mWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      SELECT CASE AS LONG m_currentPrimitive

         CASE %D3DPT_POINTLIST
            m_pD3DDevice.SetStreamSource(0, m_pPointList, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_POINTLIST, 0, 5)

         CASE %D3DPT_LINELIST
            m_pD3DDevice.SetStreamSource(0, m_pLineList, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_LINELIST, 0, 3)

         CASE %D3DPT_LINESTRIP
            m_pD3DDevice.SetStreamSource(0, m_pLineStrip, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_LINESTRIP, 0, 5)

         CASE %D3DPT_TRIANGLELIST
            m_pD3DDevice.SetStreamSource(0, m_pTriangleList, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, 2)

         CASE %D3DPT_TRIANGLESTRIP
            m_pD3DDevice.SetStreamSource(0, m_pTriangleStrip, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 6)

         CASE %D3DPT_TRIANGLEFAN
            m_pD3DDevice.SetStreamSource(0, m_pTriangleFan, 0, SIZEOF(Vertex))
            m_pD3DDevice.SetFVF(%FVF_Flags)
            m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLEFAN, 0, 4)

      END SELECT

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pPointList = NOTHING
            m_pLineList = NOTHING
            m_pLineStrip = NOTHING
            m_pTriangleList = NOTHING
            m_pTriangleStrip = NOTHING
            m_pTriangleFan = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  IF m_currentPrimitive = %D3DPT_POINTLIST THEN
                     m_currentPrimitive = %D3DPT_LINELIST
                  ELSEIF m_currentPrimitive = %D3DPT_LINELIST THEN
                     m_currentPrimitive = %D3DPT_LINESTRIP
                  ELSEIF m_currentPrimitive = %D3DPT_LINESTRIP THEN
                     m_currentPrimitive = %D3DPT_TRIANGLELIST
                  ELSEIF m_currentPrimitive = %D3DPT_TRIANGLELIST THEN
                     m_currentPrimitive = %D3DPT_TRIANGLESTRIP
                  ELSEIF m_currentPrimitive = %D3DPT_TRIANGLESTRIP THEN
                     m_currentPrimitive = %D3DPT_TRIANGLEFAN
                  ELSEIF m_currentPrimitive = %D3DPT_TRIANGLEFAN THEN
                     m_currentPrimitive = %D3DPT_POINTLIST
                  END IF
               CASE %VK_F2
                  m_bRenderInWireFrame = NOT m_bRenderInWireFrame
                  IF ISTRUE m_bRenderInWireFrame THEN
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_WIREFRAME)
                  ELSE
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_SOLID)
                  END IF
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
This sample demonstrates how to respond to the app's window getting resized by resizing the front and back buffers of the Direct3D device to match it. If you don't do this, Direct3D will be forced to perform a stretch blit when the window is enlarged and everything rendered will appear course and blocky. For example, if the initial window size and Direct3D device are set to 640x480 and you enlarge the window to be 1024x768, the Direct3D device will continue to render at 640x480 unless its front back buffers are resized accordingly.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_ResizeWindow.bas
' Contents: DX9 example
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Description: how to respond to the app's window getting resized by resizing the front
' and back buffers of the Direct3D device to match it. If you don't do this, Direct3D will
' be forced to perform a stretch blit when the window is enlarged and everything rendered
' will appear course and blocky. For example, if the initial window size and Direct3D
' device are set to 640x480 and you enlarge the window to be 1024x768, the Direct3D device
' will continue to render at 640x480 unless its front and back buffers are resized accordingly.
' To see what happens when you don't handle resizing properly, run the sample and maximize
' the window. Once maximized, note how smooth the teapot is and how clean the texturing on
' the quad is. Next, grab the window's corner and considerably reduce the window's size
' and hit F1 to toggle off the handling code and maximize it again. When the window is
' maximized the teapot and textured quad should appear highly pixilated.
' Adapted from dx9_resize_window.cpp by Kevin Harris, 06/16/05,
' available at http://www.codesampler.com/dx9src/dx9src_6.htm#dx9_resize_window
' Control Keys: F1 - Toggle handling of WM_SIZE window message
'               Left Mouse Button - Spin the teapot and textured quad
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Resize Window"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_NORMAL OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   nx AS SINGLE
   ny AS SINGLE
   nz AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, nx_, ny_, nz_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.nx = nx_ : v.ny = ny_ : v.nz = nz_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pTeapotMesh AS ID3DXMesh
   INSTANCE m_teapotMtrl AS D3DMATERIAL9
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_quadMtrl AS D3DMATERIAL9
   INSTANCE m_pLight0 AS D3DLIGHT9
   INSTANCE m_bHandleWindowResize AS LONG
   INSTANCE m_fSpinX AS SINGLE
   INSTANCE m_fSpinY AS SINGLE
   INSTANCE m_quadVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bHandleWindowResize = -1
      DIM m_quadVertices(3) AS INSTANCE Vertex
      FillVertex(m_quadVertices(0), -1.0!, 1.0!, 0.0!,  0.0!, 0.0!, -1.0!,  0.0!,0.0!)
      FillVertex(m_quadVertices(1),  1.0!, 1.0!, 0.0!,  0.0!, 0.0!, -1.0!,  1.0!,0.0!)
      FillVertex(m_quadVertices(2), -1.0!,-1.0!, 0.0!,  0.0!, 0.0!, -1.0!,  0.0!,1.0!)
      FillVertex(m_quadVertices(3),  1.0!,-1.0!, 0.0!,  0.0!, 0.0!, -1.0!,  1.0!,1.0!)
      ' // Setup a material for the teapot
      m_teapotMtrl.Diffuse.r  = 0.0!
      m_teapotMtrl.Diffuse.g  = 1.0!
      m_teapotMtrl.Diffuse.b  = 1.0!
      m_teapotMtrl.Diffuse.a  = 1.0!
      m_teapotMtrl.Specular.r = 1.0!
      m_teapotMtrl.Specular.g = 1.0!
      m_teapotMtrl.Specular.b = 1.0!
      m_teapotMtrl.Specular.a = 1.0!
      m_teapotMtrl.Power      = 40.0!
      ' // Setup a material for the textured quad
      m_quadMtrl.Diffuse.r  = 1.0!
      m_quadMtrl.Diffuse.g  = 1.0!
      m_quadMtrl.Diffuse.b  = 1.0!
      m_quadMtrl.Diffuse.a  = 1.0!
      m_quadMtrl.Specular.r = 1.0!
      m_quadMtrl.Specular.g = 1.0!
      m_quadMtrl.Specular.b = 1.0!
      m_quadMtrl.Specular.a = 1.0!
      m_quadMtrl.Power      = 40.0!
      ' // Setup a simple directional light and some ambient
      m_pLight0.Type = %D3DLIGHT_DIRECTIONAL
      m_pLight0.Direction.x  = 1.0!
      m_pLight0.Direction.y  = 0.0!
      m_pLight0.Direction.z  = 1.0!
      m_pLight0.Diffuse.r    = 1.0!
      m_pLight0.Diffuse.g    = 1.0!
      m_pLight0.Diffuse.b    = 1.0!
      m_pLight0.Diffuse.a    = 1.0!
      m_pLight0.Specular.r   = 1.0!
      m_pLight0.Specular.g   = 1.0!
      m_pLight0.Specular.b   = 1.0!
      m_pLight0.Specular.a   = 1.0!
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      ' // Sets the device render-state parameters
      m_pd3dDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
      m_pd3dDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
      m_pd3dDevice.SetRenderState(%D3DRS_SPECULARENABLE, %TRUE)

      m_pd3dDevice.SetLight(0, m_pLight0)
      m_pd3dDevice.LightEnable(0, %TRUE)

      m_pd3dDevice.SetRenderState(%D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.2!, 0.2!, 0.2!, 1.0!))

      ' // Loads the texture
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\test.bmp", m_pTexture)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      ' // Creates a vertex buffer
      ' // NOTE: When a device is lost, vertex buffers created using D3DPOOL_DEFAULT
      ' // must be released properly before calling IDirect3DDevice9.Reset.
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, %D3DUSAGE_WRITEONLY, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
      m_pVertexBuffer.Unlock

      ' // Create a mesh object...
      ' //
      ' // NOTE: When a device is lost, meshes created using D3DXMESH_DYNAMIC
      ' // must be released properly before calling IDirect3DDevice9.Reset.
      D3DXLoadMeshFromX(".\Resources\teapot.x", _
                        %D3DXMESH_DYNAMIC, _    ' // Must be Released properly before calling IDirect3DDevice9.Reset
                        m_pd3dDevice, _
                        BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, m_pTeapotMesh)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.35!,0.53!,0.7!,1.0!), 1.0!, 0)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      LOCAL matView AS D3DXMATRIX
      LOCAL matWorld AS D3DXMATRIX
      LOCAL matRotation AS D3DXMATRIX
      LOCAL matTranslation AS D3DXMATRIX

      D3DXMatrixIdentity(matView)
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, matView)

      ' // Place and render first teapot...
      D3DXMatrixRotationYawPitchRoll(matRotation, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      D3DXMatrixTranslation(matTranslation, 1.4!, 0.0!, 6.0!)
      D3DXMatrixMultiply(matWorld, matRotation, matTranslation)
      m_pd3dDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pd3dDevice.SetMaterial(m_teapotMtrl)
      m_pTeapotMesh.DrawSubset(0)

      ' // Place and render textured quad...
      D3DXMatrixTranslation(matTranslation, -1.6!, 0.0!, 6.0!)
      D3DXMatrixMultiply(matWorld, matRotation, matTranslation)
      m_pd3dDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pd3dDevice.SetMaterial(m_quadMtrl)
      m_pd3dDevice.SetTexture(0, m_pTexture)
      m_pd3dDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pd3dDevice.SetFVF(%FVF_Flags)
      m_pd3dDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pVertexBuffer = NOTHING
            m_pTexture = NOTHING
            m_pTeapotMesh = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Handle window resizing
   ' =====================================================================================
   METHOD ResizeWindow (BYVAL hwnd AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)
      LOCAL hr AS LONG
      IF ISFALSE m_bHandleWindowResize THEN EXIT METHOD
      ' // If the device is not NULL and the WM_SIZE message is not a
      ' // SIZE_MINIMIZED event, resize the device's swap buffers to match
      ' // the new window size.
      IF ISOBJECT(m_pd3dDevice) AND wParam <> %SIZE_MINIMIZED THEN
         ' // Invalidate device objects
         m_pTexture = NOTHING
         m_pVertexBuffer = NOTHING
         m_pTeapotMesh = NOTHING
         m_d3dpp.BackBufferWidth  = LO(WORD, lParam)
         m_d3dpp.BackBufferHeight = HI(WORD, lParam)
         hr = m_pd3dDevice.Reset(m_d3dpp)
         IF hr = %D3DERR_INVALIDCALL THEN
            MessageBox %NULL, "Call to Reset() failed with D3DERR_INVALIDCALL! ", _
               "ERROR", %MB_OK OR %MB_ICONEXCLAMATION
         END IF
         ME.CreateDeviceObjects
      END IF
   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  m_bHandleWindowResize = NOT m_bHandleWindowResize
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   ' ====================================================================================
   ' Processes mouse
   ' ====================================================================================
   METHOD ProcessMouse (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      STATIC ptLastMousePosit AS POINT
      STATIC ptCurrentMousePosit AS POINT
      STATIC bMousing AS LONG

      SELECT CASE wMsg

         CASE %WM_LBUTTONDOWN
            ptLastMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptLastMousePosit.y = HI(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            bMousing = %TRUE

         CASE %WM_LBUTTONUP
            bMousing = %FALSE

         CASE %WM_MOUSEMOVE
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            IF bMousing THEN
               m_fSpinX = m_fSpinX - (ptCurrentMousePosit.x - ptLastMousePosit.x)
               m_fSpinY = m_fSpinY - (ptCurrentMousePosit.y - ptLastMousePosit.y)
            END IF
            ptLastMousePosit.x = ptCurrentMousePosit.x
            ptLastMousePosit.y = ptCurrentMousePosit.y

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_LBUTTONDOWN, %WM_LBUTTONUP, %WM_MOUSEMOVE
         pDX9.ProcessMouse hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_SIZE
         IF ISOBJECT(pDX9) THEN pDX9.ResizeWindow hwnd, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to setup a spot light with Direct3D. The sample also demonstrates how the tessellation or triangle count of a mesh effects lighting.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_SpotLight.bas
' Contents: DX9 example
' Description: Demonstrates how to setup a spot light with Direct3D. The sample also
' demonstrates how the tessellation or triangle count of a mesh effects lighting.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_spot_light.cpp by Kevin Harris, 02/17/05, available at
' http://www.codesampler.com/dx9src/dx9src_5.htm#dx9_spot_light
' Control Keys: v - Decrease the mesh's tessellation or vertex count
'               V - Increase the mesh's tessellation or vertex count
'               w - Toggle wire-frame mode
'
'               r  - Decrease Range
'               R  - Increase Range
'               t  - Decrease Theta
'               T  - Increase Theta
'               p  - Decrease Phi
'               P  - Increase Phi
'               f  - Decrease Falloff
'               F  - Increase Falloff
'               F1 - Decrease Attenuation0
'               F2 - Increase Attenuation0
'               F3 - Decrease Attenuation1
'               F4 - Increase Attenuation1
'               F5 - Decrease Attenuation2
'               F6 - Increase Attenuation2
'
'               Up   - Move the point light up
'               Down - Move the point light down
'               Left  - Swing the spot to the left
'               Right - Swing the spot to the right
'
' NOTE: Please refer to the DirectX 9.0c Documentation for the more
'       information concerning the Attenuation, Theta, Phi, and Falloff controls.
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Spot Lighting"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_NORMAL OR %D3DFVF_DIFFUSE

TYPE Vertex
   ' Position of vertex in 3D space
   x       AS SINGLE
   y       AS SINGLE
   z       AS SINGLE
   ' Normal for lighting calculations
   nx      AS SINGLE
   ny      AS SINGLE
   nz      AS SINGLE
   ' Diffuse color of vertex
   diffuse AS DWORD
END TYPE

' enum LightTypes
%LIGHT_TYPE_DIRECTIONAL = 0
%LIGHT_TYPE_SPOT        = 1
%LIGHT_TYPE_POINT       = 2

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pMeshVertices AS IDirect3DVertexBuffer9
   INSTANCE m_pConeMesh AS ID3DXMesh                   ' // A mesh to represent a spot light
   INSTANCE m_light0 AS D3DLIGHT9
   INSTANCE m_meshMaterial AS D3DMATERIAL9
   INSTANCE m_coneMaterial AS D3DMATERIAL9
   INSTANCE m_bRenderInWireFrame AS LONG
   INSTANCE m_fLightPositionY AS SINGLE
   INSTANCE m_fLightDirectionX AS SINGLE
   INSTANCE m_fAttenuation0 AS SINGLE
   INSTANCE m_fAttenuation1 AS SINGLE
   INSTANCE m_fAttenuation2 AS SINGLE
   INSTANCE m_fRange AS SINGLE
   INSTANCE m_fTheta AS SINGLE
   INSTANCE m_fPhi AS SINGLE
   INSTANCE m_fFalloff AS SINGLE
   INSTANCE m_nMeshVertCount AS LONG
   INSTANCE m_nNumVerts AS LONG

   ' ====================================================================================
   ' Initializes values
   ' ====================================================================================
   CLASS METHOD Create
      m_bRenderInWireFrame = %FALSE
      m_fLightPositionY    = 3.0!
      m_fLightDirectionX   = 0.0!
      m_fAttenuation0      = 0.0!
      m_fAttenuation1      = 0.5!
      m_fAttenuation2      = 0.0!
      m_fRange             = 10.0!
      m_fTheta             = 0.5!
      m_fPhi               = 1.0!
      m_fFalloff           = 1.0!
      m_nMeshVertCount     = 0
      m_nNumVerts          = 64
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Init lighting
   ' =====================================================================================
   METHOD initLighting

      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
      m_pD3DDevice.LightEnable(0, %TRUE)

      ' // Set up our material...
      m_meshMaterial.Diffuse.r = 1.0!
      m_meshMaterial.Diffuse.g = 1.0!
      m_meshMaterial.Diffuse.b = 1.0!
      m_meshMaterial.Diffuse.a = 1.0!
      m_meshMaterial.Ambient.r = 1.0!
      m_meshMaterial.Ambient.g = 1.0!
      m_meshMaterial.Ambient.b = 1.0!
      m_meshMaterial.Ambient.a = 1.0!
      m_pD3DDevice.SetMaterial(m_meshMaterial)

      ' // Set up our point light...
      m_light0.Diffuse.r    = 1.0!
      m_light0.Diffuse.g    = 1.0!
      m_light0.Diffuse.b    = 1.0!
      m_light0.Diffuse.a    = 1.0!
      m_light0.Type         = %D3DLIGHT_SPOT
      LOCAL v AS D3DXVECTOR3
      v.x = 0.0! : v.y = m_fLightPositionY : v.z = 0.0!
      TYPE SET m_light0.Position = v
      v.x = m_fLightDirectionX : v.y = -1.0! : v.z = -0.1!
      TYPE SET m_light0.Direction = v
      m_light0.Attenuation0 = m_fAttenuation0
      m_light0.Attenuation1 = m_fAttenuation1
      m_light0.Attenuation2 = m_fAttenuation2
      m_light0.Range        = m_fRange
      m_light0.Theta        = m_fTheta
      m_light0.Phi          = m_fPhi
      m_light0.Falloff      = m_fFalloff
      m_pD3DDevice.SetLight(0, m_light0)

      ' // Enable some dim, grey ambient lighting...
      m_pD3DDevice.SetRenderState(%D3DRS_AMBIENT, _
                                  D3DCOLOR_COLORVALUE(0.25, 0.25, 0.25, 1.0))

      ' // Set up a yellow emissive material so our little sphere, which
      ' // represents our light, will appear to glow yellow.
      m_coneMaterial.Emissive.r = 1.0!
      m_coneMaterial.Emissive.g = 1.0!
      m_coneMaterial.Emissive.b = 0.0!
      m_coneMaterial.Emissive.a = 1.0!

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Create simple mesh
   ' =====================================================================================
   METHOD createSimpleMesh (BYVAL nNumVertsAlongX AS LONG, BYVAL nNumVertsAlongZ AS LONG, _
                              BYVAL fMeshLengthAlongX AS SINGLE, BYVAL fMeshLengthAlongZ AS SINGLE) AS LONG

      LOCAL nMeshVertCount AS LONG
      nMeshVertCount = (nNumVertsAlongX-1) * (nNumVertsAlongZ-1) * 6

      ' // Compute position deltas for moving down the X, and Z axis during mesh creation
      LOCAL dX, dZ AS SINGLE
      dX = 1.0! / (nNumVertsAlongX - 1)
      dZ = 1.0! / (nNumVertsAlongZ - 1)

      m_pD3DDevice.CreateVertexBuffer(nMeshVertCount * SIZEOF(Vertex), _
                                      %D3DUSAGE_WRITEONLY, %FVF_Flags, _
                                      %D3DPOOL_MANAGED, m_pMeshVertices, %NULL)

      LOCAL i, x, z AS LONG
      LOCAL v AS Vertex PTR

      m_pMeshVertices.Lock(0, 0, v, 0)

      ' // These are all the same...
      FOR i = 0 TO nMeshVertCount - 1
         ' // Mesh tesselation occurs in the X,Z plane, so Y is always zero
         @v[i].nx = 0.0!
         @v[i].ny = 1.0!
         @v[i].nz = 0.0!
         @v[i].diffuse = D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!)
      NEXT

      ' // Create all the vertex points required by the mesh...
      ' //
      ' // Note: Mesh tesselation occurs in the X,Z plane.

      ' // For each row of our mesh...
      i = 0
      FOR z = 0 TO nNumVertsAlongZ - 2
         ' // Fill the row with quads which are composed of two triangles each...
         FOR x = 0 TO nNumVertsAlongX - 2
            ' // First triangle of the current quad
            ' // 1 ___ 2
            ' //  |  /|
            ' //  |/__|
            ' // 0

            ' // 0
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1

            ' // 1
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // 2
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // Second triangle of the current quad
            ' //   ___ 1
            ' //  |  /|
            ' //  |/__|
            ' // 0     2

            ' // 0
            @v[i].x = fMeshLengthAlongX * x * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1

            ' // 1
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * (z + 1) * dZ
            i = i + 1

            ' // 2
            @v[i].x = fMeshLengthAlongX * (x + 1) * dX
            @v[i].z = fMeshLengthAlongZ * z * dZ
            i = i + 1
         NEXT
      NEXT

      m_pMeshVertices.Unlock

      METHOD = nMeshVertCount

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG
      LOCAL matProj AS D3DXMATRIX

      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      LOCAL mView AS D3DXMATRIX
      LOCAL v1, v2, v3 AS D3DXVECTOR3
      v1.x = 0.0! : v1.y = 4.0! : v1.z = -14.0!   ' // Camera position
      v2.x = 0.0! : v2.y = 0.0! : v2.z =   0.0!   ' // Look-at point
      v3.x = 0.0! : v3.y = 1.0! : v3.z =   0.0!   ' // Up vector
      D3DXMatrixLookAtLH(mView, v1, v2, v3)
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, mView)

      ME.initLighting

      ' // Create a custom mesh to test lighting on.
      m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)

      ' // Create a sphere mesh to represent our spot light's position and direction.
      D3DXCreateCylinder(m_pd3dDevice, 0.0!, 0.25!, 0.5!, 20, 20, m_pConeMesh, BYVAL %NULL)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      LOCAL matWorld AS D3DXMATRIX
      LOCAL matTrans AS D3DXMATRIX
      LOCAL matRotate AS D3DXMATRIX

      ' // Set up our light and apply a material...
      m_light0.Position.y   = m_fLightPositionY
      m_light0.Direction.x  = m_fLightDirectionX
      m_light0.Attenuation0 = m_fAttenuation0
      m_light0.Attenuation1 = m_fAttenuation1
      m_light0.Attenuation2 = m_fAttenuation2
      m_light0.Range        = m_fRange
      m_light0.Range        = m_fRange
      m_light0.Theta        = m_fTheta
      m_light0.Phi          = m_fPhi
      m_light0.Falloff      = m_fFalloff

      m_pD3DDevice.SetLight(0, m_light0)
      m_pD3DDevice.LightEnable(0, %TRUE)
      m_pD3DDevice.SetMaterial(m_meshMaterial)

      ' // Render a tesselated mesh of variable resolution so we can see how its
      ' // tessleation alters our attempt to light it.

      D3DXMatrixTranslation(matTrans, -5.0!, 0.0!, -5.0!)
      D3DXMatrixRotationZ(matRotate, D3DXToRadian(0.0!))
      D3DXMatrixMultiply(matWorld, matRotate, matTrans)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pD3DDevice.SetStreamSource(0, m_pMeshVertices, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, m_nMeshVertCount / 3)

      ' // Render a little yellow cone to represent out spot light's current
      ' // position and direction in 3D space.

      m_pD3DDevice.LightEnable(0, %FALSE)
      m_pD3DDevice.SetMaterial(m_coneMaterial)

      ' // Position the spot light and then point it in the light's direction
      LOCAL vecFrom, vecAt, vecUp AS D3DXVECTOR3
      vecFrom.x = m_light0.Position.x
      vecFrom.y = m_light0.Position.y
      vecFrom.z = m_light0.Position.z
      vecAt.x = m_light0.Position.x + m_light0.Direction.x
      vecAt.y = m_light0.Position.y + m_light0.Direction.y
      vecAt.z = m_light0.Position.z + m_light0.Direction.z
      vecUp.x = 0.0! : vecUp.y = 1.0! : vecUp.z = 0.0!

      LOCAL matWorldInv AS D3DXMATRIX
      D3DXMatrixLookAtLH(matWorldInv, vecFrom, vecAt, vecUp)
      D3DXMatrixInverse(matWorld, BYVAL %NULL, matWorldInv)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pConeMesh.DrawSubset(0)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pMeshVertices = NOTHING
            m_pConeMesh = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_CHAR
            SELECT CASE wParam
               CASE ASC("v")
                  m_nNumVerts = m_nNumVerts - 1
                  ' // Don't let the mesh's resolution get too low!
                  IF m_nNumVerts <= 1 THEN m_nNumVerts = 2
                  ' // Release the old mesh so we can create a new one.
                  m_pMeshVertices = NOTHING
                  m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)
               CASE ASC("V")
                  m_nNumVerts = m_nNumVerts + 1
                  ' // Release the old mesh so we can create a new one.
                  m_pMeshVertices = NOTHING
                  m_nMeshVertCount = ME.createSimpleMesh(m_nNumVerts, m_nNumVerts, 10.0!, 10.0!)
               CASE ASC("r")
                  m_fRange = m_fRange - 1.0!
               CASE ASC("R")
                  m_fRange = m_fRange + 1.0!
               CASE ASC("t")
                  m_fTheta = m_fTheta - 0.01!
                  IF m_fTheta < 0.0! THEN m_fTheta = 0.0!
               CASE ASC("T")
                  m_fTheta = m_fTheta + 0.01!
               CASE ASC("p")
                  m_fPhi = m_fPhi - 0.01!
                  IF m_fPhi < 0.0! THEN m_fPhi = 0.0!
               CASE ASC("P")
                  m_fPhi = m_fPhi + 0.01!
               CASE ASC("f")
                  m_fFalloff = m_fFalloff - 0.01!
                  IF m_fFalloff < 0.0! THEN m_fFalloff = 0.0!
               CASE ASC("F")
                  m_fFalloff = m_fFalloff + 0.01!
               CASE ASC("w"), ASC("W")
                  m_bRenderInWireFrame = IIF&(m_bRenderInWireFrame = 0, -1, 0)
                  IF ISTRUE m_bRenderInWireFrame THEN
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_WIREFRAME)
                  ELSE
                     m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_SOLID)
                  END IF
            END SELECT

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  m_fAttenuation0 = m_fAttenuation0 - 0.01!
                  IF m_fAttenuation0 < 0.0! THEN m_fAttenuation0 = 0.0!
               CASE %VK_F2
                  m_fAttenuation0 = m_fAttenuation0 + 0.01!
               CASE %VK_F3
                  m_fAttenuation1 = m_fAttenuation1 - 0.01!
                  IF m_fAttenuation1 < 0.0! THEN m_fAttenuation1 = 0.0!
               CASE %VK_F3
                  m_fAttenuation1 = m_fAttenuation1+ 0.01!
               CASE %VK_F5
                  m_fAttenuation2 = m_fAttenuation2 - 0.01!
                  IF m_fAttenuation2 < 0.0! THEN m_fAttenuation2 = 0.0!
               CASE %VK_F6
                  m_fAttenuation2 = m_fAttenuation2 + 0.01!
               CASE %VK_UP
                  m_fLightPositionY = m_fLightPositionY + 0.1!
               CASE %VK_DOWN
                  m_fLightPositionY = m_fLightPositionY - 0.1!
               CASE %VK_LEFT
                  m_fLightDirectionX = m_fLightDirectionX - 0.1!
               CASE %VK_RIGHT
                  m_fLightDirectionX = m_fLightDirectionX + 0.1!
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_CHAR, %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates basic texture mapping using a textured quad and a bitmap of some wooden floor tiles.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_Texture.bas
' Contents: DX9 example
' Description: Demonstrates basic texture mapping using a textured quad and a bitmap of
' some wooden floor tiles.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_texture.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_3.htm#dx9_texture
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Texturing"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_quadVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      DIM m_quadVertices(3) AS INSTANCE Vertex
      FillVertex(m_quadVertices(0), -1.0!,  1.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(1),  1.0!,  1.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(2), -1.0!, -1.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(3),  1.0!, -1.0!,  0.0!,  1.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      ' // Loads the texture
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\woodfloor.bmp", m_pTexture)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      ' // Creates a vertex buffer
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
      m_pVertexBuffer.Unlock

      ' // Sets a device render-state parameter
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL matWorld AS D3DXMATRIX
      D3DXMatrixTranslation(matWorld, 0.0!, 0.0!, 4.0!)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      m_pD3DDevice.SetTexture(0, m_pTexture)
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pVertexBuffer = NOTHING
            m_pTexture = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         SELECT CASE LO(WORD, wParam)
            CASE %VK_ESCAPE
               SendMessage hwnd, %WM_CLOSE, 0, 0
               EXIT FUNCTION
         END SELECT

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to filter out unwanted graphical artifacts from Direct3D textures.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_TextureFiltering.bas
' Contents: DX9 example
' Description: Demonstrates how to filter out unwanted graphical artifacts from Direct3D textures.
' Direct3D texture filtering is controlled by calling SetSamplerState() and setting either
' D3DSAMP_MINFILTER, D3DSAMP_MAGFILTER, or D3DSAMP_MIPFILTER to one of the following filtering modes:
'    D3DTEXF_NONE
'    D3DTEXF_POINT
'    D3DTEXF_LINEAR
'    D3DTEXF_ANISOTROPIC
'    D3DTEXF_FLATCUBIC
'    D3DTEXF_GAUSSIANCUBIC
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_texture_filtering.cpp by Kevin Harris, 03/24/05, available at
' http://www.codesampler.com/dx9src/dx9src_3.htm#dx9_texture_filtering
' Control Keys: F1 - Change Minification filter
'               F2 - Change Magnification filter
'               F3 - Change Mip-Map filter
'               F4 - Increase Mip-Map LOD Bias
'               F5 - Decrease Mip-Map LOD Bias
'               F6 - Increase Max Anisotropy value
'               F7 - Decrease Max Anisotropy value
'               Left Mouse Button - Spin the view
'               Up Arrow - Move the test quad closer
'               Down Arrow - Move the test quad away
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Texture filtering"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

%FILTER_TYPE_NONE        = 0
%FILTER_TYPE_POINT       = 1
%FILTER_TYPE_LINEAR      = 2
%FILTER_TYPE_ANISOTROPIC = 3

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pD3DXFont AS ID3DXFont
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_fDistance AS SINGLE
   INSTANCE m_fSpinX AS SINGLE
   INSTANCE m_fSpinY AS SINGLE
   INSTANCE m_MinFilterType AS LONG
   INSTANCE m_MagFilterType AS LONG
   INSTANCE m_MipFilterType AS LONG
   INSTANCE m_nAnisotropy AS LONG
   INSTANCE m_fMipMapLodBias AS LONG
   INSTANCE m_bChangeFilters AS LONG
   INSTANCE m_quadVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_fDistance      = 4.0!
      m_MinFilterType  = %FILTER_TYPE_NONE
      m_MagFilterType  = %FILTER_TYPE_NONE
      m_MipFilterType  = %FILTER_TYPE_NONE
      m_nAnisotropy    = 1
      m_fMipMapLodBias = 0.0!
      m_bChangeFilters = %TRUE
      DIM m_quadVertices(3) AS INSTANCE Vertex
      FillVertex(m_quadVertices(0), -1.0!,  1.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(1),  1.0!,  1.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(2), -1.0!, -1.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(3),  1.0!, -1.0!,  0.0!,  1.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Creates the font
   ' =====================================================================================
   METHOD createD3DXFont

   '  // To create a Windows friendly font using only a point size, an
   '  // application must calculate the logical height of the font.
   '  //
   '  // This is because functions like createFont() and createFontIndirect()
   '  // only use logical units to specify height.
   '  //
   '  // Here's the formula to find the height in logical pixels:
   '  //
   '  //             -( point_size * LOGPIXELSY )
   '  //    height = ----------------------------
   '  //                          72

      LOCAL hr AS LONG
      LOCAL hDC AS DWORD
      LOCAL nHeight AS LONG
      LOCAL nPointSize AS LONG

      nPointSize = 9

      hDC = GetDC(%NULL)
      nHeight = -(MulDiv(nPointSize, GetDeviceCaps(hDC, %LOGPIXELSY), 72))
      ReleaseDC(%NULL, hDC)

      ' // Create a font for statistics and help output
      hr = D3DXCreateFont(m_pD3DDevice, nHeight, 0, %FW_BOLD, 0, %FALSE, _
                          %DEFAULT_CHARSET, %OUT_DEFAULT_PRECIS, %DEFAULT_QUALITY, _
                          %DEFAULT_PITCH OR %FF_DONTCARE, "Arial", m_pD3DXFont)

      IF FAILED(hr) THEN
         MessageBox(%NULL,"Call to D3DXCreateFont failed!", "ERROR", %MB_OK OR %MB_ICONEXCLAMATION)
      END IF

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Sets minification filter
   ' =====================================================================================
   METHOD setMinificationFilter

      SELECT CASE AS LONG m_MinFilterType
         CASE 0
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_NONE)
         CASE 1
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_POINT)
         CASE 2
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
         CASE 3
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_ANISOTROPIC)
      END SELECT

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Sets magnification filter
   ' =====================================================================================
   METHOD setMagnificationFilter

      SELECT CASE AS LONG m_MagFilterType
         CASE 0
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_NONE)
         CASE 1
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_POINT)
         CASE 2
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)
         CASE 3
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_ANISOTROPIC)
      END SELECT

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Sets mip filter
   ' =====================================================================================
   METHOD setMipMapFilter

      SELECT CASE AS LONG m_MipFilterType
         CASE 0
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPFILTER, %D3DTEXF_NONE)
         CASE 1
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPFILTER, %D3DTEXF_POINT)
         CASE 2
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPFILTER, %D3DTEXF_LINEAR)
         CASE 3
            m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPFILTER, %D3DTEXF_ANISOTROPIC)
      END SELECT

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG

      ' // Load the texture
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\texture_filtering.bmp", m_pTexture)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_NONE)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_NONE)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPFILTER, %D3DTEXF_NONE)

      ' // Create the font
      ME.createD3DXFont

      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
      m_pVertexBuffer.Unlock

      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_NONE)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene (BYVAL pWindow AS IWindow)

      LOCAL hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL matTrans AS D3DXMATRIX
      LOCAL matRot AS D3DXMATRIX
      LOCAL matWorld AS D3DXMATRIX

      D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, m_fDistance)
      D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      D3DXMatrixMultiply(matWorld, matRot, matTrans)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      IF ISTRUE m_bChangeFilters THEN
         ME.setMinificationFilter
         ME.setMagnificationFilter
         ME.setMipMapFilter
         m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAXANISOTROPY, m_nAnisotropy)
         m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MIPMAPLODBIAS, m_fMipMapLodBias)
         m_bChangeFilters = %FALSE
      END IF

      m_pD3DDevice.SetTexture(0, m_pTexture)
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)

      ' // Output the current settings...
      LOCAL destRect1, destRect2, destRect3 AS RECT
      SetRect(destRect1, 5 * pWindow.rxRatio, 5 * pWindow.ryRatio, 0, 0)
      SetRect(destRect2, 5 * pWindow.rxRatio, 20 * pWindow.ryRatio, 0, 0 )
      SetRect(destRect3, 5 * pWindow.rxRatio, 35 * pWindow.ryRatio, 0, 0)

      STATIC szMinFilter AS ASCIIZ * 255
      STATIC szMagFilter AS ASCIIZ * 255
      STATIC szMipFilter AS ASCIIZ * 255

      SELECT CASE AS LONG m_MinFilterType
         CASE %FILTER_TYPE_NONE
            szMinFilter = "D3DSAMP_MINFILTER = D3DTEXF_NONE    (Change: F1)"
         CASE %FILTER_TYPE_POINT
            szMinFilter = "D3DSAMP_MINFILTER = D3DTEXF_POINT    (Change: F1)"
         CASE %FILTER_TYPE_LINEAR
            szMinFilter = "D3DSAMP_MINFILTER = D3DTEXF_LINEAR    (Change: F1)"
         CASE %FILTER_TYPE_ANISOTROPIC
            szMinFilter = "D3DSAMP_MINFILTER = D3DTEXF_ANISOTROPIC    (Change: F1)"
      END SELECT

      SELECT CASE AS LONG m_MagFilterType
         CASE %FILTER_TYPE_NONE
            szMagFilter = "D3DSAMP_MAGFILTER = D3DTEXF_NONE    (Change: F2)"
         CASE %FILTER_TYPE_POINT
            szMagFilter = "D3DSAMP_MAGFILTER = D3DTEXF_POINT    (Change: F2)"
         CASE %FILTER_TYPE_LINEAR
            szMagFilter = "D3DSAMP_MAGFILTER = D3DTEXF_LINEAR    (Change: F2)"
         CASE %FILTER_TYPE_ANISOTROPIC
            szMagFilter = "D3DSAMP_MAGFILTER = D3DTEXF_ANISOTROPIC    (Change: F2)"
      END SELECT

      SELECT CASE AS LONG m_MipFilterType
         CASE %FILTER_TYPE_NONE
            szMipFilter = "D3DSAMP_MIPFILTER = D3DTEXF_NONE    (Change: F3)"
         CASE %FILTER_TYPE_POINT
            szMipFilter = "D3DSAMP_MIPFILTER = D3DTEXF_POINT    (Change: F3)"
         CASE %FILTER_TYPE_LINEAR
            szMipFilter = "D3DSAMP_MIPFILTER = D3DTEXF_LINEAR    (Change: F3)"
         CASE %FILTER_TYPE_ANISOTROPIC
            szMipFilter = "D3DSAMP_MIPFILTER = D3DTEXF_ANISOTROPIC    (Change: F3)"
      END SELECT

      m_pD3DXFont.DrawTextA(NOTHING, szMinFilter, -1, destRect1, %DT_NOCLIP, _
                           D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!))
      m_pD3DXFont.DrawTextA(NOTHING, szMagFilter, -1, destRect2, %DT_NOCLIP, _
                           D3DCOLOR_COLORVALUE( 1.0!, 1.0!, 1.0!, 1.0!))
      m_pD3DXFont.DrawTextA(NOTHING, szMipFilter, -1, destRect3, %DT_NOCLIP, _
                           D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!))

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pD3DXFont = NOTHING
            m_pTexture = NOTHING
            m_pVertexBuffer = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  m_MinFilterType = m_MinFilterType + 1
                  IF m_MinFilterType > 3 THEN m_MinFilterType = 0
                  m_bChangeFilters = %TRUE
               CASE %VK_F2
                  m_MagFilterType = m_MagFilterType + 1
                  IF m_MagFilterType > 3 THEN m_MagFilterType = 0
                  m_bChangeFilters = %TRUE
               CASE %VK_F3
                  m_MipFilterType = m_MipFilterType + 1
                  IF m_MipFilterType > 3 THEN m_MipFilterType = 0
                  m_bChangeFilters = %TRUE
               CASE %VK_F4
                  m_fMipMapLodBias = m_fMipMapLodBias + 1.0!
                  m_bChangeFilters = %TRUE
               CASE %VK_F5
                  m_fMipMapLodBias = m_fMipMapLodBias - 1.0!
                  m_bChangeFilters = %TRUE
               CASE %VK_F6
                  m_nAnisotropy = m_nAnisotropy + 1.0!
                  m_bChangeFilters = %TRUE
               CASE %VK_F7
                  m_nAnisotropy = m_nAnisotropy - 1.0!
                  m_bChangeFilters = %TRUE
               CASE 38   ' // Up Arrow Key
                  m_fDistance = m_fDistance - 1.0!
               CASE 40   ' // Down Arrow Key
                  m_fDistance = m_fDistance + 1.0!
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   ' ====================================================================================
   ' Processes mouse
   ' ====================================================================================
   METHOD ProcessMouse (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      STATIC ptLastMousePosit AS POINT
      STATIC ptCurrentMousePosit AS POINT
      STATIC bMousing AS LONG

      SELECT CASE wMsg

         CASE %WM_LBUTTONDOWN
            ptLastMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptLastMousePosit.y = HI(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            bMousing = %TRUE

         CASE %WM_LBUTTONUP
            bMousing = %FALSE

         CASE %WM_MOUSEMOVE
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            IF bMousing THEN
               m_fSpinX = m_fSpinX - (ptCurrentMousePosit.x - ptLastMousePosit.x)
               m_fSpinY = m_fSpinY - (ptCurrentMousePosit.y - ptLastMousePosit.y)
            END IF
            ptLastMousePosit.x = ptCurrentMousePosit.x
            ptLastMousePosit.y = ptCurrentMousePosit.y

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   STATIC pWindow AS IWindow        ' // Reference to the IWindow interface

   SELECT CASE wMsg

      CASE %WM_CREATE
         ' // Get a reference to the IWindow interface from the CREATESTRUCT structure
         pWindow = CWindow_GetObjectFromCreateStruct(lParam)
         EXIT FUNCTION

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene(pWindow)
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_LBUTTONDOWN, %WM_LBUTTONUP, %WM_MOUSEMOVE
         pDX9.ProcessMouse hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how texture sub-loading works under Direct3D by copying a smaller texture over the texel data of a larger texture.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_TextureSubloading.bas
' Contents: DX9 example
' Description: Demonstrates how texture sub-loading works under Direct3D by copying a
' smaller texture over the texel data of a larger texture.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_texture_subloading.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_3.htm#dx9_texture_subloading
' Control Keys: F1 - Toggle subloading
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Texture subloading"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_quadVertices () AS Vertex
   INSTANCE m_bAlterTexture AS LONG
   INSTANCE m_bDoSubload AS LONG

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bAlterTexture = %TRUE
      m_bDoSubload = %TRUE
      DIM m_quadVertices(3) AS INSTANCE Vertex
      FillVertex(m_quadVertices(0), -1.0!,  1.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(1),  1.0!,  1.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(2), -1.0!, -1.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(3),  1.0!, -1.0!,  0.0!,  1.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture
   ' =====================================================================================
   METHOD LoadTexture () AS LONG
      LOCAL hr AS LONG
      m_pTexture = NOTHING
      hr = D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\tex128.bmp", m_pTexture)
      IF hr <> %D3D_OK THEN METHOD = hr : EXIT METHOD
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)
   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the subtexture
   ' =====================================================================================
   METHOD LoadSubTexture () AS LONG

      LOCAL hr AS LONG
      LOCAL pSubTexture AS IDirect3DTexture9
      LOCAL pDestSurface AS IDirect3DSurface9
      LOCAL pSrcSurface AS IDirect3DSurface9
      LOCAL srcRect AS RECT
      LOCAL destRect AS RECT

      hr = D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\tex64.bmp", pSubTexture)
      IF hr <> %D3D_OK THEN METHOD = hr : EXIT METHOD
      m_pTexture.GetSurfaceLevel(0, pDestSurface)
      pSubTexture.GetSurfaceLevel(0, pSrcSurface)

      SetRect(srcRect, 0, 0, 64, 64)
      SetRect(destRect, 32, 32, 96, 96)

      D3DXLoadSurfaceFromSurface(pDestSurface, BYVAL %NULL, destRect, _
                                 pSrcSurface,  BYVAL %NULL, srcRect, _
                                 %D3DX_DEFAULT, 0)

      pSrcSurface = NOTHING
      pDestSurface = NOTHING
      pSubTexture = NOTHING

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG

      ' // Load the texture
      ME.LoadTexture

      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, %D3DUSAGE_WRITEONLY, %FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
      m_pVertexBuffer.Unlock

      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene (BYVAL pWindow AS IWindow)

      LOCAL hr AS LONG

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL matWorld AS D3DXMATRIX
      D3DXMatrixTranslation(matWorld, 0.0!, 0.0!, 4.0!)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      IF ISTRUE m_bAlterTexture THEN
         IF ISTRUE m_bDoSubload THEN
            ME.LoadSubTexture
         ELSE
            ME.LoadTexture
         END IF
         m_bAlterTexture = %FALSE
      END IF

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      m_pD3DDevice.SetTexture(0, m_pTexture)
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      m_pD3DDevice.SetFVF(%FVF_Flags)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pTexture = NOTHING
            m_pVertexBuffer = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_F1
                  IF m_bDoSubload = 0 THEN m_bDoSubload = -1 ELSE m_bDoSubload = 0
                  m_bAlterTexture = %TRUE
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   STATIC pWindow AS IWindow        ' // Reference to the IWindow interface

   SELECT CASE wMsg

      CASE %WM_CREATE
         ' // Get a reference to the IWindow interface from the CREATESTRUCT structure
         pWindow = CWindow_GetObjectFromCreateStruct(lParam)
         EXIT FUNCTION

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene(pWindow)
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to use concatenated translation, rotation, and scaling matrices to create a simulated solar system. And as a small bonus, the sample also demonstrates how to optimize Direct3D applications using a matrix stack to prevent continuous changes to the view matrix, which can kill your apps draw time.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_Transforms.bas
' Contents: DX9 example
' Description: how to use translation, rotation, and scaling matrices to create a simulated solar system.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_transforms.cpp by Kevin Harris, 06/28/05, available at
' http://www.codesampler.com/dx9src/dx9src_2.htm#dx9_transforms
' Control Keys: F1    - Speed up rotations
'               F2    - Slow down rotations
'               Space - Toggle orbiting on/off
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Transforms"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_DIFFUSE

TYPE Vertex
   x       AS SINGLE
   y       AS SINGLE
   z       AS SINGLE
   diffuse AS DWORD
END TYPE

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pSunMesh AS ID3DXMesh
   INSTANCE m_pEarthMesh AS ID3DXMesh
   INSTANCE m_pMoonMesh AS ID3DXMesh
   INSTANCE m_matrixStack AS ID3DXMatrixStack
   INSTANCE m_fSpeedmodifier AS SINGLE
   INSTANCE m_bOrbitOn AS LONG

   ' ====================================================================================
   ' Initializes values
   ' ====================================================================================
   CLASS METHOD Create
      m_fSpeedmodifier = 1.0!
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      LOCAL hr AS LONG
      LOCAL matProj AS D3DXMATRIX

      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_NONE)
      m_pD3DDevice.SetRenderState(%D3DRS_FILLMODE, %D3DFILL_WIREFRAME)

      ' // We'll use the D3DXCreateSphere utility function to create three simple
      ' // sphere meshes to experiment with.
      LOCAL pTempEarthMesh AS ID3DXMesh
      LOCAL pTempSunMesh AS ID3DXMesh

      D3DXCreateSphere(m_pD3DDevice, 1.0!, 20, 20, pTempSunMesh, BYVAL %NULL)
      D3DXCreateSphere(m_pD3DDevice, 1.0!, 10, 10, pTempEarthMesh, BYVAL %NULL)
      D3DXCreateSphere(m_pD3DDevice, 0.5!, 8, 8, m_pMoonMesh, BYVAL %NULL)

      ' // Unfortunately, the D3DXCreateSphere utility function creates a mesh
      ' // with no color, so we'll need to make a clone of the original meshes
      ' // using a FVF code that does include color so we can set up the Earth
      ' // and Sun with color.
      ' //
      ' // Once that's been done, we'll need to set the color values to something
      ' // appropriate for our solar system model.

      ' // Clone the original Earth mesh and make it blue...

      LOCAL i AS LONG
      LOCAL pTempVertexBuffer AS IDirect3DVertexBuffer9
      LOCAL nNumVerts AS LONG
      LOCAL pVertices AS Vertex PTR

      pTempEarthMesh.CloneMeshFVF(0, %FVF_Flags, m_pD3DDevice, m_pEarthMesh)
      IF SUCCEEDED(m_pEarthMesh.GetVertexBuffer(pTempVertexBuffer)) THEN
         nNumVerts = m_pEarthMesh.GetNumVertices
         pTempVertexBuffer.Lock(0, 0, pVertices, 0)
         FOR i = 0 TO nNumVerts - 1
            @pVertices[i].diffuse = D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0)
         NEXT
         pTempVertexBuffer.Unlock
         pTempVertexBuffer = NOTHING
      END IF

      ' // Clone the original Sun mesh and make it yellow...
      pVertices = %NULL
      pTempSunMesh.CloneMeshFVF(0, %FVF_Flags, m_pD3DDevice, m_pSunMesh)
      IF SUCCEEDED(m_pSunMesh.GetVertexBuffer(pTempVertexBuffer)) THEN
         nNumVerts = m_pSunMesh.GetNumVertices
         pTempVertexBuffer.Lock(0, 0, pVertices, 0)
         FOR i = 0 TO nNumVerts - 1
            @pVertices[i].diffuse = D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0 )
         NEXT
         pTempVertexBuffer.Unlock
         pTempVertexBuffer = NOTHING
      END IF

      ' // The temp meshes are no longer needed...
      pTempEarthMesh = NOTHING
      pTempSunMesh = NOTHING

      ' // Create a matrix stack...
      D3DXCreateMatrixStack(0, m_matrixStack)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL hr AS LONG
      STATIC fElpasedTime AS SINGLE
      STATIC dCurrentTime AS DOUBLE
      STATIC dLastTime    AS DOUBLE
      STATIC fSunSpin     AS SINGLE
      STATIC fEarthSpin   AS SINGLE
      STATIC fEarthOrbit  AS SINGLE
      STATIC fMoonSpin    AS SINGLE
      STATIC fMoonOrbit   AS SINGLE

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      ' // Have the view matrix move the view move us to a good vantage point so
      ' // we can see the Sun sitting at the origin while the Earth orbits it.

      LOCAL matView AS D3DXMATRIX
      LOCAL v1, v2, v3 AS D3DXVECTOR3

      v1.x = 0.0! : v1.y = 2.0! : v1.z = -25.0!   ' Camera position
      v2.x = 0.0! : v2.y = 0.0! : v2.z =   0.0!   ' Look-at point
      v3.x = 0.0! : v3.y = 1.0! : v3.z =   0.0!   ' Up vector

      D3DXMatrixLookAtLH(matView, v1, v2, v3)
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, matView)

      m_matrixStack.LoadIdentity()
      m_matrixStack.LoadMatrix(matView)

      ' // Cache rotational positions between frames...
      dCurrentTime = timeGetTime
      fElpasedTime = (dCurrentTime - dLastTime) * 0.001
      dLastTime    = dCurrentTime

      IF ISTRUE m_bOrbitOn THEN
         fSunSpin = fSunSpin + m_fSpeedmodifier * (fElpasedTime * 10.0!)
         fEarthSpin = fEarthSpin + m_fSpeedmodifier * (fElpasedTime * 100.0!)
         fEarthOrbit = fEarthOrbit + m_fSpeedmodifier * (fElpasedTime * 20.0!)
         fMoonSpin = fMoonSpin + m_fSpeedmodifier * (fElpasedTime * 50.0!)
         fMoonOrbit = fMoonOrbit + m_fSpeedmodifier * (fElpasedTime * 200.0!)
      END IF

      ' // The Sun is easy because the mesh for it is initially created centered
      ' // at origin. All we have to do is spin it by rotating it about the Y axis
      ' // and scale it by 5.0f.

      LOCAL mSunScale AS D3DXMATRIX
      LOCAL mSunSpinRotation AS D3DXMATRIX
      LOCAL mSunMatrix AS D3DXMATRIX

      D3DXMatrixRotationY(mSunSpinRotation, D3DXToRadian(fSunSpin))
      D3DXMatrixScaling(mSunScale, 5.0!, 5.0!, 5.0!)

      ' // Now, concatenate them together...

      ' // Uniformly scale the Sun up in size and then spin it on its axis.
      D3DXMatrixMultiply(mSunMatrix, mSunScale, mSunSpinRotation)

      m_pD3DDevice.SetTransform(%D3DTS_WORLD, mSunMatrix)
      m_pSunMesh.DrawSubset(0)

      ' // The Earth is a little more complicated since it needs to spin as well
      ' // as orbit the Sun. This can be done by combining three transformations
      ' // together.

      LOCAL mEarthTranslationToOrbit AS D3DXMATRIX
      LOCAL mEarthSpinRotation AS D3DXMATRIX
      LOCAL mEarthOrbitRotation AS D3DXMATRIX
      LOCAL mEarthMatrix AS D3DXMATRIX
      LOCAL mTmpMatrix AS D3DXMATRIX

      D3DXMatrixRotationY(mEarthSpinRotation, D3DXToRadian(fEarthSpin))
      D3DXMatrixTranslation(mEarthTranslationToOrbit, 0.0!, 0.0!, 12.0!)
      D3DXMatrixRotationY(mEarthOrbitRotation, D3DXToRadian( fEarthOrbit))

      ' // Now, concatenate them together...

      ' mEarthMatrix = mEarthSpinRotation *       // 1. Spin the Earth on its own axis.
      '                mEarthTranslationToOrbit * // 2. Then translate it away from the origin (where the Sun's at)
      '                mEarthOrbitRotation;       // 3. and rotate it again to make it orbit the origin (or the Sun).

      D3DXMatrixMultiply(mTmpMatrix, mEarthSpinRotation, mEarthTranslationToOrbit)
      D3DXMatrixMultiply(mEarthMatrix, mTmpMatrix, mEarthOrbitRotation)

      m_pD3DDevice.SetTransform(%D3DTS_WORLD, mEarthMatrix)
      m_pEarthMesh.DrawSubset(0)

      ' // The Moon is the hardest to understand since it needs to not only spin on
      ' // its own axis and orbit the Earth, but needs to follow the Earth,
      ' // which is orbiting the Sun.
      ' //
      ' // This can be done by combining five transformations together with the last
      ' // two being borrowed from the Earth's transformation.

      LOCAL mMoonTranslationToOrbit AS D3DXMATRIX
      LOCAL mMoonSpinRotation AS D3DXMATRIX
      LOCAL mMoonOrbitRotation AS D3DXMATRIX
      LOCAL mMoonMatrix AS D3DXMATRIX

      D3DXMatrixRotationY(mMoonSpinRotation, D3DXToRadian(fMoonSpin))
      D3DXMatrixRotationY(mMoonOrbitRotation, D3DXToRadian(fMoonOrbit))
      D3DXMatrixTranslation(mMoonTranslationToOrbit, 0.0!, 0.0!, 2.0!)

      ' // The key to understanding the first three transforms is to pretend that
      ' // the Earth is located at the origin. We know it's not, but if we pretend
      ' // that it is, we can set up the Moon just like the we did the Earth since
      ' // the Moon orbits the Earth just like the Earth orbits the Sun.
      ' //
      ' // Once the Moon's transforms are set up we simply reuse the Earth's
      ' // translation and rotation matrix, which placed it in orbit, to offset
      ' // the Moon out to where it should be... following the Earth.

      ' // Now, concatenate them together...

      ' mMoonMatrix = mMoonSpinRotation *        // 1. Spin the Moon on its own axis.
      '               mMoonTranslationToOrbit *  // 2. Then translate it away from the origin (pretending that the Earth is there)
      '               mMoonOrbitRotation *       // 3. and rotate it again to make it orbit the origin (or the pretend Earth).

      '               mEarthTranslationToOrbit * // 4. Now, translate out to where the Earth is really at
      '               mEarthOrbitRotation;       // 5. and move with it by matching its orbit of the Earth.

      LOCAL mTmpMatrix2 AS D3DXMATRIX
      LOCAL mTmpMatrix3 AS D3DXMATRIX

      D3DXMatrixMultiply(mTmpMatrix2, mMoonSpinRotation, mMoonTranslationToOrbit)
      D3DXMatrixMultiply(mTmpMatrix3, mMoonOrbitRotation, mEarthTranslationToOrbit)
      D3DXMatrixMultiply(mTmpMatrix, mTmpMatrix2, mTmpMatrix3)
      D3DXMatrixMultiply(mMoonMatrix, mTmpMatrix, mEarthOrbitRotation)

      m_pD3DDevice.SetTransform(%D3DTS_WORLD, mMoonMatrix)
      m_pMoonMesh.DrawSubset(0)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_matrixStack = NOTHING
            m_pSunMesh = NOTHING
            m_pEarthMesh = NOTHING
            m_pD3DDevice = NOTHING
            m_pD3D = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes keystrokes
   ' ====================================================================================
   METHOD ProcessKeys (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      SELECT CASE wMsg

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE %VK_SPACE
                  m_bOrbitOn = NOT m_bOrbitOn
               CASE %VK_F1
                  m_fSpeedmodifier = m_fSpeedmodifier + 1
               CASE %VK_F2
                  m_fSpeedmodifier = m_fSpeedmodifier - 1
            END SELECT

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         pDX9.ProcessKeys hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
Demonstrates how to use Vertex Buffers for the storage of model data. The sample creates a textured cube as an example.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_VertexData.bas
' Contents: DX9 example
' Description: Demonstrates how to use Vertex Buffers for the storage of model data.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_vertex_data.cpp by Kevin Harris, 06/06/05,
' downloadable at http://www.codesampler.com/dx9src/dx9src_2.htm#dx9_vertex_data
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Vertex Data"

%D3DFVF_CUSTOMVERTEX = %D3DFVF_XYZ OR %D3DFVF_TEX1

TYPE Vertex
   x  AS SINGLE
   y  AS SINGLE
   z  AS SINGLE
   tu AS SINGLE
   tv AS SINGLE
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_cubeVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      DIM m_cubeVertices(23) AS INSTANCE Vertex
      FillVertex(m_cubeVertices( 0), -1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 1),  1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices( 2), -1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices( 3),  1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices( 4), -1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices( 5), -1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices( 6),  1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 7),  1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices( 8), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices( 9),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(10), -1.0!,  1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(11),  1.0!,  1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(12), -1.0!, -1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(13), -1.0!, -1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(14),  1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(15),  1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(16),  1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(17),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(18),  1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_cubeVertices(19),  1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(20), -1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_cubeVertices(21), -1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_cubeVertices(22), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_cubeVertices(23), -1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
   END METHOD
   ' ====================================================================================

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      ' // Loads the texture
      D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\Vertex_Data.bmp", m_pTexture)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
      m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)

      ' // Creates a vertex buffer
      LOCAL nSize AS LONG
      LOCAL pVertices AS Vertex PTR
      nSize = (UBOUND(m_cubeVertices) - LBOUND(m_cubeVertices) + 1) * SIZEOF(Vertex)
      m_pD3DDevice.CreateVertexBuffer(nSize, 0, %D3DFVF_CUSTOMVERTEX, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
      m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
      MoveMemory BYVAL pVertices, BYVAL VARPTR(m_cubeVertices(0)), nSize
      m_pVertexBuffer.Unlock

      ' // Sets a device render-state parameter
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
      m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG
      STATIC fXrot AS SINGLE
      STATIC fYrot AS SINGLE
      STATIC fZrot AS SINGLE
      STATIC fElpasedTime AS SINGLE
      STATIC dCurrentTime AS DOUBLE
      STATIC dLastTime AS DOUBLE

      dCurrentTime = timeGetTime
      fElpasedTime = (dCurrentTime - dLastTime) * 0.001
      dLastTime    = dCurrentTime

      fXrot = fXrot + 10.1! * fElpasedTime
      fYrot = fYrot + 10.2! * fElpasedTime
      fZrot = fZrot + 10.3! * fElpasedTime

      ' // Clears the surface
      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
                         D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      LOCAL matWorld AS D3DXMATRIX
      LOCAL matTrans AS D3DXMATRIX
      LOCAL matRot AS D3DXMATRIX

      ' // Builds a matrix using the specified offsets
      D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, 5.0!)
      ' // Builds a matrix with a specified yaw, pitch, and roll
      D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(fXrot), D3DXToRadian(fYrot), D3DXToRadian(fZrot))
      ' // Determines the product of the two matrices
      D3DXMatrixMultiply(matWorld, matRot, matTrans)
      ' // Sets the device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      ' // Begins the scene
      m_pD3DDevice.BeginScene

      ' // Assigns the texture to a stage for the device
      m_pD3DDevice.SetTexture(0, m_pTexture)
      ' // Binds a vertex buffer to a device data stream
      m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
      ' // Sets the current vertex stream declaration
      m_pD3DDevice.SetFVF(%D3DFVF_CUSTOMVERTEX)

      ' // Renders a sequence of nonindexed, geometric primitives of the
      ' // specified type from the current set of data input streams.
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  0, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  4, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP,  8, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 12, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 16, 2)
      m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 20, 2)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pVertexBuffer = NOTHING
            m_pTexture = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         SELECT CASE LO(WORD, wParam)
            CASE %VK_ESCAPE
               SendMessage hwnd, %WM_CLOSE, 0, 0
               EXIT FUNCTION
         END SELECT

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


José Roca

 
The following example demonstrates how to set multiple view ports using DirectX 9.0.


' ########################################################################################
' Microsoft Windows
' File: CW_DX9_ViewPorts.bas
' Contents: DX9 example
' Description: Demonstrates how to set multiple view ports with DirectX 9.0.
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.04+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk
' Adapted from dx9_view_ports.cpp by Kevin Harris, 06/02/05, available at
' http://www.codesampler.com/dx9src/dx9src_1.htm#dx9_view_ports
' Control Keys: Left Mouse Button - Spin the teapot
' ########################################################################################

' CSED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
%UNICODE = 1

#INCLUDE ONCE "CWindow.inc"
' DirectX End-User Runtimes (June 2010)
' http://www.microsoft.com/download/en/confirmation.aspx?id=8109
$D3DX_DLLNAME = "d3dx9_43.dll"   ' --> change as needed
#INCLUDE ONCE "D3DX9.INC"

$WindowCaption = "Direct3D (DX9) - Setting Multiple View Ports"

%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_NORMAL OR %D3DFVF_DIFFUSE

TYPE Vertex
   ' Position of vertex in 3D space
   x       AS SINGLE
   y       AS SINGLE
   z       AS SINGLE
   ' Normal for lighting calculations
   nx      AS SINGLE
   ny      AS SINGLE
   nz      AS SINGLE
   ' Diffuse color of vertex
   diffuse AS DWORD
END TYPE

' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, nx_, ny_, nz_, tu_, tv_)
   v.x = x_ : v.y = y_ : v.z = z_ : v.nx = nx_ : v.ny = ny_ : v.nz = nz_ : v.tu = tu_ : v.tv = tv_
END MACRO
' ========================================================================================

GLOBAL pDX9 AS IDX9

' =======================================================================================
' DX9 class
' =======================================================================================
CLASS CDX9

   INSTANCE m_pD3D AS IDirect3D9
   INSTANCE m_pD3DDevice AS IDirect3DDevice9
   INSTANCE m_d3ddm AS D3DDISPLAYMODE
   INSTANCE m_d3dpp AS D3DPRESENT_PARAMETERS
   INSTANCE m_pTeapotMesh AS ID3DXMesh
   INSTANCE m_teapotMtrl AS D3DMATERIAL9
   INSTANCE m_pLight0 AS D3DLIGHT9
   INSTANCE m_dwBackBufferWidth AS DWORD
   INSTANCE m_dwBackBufferHeight AS DWORD
   INSTANCE m_fSpinX AS SINGLE
   INSTANCE m_fSpinY AS SINGLE

   ' =====================================================================================
   INTERFACE IDX9 : INHERIT IUnknown
   ' =====================================================================================

   ' =====================================================================================
   ' Initializes DirectX9
   ' =====================================================================================
   METHOD InitD3D (BYVAL hwnd AS DWORD) AS LONG

      LOCAL hr AS LONG

      ' // Creates an IDirect3D9 object and returns an interface to it
      m_pD3D = Direct3DCreate9(%D3D_SDK_VERSION)
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Creates a device to represent the display adapter
      m_d3dpp.Windowed               = %TRUE
      m_d3dpp.SwapEffect             = %D3DSWAPEFFECT_DISCARD
      m_d3dpp.BackBufferFormat       = m_d3ddm.Format
      m_d3dpp.EnableAutoDepthStencil = %TRUE
      m_d3dpp.AutoDepthStencilFormat = %D3DFMT_D16
      m_d3dpp.PresentationInterval   = %D3DPRESENT_INTERVAL_IMMEDIATE

      hr = m_pD3D.CreateDevice (%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, hwnd, _
                                %D3DCREATE_SOFTWARE_VERTEXPROCESSING, m_d3dpp, m_pD3DDevice)
      IF hr <> %D3D_OK THEN EXIT METHOD

      '// Create the device objects
      ME.CreateDeviceObjects

      ' // Return success
      METHOD = %TRUE

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Loads the texture and creates the vertex buffers
   ' =====================================================================================
   METHOD CreateDeviceObjects () AS LONG

      ' // Builds a left-handed perspective projection matrix based on a field of view
      LOCAL matProj AS D3DXMATRIX
      D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 600.0! / 400.0!, 0.1!, 100.0!)
      ' // Sets a device transformation-related state
      m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)

      ' // Se5ts the render states
      m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
      m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
      m_pD3DDevice.SetRenderState(%D3DRS_SPECULARENABLE, %TRUE)
      m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %FALSE)

      ' // Setup a simple directional light and some ambient...
      LOCAL v AS D3DVECTOR
      v.x = 1.0! : v.y = 0.0! : v.x = 1.0!
      m_pLight0.Type = %D3DLIGHT_DIRECTIONAL
      m_pLight0.Direction = v

      m_pLight0.Diffuse.r = 1.0!
      m_pLight0.Diffuse.g = 1.0!
      m_pLight0.Diffuse.b = 1.0!
      m_pLight0.Diffuse.a = 1.0!

      m_pLight0.Specular.r = 1.0!
      m_pLight0.Specular.g = 1.0!
      m_pLight0.Specular.b = 1.0!
      m_pLight0.Specular.a = 1.0!

      m_pD3DDevice.SetLight(0, m_pLight0)
      m_pD3DDevice.LightEnable(0, %TRUE)

      m_pD3DDevice.SetRenderState(%D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.2!, 0.2!, 0.2!, 1.0!))

      ' // Setup a material for the teapot
      m_teapotMtrl.Diffuse.r = 1.0!
      m_teapotMtrl.Diffuse.g = 1.0!
      m_teapotMtrl.Diffuse.b = 1.0!
      m_teapotMtrl.Diffuse.a = 1.0!

      ' // Load up the teapot mesh...
      D3DXLoadMeshFromX(".\Resources\teapot.x", %D3DXMESH_SYSTEMMEM, m_pD3DDevice, _
                        BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, m_pTeapotMesh)

      ' // Cache the width & height of the back-buffer...
      LOCAL pBackBuffer AS IDirect3DSurface9
      LOCAL d3dsd AS D3DSURFACE_DESC
      m_pD3DDevice.GetBackBuffer(0, 0, %D3DBACKBUFFER_TYPE_MONO, pBackBuffer)
      pBackBuffer.GetDesc(d3dsd)
      pBackBuffer = NOTHING
      m_dwBackBufferWidth  = d3dsd.Width
      m_dwBackBufferHeight = d3dsd.Height

      ' // Return success
      METHOD = %S_OK

   END METHOD
   ' =====================================================================================

   ' =====================================================================================
   ' Renders the scene
   ' =====================================================================================
   METHOD RenderD3DScene

      LOCAL  hr AS LONG
      LOCAL matView AS D3DXMATRIX
      LOCAL matWorld AS D3DXMATRIX
      LOCAL matRotation AS D3DXMATRIX
      LOCAL matTranslation AS D3DXMATRIX

      ' // Render to the left viewport
      LOCAL leftViewPort AS D3DVIEWPORT9

      leftViewPort.X      = 0
      leftViewPort.Y      = 0
      leftViewPort.Width  = m_dwBackBufferWidth \ 2
      leftViewPort.Height = m_dwBackBufferHeight
      leftViewPort.MinZ   = 0.0!
      leftViewPort.MaxZ   = 1.0!

      m_pD3DDevice.SetViewport(leftViewPort)

      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
         D3DCOLOR_COLORVALUE(1.0!,0.0!,0.0!,1.0!), 1.0!, 0)

      ' // Begin the scene
      m_pD3DDevice.BeginScene

      ' // For the left view-port, leave the view at the origin...
      D3DXMatrixIdentity(matView )
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, matView)

      ' // ... and use the world matrix to spin and translate the teapot
      ' // out where we can see it...
      D3DXMatrixRotationYawPitchRoll(matRotation, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      D3DXMatrixTranslation(matTranslation, 0.0!, 0.0!, 5.0!)
      D3DXMatrixMultiply(matWorld, matRotation, matTranslation)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pD3DDevice.SetMaterial(m_teapotMtrl)
      m_pTeapotMesh.DrawSubset(0)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Render to the right viewport
      LOCAL rightViewPort AS D3DVIEWPORT9

      rightViewPort.X      = m_dwBackBufferWidth \ 2
      rightViewPort.Y      = 0
      rightViewPort.Width  = m_dwBackBufferWidth \ 2
      rightViewPort.Height = m_dwBackBufferHeight
      rightViewPort.MinZ   = 0.0!
      rightViewPort.MaxZ   = 1.0!

      m_pD3DDevice.SetViewport(rightViewPort)

      m_pD3DDevice.Clear(0, BYVAL %NULL, %D3DCLEAR_TARGET OR %D3DCLEAR_ZBUFFER, _
         D3DCOLOR_COLORVALUE(0.0!,1.0!,0.0!,1.0!), 1.0!, 0)

      ' // Begin the scene
      m_pD3DDevice.BeginScene

      ' // For the right view-port, translate and rotate the view around
      ' // the teapot so we can see it...
      D3DXMatrixRotationYawPitchRoll(matRotation, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      D3DXMatrixTranslation(matTranslation, 0.0!, 0.0!, 5.0!)
      D3DXMatrixMultiply(matView, matRotation, matTranslation)
      m_pD3DDevice.SetTransform(%D3DTS_VIEW, matView)

      ' // ... and don't bother with the world matrix at all.
      D3DXMatrixIdentity(matWorld)
      m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)

      m_pD3DDevice.SetMaterial(m_teapotMtrl)
      m_pTeapotMesh.DrawSubset(0)

      ' // Ends the scene
      m_pD3DDevice.EndScene

      ' // Presents the contents of the next buffer in the sequence of back buffers owned by the device
      hr = m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)
      IF hr = %D3DERR_DEVICELOST THEN
         ' // The application can determine what to do on encountering a lost device
         ' // by querying the return value of the TestCooperativeLevel method.
         hr = m_pD3DDevice.TestCooperativeLevel
         IF hr = %D3DERR_DEVICENOTRESET THEN
            ' // Invalidate the device objects
            m_pTeapotMesh = NOTHING
            ' // Reset the type, size, and format of the swap chain
            m_pD3DDevice.Reset(m_d3dpp)
            ' // Recreate the device objects
            ME.CreateDeviceObjects
         END IF
      END IF

   END METHOD
   ' =====================================================================================

   ' ====================================================================================
   ' Processes mouse
   ' ====================================================================================
   METHOD ProcessMouse (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG)

      STATIC ptLastMousePosit AS POINT
      STATIC ptCurrentMousePosit AS POINT
      STATIC bMousing AS LONG

      SELECT CASE wMsg

         CASE %WM_LBUTTONDOWN
            ptLastMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptLastMousePosit.y = HI(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            bMousing = %TRUE

         CASE %WM_LBUTTONUP
            bMousing = %FALSE

         CASE %WM_MOUSEMOVE
            ptCurrentMousePosit.x = LO(WORD, lParam)
            ptCurrentMousePosit.y = HI(WORD, lParam)
            IF bMousing THEN
               m_fSpinX = m_fSpinX - (ptCurrentMousePosit.x - ptLastMousePosit.x)
               m_fSpinY = m_fSpinY - (ptCurrentMousePosit.y - ptLastMousePosit.y)
            END IF
            ptLastMousePosit.x = ptCurrentMousePosit.x
            ptLastMousePosit.y = ptCurrentMousePosit.y

      END SELECT

   END METHOD
   ' ====================================================================================

   END INTERFACE

END CLASS
' =======================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI Aware
'   SetProcessDPIAware

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) THEN EXIT FUNCTION

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pWindow.CreateWindow(%NULL, $WindowCaption, 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the class style to remove flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize 600, 400
   ' // Center the window
   pWindow.CenterWindow

   ' // Initialize DX9
   IF ISFALSE pDX9.InitD3D(hwnd) THEN EXIT FUNCTION

   ' // Set the timer
   SetTimer(hwnd, 1, 0, %NULL)

   ' // Show the window
   ShowWindow hwnd, nCmdShow
   UpdateWindow hwnd

   ' // Message loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      TranslateMessage uMsg
      DispatchMessage uMsg
   WEND

   ' // Kill the timer
   KillTimer(hwnd, 1)

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure callback
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE wMsg

      CASE %WM_SYSCOMMAND
         ' // Disable the Windows screensaver
         IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
         ' // Close the window
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_TIMER
         ' // Render the scene
         pDX9.RenderD3DScene
         EXIT FUNCTION

      CASE %WM_KEYDOWN
         SELECT CASE LO(WORD, wParam)
            CASE %VK_ESCAPE
               SendMessage hwnd, %WM_CLOSE, 0, 0
               EXIT FUNCTION
         END SELECT

      CASE %WM_LBUTTONDOWN, %WM_LBUTTONUP, %WM_MOUSEMOVE
         pDX9.ProcessMouse hwnd, wMsg, wParam, lParam
         EXIT FUNCTION

      CASE %WM_DESTROY
         ' // Destroy the class
         pDX9 = NOTHING
         ' // Close the application by sending a WM_QUIT message
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================