IT-Consultant: José Roca (PBWIN 10+/PBCC 6+) (Archive only) > DirectX

DirectX 9 Examples

(1/6) > >>

José Roca:
 
Microsoft DirectX graphics provides a set of APIs that you can use to create games and other high-performance multimedia applications. DirectX graphics includes support for high-performance 2-D and 3-D graphics.

José Roca:
 
The following example demonstrates how to initialize Direct3D.


--- Code: ---' ########################################################################################
' Microsoft Windows
' File: CW_DX9_Initialization.bas
' Contents: DX9 example
' Description: Demonstrates how to initialize 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
' ########################################################################################

' 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) - Initialization"

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

   ' =====================================================================================
   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)
      ' // TO DO: Respond to failure of Direct3DCreate9
      IF ISNOTHING(m_pD3D) THEN EXIT METHOD

      ' // Retrieves the current display mode of the adapter
      LOCAL d3ddm AS D3DDISPLAYMODE
      hr = m_pD3D.GetAdapterDisplayMode(%D3DADAPTER_DEFAULT, m_d3ddm)
      ' // TO DO: Respond to failure of GetAdapterDisplayMode
      IF hr <> %D3D_OK THEN EXIT METHOD

      hr = m_pD3D.CheckDeviceFormat(%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, _
                                    d3ddm.Format, %D3DUSAGE_DEPTHSTENCIL, _
                                    %D3DRTYPE_SURFACE, %D3DFMT_D16)
      IF FAILED(hr) THEN
         IF hr = %D3DERR_NOTAVAILABLE THEN
            ' // POTENTIAL PROBLEM: We need at least a 16-bit z-buffer!
            EXIT METHOD
         END IF
      END IF

      ' // Do we support hardware vertex processing? if so, use it.
      ' // If not, downgrade to software.
      LOCAL dCaps AS D3DCAPS9
      IF FAILED(m_pD3D.GetDeviceCaps(%D3DADAPTER_DEFAULT, _
                                     %D3DDEVTYPE_HAL, dCaps)) THEN
         ' // TO DO: Respond to failure of GetDeviceCaps
         EXIT METHOD
      END IF

      LOCAL dwBehaviorFlags AS DWORD
      IF dCaps.VertexProcessingCaps <> 0 THEN
         dwBehaviorFlags = %D3DCREATE_HARDWARE_VERTEXPROCESSING
      ELSE
         dwBehaviorFlags = %D3DCREATE_SOFTWARE_VERTEXPROCESSING
      END IF

      ' // Everything checks out - create a simple, windowed device.

      ' // 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)
      ' // TO DO: Respond to failure of CreateDevice
      IF hr <> %D3D_OK THEN EXIT METHOD

      ' // Return success
      METHOD = %TRUE

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

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

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

      m_pD3DDevice.BeginScene

      ' // Render geometry here...

      m_pD3DDevice.EndScene

      m_pD3DDevice.Present(BYVAL %NULL, BYVAL %NULL, %NULL, BYVAL %NULL)

   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

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

   ' // Create an instance of the DX9 class
   pDX9 = CLASS "CDX9"
   IF ISNOTHING(pDX9) 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
         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
' ========================================================================================

--- End code ---

José Roca:
 
Demonstrates how to perform alpha-blending in the frame-buffer. The sample renders a textured cube which is alpha-blended into the frame-buffer in such a way as to create a translucent effect.


--- Code: ---' ########################################################################################
' Microsoft Windows
' File: CW_DX9_AlphaBlendingFrameBuffer.bas
' Contents: DX9 example
' Description: Demonstrates how to perform alpha-blending in the frame-buffer. The sample
' renders a textured cube which is alpha-blended into the frame-buffer in such a way as to
' create a translucent effect.
' 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_alpha_blending_framebuffer.cpp, by Kevin Harris, 25 Mar 2005,
' downloadable at http://www.codesampler.com/dx9src/dx9src_4.htm#dx9_alpha_blending_framebuffer
' Control Keys: b - Toggle blending
' ########################################################################################

' 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) - Alpha Blending with the Frame Buffer"

%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_bBlending AS LONG
   INSTANCE m_quadVertices () AS Vertex

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bBlending = -1
      DIM m_quadVertices(23) AS INSTANCE Vertex
      FillVertex(m_quadVertices( 0), -1.0!,  1.0!, -1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices( 1),  1.0!,  1.0!, -1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices( 2), -1.0!, -1.0!, -1.0!, 0.0!, 1.0!)
      FillVertex(m_quadVertices( 3),  1.0!, -1.0!, -1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices( 4), -1.0!,  1.0!,  1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices( 5), -1.0!, -1.0!,  1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices( 6),  1.0!,  1.0!,  1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices( 7),  1.0!, -1.0!,  1.0!, 0.0!, 1.0!)
      FillVertex(m_quadVertices( 8), -1.0!,  1.0!,  1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices( 9),  1.0!,  1.0!,  1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices(10), -1.0!,  1.0!, -1.0!, 0.0!, 1.0!)
      FillVertex(m_quadVertices(11),  1.0!,  1.0!, -1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices(12), -1.0!, -1.0!,  1.0!, 0.0!, 1.0!)
      FillVertex(m_quadVertices(13), -1.0!, -1.0!, -1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices(14),  1.0!, -1.0!,  1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices(15),  1.0!, -1.0!, -1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices(16),  1.0!,  1.0!, -1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices(17),  1.0!,  1.0!,  1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices(18),  1.0!, -1.0!, -1.0!, 0.0!, 1.0!)
      FillVertex(m_quadVertices(19),  1.0!, -1.0!,  1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices(20), -1.0!,  1.0!, -1.0!, 1.0!, 0.0!)
      FillVertex(m_quadVertices(21), -1.0!, -1.0!, -1.0!, 1.0!, 1.0!)
      FillVertex(m_quadVertices(22), -1.0!,  1.0!,  1.0!, 0.0!, 0.0!)
      FillVertex(m_quadVertices(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\Glass.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, %D3DFVF_CUSTOMVERTEX, %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)

      ' // 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

      IF ISTRUE m_bBlending THEN
         ' // Sets the device render-state parameters
         m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_NONE)
         m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %FALSE)
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %TRUE)
         m_pD3DDevice.SetRenderState(%D3DRS_SRCBLEND, %D3DBLEND_SRCALPHA)
         m_pD3DDevice.SetRenderState(%D3DRS_DESTBLEND, %D3DBLEND_ONE)
      ELSE
         ' // Sets the device render-state parameters
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %FALSE)
         m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
      END IF

      ' // 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
   ' =====================================================================================

   ' ====================================================================================
   ' 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 66, 98    ' B, b
                  m_bBlending = NOT m_bBlending
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 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_CHAR
         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
' ========================================================================================

--- End code ---

José Roca:
 
Demonstrates how to perform alpha-blending using a material. This alpha-blending technique is widely used to make entire objects fade out of existence over some amount of time.


--- Code: ---' ########################################################################################
' Microsoft Windows
' File: CW_DX9_AlphaBlendingMaterial.bas
' Contents: DX9 example
' Description: Demonstrates how to perform alpha-blending using a material.
' This alpha-blending technique is widely used to make entire objects fade out of
' existence over some amount of time.
' 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_alpha_blending_material.cpp by Kevin Harris, 04/04/05, available at
' http://www.codesampler.com/dx9src/dx9src_4.htm#dx9_alpha_blending_material
' Control Keys: b - Toggle blending
'               a - Reduce alpha on the materials Diffuse color
'               A - Increase alpha on the materials Diffuse color
' ########################################################################################

' 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) - Alpha Blending with a Material"

%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_pVertexBuffer AS IDirect3DVertexBuffer9
   INSTANCE m_pTexture AS IDirect3DTexture9
   INSTANCE m_alphaMaterial AS D3DMATERIAL9
   INSTANCE m_bBlending AS LONG
   INSTANCE m_quadVertices () AS Vertex
   INSTANCE m_fDistance AS SINGLE
   INSTANCE m_fSpinX AS SINGLE
   INSTANCE m_fSpinY AS SINGLE

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bBlending = -1
      m_fDistance = 4.5!
      DIM m_quadVertices(23) AS INSTANCE Vertex
      ' // Front Face
      FillVertex(m_quadVertices( 0), -1.0!,  1.0!, -1.0!,  0.0!,  0.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 1),  1.0!,  1.0!, -1.0!,  0.0!,  0.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices( 2), -1.0!, -1.0!, -1.0!,  0.0!,  0.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices( 3),  1.0!, -1.0!, -1.0!,  0.0!,  0.0!, -1.0!,  1.0!,  1.0!)
      ' // Back Face
      FillVertex(m_quadVertices( 4), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices( 5), -1.0!, -1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices( 6),  1.0!,  1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 7),  1.0!, -1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  0.0!,  1.0!)
      ' // Top Face
      FillVertex(m_quadVertices( 8), -1.0!,  1.0!,  1.0!,  0.0!,  1.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 9),  1.0!,  1.0!,  1.0!,  0.0!,  1.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(10), -1.0!,  1.0!, -1.0!,  0.0!,  1.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(11),  1.0!,  1.0!, -1.0!,  0.0!,  1.0!,  0.0!,  1.0!,  1.0!)
      ' // Bottom Face
      FillVertex(m_quadVertices(12), -1.0!, -1.0!,  1.0!,  0.0!, -1.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(13), -1.0!, -1.0!, -1.0!,  0.0!, -1.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(14),  1.0!, -1.0!,  1.0!,  0.0!, -1.0!,  0.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(15),  1.0!, -1.0!, -1.0!,  0.0!, -1.0!,  0.0!,  1.0!,  0.0!)
      ' // Right Face
      FillVertex(m_quadVertices(16),  1.0!,  1.0!, -1.0!,  1.0!,  0.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(17),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(18),  1.0!, -1.0!, -1.0!,  1.0!,  0.0!,  0.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(19),  1.0!, -1.0!,  1.0!,  1.0!,  0.0!,  0.0!,  1.0!,  1.0!)
      ' // Left Face
      FillVertex(m_quadVertices(20), -1.0!,  1.0!, -1.0!, -1.0!,  0.0!,  0.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(21), -1.0!, -1.0!, -1.0!, -1.0!,  0.0!,  0.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(22), -1.0!,  1.0!,  1.0!, -1.0!,  0.0!,  0.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(23), -1.0!, -1.0!,  1.0!, -1.0!,  0.0!,  0.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\Glass.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, %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)

      ' // Set up our alpha material...
      m_alphaMaterial.Diffuse.r = 1.0!
      m_alphaMaterial.Diffuse.g = 1.0!
      m_alphaMaterial.Diffuse.b = 1.0!
      m_alphaMaterial.Diffuse.a = 0.5!
      m_pD3DDevice.SetMaterial(m_alphaMaterial)

      ' // Set light 0 to be a pure white directional light
      LOCAL light0 AS D3DLIGHT9
      light0.Type = %D3DLIGHT_DIRECTIONAL
      light0.Direction.x = 0.0!
      light0.Direction.y = 0.0!
      light0.Direction.z = 1.0!
      light0.Diffuse.r = 1.0!
      light0.Diffuse.g = 1.0!
      light0.Diffuse.b = 1.0!
      light0.Diffuse.a = 1.0!
      m_pD3DDevice.SetLight(0, light0)
      m_pD3DDevice.LightEnable(0, %TRUE)

      ' // 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)

      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!, m_fDistance)
      ' // Builds a matrix with a specified yaw, pitch, and roll
      D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      ' // 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

      IF ISTRUE m_bBlending THEN
         ' // Sets the device render-state parameters
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %TRUE)
         m_pD3DDevice.SetMaterial(m_alphaMaterial)
         ' // Use material's alpha
         m_pD3DDevice.SetRenderState(%D3DRS_DIFFUSEMATERIALSOURCE, %D3DMCS_MATERIAL)
         m_pD3DDevice.SetTextureStageState(0, %D3DTSS_ALPHAARG1, %D3DTA_DIFFUSE)
         m_pD3DDevice.SetTextureStageState(0, %D3DTSS_ALPHAOP, %D3DTOP_SELECTARG1)
         ' // Use alpha for transparency
         m_pD3DDevice.SetRenderState(%D3DRS_SRCBLEND, %D3DBLEND_SRCALPHA)
         m_pD3DDevice.SetRenderState(%D3DRS_DESTBLEND, %D3DBLEND_INVSRCALPHA)
      ELSE
         ' // Sets the device render-state parameters
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %FALSE)
      END IF

      ' // Render the cube
      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)
      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
   ' =====================================================================================

   ' ====================================================================================
   ' 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 66, 98    ' B, b
                  m_bBlending = NOT m_bBlending
               CASE 97        ' a
                  m_alphaMaterial.Diffuse.a = m_alphaMaterial.Diffuse.a - 0.1!
               CASE 65        ' A
                  m_alphaMaterial.Diffuse.a = m_alphaMaterial.Diffuse.a + 0.1!
            END SELECT

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE 38   ' // Up Arrow Key
                  m_fDistance = m_fDistance - 0.1!
               CASE 40   ' // Down Arrow Key
                  m_fDistance = m_fDistance + 0.1!
            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_CHAR, %WM_KEYDOWN, %WM_KEYUP
         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
' ========================================================================================

--- End code ---

José Roca:
 
Demonstrates how to perform alpha blending using the alpha channel of a standard .tga texture. For proper alpha blending, the sample uses a cull-mode sorting trick to ensure the sides of the textured cube get rendered in back-to-front order.


--- Code: ---' ########################################################################################
' Microsoft Windows
' File: CW_DX9_AlphaBlendingTexture.bas
' Contents: DX9 example
' Description: Demonstrates how to perform alpha blending using the alpha channel of a
' standard .tga texture. For proper alpha blending, the sample uses a cull-mode sorting trick
' to ensure the sides of the textured cube get rendered in back-to-front order.
' 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_alpha_blending_texture.cpp by Kevin Harris, 03/27/05, available at
' http://www.codesampler.com/dx9src/dx9src_4.htm#dx9_alpha_blending_texture
' Control Keys: b - Toggle blending
'               s - Toggle usage of cull-mode sorting trick
'               Up Arrow - Move the test cube closer
'               Down Arrow - Move the test cube 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 Alpha Blending"

%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_alphaMaterial AS D3DMATERIAL9
   INSTANCE m_bBlending AS LONG
   INSTANCE m_quadVertices () AS Vertex
   INSTANCE m_fDistance AS SINGLE
   INSTANCE m_fSpinX AS SINGLE
   INSTANCE m_fSpinY AS SINGLE
   INSTANCE m_bSortUsingCullModeTrick AS LONG

   ' ====================================================================================
   ' Initializes the vertex array
   ' ====================================================================================
   CLASS METHOD Create
      m_bBlending = -1
      m_bSortUsingCullModeTrick = -1
      m_fDistance = 4.5!
      DIM m_quadVertices(23) AS INSTANCE Vertex
      FillVertex(m_quadVertices( 0), -1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 1),  1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices( 2), -1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices( 3),  1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices( 4), -1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices( 5), -1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices( 6),  1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 7),  1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices( 8), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices( 9),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(10), -1.0!,  1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(11),  1.0!,  1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(12), -1.0!, -1.0!,  1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(13), -1.0!, -1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(14),  1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(15),  1.0!, -1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(16),  1.0!,  1.0!, -1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(17),  1.0!,  1.0!,  1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(18),  1.0!, -1.0!, -1.0!,  0.0!,  1.0!)
      FillVertex(m_quadVertices(19),  1.0!, -1.0!,  1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(20), -1.0!,  1.0!, -1.0!,  1.0!,  0.0!)
      FillVertex(m_quadVertices(21), -1.0!, -1.0!, -1.0!,  1.0!,  1.0!)
      FillVertex(m_quadVertices(22), -1.0!,  1.0!,  1.0!,  0.0!,  0.0!)
      FillVertex(m_quadVertices(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\Radiation_Box.tga", 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_CULLMODE, %D3DCULL_NONE)

      ' // 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.35!,0.53!,0.7!,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!, m_fDistance)
      ' // Builds a matrix with a specified yaw, pitch, and roll
      D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
      ' // 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

      ' // Transparency sorting for our cube...
      ' //
      ' // If you have a single transparent object, or multiple transparent objects
      ' // which do not overlap in screen space (i.e., each screen pixel is touched
      ' // by at most one of the transparent objects), there's a sorting short-cut
      ' // which can be used under certain conditions.
      ' //
      ' // If your transparent objects are closed, convex, and viewed from the
      ' // outside, culling may be used to draw the back-facing polygons prior to
      ' // the front-facing polygons. This will accomplish the same thing
      ' // as sorting your objects or polygons into back-to-front order.
      ' // Fortunately for us, our cube is a perfect candidate for this sorting
      ' // trick.
      ' //
      ' // On the other hand, If we can't use the cull-mode sorting trick, we would
      ' // need to sort our objects manually, which would require us to transform
      ' // the geometry into eye-space so we could compare their final position
      ' // along the z axis. Only then, could we could render them in the proper
      ' // back-to-front order for alpha blending.
      ' //
      ' // Also, if transparent objects intersect in any way, the individual
      ' // triangles of the objects touching will have to be sorted and drawn
      ' // individually from back-to-front. And is some rare cases, triangles that
      ' // intersect each other may have to be broken into smaller triangles so they
      ' // no longer intersect or blending artifacts will persist regardless of our
      ' // sorting efforts.
      ' //
      ' // It’s plain to see, transparency sorting can become a big, hairy mess real quick.
      ' //
      ' // http://www.opengl.org/resources/tutorials/sig99/advanced99/notes/node204.html
      IF ISTRUE m_bBlending THEN
         ' // Use the texture's alpha channel to blend it with whatever’s already in the frame-buffer.
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %TRUE)
         m_pD3DDevice.SetRenderState(%D3DRS_SRCBLEND, %D3DBLEND_SRCALPHA)
         m_pD3DDevice.SetRenderState(%D3DRS_DESTBLEND, %D3DBLEND_INVSRCALPHA)
         m_pD3DDevice.SetTexture(0, m_pTexture)
         m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
         m_pD3DDevice.SetFVF(%FVF_Flags)
         IF m_bSortUsingCullModeTrick THEN
            ' // Use the cull-mode sorting trick for convex non-overlapping geometry.
            ' // Render the cube but only render the back-facing polygons.
            m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_CW)
            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)
            ' // Render the cube again, but this time we only render the front-facing polygons.
            m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_CCW)
            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)
         ELSE
            ' // Do no sorting and hope for the best. From certain viewing
            ' // positions the cube's sides will appear sorted correctly, but this
            ' // is typically rare and the cube will not look right most of the
            ' // time.
            m_pD3DDevice.SetRenderState(%D3DRS_CULLMODE, %D3DCULL_NONE)
            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)
         END IF
      ELSE
         ' // Render the cube, but do no blending...
         m_pD3DDevice.SetRenderState(%D3DRS_ALPHABLENDENABLE, %FALSE)
         m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
         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)
         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)
      END IF

      ' // 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
   ' =====================================================================================

   ' ====================================================================================
   ' 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 66, 98    ' B, b
                  m_bBlending = NOT m_bBlending
               CASE 83, 115   ' S, s
                  m_bSortUsingCullModeTrick = NOT m_bSortUsingCullModeTrick
            END SELECT

         CASE %WM_KEYDOWN
            SELECT CASE LO(WORD, wParam)
               CASE %VK_ESCAPE
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               CASE 38   ' // Up Arrow Key
                  m_fDistance = m_fDistance - 0.1!
               CASE 40   ' // Down Arrow Key
                  m_fDistance = m_fDistance + 0.1!
            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_CHAR, %WM_KEYDOWN, %WM_KEYUP
         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
' ========================================================================================

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version