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.
The following example demonstrates how to initialize Direct3D.
' ########################################################################################
' 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
' ========================================================================================
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.
' ########################################################################################
' 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
' ========================================================================================
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.
' ########################################################################################
' 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
' ========================================================================================
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.
' ########################################################################################
' 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
' ========================================================================================
Demonstrates how to create an animated 2D sprite using D3DXSprite which is hardware accelerated and fully compatible with 3D generated content.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_D3DXSprite.bas
' Contents: DX9 example
' Description: Demonstrates how to create a animated 2D sprite using D3DXSprite which is
' hardware accelerated and fully compatible with 3D generated content.
' 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_d3dxsprite.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_8.htm#dx9_d3dxsprite
' ########################################################################################
' 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) - Creating 2D Sprites with D3DXSPRITE"
%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_pDonutTexture AS IDirect3DTexture9
INSTANCE m_pDonutSprite AS ID3DXSprite
INSTANCE m_quadVertices () AS Vertex
INSTANCE m_fMoveSpeed AS SINGLE
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
' ====================================================================================
' Initializes the vertex array
' ====================================================================================
CLASS METHOD Create
m_fMoveSpeed = 50.0!
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
LOCAL d3dxImageInfo AS D3DXIMAGE_INFO
D3DXCreateTextureFromFileEx(m_pD3DDevice, _
".\Resources\Donut.bmp", _
320, _ ' // I had to set width manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE.
384, _ ' // I had to set height manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE.
1, _ ' // Don't create mip-maps when you plan on using D3DXSPRITE. It throws off the pixel math for sprite animation.
%D3DPOOL_DEFAULT, _
%D3DFMT_UNKNOWN, _
%D3DPOOL_DEFAULT, _
%D3DX_DEFAULT, _
%D3DX_DEFAULT, _
D3DCOLOR_COLORVALUE(0.0!,0.0!,0.0!,1.0!), _
d3dxImageInfo, _
BYVAL %NULL, _
m_pDonutTexture)
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, %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)
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)
' // Create our sprite...
D3DXCreateSprite(m_pD3DDevice, m_pDonutSprite)
' // Return success
METHOD = %S_OK
END METHOD
' =====================================================================================
' =====================================================================================
' Renders the scene
' =====================================================================================
METHOD RenderD3DScene
STATIC fElapsedTime AS SINGLE
STATIC dCurTime AS DOUBLE
STATIC dLastTime AS DOUBLE
dCurTime = timeGetTime
fElapsedTime = (dCurTime - dLastTime) * 0.001
dLastTime = dCurTime
' // 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 hr AS LONG
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!, 4.0!)
' // 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
' // Render a simple quad using the whole donut texture...
m_pD3DDevice.SetTexture(0, m_pDonutTexture)
m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
m_pD3DDevice.SetFVF(%D3DFVF_CUSTOMVERTEX)
m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)
' // Render our sprite, which only uses only a single frame from the dount
' // texture per update. This will create an animated sprite.
STATIC fPosition AS SINGLE
STATIC nFrame AS LONG
' // Build a source RECT which will copy only a small portion of the texture.
LOCAL srcRect AS RECT
srcRect.nTop = (nFrame \ 5 ) * 64
srcRect.nLeft = (nFrame MOD 5 ) * 64
srcRect.nBottom = srcRect.nTop + 64
srcRect.nRight = srcRect.nLeft + 64
LOCAL vCenter, vPosition AS D3DXVECTOR3
vCenter.x = 0.0! : vCenter.y = 0.0! : vCenter.z = 0.0!
vPosition.x = fPosition : vPosition.y = 170.0! : vPosition.z = 0.0!
m_pDonutSprite.Begin(%D3DXSPRITE_ALPHABLEND)
m_pDonutSprite.Draw(m_pDonutTexture, _
srcRect, _
vCenter, _
vPosition, _
D3DCOLOR_COLORVALUE(1.0!,1.0!,1.0!,1.0!))
m_pDonutSprite.End
' // Ends the scene
m_pD3DDevice.EndScene
' // Increment the sprite's frame number. Our sprite's animation sequence
' // consists of 30 frames (0-29).
STATIC fAnimationTimer AS SINGLE
fAnimationTimer = fAnimationTimer + fElapsedTime
IF fAnimationTimer > 0.01! THEN
nFrame = nFrame + 1
IF nFrame > 29 THEN nFrame = 0
fAnimationTimer = 0.0!
END IF
' // Slowly move our sprite across the screen. This demonstrates how to use
' // the Draw method of a D3DXSPRITE to place a sprite on the screen.
fPosition = fPosition + m_fMoveSpeed * fElapsedTime
IF fPosition > 600.0! THEN fPosition = 0.0!
' // 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_pDonutTexture = NOTHING
m_pDonutSprite = 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 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
' ========================================================================================
Demonstrates how to eliminate z-fighting when rendering polygons directly on top of other polygons by using Direct3D's D3DRS_SLOPESCALEDEPTHBIAS and D3DRS_DEPTHBIAS render states.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_DepthBias.bas
' Contents: DX9 example
' Description: Demonstrates how to eliminate z-fighting when rendering polygons directly
' on top of other polygons by using Direct3D's D3DRS_SLOPESCALEDEPTHBIAS and
' D3DRS_DEPTHBIAS render states.
' 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_5.htm#dx9_depth_bias
' Control Keys: Left Mouse Button - Spin the view
' F1 - Increase Z-Slope Scale
' F2 - Decrease Z-Slope Scale
' F3 - Increase Depth Bias
' F4 - Decrease Depth Bias
' ########################################################################################
' 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) - Depth Bias"
%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
' ========================================================================================
' Converts a float to a dword
' Note: An alternate way is to use MEMORY COPY:
' MEMORY COPY dw, f, 4
' ========================================================================================
FUNCTION F2DW (BYVAL f AS SINGLE) AS DWORD
LOCAL pdw AS DWORD PTR
pdw = VARPTR(f)
FUNCTION = @pdw
END FUNCTION
' ========================================================================================
' ========================================================================================
' 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_pD3DXFont AS ID3DXFont
INSTANCE m_quadVertices () AS Vertex
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
INSTANCE m_fZSlopeScale AS SINGLE
INSTANCE m_fDepthBias AS SINGLE
' ====================================================================================
' Initializes the vertex array
' ====================================================================================
CLASS METHOD Create
m_fZSlopeScale = -0.1!
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
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
' =====================================================================================
' =====================================================================================
' 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
' // Creates the font
ME.CreateD3DXFont
' // Loads the texture
D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\Checker.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_CULLMODE, %D3DCULL_NONE)
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 (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
LOCAL matTrans AS D3DXMATRIX
LOCAL matRot AS D3DXMATRIX
' // Builds a matrix using the specified offsets
D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, 4.0!)
' // 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
' // Set up the world matrix for spinning the quads about and render the
' // larger textured quad first.
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)
' // Now, for the second quad, scale it down a bit but use the same
' // translation and rotation matrices so we render it right on top of the
' // first quad. This will, of course, cause some z-fighting issues, which
' // we will fix via D3DRS_SLOPESCALEDEPTHBIAS and D3DRS_DEPTHBIAS.
' // Use depth bias
m_pD3DDevice.SetRenderState(%D3DRS_SLOPESCALEDEPTHBIAS, F2DW(m_fZSlopeScale))
m_pD3DDevice.SetRenderState(%D3DRS_DEPTHBIAS, F2DW(m_fDepthBias))
LOCAL matScale AS D3DXMATRIX
LOCAL matTemp AS D3DXMATRIX
D3DXMatrixScaling(matScale, 0.5!, 0.5!, 0.0!)
D3DXMatrixMultiply(matTemp, matScale, matRot)
D3DXMatrixMultiply(matWorld, matTemp, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.SetTexture(0, NOTHING)
m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
m_pD3DDevice.SetFVF(%FVF_Flags)
m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLESTRIP, 0, 2)
' // Turn off depth bias
m_pD3DDevice.SetRenderState(%D3DRS_SLOPESCALEDEPTHBIAS, F2DW(0.0!))
m_pD3DDevice.SetRenderState(%D3DRS_DEPTHBIAS, F2DW(0.0!))
' // Output the current settings...
LOCAL destRect1, destRect2 AS RECT
SetRect(destRect1, 5 * pWindow.rxRatio, 5 * pWindow.ryRatio, 0, 0)
SetRect(destRect2, 5 * pWindow.rxRatio, 20 * pWindow.ryRatio, 0, 0)
LOCAL szZSlope AS ASCIIZ * 255
LOCAL szDepthBias AS ASCIIZ * 255
szZSlope = "Z-Slope Scale = " & FORMAT$(m_fZSlopeScale, "#.00") & " (Change: F1 and F2)"
szDepthBias = "Depth Bias = " & FORMAT$(m_fDepthBias, "#.00") & " (Change: F3 and F4)"
m_pD3DXFont.DrawTextA(NOTHING, szZSlope, -1, destRect1, %DT_NOCLIP, _
D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!))
m_pD3DXFont.DrawTextA(NOTHING, szDepthBias, -1, destRect2, %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_pVertexBuffer = NOTHING
m_pTexture = NOTHING
m_pD3DXFont = 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_fZSlopeScale += 0.05!
CASE %VK_F2
m_fZSlopeScale -= 0.05!
CASE %VK_F3
m_fDepthBias += 0.005!
CASE %VK_F4
m_fDepthBias -= 0.005!
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_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
' ========================================================================================
Demonstrates how to perform Dot3 per-pixel bump mapping using a normal map and the D3DTOP_DOTPRODUCT3 texture-blending operation. This technique is sometimes referred to as per-pixel lighting or per-pixel attenuation, but Dot3 per-pixel bump-mapping is what most programmers know it as.
' ########################################################################################
' Control Keys: d/D - Toggle Dot3 bump mapping
' l/L - Toggle the usage of regular lighting in addition
' to the per-pixel lighting effect of bump mapping.
' m/M - Toggle motion of point light
' 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) - Dot3 Per-Pixel Bump-Mapping"
%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_NORMAL OR %D3DFVF_DIFFUSE OR %D3DFVF_TEX2
TYPE Vertex
x AS SINGLE
y AS SINGLE
z AS SINGLE
nx AS SINGLE
ny AS SINGLE
nz AS SINGLE
diffuse AS DWORD
tu1 AS SINGLE
tv1 AS SINGLE
tu2 AS SINGLE
tv2 AS SINGLE
END TYPE
%NUM_VERTICES = 24
' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_, nx_, ny_, nz_, diffuse_, tu1_, tv1_, tu2_, tv2_)
v.x = x_ : v.y = y_ : v.z = z_
v.nx = nx_ : v.ny = ny_ : v.nz = nz_
v.diffuse = diffuse_
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_deviceType AS DWORD
INSTANCE m_pVertexBuffer AS IDirect3DVertexBuffer9
INSTANCE m_pSphereMesh AS ID3DXMesh
INSTANCE m_pTexture AS IDirect3DTexture9
INSTANCE m_pNormalMapTexture AS IDirect3DTexture9
INSTANCE m_bDoDot3BumpMapping AS LONG
INSTANCE m_bMoveLightAbout AS LONG
INSTANCE m_bToggleRegularLighting AS LONG
INSTANCE m_light0 AS D3DLIGHT9
INSTANCE m_fDistance AS SINGLE
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
INSTANCE m_cubeVertices () AS Vertex
INSTANCE m_vTangents () AS D3DXVECTOR3
INSTANCE m_vBiNormals () AS D3DXVECTOR3
INSTANCE m_vNormals () AS D3DXVECTOR3
' ====================================================================================
' Initializes the vertex array
' ====================================================================================
CLASS METHOD Create
m_bDoDot3BumpMapping = %TRUE
m_bMoveLightAbout = %TRUE
m_bToggleRegularLighting = %FALSE
m_deviceType = %D3DDEVTYPE_HAL
m_fDistance = 5.0!
DIM m_cubeVertices(%NUM_VERTICES - 1) AS INSTANCE Vertex
' // Front Face
FillVertex(m_cubeVertices( 0), -1.0!, 1.0!, -1.0!, 0.0!, 0.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices( 1), 1.0!, 1.0!, -1.0!, 0.0!, 0.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
FillVertex(m_cubeVertices( 2), -1.0!, -1.0!, -1.0!, 0.0!, 0.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
FillVertex(m_cubeVertices( 3), 1.0!, -1.0!, -1.0!, 0.0!, 0.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
' // Back Face
FillVertex(m_cubeVertices( 4), -1.0!, 1.0!, 1.0!, 0.0!, 0.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
FillVertex(m_cubeVertices( 5), -1.0!, -1.0!, 1.0!, 0.0!, 0.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices( 6), 1.0!, 1.0!, 1.0!, 0.0!, 0.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices( 7), 1.0!, -1.0!, 1.0!, 0.0!, 0.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
' // Top Face
FillVertex(m_cubeVertices( 8), -1.0!, 1.0!, 1.0!, 0.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices( 9), 1.0!, 1.0!, 1.0!, 0.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
FillVertex(m_cubeVertices(10), -1.0!, 1.0!, -1.0!, 0.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
FillVertex(m_cubeVertices(11), 1.0!, 1.0!, -1.0!, 0.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
' // Bottom Face
FillVertex(m_cubeVertices(12), -1.0!, -1.0!, 1.0!, 0.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
FillVertex(m_cubeVertices(13), -1.0!, -1.0!, -1.0!, 0.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices(14), 1.0!, -1.0!, 1.0!, 0.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices(15), 1.0!, -1.0!, -1.0!, 0.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
' // Right Face
FillVertex(m_cubeVertices(16), 1.0!, 1.0!, -1.0!, 1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices(17), 1.0!, 1.0!, 1.0!, 1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
FillVertex(m_cubeVertices(18), 1.0!, -1.0!, -1.0!, 1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
FillVertex(m_cubeVertices(19), 1.0!, -1.0!, 1.0!, 1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
' // Left Face
FillVertex(m_cubeVertices(20), -1.0!, 1.0!, -1.0!, -1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 0.0!, 1.0!, 0.0!)
FillVertex(m_cubeVertices(21), -1.0!, -1.0!, -1.0!, -1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 1.0!, 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices(22), -1.0!, 1.0!, 1.0!, -1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 0.0!, 0.0!, 0.0!)
FillVertex(m_cubeVertices(23), -1.0!, -1.0!, 1.0!, -1.0!, 0.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!), 0.0!, 1.0!, 0.0!, 1.0!)
' // For each vertex defined above, we'll need to create a Tangent, BiNormal, and
' // Normal vector, which together define a tangent matrix for Dot3 bump mapping.
DIM m_vTangents (%NUM_VERTICES - 1) AS INSTANCE D3DXVECTOR3
DIM m_vBiNormals (%NUM_VERTICES - 1) AS INSTANCE D3DXVECTOR3
DIM m_vNormals (%NUM_VERTICES - 1) AS INSTANCE D3DXVECTOR3
END METHOD
' ====================================================================================
' =====================================================================================
INTERFACE IDX9 : INHERIT IUnknown
' =====================================================================================
' =====================================================================================
METHOD EncodeVectorAsDWORDColor(BYREF vVector AS D3DXVECTOR3) AS DWORD
LOCAL dwRed, dwGreen, dwBlue AS DWORD
dwRed = 127 * vVector.x + 128
dwGreen = 127 * vVector.y + 128
dwBlue = 127 * vVector.z + 128
SHIFT LEFT dwRed, 16
SHIFT LEFT dwGreen, 8
METHOD = &Hff000000 + dwRed + dwGreen + dwBlue
END METHOD
' =====================================================================================
' =====================================================================================
'// Name: CreateTangentSpaceVectors()
'// Desc: Given a vertex (v1) and two other vertices (v2 & v3) which define a
'// triangle, this function will return Tangent, BiNormal, and Normal,
'// vectors which can be used to define the tangent matrix for the first
'// vertex's position (v1).
'//
'// Args: v1 - vertex 1
'// v2 - vertex 2
'// v3 - vertex 3
'// v1u, v1v - texture-coordinates of vertex 1
'// v2u, v2v - texture-coordinates of vertex 2
'// v3u, v3v - texture-coordinates of vertex 3
'// vTangent - When the function returns, this will be set as the tangent vector
'// vBiNormal - When the function returns, this will be set as the binormal vector
'// vNormal - When the function returns, this will be set as the normal vector
'//
'// Note: This function is based on an article by By Jakob Gath and Sbren Dreijer.
'// http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php
' =====================================================================================
METHOD CreateTangentSpaceVectors(BYREF v1 AS D3DXVECTOR3, _
BYREF v2 AS D3DXVECTOR3, _
BYREF v3 AS D3DXVECTOR3, _
BYVAL v1u AS SINGLE, BYVAL v1v AS SINGLE, _
BYVAL v2u AS SINGLE, BYVAL v2v AS SINGLE, _
BYVAL v3u AS SINGLE, BYVAL v3v AS SINGLE, _
BYREF vTangent AS D3DXVECTOR3, _
BYREF vBiNormal AS D3DXVECTOR3, _
BYREF vNormal AS D3DXVECTOR3)
' // Create edge vectors from vertex 1 to vectors 2 and 3.
LOCAL vDirVec_v2_to_v1, vDirVec_v3_to_v1 AS D3DXVECTOR3
vDirVec_v2_to_v1.x = v2.x - v1.x : vDirVec_v2_to_v1.y = v2.y - v1.y : vDirVec_v2_to_v1.z = v2.z - v1.z
vDirVec_v3_to_v1.x = v3.x - v1.x : vDirVec_v3_to_v1.y = v3.y - v1.y : vDirVec_v3_to_v1.z = v3.z - v1.z
' // Create edge vectors from the texture coordinates of vertex 1 to vector 2.
LOCAL vDirVec_v2u_to_v1u, vDirVec_v2v_to_v1v AS SINGLE
vDirVec_v2u_to_v1u = v2u - v1u : vDirVec_v2v_to_v1v = v2v - v1v
' // Create edge vectors from the texture coordinates of vertex 1 to vector 3.
LOCAL vDirVec_v3u_to_v1u, vDirVec_v3v_to_v1v AS SINGLE
vDirVec_v3u_to_v1u = v3u - v1u : vDirVec_v3v_to_v1v = v3v - v1v
LOCAL fDenominator AS SINGLE
fDenominator = vDirVec_v2u_to_v1u * vDirVec_v3v_to_v1v - vDirVec_v3u_to_v1u * vDirVec_v2v_to_v1v
IF fDenominator < 0.0001! AND fDenominator > -0.0001! THEN
' // We're too close to zero and we're at risk of a divide-by-zero!
' // Set the tangent matrix to the identity matrix and do nothing.
vTangent.x = 1.0! : vTangent.y = 0.0! : vTangent.z = 0.0!
vBiNormal.x = 0.0! : vBiNormal.y = 1.0! : vBiNormal.z = 0.0!
vNormal.x = 0.0! : vNormal.y = 0.0! : vNormal.z = 1.0!
ELSE
' // Calculate and cache the reciprocal value
LOCAL fScale1 AS SINGLE
fScale1 = 1.0! / fDenominator
LOCAL T, B, N AS D3DXVECTOR3
T.x = (vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.x - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.x) * fScale1
T.y = (vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.y - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.y) * fScale1
T.z = (vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.z - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.z) * fScale1
B.x = (-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.x + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.x) * fScale1
B.y = (-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.y + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.y) * fScale1
B.z = (-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.z + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.z) * fScale1
' // The normal N is calculated as the cross product between T and B
D3DXVec3Cross(N, T, B)
' // Calculate and cache the reciprocal value
LOCAL fScale2 AS SINGLE
fScale2 = 1.0! / ((T.x * B.y * N.z - T.z * B.y * N.x) + (B.x * N.y * T.z - B.z * N.y * T.x) + (N.x * T.y * B.z - N.z * T.y * B.x))
' // Use the temporary T (Tangent), (B) Binormal, and N (Normal) vectors
' // to calculate the inverse of the tangent matrix that they represent.
' // The inverse of the tangent matrix is what we want since we need that
' // to transform the light's vector into tangent-space.
LOCAL vTemp AS D3DXVECTOR3
D3DXVec3Cross(vTemp, B, N) : vTangent.x = vTemp.x * fScale2
D3DXVec3Cross(vTemp, N, T) : vTangent.y = -(vTemp.x * fScale2)
D3DXVec3Cross(vTemp, T, B) : vTangent.z = vTemp.x * fScale2
D3DXVec3Normalize(vTangent, vTangent)
D3DXVec3Cross(vTemp, B, N) : vBiNormal.x = vTemp.y * fScale2
D3DXVec3Cross(vTemp, N, T) : vBiNormal.y = vTemp.y * fScale2
D3DXVec3Cross(vTemp, T, B) : vBiNormal.z = -(vTemp.y * fScale2)
D3DXVec3Normalize(vBiNormal, vBiNormal)
D3DXVec3Cross(vTemp, B, N) : vNormal.x = vTemp.z * fScale2
D3DXVec3Cross(vTemp, N, T) : vNormal.y = -(vTemp.z * fScale2)
D3DXVec3Cross(vTemp, T, B) : vNormal.z = vTemp.z * fScale2
D3DXVec3Normalize(vNormal, vNormal)
' // NOTE: Since the texture-space of Direct3D and OpenGL are laid-out
' // differently, a single normal map can't look right in both
' // unless you make some adjustments somewhere.
' //
' // You can adjust or fix this problem in three ways:
' //
' // 1. Create two normal maps: one for OpenGL and one for Direct3D.
' // 2. Flip the normal map image over as you load it into a texture
' // object.
' // 3. Flip the binormal over when computing the tangent-space
' // matrix.
' //
' // Since the normal map used by this sample was created for Direct3D,
' // no adjustment is necessary.
' //
' //*vBiNormal = *vBiNormal * -1.0f;
END IF
END METHOD
' =====================================================================================
' =====================================================================================
METHOD ComputeTangentsMatricesForEachVertex
LOCAL v1, v2, v3, vTangent, vBiNormal, vNormal AS D3DXVECTOR3
LOCAL i AS LONG
' // For each cube face defined in the vertex array, compute a tangent matrix
' // for each of the four vertices that define it.
FOR i = 0 TO %NUM_VERTICES - 1 STEP 4 ' // Use += 4 to process 1 face at a time
' //
' // Vertex 0 of current cube face...
' //
' // v2
' // 3----2
' // | |
' // | |
' // 0----1
' // v1 v3
' //
v1.x = m_cubeVertices(i).x : v1.y = m_cubeVertices(i).y : v1.z = m_cubeVertices(i).z
v2.x = m_cubeVertices(i+3).x : v2.y = m_cubeVertices(i+3).y : v2.z = m_cubeVertices(i+3).z
v3.x = m_cubeVertices(i+1).x : v3.y = m_cubeVertices(i+1).y : v3.z = m_cubeVertices(i+1).z
ME.CreateTangentSpaceVectors(v1, v2, v3, _
m_cubeVertices(i).tu1, m_cubeVertices(i).tv1, _
m_cubeVertices(i+3).tu1, m_cubeVertices(i+3).tv1, _
m_cubeVertices(i+1).tu1, m_cubeVertices(i+1).tv1, _
vTangent, vBiNormal, vNormal)
m_vTangents(i) = vTangent : m_vBiNormals(i) = vBiNormal : m_vNormals(i) = vNormal
' // Vertex 1 of current cube face...
' //
' // v3
' // 3----2
' // | |
' // | |
' // 0----1
' // v2 v1
v1.x = m_cubeVertices(i+1).x : v1.y = m_cubeVertices(i+1).y : v1.z = m_cubeVertices(i+1).z
v2.x = m_cubeVertices(i).x : v2.y = m_cubeVertices(i).y : v2.z = m_cubeVertices(i).z
v3.x = m_cubeVertices(i+2).x : v3.y = m_cubeVertices(i+2).y : v3.z = m_cubeVertices(i+2).z
ME.CreateTangentSpaceVectors(v1, v2, v3, _
m_cubeVertices(i+1).tu1, m_cubeVertices(i+1).tv1, _
m_cubeVertices(i).tu1, m_cubeVertices(i).tv1, _
m_cubeVertices(i+2).tu1, m_cubeVertices(i+2).tv1, _
vTangent, vBiNormal, vNormal)
m_vTangents(i+1) = vTangent : m_vBiNormals(i+1) = vBiNormal : m_vNormals(i+1) = vNormal
' // Vertex 2 of current cube face...
' //
' // v3 v1
' // 3----2
' // | |
' // | |
' // 0----1
' // v2
v1.x = m_cubeVertices(i+2).x : v1.y = m_cubeVertices(i+2).y : v1.z = m_cubeVertices(i+2).z
v2.x = m_cubeVertices(i+1).x : v2.y = m_cubeVertices(i+1).y : v2.x = m_cubeVertices(i+1).z
v3.x = m_cubeVertices(i+3).x : v3.y = m_cubeVertices(i+3).y : v3.z = m_cubeVertices(i+3).z
ME.CreateTangentSpaceVectors(v1, v2, v3, _
m_cubeVertices(i+2).tu1, m_cubeVertices(i+2).tv1, _
m_cubeVertices(i+1).tu1, m_cubeVertices(i+1).tv1, _
m_cubeVertices(i+3).tu1, m_cubeVertices(i+3).tv1, _
vTangent, vBiNormal, vNormal)
m_vTangents(i+2) = vTangent : m_vBiNormals(i+2) = vBiNormal : m_vNormals(i+2) = vNormal
' // Vertex 3 of current cube face...
' //
' // v1 v2
' // 3----2
' // | |
' // | |
' // 0----1
' // v3
v1.x = m_cubeVertices(i+3).x : v1.y = m_cubeVertices(i+3).y : v1.z = m_cubeVertices(i+3).z
v2.x = m_cubeVertices(i+2).x : v2.y = m_cubeVertices(i+2).y : v2.z = m_cubeVertices(i+2).z
v3.x = m_cubeVertices(i).x : v3.y = m_cubeVertices(i).y : v3.z = m_cubeVertices(i).z
ME.CreateTangentSpaceVectors(v1, v2, v3, _
m_cubeVertices(i+3).tu1, m_cubeVertices(i+3).tv1, _
m_cubeVertices(i+2).tu1, m_cubeVertices(i+2).tv1, _
m_cubeVertices(i).tu1, m_cubeVertices(i).tv1, _
vTangent, vBiNormal, vNormal)
m_vTangents(i+3) = vTangent : m_vBiNormals(i+3) = vBiNormal : m_vNormals(i+3) = vNormal
NEXT
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
' // Check Direct3D driver for hardware support...
LOCAL d3dCaps AS D3DCAPS9
IF FAILED(m_pD3D.GetDeviceCaps(%D3DADAPTER_DEFAULT, _
%D3DDEVTYPE_HAL, d3dCaps)) THEN
' // Respond to failure of GetDeviceCaps
MessageBox(%NULL, "Call to GetDeviceCaps failed!", _
"WARNING", %MB_OK OR %MB_ICONEXCLAMATION)
EXIT METHOD
END IF
' // Does this device support the D3DTOP_DOTPRODUCT3 texture-blending operation?
IF (d3dCaps.TextureOpCaps AND %D3DTOP_DOTPRODUCT3) = 0 THEN
MessageBox(%NULL, "Current Direct3D driver does not support the " & $CRLF & _
"D3DTOP_DOTPRODUCT3 texture-blending operation!" & $CRLF & _
"Switching to reference rasterizer!", "WARNING", %MB_OK OR %MB_ICONEXCLAMATION)
m_deviceType = %D3DDEVTYPE_REF
END IF
' // 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
' // Load the normal map...
D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\stone_wall_normal_map.bmp", m_pNormalMapTexture)
m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
m_pD3DDevice.SetSamplerState(0, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)
' // Load the base texture
D3DXCreateTextureFromFile(m_pD3DDevice, ".\Resources\stone_wall.bmp", m_pTexture)
m_pD3DDevice.SetSamplerState(1, %D3DSAMP_MINFILTER, %D3DTEXF_LINEAR)
m_pD3DDevice.SetSamplerState(1, %D3DSAMP_MAGFILTER, %D3DTEXF_LINEAR)
LOCAL nSize AS LONG
LOCAL pVertices AS Vertex PTR
nSize = (UBOUND(m_cubeVertices) - LBOUND(m_cubeVertices) + 1) * SIZEOF(Vertex)
m_pD3DDevice.CreateVertexBuffer(nSize, %D3DUSAGE_DYNAMIC, _
%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
LOCAL matProj AS D3DXMATRIX
D3DXMatrixPerspectiveFovLH(matProj, D3DXToRadian(45.0!), 640.0! / 480.0!, 0.1!, 100.0!)
m_pD3DDevice.SetTransform(%D3DTS_PROJECTION, matProj)
m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
' m_pD3DDevice.SetRenderState(%D3DRS_SHADEMODE, %D3DSHADE_FLAT) ' // Direct3d doesn't like this at all when doing Dot3.
m_pD3DDevice.SetRenderState(%D3DRS_SHADEMODE, %D3DSHADE_GOURAUD)
' // Set up lighting...
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
' // Set up our alpha material...
LOCAL mtrl AS D3DMATERIAL9
mtrl.Diffuse.r = 1.0! : mtrl.Diffuse.g = 1.0! : mtrl.Diffuse.b = 1.0! : mtrl.Diffuse.a = 1.0!
mtrl.Ambient.r = 1.0! : mtrl.Ambient.g = 1.0! : mtrl.Ambient.b = 1.0! : mtrl.Ambient.a = 1.0!
m_pD3DDevice.SetMaterial(mtrl)
' // Set light 0 to be a pure white point light
LOCAL m_light0 AS D3DLIGHT9
m_light0.Type = %D3DLIGHT_POINT
m_light0.Position.x = 0.0! : m_light0.Position.y = 0.0! : m_light0.Position.z = 0.0!
' //m_light0.Range = 10.0!
' //m_light0.Attenuation1 = 0.4!
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_pD3DDevice.SetLight(0, m_light0)
m_pD3DDevice.LightEnable(0, %TRUE)
' // Create a sphere mesh to represent a point light.
D3DXCreateSphere(m_pD3DDevice, 0.05!, 8, 8, m_pSphereMesh, BYVAL %NULL)
' // For each vertex, create a tangent vector, binormal, and normal
' // Initialize the inverse tangent matrix for each vertex to the identity
' // matrix before we get started.
LOCAL i AS LONG
FOR i = 0 TO %NUM_VERTICES - 1
m_vTangents(i).x = 1.0! : m_vTangents(i).y = 0.0! : m_vTangents(i).z = 0.0!
m_vBiNormals(i).x = 0.0! : m_vBiNormals(i).y = 1.0! : m_vBiNormals(i).z = 0.0!
m_vNormals(i).x = 0.0! : m_vNormals(i).y = 0.0! : m_vNormals(i).z = 1.0!
NEXT
ME.ComputeTangentsMatricesForEachVertex
' // Return success
METHOD = %S_OK
END METHOD
' =====================================================================================
' =====================================================================================
' Renders the scene
' =====================================================================================
METHOD RenderD3DScene
LOCAL hr AS LONG
STATIC fElapsedTime AS SINGLE
STATIC dCurTime AS DOUBLE
STATIC dLastTime AS DOUBLE
dCurTime = timeGetTime
fElapsedTime = (dCurTime - dLastTime) * 0.001!
dLastTime = dCurTime
' // 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)
IF ISTRUE m_bMoveLightAbout THEN
' //
' // Spin our point light around the cube...
' //
STATIC fAngle AS SINGLE
fAngle = fAngle + 60 * fElapsedTime
' // Wrap it around, if it gets too big
WHILE fAngle > 360.0!
fAngle = fAngle - 360.0!
WEND
WHILE fAngle < 0.0!
fAngle = fAngle + 360.0!
WEND
LOCAL x, y AS SINGLE
x = SIN(D3DXToRadian(fAngle))
y = COS(D3DXToRadian(fAngle))
' // This will place the light directly into world-space
m_light0.Position.x = 1.2! * x
m_light0.Position.y = 1.2! * y
m_light0.Position.z = m_fDistance - 2.0!
m_pD3DDevice.SetLight(0, m_light0)
END IF
LOCAL matWorld, matView, matProj, matTrans, matRot AS D3DXMATRIX
D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, m_fDistance)
D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
' // This sample is not really making use of a view matrix
D3DXMatrixIdentity(matView)
D3DXMatrixMultiply(matWorld, matRot, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
' // Begin the scene
m_pD3DDevice.BeginScene
IF ISTRUE m_bToggleRegularLighting THEN
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
ELSE
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
END IF
LOCAL i AS LONG
LOCAL pVertices AS Vertex PTR
pVertices = %NULL
IF ISTRUE m_bDoDot3BumpMapping THEN
' // Render a Dot3 bump mapped cube...
' // Transform the light's position from world-space to model-space
LOCAL vLightPosWS AS D3DXVECTOR3 ' // Light position (in world-space)
LOCAL vLightPosMS AS D3DXVECTOR3 ' // Light position (in model-space)
LOCAL vVertToLightMS AS D3DXVECTOR3 ' // L vector of N.L (in model-space)
LOCAL vVertToLightTS AS D3DXVECTOR3 ' // L vector of N.L (in tangent-space)
' // Get the light's current position, which is in world-space.
TYPE SET vLightPosWS = m_light0.Position
' // Transform the light's position into model-space
LOCAL worldInverse AS D3DXMATRIX
D3DXMatrixInverse(worldInverse, BYVAL %NULL, matWorld)
D3DXVec3TransformCoord(vLightPosMS, vLightPosWS, worldInverse)
' // Since our cube's vertex data is stored in a Vertex Buffer, we will
' // need to lock it briefly so we can encode the new tangent-space
' // L vectors that we're going to create into the diffuse color of each
' // vertex.
m_pVertexBuffer.Lock(0, 0, pVertices, 0)
FOR i = 0 TO %NUM_VERTICES - 1
' // For each vertex, rotate L (of N.L) into tangent-space and
' // pass it into Direct3D's texture blending system by packing it
' // into the vertex's diffuse color.
LOCAL vCurrentVertex AS D3DXVECTOR3
vCurrentVertex.x = m_cubeVertices(i).x
vCurrentVertex.y = m_cubeVertices(i).y
vCurrentVertex.z = m_cubeVertices(i).z
vVertToLightMS.x = vLightPosMS.x - vCurrentVertex.x
vVertToLightMS.y = vLightPosMS.y - vCurrentVertex.y
vVertToLightMS.z = vLightPosMS.z - vCurrentVertex.z
D3DXVec3Normalize(vVertToLightMS, vVertToLightMS)
' // Build up an inverse tangent-space matrix using the Tangent,
' // Binormal, and Normal calculated for the current vertex and
' // then use it to transform our L vector (of N.L), which is in
' // model-space, into tangent-space.
' //
' // A tangent matrix is of the form:
' //
' // |Tx Bx Nx 0|
' // |Ty By Ny 0|
' // |Tz Bz Nz 0|
' // |0 0 0 1|
' //
' // Note: Our vectors have already been inverted, so there is no
' // need to invert our tangent matrix once we build it up.
' // Tangent Binormal Normal
LOCAL invTangentMatrix AS D3DXMATRIX
invTangentMatrix.m11 = m_vTangents(i).x
invTangentMatrix.m12 = m_vBiNormals(i).x
invTangentMatrix.m13 = m_vNormals(i).x
invTangentMatrix.m14 = 0.0!
invTangentMatrix.m21 = m_vTangents(i).y
invTangentMatrix.m22 = m_vBiNormals(i).y
invTangentMatrix.m23 = m_vNormals(i).y
invTangentMatrix.m24 = 0.0!
invTangentMatrix.m31 = m_vTangents(i).z
invTangentMatrix.m32 = m_vBiNormals(i).z
invTangentMatrix.m33 = m_vNormals(i).z
invTangentMatrix.m34 = 0.0!
invTangentMatrix.m41 = 0.0!
invTangentMatrix.m42 = 0.0!
invTangentMatrix.m43 = 0.0!
invTangentMatrix.m44 = 1.0!
D3DXVec3TransformNormal(vVertToLightTS, vVertToLightMS, invTangentMatrix)
' // Last but not least, we must encode our new L vector as a DWORD
' // value so we can set it as the new vertex color. Of course, the
' // hardware assumes that we are going to do this, so it will
' // simply decode the original vector back out by reversing the
' // DOWRD encdoing we've performed here.
@pVertices[i].diffuse = ME.EncodeVectorAsDWORDColor(vVertToLightTS)
NEXT
m_pVertexBuffer.Unlock
' // STAGE 0
' //
' // Use D3DTOP_DOTPRODUCT3 to find the dot-product of (N.L), where N is
' // stored in the normal map, and L is passed in as the vertex color -
' // D3DTA_DIFFUSE.
m_pD3DDevice.SetTexture(0, m_pNormalMapTexture)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_TEXCOORDINDEX, 0)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLOROP, %D3DTOP_DOTPRODUCT3) ' // Perform a Dot3 operation...
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG1, %D3DTA_TEXTURE) ' // between the N (of N.L) which is stored in a normal map texture...
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG2, %D3DTA_DIFFUSE) ' // with the L (of N.L) which is stored in the vertex's diffuse color.
' // STAGE 1
' //
' // Modulate the base texture by N.L calculated in STAGE 0.
m_pD3DDevice.SetTexture(1, m_pTexture)
m_pD3DDevice.SetTextureStageState(1, %D3DTSS_TEXCOORDINDEX, 1)
m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLOROP, %D3DTOP_MODULATE) ' // Modulate...
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
ELSE
' // Render a regular textured cube with no Dot3 bump mapping...
' // Reset the vertex colors back to pure white...
m_pVertexBuffer.Lock(0, 0, pVertices, 0)
FOR i = 0 TO %NUM_VERTICES - 1
@pVertices[i].diffuse = D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!)
NEXT
m_pVertexBuffer.Unlock
' // STAGE 0
m_pD3DDevice.SetTexture(0, m_pTexture)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_TEXCOORDINDEX, 0)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLOROP, %D3DTOP_MODULATE)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG1, %D3DTA_TEXTURE)
m_pD3DDevice.SetTextureStageState(0, %D3DTSS_COLORARG2, %D3DTA_DIFFUSE)
' // STAGE 1
m_pD3DDevice.SetTexture(1, NOTHING)
m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLOROP, %D3DTOP_MODULATE)
m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLORARG1, %D3DTA_TEXTURE)
m_pD3DDevice.SetTextureStageState(1, %D3DTSS_COLORARG2, %D3DTA_CURRENT)
END IF
' // Now, render our textured test cube, which consists of 6 cube faces...
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)
' // Render a small white sphere to mark the point light's position...
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
m_pD3DDevice.SetTexture(0, NOTHING)
m_pD3DDevice.SetTexture(1, NOTHING)
D3DXMatrixIdentity(matWorld)
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_pSphereMesh = NOTHING
m_pNormalMapTexture = 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_CHAR
SELECT CASE wParam
CASE 68, 100 ' D, d
m_bDoDot3BumpMapping = IIF&(m_bDoDot3BumpMapping = 0, -1, 0)
CASE 76, 108 ' L, l
m_bToggleRegularLighting = IIF&(m_bToggleRegularLighting = 0, -1, 0)
CASE 77, 109 ' M, m
m_bMoveLightAbout = IIF&(m_bMoveLightAbout = 0, -1, 0)
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
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
' ========================================================================================
Demonstrates how to render text to the screen using Direct3D's ID3DXFont interface.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_Fonts.bas
' Contents: DX9 example
' Description: Demonstrates how to render text to the screen using Direct3D's ID3DXFont class.
' 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_fonts.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_5.htm#dx9_fonts
' ########################################################################################
' 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) - Fonts"
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
' =====================================================================================
INTERFACE IDX9 : INHERIT IUnknown
' =====================================================================================
' =====================================================================================
' Creates the font
' =====================================================================================
METHOD CreateD3DXFont
LOCAL hr AS LONG
LOCAL hDC AS DWORD
LOCAL nHeight AS LONG
LOCAL nPointSize AS LONG
nPointSize = 18
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
' =====================================================================================
' =====================================================================================
' 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
' // Creates the font
ME.CreateD3DXFont
' // Return success
METHOD = %TRUE
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)
' // Begins the scene
m_pD3DDevice.BeginScene
' // Render some text using our new font...
LOCAL destRect1, destRect2, destRect3 AS RECT
SetRect(destRect1, 100 * pWindow.rxRatio, 100 * pWindow.ryRatio, 0, 0)
SetRect(destRect2, 200 * pWindow.rxRatio, 200 * pWindow.ryRatio, 0, 0)
SetRect(destRect3, 300 * pWindow.rxRatio, 300 * pWindow.ryRatio, 0, 0)
m_pD3DXFont.DrawTextA(NOTHING, "This is line 1", -1, destRect1, %DT_NOCLIP, _
D3DCOLOR_COLORVALUE(1.0!, 0.0!, 0.0!, 1.0!))
m_pD3DXFont.DrawTextA(NOTHING, "This is line 2", -1, destRect2, %DT_NOCLIP, _
D3DCOLOR_COLORVALUE(1.0!, 1.0!, 1.0!, 1.0!))
m_pD3DXFont.DrawTextA(NOTHING, "This is line 3", -1, destRect3, %DT_NOCLIP, _
D3DCOLOR_COLORVALUE(0.0!, 0.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 font
m_pD3DXFont = NOTHING
' // Reset the type, size, and format of the swap chain
m_pD3DDevice.Reset(m_d3dpp)
' // Recreate the font
ME.CreateD3DXFont
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
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
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
' ========================================================================================
Demonstrates how to optimize performance by using indexed geometry. As a demonstration, the sample reduces the vertex count of a simple cube from 24 to 8 by redefining the cube's geometry using an indices array.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_IndexedGeometry.bas
' Contents: DX9 example
' Description: Demonstrates how to optimize performance by using indexed geometry. As a
' demonstration, the sample reduces the vertex count of a simple cube from 24 to 8 by
' redefining the cube's geometry using an indices array.
' 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_indexed_geometry.cpp by Kevin Harris, 06/15/05, available at
' http://www.codesampler.com/dx9src/dx9src_2.htm#dx9_indexed_geometry
' Control Keys: F1 - Toggles between indexed and non-indexed geometry.
' Shouldn't produce any noticeable change since they render the same cube.
' ########################################################################################
' 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) - Indexed Geometry"
%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_pVertexBuffer AS IDirect3DVertexBuffer9
INSTANCE m_pVertexBuffer_Indexed AS IDirect3DVertexBuffer9
INSTANCE m_pIndexBuffer AS IDirect3DIndexBuffer9
INSTANCE m_cubeVertices () AS Vertex
INSTANCE m_cubeVertices_indexed () AS Vertex
INSTANCE m_cubeIndices () AS WORD
INSTANCE m_bUseIndexedGeometry AS LONG
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
' ====================================================================================
' Initializes the vertex array
' ====================================================================================
CLASS METHOD Create
DIM m_cubeVertices(23) AS INSTANCE Vertex
' Quad 0
FillVertex(m_cubeVertices( 0), -1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_cubeVertices( 1), 1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_cubeVertices( 2), -1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices( 3), 1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
' Quad 1
FillVertex(m_cubeVertices( 4), -1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices( 5), -1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices( 6), 1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices( 7), 1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
' Quad 2
FillVertex(m_cubeVertices( 8), -1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices( 9), 1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices(10), -1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_cubeVertices(11), 1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
' Quad 3
FillVertex(m_cubeVertices(12), -1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices(13), -1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices(14), 1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_cubeVertices(15), 1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
' Quad 4
FillVertex(m_cubeVertices(16), 1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_cubeVertices(17), 1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices(18), 1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
FillVertex(m_cubeVertices(19), 1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
' Quad 5
FillVertex(m_cubeVertices(20), -1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_cubeVertices(21), -1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices(22), -1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices(23), -1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
'// Now, to save ourselves the bandwidth of passing a bunch or redundant vertices
'// down the graphics pipeline, we shorten our vertex list and pass only the
'// unique vertices. We then create a indices array, which contains index values
'// that reference vertices in our vertex array.
'//
'// In other words, the vertex array doens't actually define our cube anymore,
'// it only holds the unique vertices; it's the indices array that now defines
'// the cube's geometry.
DIM m_cubeVertices_indexed(7)
FillVertex(m_cubeVertices_indexed(0), -1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_cubeVertices_indexed(1), 1.0!, 1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_cubeVertices_indexed(2), -1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices_indexed(3), 1.0!, -1.0!, -1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0))
FillVertex(m_cubeVertices_indexed(4), -1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 1.0, 1.0))
FillVertex(m_cubeVertices_indexed(5), -1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices_indexed(6), 1.0!, 1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 1.0, 1.0, 1.0))
FillVertex(m_cubeVertices_indexed(7), 1.0!, -1.0!, 1.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
DIM m_cubeIndices(23)
ARRAY ASSIGN m_cubeIndices() = 0, 1, 2, 3, 4, 5, 6, 7, 4, 6, 0, 1, 5, 2, 7, 3, 1, 6, 3, 7, 0, 2, 4, 5
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
' // 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)
' // Create a vertex buffer...
LOCAL nSize AS LONG
LOCAL pVertices AS DWORD
nSize = (UBOUND(m_cubeVertices) - LBOUND(m_cubeVertices) + 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_cubeVertices(0)), nSize
m_pVertexBuffer.Unlock
' // Create a vertex buffer, which contains indexed geometry...
pVertices = 0
nSize = (UBOUND(m_cubeVertices_indexed) - LBOUND(m_cubeVertices_indexed) + 1) * SIZEOF(Vertex)
m_pD3DDevice.CreateVertexBuffer(nSize, %D3DUSAGE_WRITEONLY, _
%FVF_Flags, %D3DPOOL_DEFAULT, m_pVertexBuffer_Indexed, %NULL)
m_pVertexBuffer_Indexed.Lock(0, nSize, pVertices, 0)
MoveMemory BYVAL pVertices, BYVAL VARPTR(m_cubeVertices_indexed(0)), nSize
m_pVertexBuffer_Indexed.Unlock
' // Create an index buffer to use with our indexed vertex buffer...
LOCAL pIndices AS DWORD
nSize = (UBOUND(m_cubeIndices) - LBOUND(m_cubeIndices) + 1) * SIZEOF(Vertex)
m_pD3DDevice.CreateIndexBuffer(nSize, %D3DUSAGE_WRITEONLY, _
%D3DFMT_INDEX16, %D3DPOOL_DEFAULT, m_pIndexBuffer, %NULL)
m_pIndexBuffer.Lock(0, nSize, pIndices, 0)
MoveMemory BYVAL pIndices, BYVAL VARPTR(m_cubeIndices(0)), nSize
m_pIndexBuffer.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.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!, 5.0!)
' // 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_bUseIndexedGeometry THEN
m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer_Indexed, 0, SIZEOF(Vertex))
m_pD3DDevice.SetIndices(m_pIndexBuffer)
m_pD3DDevice.SetFVF(%FVF_Flags)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 0, 2)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 4, 2)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 8, 2)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 12, 2)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 16, 2)
m_pD3DDevice.DrawIndexedPrimitive(%D3DPT_TRIANGLESTRIP, 0, 0, 8, 20, 2)
ELSE
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_pVertexBuffer_Indexed = NOTHING
m_pIndexBuffer = 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_bUseIndexedGeometry = NOT m_bUseIndexedGeometry
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_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
' ========================================================================================
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_Lighting.bas
' Contents: DX9 example
' Description: Demonstrates the three basic types of lights that are available in
' Direct3D: directional, spot, and point.
' 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/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_6.htm#dx9_lighting
' Control Keys: F1 - Changes the light's type
' F2 - Toggles 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) - 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 ' // Vertex buffer for the walls and floor
INSTANCE m_pSphereMesh AS ID3DXMesh ' // A mesh to represent a point light
INSTANCE m_pConeMesh AS ID3DXMesh ' // A mesh to represent a directional or spot light
INSTANCE m_bRenderInWireFrame AS LONG
INSTANCE m_lightType AS LONG
'// Mesh properties...
INSTANCE m_nNumVertsAlongX AS LONG
INSTANCE m_nNumVertsAlongZ AS LONG
INSTANCE m_fMeshLengthAlongX AS SINGLE
INSTANCE m_fMeshLengthAlongZ AS SINGLE
INSTANCE m_nMeshVertCount AS LONG
' ====================================================================================
' Initializes values
' ====================================================================================
CLASS METHOD Create
m_bRenderInWireFrame = %FALSE
m_nNumVertsAlongX = 32
m_nNumVertsAlongZ = 32
m_fMeshLengthAlongX = 10.0!
m_fMeshLengthAlongZ = 10.0!
m_nMeshVertCount = (m_nNumVertsAlongX - 1) * (m_nNumVertsAlongZ - 1) * 6
m_lightType = %LIGHT_TYPE_DIRECTIONAL
END METHOD
' ====================================================================================
' =====================================================================================
INTERFACE IDX9 : INHERIT IUnknown
' =====================================================================================
' =====================================================================================
' Init lights
' =====================================================================================
METHOD initLights
' // Set up a material
LOCAL mtrl AS D3DMATERIAL9
mtrl.Diffuse.r = 1.0!
mtrl.Diffuse.g = 1.0!
mtrl.Diffuse.b = 1.0!
mtrl.Diffuse.a = 1.0!
mtrl.Ambient.r = 1.0!
mtrl.Ambient.g = 1.0!
mtrl.Ambient.b = 1.0!
mtrl.Ambient.a = 1.0!
m_pD3DDevice.SetMaterial(mtrl)
' // Set light 0 to be a simple, bright directional light to use
' // on the mesh that will represent light 2
LOCAL v AS D3DXVECTOR3
LOCAL light_0 AS D3DLIGHT9
light_0.Type = %D3DLIGHT_DIRECTIONAL
v.x = 0.5! : v.y = -0.5! : v.z = 0.5!
TYPE SET light_0.Direction = v
light_0.Diffuse.r = 1.0!
light_0.Diffuse.g = 1.0!
light_0.Diffuse.b = 1.0!
m_pD3DDevice.SetLight(0, light_0)
' // Set light 1 to be a simple, faint grey directional light so
' // the walls and floor are slightly different shades of grey
LOCAL light_1 AS D3DLIGHT9
light_1.Type = %D3DLIGHT_DIRECTIONAL
v.x = 0.3! : v.y = -0.5! : v.z = 0.2!
TYPE SET light_1.Direction = v
light_1.Diffuse.r = 0.25!
light_1.Diffuse.g = 0.25!
light_1.Diffuse.b = 0.25!
m_pD3DDevice.SetLight(1, light_1)
' // Light #2 will be the demo light used to light the floor and walls.
' // It will be set up in render() since its type can be changed at
' // run-time.
' // Enable some dim, grey ambient lighting so objects that are not lit
' // by the other lights are not completely black.
m_pD3DDevice.SetRenderState(%D3DRS_AMBIENT, _
D3DCOLOR_COLORVALUE(0.25, 0.25, 0.25, 1.0))
END METHOD
' =====================================================================================
' =====================================================================================
' Create mesh
' =====================================================================================
METHOD createMesh
' // Compute position deltas for moving down the X, and Z axis during mesh creation
LOCAL dX, dZ AS SINGLE
dX = 1.0! / (m_nNumVertsAlongX - 1)
dZ = 1.0! / (m_nNumVertsAlongZ - 1)
m_pD3DDevice.CreateVertexBuffer(m_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 m_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 m_nNumVertsAlongZ - 2
' // Fill the row with quads which are composed of two triangles each...
FOR x = 0 TO m_nNumVertsAlongX - 2
' // First triangle of the current quad
' // 1 ___ 2
' // | /|
' // |/__|
' // 0
' // 0
@v[i].x = m_fMeshLengthAlongX * x * dX
@v[i].z = m_fMeshLengthAlongZ * z * dZ
i = i + 1
' // 1
@v[i].x = m_fMeshLengthAlongX * x * dX
@v[i].z = m_fMeshLengthAlongZ * (z + 1) * dZ
i = i + 1
' // 2
@v[i].x = m_fMeshLengthAlongX * (x + 1) * dX
@v[i].z = m_fMeshLengthAlongZ * (z + 1) * dZ
i = i + 1
' // Second triangle of the current quad
' // ___ 1
' // | /|
' // |/__|
' // 0 2
' // 0
@v[i].x = m_fMeshLengthAlongX * x * dX
@v[i].z = m_fMeshLengthAlongZ * z * dZ
i = i + 1
' // 1
@v[i].x = m_fMeshLengthAlongX * (x + 1) * dX
@v[i].z = m_fMeshLengthAlongZ * (z + 1) * dZ
i = i + 1
' // 2
@v[i].x = m_fMeshLengthAlongX * (x + 1) * dX
@v[i].z = m_fMeshLengthAlongZ * z * dZ
i = i + 1
NEXT
NEXT
m_pMeshVertices.Unlock
' // Create a sphere mesh to represent a point light.
D3DXCreateSphere(m_pD3DDevice, 0.25!, 20, 20, m_pSphereMesh, BYVAL %NULL)
' // Create a cone mesh to represent a directional or spot light.
D3DXCreateCylinder(m_pD3DDevice, 0.0!, 0.25!, 0.5!, 20, 20, m_pConeMesh, BYVAL %NULL)
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
LOCAL dCaps AS D3DCAPS9
m_pD3D.GetDeviceCaps(%D3DADAPTER_DEFAULT, %D3DDEVTYPE_HAL, dCaps)
IF (dCaps.VertexProcessingCaps AND %D3DVTXPCAPS_POSITIONALLIGHTS) = 0 THEN
' // If D3DVTXPCAPS_POSITIONALLIGHTS is not set, the device does
' // not support point or spot lights and the demo won't run properly.
' //MessageBox( g_hWnd, "This hardware doesn't support spot or point lights!",
' //"Direct3D Lighting", MB_OK );
END IF
' // 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, %TRUE)
m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %FALSE)
m_pD3DDevice.SetRenderState(%D3DRS_DITHERENABLE, %FALSE)
m_pD3DDevice.SetRenderState(%D3DRS_SPECULARENABLE, %FALSE)
LOCAL matView AS D3DXMATRIX
LOCAL v1, v2, v3 AS D3DXVECTOR3
v1.x = -12.0! : v1.y = 12.0! : v1.z = -12.0! ' // Camera position
v2.x = 0.0! : v2.y = -1.5! : 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)
ME.initLights
ME.createMesh
' // Return success
METHOD = %S_OK
END METHOD
' =====================================================================================
' =====================================================================================
' Renders the scene
' =====================================================================================
METHOD RenderD3DScene
LOCAL hr AS LONG
' // Create light 2 at run-time based on the light type the user has selected.
STATIC fElapsedAppTime AS SINGLE
STATIC dStartTime AS DOUBLE
IF dStartTime = 0 THEN dStartTime = timeGetTime
fElapsedAppTime = (timeGetTime - dStartTime) * 0.001!
LOCAL x, y, z AS SINGLE
x = SIN(fElapsedAppTime * 2.000!)
y = SIN(fElapsedAppTime * 2.246!)
z = SIN(fElapsedAppTime * 2.640!)
LOCAL light_2 AS D3DLIGHT9
light_2.Diffuse.r = 1.0!
light_2.Diffuse.g = 1.0!
light_2.Diffuse.b = 1.0!
light_2.Range = 100.0!
' // While both Direct3D and OpenGL use the same formula for lighting
' // attenuation, they call the variables by different names when setting
' // them through the API. The following two formulas are the same and
' // only differ by the API names used for each variable.
' //
' // Direct3D:
' //
' // attenuation = 1 / ( Attenuation0 +
' // Attenuation1 * d +
' // Attenuation2 * d2 )
' //
' // OpenGL:
' //
' // attenuation = 1 / ( GL_CONSTANT_ATTENUATION +
' // GL_LINEAR_ATTENUATION * d +
' // GL_QUADRATIC_ATTENUATION * d2 )
' //
' // Where: d = Distance from vertex position to light position
' // d2 = d squared
LOCAL v AS D3DXVECTOR3
SELECT CASE AS LONG m_lightType
CASE %LIGHT_TYPE_DIRECTIONAL
light_2.Type = %D3DLIGHT_DIRECTIONAL
v.x = x : v.y = y : v.z = z
TYPE SET light_2.Direction = v
CASE %LIGHT_TYPE_SPOT
light_2.Type = %D3DLIGHT_SPOT
v.x = x * 2.0! : v.y = y * 2.0! : v.z = z * 2.0!
TYPE SET light_2.Position = v
v.x = x : v.y = y : v.z = z
TYPE SET light_2.Direction = v
light_2.Theta = 0.5!
light_2.Phi = 1.0!
light_2.Falloff = 1.0!
light_2.Attenuation0 = 1.0!
CASE %LIGHT_TYPE_POINT
light_2.Type = %D3DLIGHT_POINT
v.x = x * 4.5! : v.y = y * 4.5! : v.z = z * 4.5!
TYPE SET light_2.Position = v
light_2.Attenuation1 = 0.4!
END SELECT
m_pD3DDevice.SetLight(2, light_2)
' // Render...
' // 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
m_pD3DDevice.SetStreamSource(0, m_pMeshVertices, 0, SIZEOF(Vertex))
m_pD3DDevice.SetFVF(%FVF_Flags)
LOCAL matWorld AS D3DXMATRIX
LOCAL matTrans AS D3DXMATRIX
LOCAL matRotate AS D3DXMATRIX
' // The first thing we draw is our walls. The walls are to be lit
' // by lights 1 and 2 only, so we need to turn on lights 1 and 2,
' // and turn off light 0. Light 0 will be used later for the meshes.
m_pD3DDevice.LightEnable(0, %FALSE)
m_pD3DDevice.LightEnable(1, %TRUE)
m_pD3DDevice.LightEnable(2, %TRUE)
' // Draw the floor
D3DXMatrixTranslation(matTrans, -5.0!, -5.0!, -5.0!)
D3DXMatrixRotationZ(matRotate, 0.0!)
D3DXMatrixMultiply(matWorld, matRotate, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, m_nMeshVertCount / 3)
' // Draw the back wall
D3DXMatrixTranslation(matTrans, 5.0!,-5.0!, -5.0!)
D3DXMatrixRotationZ(matRotate, D3DXToRadian(90.0))
D3DXMatrixMultiply(matWorld, matRotate, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, m_nMeshVertCount / 3)
' // Draw the side wall
D3DXMatrixTranslation(matTrans, -5.0!, -5.0!, 5.0!)
D3DXMatrixRotationX(matRotate, -D3DXToRadian(90.0))
D3DXMatrixMultiply(matWorld, matRotate, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.DrawPrimitive(%D3DPT_TRIANGLELIST, 0, m_nMeshVertCount / 3)
' // We're finished drawing the walls, we'll now draw the mesh that
' // represents the light's type. We'll use a little cone for a
' // directional or spot light and a little sphere for a point light.
' // Light 0 is just for our little meshes, so turn on light 0, and
' // turn off lights 1 and 2 before rendering.
m_pD3DDevice.LightEnable(0, %TRUE)
m_pD3DDevice.LightEnable(1, %FALSE)
m_pD3DDevice.LightEnable(2, %FALSE)
' // Draw the correct mesh representing the current light type...
IF m_lightType = %LIGHT_TYPE_POINT THEN
' // Just position the point light - no need to orient it
D3DXMatrixTranslation(matWorld, light_2.Position.x, _
light_2.Position.y, light_2.Position.z)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pSphereMesh.DrawSubset(0)
ELSE
' // Position the light and then point it in the light's direction
LOCAL vecFrom, vecAt, vecUp AS D3DXVECTOR3
vecFrom.x = light_2.Position.x
vecFrom.y = light_2.Position.y
vecFrom.z = light_2.Position.z
vecAt.x = light_2.Position.x + light_2.Direction.x
vecAt.y = light_2.Position.y + light_2.Direction.y
vecAt.z = light_2.Position.z + light_2.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)
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_pMeshVertices = NOTHING
m_pSphereMesh = 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_KEYDOWN
SELECT CASE LO(WORD, wParam)
CASE %VK_ESCAPE
SendMessage hwnd, %WM_CLOSE, 0, 0
CASE %VK_F1
m_lightType = m_lightType + 1
IF m_lightType > 2 THEN m_lightType = 0
CASE %VK_F2
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
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
' ========================================================================================
Demonstrates how to manually load the vertex buffer of a D3DXMesh object.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_LoadingMesh.bas
' Contents: DX9 example
' Description: Demonstrates how to manually load the vertex buffer of a D3DXMesh object.
' 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_loading_mesh_vb.cpp by Kevin Harris, 05/22/05, available at
' http://www.codesampler.com/dx9src/dx9src_11.htm#dx9_mesh_loading_vb
' ########################################################################################
' 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) - Loading Mesh Vertex Buffers"
%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_pMesh AS ID3DXMesh
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_fDistance = 4.0!
DIM m_quadVertices(3) AS INSTANCE Vertex
' // Bottom-Left, color = yellow
FillVertex(m_quadVertices(0), -1.0!, -1.0!, 0.0!, &Hffffff00)
' // Bottom-Right, color = green
FillVertex(m_quadVertices(1), 1.0!, -1.0!, 0.0!, &Hff00ff00)
' // Top-Right, color = red
FillVertex(m_quadVertices(2), 1.0!, 1.0!, 0.0!, &Hffff0000)
' // Top-Left, color = blue
FillVertex(m_quadVertices(3), -1.0!, 1.0!, 0.0!, &Hff0000ff)
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)
' // Create a mesh container...
hr = D3DXCreateMeshFVF(2, _ ' // Our quads has 2 faces or triangles...
4, _ ' // which require 4 vertices to define.
%D3DXMESH_MANAGED, %FVF_Flags, _
m_pd3dDevice, m_pMesh)
' // Load our quad's vertices...
LOCAL pVertices AS Vertex PTR
m_pMesh.LockVertexBuffer(0, pVertices)
@pVertices[0] = m_quadVertices(0)
@pVertices[1] = m_quadVertices(1)
@pVertices[2] = m_quadVertices(2)
@pVertices[3] = m_quadVertices(3)
' // If you wanted, you could also memcpy the whole thing in like so.
' //memcpy( pVertices, m_quadVertices, sizeof(m_quadVertices) );
' nSize = (UBOUND(m_quadVertices) - LBOUND(m_quadVertices) + 1) * SIZEOF(Vertex)
' MoveMemory BYVAL pVertices, BYVAL VARPTR(m_quadVertices(0)), nSize
m_pMesh.UnlockVertexBuffer
' //
' // Define our quad's indices...
' //
LOCAL pIndices AS WORD PTR
m_pMesh.LockIndexBuffer(0, pIndices)
' // First triangle of quad
@pIndices[0] = 0
@pIndices[1] = 1
@pIndices[2] = 2
' // Second triangle of quad
@pIndices[3] = 0
@pIndices[4] = 2
@pIndices[5] = 3
m_pMesh.UnlockIndexBuffer
' // Return success
METHOD = %S_OK
END METHOD
' =====================================================================================
' =====================================================================================
' Renders the scene
' =====================================================================================
METHOD RenderD3DScene
' // 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 hr AS LONG
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
' // Now, lets render something with our newly loaded mesh object...
m_pMesh.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_pMesh = 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 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
' ========================================================================================
Demonstrates how to use materials with lighting to produce different surface effects.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_Material.bas
' Contents: DX9 example
' Description: Demonstrates how to use materials with lighting to produce different surface effects.
' 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_material.cpp by Kevin Harris, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_6.htm#dx9_material
' Control Keys: Left Mouse Button - Spin the view
' ########################################################################################
' 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) - Material"
%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
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_pLight0 AS D3DLIGHT9
INSTANCE m_redClayMtrl AS D3DMATERIAL9
INSTANCE m_greenPlasticMtrl AS D3DMATERIAL9
INSTANCE m_silverMetalMtrl AS D3DMATERIAL9
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
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_ZENABLE, %TRUE)
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %TRUE)
m_pD3DDevice.SetRenderState(%D3DRS_SPECULARENABLE, %TRUE)
' //-------------------------------------------------------------------------
' // Setup material - Used to create a reddish clay teapot
' //-------------------------------------------------------------------------
' // A matte clay look is easy. All we really have to do is set the color to
' // look like clay pottery.
m_redClayMtrl.Diffuse.r = 1.0!
m_redClayMtrl.Diffuse.g = 0.5!
m_redClayMtrl.Diffuse.b = 0.2!
m_redClayMtrl.Diffuse.a = 1.0!
' //-------------------------------------------------------------------------
' // Setup material - Used to create a green plastic teapot
' //-------------------------------------------------------------------------
' // Set the material's main color to green.
m_greenPlasticMtrl.Diffuse.r = 0.0!
m_greenPlasticMtrl.Diffuse.g = 1.0!
m_greenPlasticMtrl.Diffuse.b = 0.0!
m_greenPlasticMtrl.Diffuse.a = 1.0!
' // Lets favor the ambient's green over the other colors. Why? I don't know.
' // It just looks better to me. Using materials is some what more artistic
' // than scientific, so just play around till you get what you want.
m_greenPlasticMtrl.Ambient.r = 0.5!
m_greenPlasticMtrl.Ambient.g = 1.0!
m_greenPlasticMtrl.Ambient.b = 0.5!
m_greenPlasticMtrl.Ambient.a = 1.0!
' // Plastic can be shiny, but we don't want it too shiny are it will look
' // more like glass or metal. We'll have the material reflect back more
' // green than red and blue so the highlights won't be pure white.
m_greenPlasticMtrl.Specular.r = 0.5!
m_greenPlasticMtrl.Specular.g = 1.0!
m_greenPlasticMtrl.Specular.b = 0.5!
m_greenPlasticMtrl.Specular.a = 1.0!
' // It seems backwards, but increasing the Power value reduces the
' // highlight's size
m_greenPlasticMtrl.Power = 40.0!
' //-------------------------------------------------------------------------
' // Setup material - Used to create a silver metallic teapot
' //-------------------------------------------------------------------------
' // Set the material's main color to a silver-like gray color.
m_silverMetalMtrl.Diffuse.r = 0.5!
m_silverMetalMtrl.Diffuse.g = 0.5!
m_silverMetalMtrl.Diffuse.b = 0.5!
m_silverMetalMtrl.Diffuse.a = 1.0!
' // A silver metal would be very shiny, so we'll reflect back all ambient.
m_silverMetalMtrl.Ambient.r = 1.0!
m_silverMetalMtrl.Ambient.g = 1.0!
m_silverMetalMtrl.Ambient.b = 1.0!
m_silverMetalMtrl.Ambient.a = 1.0!
' // We can make it seem extra shiny by having it actually emit some light
' // of its own... but not too much are we'll wash the color out.
m_silverMetalMtrl.Emissive.r = 0.1!
m_silverMetalMtrl.Emissive.g = 0.1!
m_silverMetalMtrl.Emissive.b = 0.1!
m_silverMetalMtrl.Emissive.a = 1.0!
' // Polished silver can reflect back pure white highlights, so set the
' // specular to pure white.
m_silverMetalMtrl.Specular.r = 1.0!
m_silverMetalMtrl.Specular.g = 1.0!
m_silverMetalMtrl.Specular.b = 1.0!
m_silverMetalMtrl.Specular.a = 1.0!
' // Set the Power value to a small number to make the highlight's size bigger.
m_silverMetalMtrl.Power = 5.0!
' //
' // If you're dealing with a model that provides its own per-vertex colors,
' // you'll probably need to disable the usage of vertex colors by Direct3D's
' // lighting calculations to get the right effect. This can be accomplished
' // by setting D3DRS_COLORVERTEX to FALSE like so...
' //
' // Comment out this line to use the teapot's real color, which is blue.
' //
m_pD3DDevice.SetRenderState(%D3DRS_COLORVERTEX, %FALSE)
' // Another way to ignore per-vertex colors is to simply force all lighting
' // calculations to use your material settings explicitly like so...
' //m_pD3DDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );
' //m_pD3DDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL );
' //m_pD3DDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL );
' //m_pD3DDevice->SetRenderState( D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL );
' //
' // Setup a simple directional light and some ambient...
' //
m_pLight0.Type = %D3DLIGHT_DIRECTIONAL
LOCAL v AS D3DXVECTOR3
v.x = 1.0! : v.y = 0.0! : v.z = 1.0!
TYPE SET 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)
' // Be careful when setting up ambient lighting. You can very easily wash
' // out the material's specular highlights.
m_pD3DDevice.SetRenderState(%D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.2!, 0.2!, 0.2!, 1.0!))
' //
' // Load up the teapot mesh and then clone it so we can add per-vertex
' // colors to it. I'm only doing this so I can demonstrate what happens if
' // we fail to ignore vertex colors when using materials. Failure to
' // understand this causes many beginners a lot of headaches.
' //
LOCAL pTempTeapotMesh AS ID3DXMesh
D3DXLoadMeshFromX(".\Resources\teapot.x", %D3DXMESH_SYSTEMMEM, m_pD3DDevice, _
BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, BYVAL %NULL, pTempTeapotMesh)
LOCAL pTempVertexBuffer AS IDirect3DVertexBuffer9
pTempTeapotMesh.CloneMeshFVF(0, %FVF_Flags, m_pD3DDevice, m_pTeapotMesh)
IF SUCCEEDED(m_pTeapotMesh.GetVertexBuffer(pTempVertexBuffer)) THEN
LOCAL nNumVerts AS LONG
nNumVerts = m_pTeapotMesh.GetNumVertices
LOCAL pVertices AS Vertex PTR
pTempVertexBuffer.Lock(0, 0, pVertices, 0)
' // Make each vertex blue
LOCAL i AS LONG
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
pTempTeapotMesh = NOTHING
' // 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 matView AS D3DXMATRIX
LOCAL matWorld AS D3DXMATRIX
LOCAL matTrans AS D3DXMATRIX
LOCAL matRot AS D3DXMATRIX
' // Begins the scene
m_pD3DDevice.BeginScene
D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, 6.5!)
matView = matTrans
m_pD3DDevice.SetTransform(%D3DTS_VIEW, matView)
' // We'll reuse this rotation for all three teapots
D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
' // Render the first teapot using a red clay material
D3DXMatrixTranslation(matTrans, 0.0!, 1.2!, 0.0!)
D3DXMatrixMultiply(matWorld, matRot, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.SetMaterial(m_redClayMtrl)
m_pTeapotMesh.DrawSubset(0)
' // Render the second teapot using a green plastic material
D3DXMatrixTranslation(matTrans, 1.7!, -0.8!, 0.0!)
D3DXMatrixMultiply(matWorld, matRot, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.SetMaterial(m_greenPlasticMtrl)
m_pTeapotMesh.DrawSubset(0)
' // Render the third teapot using a silver metallic material
D3DXMatrixTranslation(matTrans, -1.7!, -0.8!, 0.0!)
D3DXMatrixMultiply(matWorld, matRot, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
m_pD3DDevice.SetMaterial(m_silverMetalMtrl)
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 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 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_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
' ========================================================================================
Demonstrates how to manually load the vertex buffer of a single ID3DXMesh object with three separate colored quads. We then use an attribute table to ID these three quads so we can render them separately as subsets of the mesh using DrawSubset.
The example also demonstrates how to use the ID3DXMesh methods GenerateAdjacency and OptimizeInplace to optimize our test mesh.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_MeshAttributes.bas
' Contents: DX9 example
' Description: Demonstrates how to manually load the vertex buffer of a single ID3DXMesh
' object with three separate colored quads. We then use an attribute table to ID these
' three quads so we can render them separately as subsets of the mesh using DrawSubset.
' The sample also demonstrates how to use the ID3DXMesh methods GenerateAdjacency and
' OptimizeInplace to optimize our test mesh.
' http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx11192002.asp
' 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_mesh_attributes.cpp by Kevin Harris, 05/22/05, available at
' http://www.codesampler.com/dx9src/dx9src_11.htm#dx9_mesh_attributes
' Control Keys: Left Mouse Button - Spin the view
' F1 - Toggle rendering of subset #0 of mesh object
' F2 - Toggle rendering of subset #1 of mesh object
' F3 - Toggle rendering of subset #2 of mesh object
' ########################################################################################
' 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) - Using Mesh Attributes to Render Subsets"
%FVF_Flags = %D3DFVF_XYZ OR %D3DFVF_DIFFUSE
TYPE Vertex
x AS SINGLE
y AS SINGLE
z AS SINGLE
dwColor AS DWORD
END TYPE
GLOBAL pDX9 AS IDX9
' ========================================================================================
' 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
' ========================================================================================
' =======================================================================================
' 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_pMesh AS ID3DXMesh
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
INSTANCE m_bRenderSubset0 AS LONG
INSTANCE m_bRenderSubset1 AS LONG
INSTANCE m_bRenderSubset2 AS LONG
INSTANCE m_verticesFor3Quads () AS Vertex
' ====================================================================================
' Initializes values
' ====================================================================================
CLASS METHOD Create
m_bRenderSubset0 = %TRUE
m_bRenderSubset1 = %TRUE
m_bRenderSubset2 = %TRUE
'// Define three quads and create each one from two separate triangles.
'// Using two separate triangles will give us redundant or repeated vertices,
'// which is bad practice, but this will let us test out the OptimizeInplace
'// method of ID3DXMesh.
DIM m_verticesFor3Quads(17) AS INSTANCE Vertex
' // Bottom-Left, color = yellow
FillVertex(m_verticesFor3Quads( 0), -1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads( 1), 1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads( 2), 1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
' // Second triangle of quad #1
FillVertex(m_verticesFor3Quads( 3), -1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads( 4), 1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads( 5), -1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 1.0, 0.0, 1.0))
' // First triangle of quad #2
FillVertex(m_verticesFor3Quads( 6), 1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_verticesFor3Quads( 7), 3.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_verticesFor3Quads( 8), 3.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
' // Second triangle of quad #2
FillVertex(m_verticesFor3Quads( 9), 1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_verticesFor3Quads(10), 3.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
FillVertex(m_verticesFor3Quads(11), 1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0))
' // First triangle of quad #3
FillVertex(m_verticesFor3Quads(12), -3.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads(13), -1.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads(14), -1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
' // Second triangle of quad #3
FillVertex(m_verticesFor3Quads(15), -3.0!, -1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads(16), -1.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.0, 0.0, 0.0, 1.0))
FillVertex(m_verticesFor3Quads(17), -3.0!, 1.0!, 0.0!, D3DCOLOR_COLORVALUE(1.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
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)
' // Create a mesh container...
hr = D3DXCreateMeshFVF(6, _ ' // Our 3 quads have a total of 6 faces or triangles (3 quads * 2 triangles each)
19, _ ' // which will require 18 vertices to define them.
%D3DXMESH_MANAGED, _
%FVF_Flags, _ ' // This is how each vertex is laid out.
m_pd3dDevice, _
m_pMesh)
' // Load our vertices...
LOCAL pVertices AS Vertex PTR
m_pMesh.LockVertexBuffer(0, pVertices)
' // First triangle of quad #1
@pVertices[0] = m_verticesFor3Quads(0)
@pVertices[1] = m_verticesFor3Quads(1)
@pVertices[2] = m_verticesFor3Quads(2)
' // Second triangle of quad #1
@pVertices[3] = m_verticesFor3Quads(3)
@pVertices[4] = m_verticesFor3Quads(4)
@pVertices[5] = m_verticesFor3Quads(5)
' // First triangle of quad #2
@pVertices[6] = m_verticesFor3Quads(6)
@pVertices[7] = m_verticesFor3Quads(7)
@pVertices[8] = m_verticesFor3Quads(8)
' // Second triangle of quad #2
@pVertices[9] = m_verticesFor3Quads(9)
@pVertices[10] = m_verticesFor3Quads(10)
@pVertices[11] = m_verticesFor3Quads(11)
' // First triangle of quad #3
@pVertices[12] = m_verticesFor3Quads(12)
@pVertices[13] = m_verticesFor3Quads(13)
@pVertices[14] = m_verticesFor3Quads(14)
' // Second triangle of quad #3
@pVertices[15] = m_verticesFor3Quads(15)
@pVertices[16] = m_verticesFor3Quads(16)
@pVertices[17] = m_verticesFor3Quads(17)
' // If you wanted, you could also memcpy the whole thing in like so.
' //memcpy( pVertices, m_verticesFor3Quads, sizeof(m_verticesFor3Quads) );
' nSize = (UBOUND(m_verticesFor3Quads) - LBOUND(m_verticesFor3Quads) + 1) * SIZEOF(Vertex)
' MoveMemory BYVAL pVertices, BYVAL VARPTR(m_verticesFor3Quads(0)), nSize
m_pMesh.UnlockVertexBuffer
' // Define our indices...
LOCAL pIndices AS WORD PTR
m_pMesh.LockIndexBuffer(0, pIndices)
' // First triangle of quad #1
@pIndices[0] = 0
@pIndices[1] = 1
@pIndices[2] = 2
' // Second triangle of quad #1
@pIndices[3] = 3
@pIndices[4] = 4
@pIndices[5] = 5
' // First triangle of quad #2
@pIndices[6] = 6
@pIndices[7] = 7
@pIndices[8] = 8
' // Second triangle of quad #2
@pIndices[9] = 9
@pIndices[10] = 10
@pIndices[11] = 11
' // First triangle of quad #3
@pIndices[12] = 12
@pIndices[13] = 13
@pIndices[14] = 14
' // Second triangle of quad #3
@pIndices[15] = 15
@pIndices[16] = 16
@pIndices[17] = 17
m_pMesh.UnlockIndexBuffer
' //
' // Now, if you would like to render each quad separately, you can use an
' // attribute buffer to ID them. We'll use ID #0 for the first quad, ID #1
' // for second quad, and ID #2 for the third quad. This way, we can use
' // DrawSubset to pick which quad we want to render. This is very useful if
' // our quads use different textures, or materials which need to be applied
' // to each one before rendering. Otherwise, we would not have an
' // opportunity to switch textures or materials once the mesh object starts
' // rendering them.
' //
' // NOTE: Keep in mind that defining attributes hinders our ability to
' // optimize the mesh with a call to OptimizeInplace. This is because
' // attributes are meant to isolate one subset of a mesh from another
' // subset for rendering purposes, and vertices can't be shared among
' // subsets. Therefore, even if a mesh can be rearranged into a
' // nice long tri-strip, which can be rendered in one call, it will
' // have to be broken into multiple pieces to support calling
' // DrawSubset with a attribute ID.
' //
LOCAL pAttributes AS DWORD PTR
m_pMesh.LockAttributeBuffer(0, pAttributes)
@pAttributes[0] = 0 ' // First face or triangle of quad #1
@pAttributes[1] = 0 ' // First face or triangle of quad #1
@pAttributes[2] = 1 ' // First face or triangle of quad #2
@pAttributes[3] = 1 ' // First face or triangle of quad #2
@pAttributes[4] = 2 ' // First face or triangle of quad #3
@pAttributes[5] = 2 ' // First face or triangle of quad #3
m_pMesh.UnlockAttributeBuffer
' //
' // The last step for our mesh object is to optimize the mesh. To assist in
' // the optimization step, we need to create a special buffer to hold the
' // adjacency information concerning each triangle face present in the mesh.
' // Since each triangle can have up to 3 neighbors, which are adjacent, we
' // need a buffer of size (numFaces * 3).
' //
' // Create an adjacency buffer
REDIM rgAdjacencyBuffer ((m_pMesh.GetNumFaces * 3 * 4) - 1) AS DWORD
' // Using a vertex positional tolerance of 0.0!, ask the mesh for its
' // adjacency information.
m_pMesh.GenerateAdjacency(0.0!, rgAdjacencyBuffer(0))
' // Now, tell the mesh to attempt an optimization based on that
' // adjacency information.
hr = m_pMesh.OptimizeInplace(%D3DXMESHOPT_VERTEXCACHE OR _ ' // Reorders faces to increase the cache hit rate of vertex caches.
%D3DXMESHOPT_IGNOREVERTS, _ ' // Optimize the faces only; do not optimize the vertices.
rgAdjacencyBuffer(0), _
BYVAL %NULL, BYVAL %NULL, 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.35!,0.53!,0.7!,1.0!), 1.0!, 0)
LOCAL matTrans AS D3DXMATRIX
LOCAL matRot AS D3DXMATRIX
LOCAL matWorld AS D3DXMATRIX
D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(m_fSpinX), D3DXToRadian(m_fSpinY), 0.0!)
D3DXMatrixTranslation(matTrans, 0.0!, 0.0!, 6.5!)
D3DXMatrixMultiply(matWorld, matRot, matTrans)
m_pD3DDevice.SetTransform(%D3DTS_WORLD, matWorld)
' // Begins the scene
m_pD3DDevice.BeginScene
' // Now, lets render the three quads in our mesh via their attribute IDs.
IF ISTRUE m_bRenderSubset0 THEN
m_pMesh.DrawSubset(0)
END IF
IF ISTRUE m_bRenderSubset1 THEN
m_pMesh.DrawSubset(1)
END IF
IF ISTRUE m_bRenderSubset2 THEN
m_pMesh.DrawSubset(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_pMesh = 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_bRenderSubset0 = IIF&(m_bRenderSubset0 = 0, -1, 0)
CASE %VK_F2
m_bRenderSubset1 = IIF&(m_bRenderSubset1 = 0, -1, 0)
CASE %VK_F3
m_bRenderSubset2 = IIF&(m_bRenderSubset2 = 0, -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
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_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
' ========================================================================================
Demonstrates how to create 3D geometry with Direct3D by loading vertex data into multiple vertex nuffers.
' ########################################################################################
' Microsoft Windows
' File: CW_DX9_MultipleVertexBuffers.bas
' Contents: DX9 example
' Description: Demonstrates how to create 3D geometry with Direct3D by loading vertex data
' into multiple Vertex Buffers.
' 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, 02/01/05, available at
' http://www.codesampler.com/dx9src/dx9src_2.htm#dx9_multiple_vertex_buffers
' ########################################################################################
' 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) - Multiple Vertex Buffers"
TYPE Vertex
x AS SINGLE
y AS SINGLE
z AS SINGLE
END TYPE
TYPE tagColor
dwcolor AS DWORD
END TYPE
TYPE TexCoord
tu AS SINGLE
tv AS SINGLE
END TYPE
' ========================================================================================
' Fills a Vertex structure
' ========================================================================================
MACRO FillVertex (v, x_, y_, z_)
v.x = x_ : v.y = y_ : v.z = z_
END MACRO
' ========================================================================================
' ========================================================================================
' Fills a TexCoord structure
' ========================================================================================
MACRO FillTexCoord (t, tu_, tv_)
t.tu = tu_ : t.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_pVertexDeclaration AS IDirect3DVertexDeclaration9
INSTANCE m_pColorBuffer AS IDirect3DVertexBuffer9
INSTANCE m_pTexCoordBuffer AS IDirect3DVertexBuffer9
INSTANCE m_fSpinX AS SINGLE
INSTANCE m_fSpinY AS SINGLE
INSTANCE m_cubeVertices () AS Vertex
INSTANCE m_cubeColors () AS tagColor
INSTANCE m_cubeTexCoords() AS TexCoord
INSTANCE dwDecl() AS D3DVERTEXELEMENT9
' ====================================================================================
' Initializes the vertex array
' ====================================================================================
CLASS METHOD Create
DIM m_cubeVertices(23) AS INSTANCE Vertex
FillVertex(m_cubeVertices( 0), -1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices( 1), 1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices( 2), -1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices( 3), 1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices( 4), -1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices( 5), -1.0!, -1.0!, 1.0!)
FillVertex(m_cubeVertices( 6), 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices( 7), 1.0!, -1.0!, 1.0!)
FillVertex(m_cubeVertices( 8), -1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices( 9), 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices(10), -1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices(11), 1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices(12), -1.0!, -1.0!, 1.0!)
FillVertex(m_cubeVertices(13), -1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices(14), 1.0!, -1.0!, 1.0!)
FillVertex(m_cubeVertices(15), 1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices(16), 1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices(17), 1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices(18), 1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices(19), 1.0!, -1.0!, 1.0!)
FillVertex(m_cubeVertices(20), -1.0!, 1.0!, -1.0!)
FillVertex(m_cubeVertices(21), -1.0!, -1.0!, -1.0!)
FillVertex(m_cubeVertices(22), -1.0!, 1.0!, 1.0!)
FillVertex(m_cubeVertices(23), -1.0!, -1.0!, 1.0!)
DIM m_cubeColors(23) AS INSTANCE tagColor
m_cubeColors( 0).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 )
m_cubeColors( 1).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 )
m_cubeColors( 2).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 )
m_cubeColors( 3).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 )
m_cubeColors( 4).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 )
m_cubeColors( 5).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 )
m_cubeColors( 6).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 )
m_cubeColors( 7).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 )
m_cubeColors( 8).dwColor = D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 )
m_cubeColors( 9).dwColor = D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 )
m_cubeColors(10).dwColor = D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 )
m_cubeColors(11).dwColor = D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 )
m_cubeColors(12).dwColor = D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 )
m_cubeColors(13).dwColor = D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 )
m_cubeColors(14).dwColor = D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 )
m_cubeColors(15).dwColor = D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 )
m_cubeColors(16).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 )
m_cubeColors(17).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 )
m_cubeColors(18).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 )
m_cubeColors(19).dwColor = D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 )
m_cubeColors(20).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 )
m_cubeColors(21).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 )
m_cubeColors(22).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 )
m_cubeColors(23).dwColor = D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 )
DIM m_cubeTexCoords(23) AS INSTANCE TexCoord
FillTexCoord(m_cubeTexCoords( 0), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords( 1), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords( 2), 0.0!, 1.0!)
FillTexCoord(m_cubeTexCoords( 3), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords( 4), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords( 5), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords( 6), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords( 7), 0.0!, 1.0!)
FillTexCoord(m_cubeTexCoords( 8), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords( 9), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(10), 0.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(11), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(12), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(13), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(14), 0.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(15), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(16), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(17), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(18), 0.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(19), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(20), 1.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(21), 1.0!, 1.0!)
FillTexCoord(m_cubeTexCoords(22), 0.0!, 0.0!)
FillTexCoord(m_cubeTexCoords(23), 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
m_pD3DDevice.SetRenderState(%D3DRS_LIGHTING, %FALSE)
m_pD3DDevice.SetRenderState(%D3DRS_ZENABLE, %TRUE)
' // 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)
' // 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)
' // Create a vertex buffer that contains only the cube's vertex data
LOCAL nSize AS LONG
LOCAL pVertices AS Vertex PTR
nSize = (UBOUND(m_cubeVertices) - LBOUND(m_cubeVertices) + 1) * SIZEOF(Vertex)
m_pD3DDevice.CreateVertexBuffer(nSize, 0, 0, %D3DPOOL_DEFAULT, m_pVertexBuffer, %NULL)
m_pVertexBuffer.Lock(0, nSize, pVertices, 0)
MoveMemory BYVAL pVertices, BYVAL VARPTR(m_cubeVertices(0)), nSize
m_pVertexBuffer.Unlock
' // Create a vertex buffer that contains only the cube's color data
LOCAL pColors AS tagColor PTR
nSize = (UBOUND(m_cubeColors) - LBOUND(m_cubeColors) + 1) * SIZEOF(tagColor)
m_pD3DDevice.CreateVertexBuffer(nSize, 0, 0, %D3DPOOL_DEFAULT, m_pColorBuffer, %NULL)
m_pColorBuffer.Lock(0, nSize, pColors, 0)
MoveMemory BYVAL pColors, BYVAL VARPTR(m_cubeColors(0)), nSize
m_pColorBuffer.Unlock
' // Create a vertex buffer that contains only the cube's texture coordinate data
LOCAL pTexCoords AS TexCoord PTR
nSize = (UBOUND(m_cubeTexCoords) - LBOUND(m_cubeTexCoords) + 1) * SIZEOF(TexCoord)
m_pD3DDevice.CreateVertexBuffer(nSize, 0, 0, %D3DPOOL_DEFAULT, m_pTexCoordBuffer, %NULL)
m_pTexCoordBuffer.Lock(0, nSize, pTexCoords, 0)
MoveMemory BYVAL pTexCoords, BYVAL VARPTR(m_cubeTexCoords(0)), nSize
m_pTexCoordBuffer.Unlock
' // Create a vertex declaration so we can describe to Direct3D how we'll
' // be passing our data to it.
DIM dwDecl(3) AS INSTANCE D3DVERTEXELEMENT9
dwDecl(0).Stream = 0
dwDecl(0).Offset = 0
dwDecl(0).Type = %D3DDECLTYPE_FLOAT3
dwDecl(0).Method = %D3DDECLMETHOD_DEFAULT
dwDecl(0).Usage = %D3DDECLUSAGE_POSITION
dwDecl(0).UsageIndex = 0
dwDecl(1).Stream = 1
dwDecl(1).Offset = 0
dwDecl(1).Type = %D3DDECLTYPE_D3DCOLOR
dwDecl(1).Method = %D3DDECLMETHOD_DEFAULT
dwDecl(1).Usage = %D3DDECLUSAGE_COLOR
dwDecl(1).UsageIndex = 0
dwDecl(2).Stream = 2
dwDecl(2).Offset = 0
dwDecl(2).Type = %D3DDECLTYPE_FLOAT2
dwDecl(2).Method = %D3DDECLMETHOD_DEFAULT
dwDecl(2).Usage = %D3DDECLUSAGE_TEXCOORD
dwDecl(2).UsageIndex = 0
dwDecl(3).Stream = &HFF
dwDecl(3).Offset = 0
dwDecl(3).Type = %D3DDECLTYPE_UNUSED
dwDecl(3).Method = 0
dwDecl(3).Usage = 0
dwDecl(3).UsageIndex = 0
m_pD3DDevice.CreateVertexDeclaration(dwDecl(0), m_pVertexDeclaration)
' // 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
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(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
m_pD3DDevice.SetTexture(0, m_pTexture)
m_pD3DDevice.SetVertexDeclaration(m_pVertexDeclaration)
m_pD3DDevice.SetStreamSource(0, m_pVertexBuffer, 0, SIZEOF(Vertex))
m_pD3DDevice.SetStreamSource(1, m_pColorBuffer, 0, SIZEOF(tagColor))
m_pD3DDevice.SetStreamSource(2, m_pTexCoordBuffer, 0, SIZEOF(TexCoord))
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
m_pColorBuffer = NOTHING
m_pTexCoordBuffer = 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 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_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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================
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
' ========================================================================================